Upgrading from pol95 to pol99 - My experience

Here you can post threads specific to the current release of the core (099)

Moderator: POL Developer

Post Reply
New User
Posts: 3
Joined: Sun Apr 17, 2016 11:55 pm

Upgrading from pol95 to pol99 - My experience

Post by seravy » Sat Aug 06, 2016 12:09 am

After over a decade of not touching UO/Pol I recently performed an upgrade of our server's distro scripts from POL95 to POL99 (Or latest build as of April-2016).
I thought I would write down my experience in case anyone else in the future was to do the same and ran into one of these problems.
This doesn't mean that all the realms are available and scripts support them, it just means you can run it on the latest core. Obviously updating those scripts is highly distro dependant.
Someone has already mentioned what is the point in upgrading when there are distros on 99 already but in this case keeping the nostalgia of the whole shard was important.

1. I took a copy of the POL95 Server I wanted to upgrade.
2. I removed all the extra files, deleting all the scripts\**\*.em files, .dep, .lst, .ecl, .dbg, .dbg.txt, .dmp. Extra pol files (.pol), supporting files, assorted batch files, executables. As we have new scripting calls need to get rid of all the .em files too which may be scattered around. We also used POLHook so clean that up.
> DEL /Q /S *.ecl *.bak *.dep *.log *.lst *.dbg *.dbg.txt *.pol *.exe *.bat *.em core-changes.txt objtypes.txt orphans.txt dbghelp.dll LOG POLHook.cfg POLHook

3. Download the latest distro, in my case the windows version is so old that I compiled a newer copy. Drop all the files into the root folder, overriding animxlate.cfg, boats.cfg, ecompile.cfg.example.

4. The first and hardest job is to get the scripts to compile.
Running your compiler 'ecompile.exe -C ecompile.cfg' you need to sift through all of the errors one at a time.
There are a few find and replaces which i found helped though. Here are a list of errors you can run into and what i did to fix them.

* Function names which are now core:
eg: 'RandomFloat' is already defined as a function., Expected an identifier, got User Function Min instead.
Some of them i used regular expressions to run a replacement over the entire codebase and present it in the format: Orginial -> Replacement

RandomFloat() -> RandomFloatInline().
function min(x, y) -> function minInline(x, y)
function max(x, y) -> function maxInline(x, y)
"Function Damage() is not defined." is now ApplyDamage ^([^\S\r\n]*)(Damage\([^\r?\n]*) -> $1Apply$2
IsStackable\( -> IsStackableInline(
FindPath( -> FindPathInline(
var max - Rename instances of these variables with something else eg 'maxVar'.
var min
SYSFIND_SEARCH_STORAGE_AREAS - No longer exists, delete it.
GameStat(?) - Gone, use polcore().?
program SingleClick(who, singleSerial) -> program SingleClickHook(who, singleSerial)
+"Error reading function declaration in module uo" was because of "PlaySound", renamed to "PlaySoundInline"
PlayMusic( -> PlayMusicInline(

* Function parameters change
There are two really big ones here, MoveCharacterToLocation and MoveItemToLocation which is now MoveObjectToLocation and requires the default realm variable if the force location flag was provided.
These regex will catch 5 parameter long (so needing default realm subbed in, could be a 0/1 or a MOVECHAR_FORCELOCATION) calls, but anything spanning two lines or without a ; on the end will need manual intervention.

a. MoveCharacterToLocation([^,\n]*,[^,\n]*,[^,\n]*,[^,\n]*,)([^;\n]*.*) -> MoveObjectToLocation$1 _DEFAULT_REALM,$2
b. MoveItemToLocation([^,\n]*,[^,\n]*,[^,\n]*,[^,\n]*,)([^;\n]*.*) -> MoveObjectToLocation$1 _DEFAULT_REALM,$2

Now try catch the one with only 4 parameters, put in _DEFAULT_REALM still because its a placeholder for us to know where to look to change realms in the future.
When replaced you might get an issue where its botched it eg (CInt(targ.x), CInt(targ.y), CInt(targ.z, _DEFAULT_REALM));) so need to pull it out of the function.

h. MoveCharacterToLocation([^,\n]*,[^,\n]*,[^,\n]*,[^\)\n]*)(\)) -> MoveObjectToLocation$1, _DEFAULT_REALM$2
i. MoveItemToLocation([^,\n]*,[^,\n]*,[^,\n]*,[^\)\n]*)(\)) -> MoveObjectToLocation$1, _DEFAULT_REALM$2

Search for MoveCharacterToLocation and find the remaining ones, probably across new lines. There may be a few which got changed but still compile, for example for me go.src had a GetMapInfo(dest.X, dest.Y) call which it stuck the _DEFAULT_REAM in the wrong spot.

* Next kind of errors are ones due the functions moving from one em file to another. Nothing to do but find which file the function is is and look at https://docs.polserver.com/pol099/index.php to see which EM file the function has gone to. Its probably going to be one of the following:
use attributes; use vitals; use storage; use guilds; so figure out which of those you need and append them.
"Function FindStorageArea() is not defined." etc,etc

* Script syntanx changes
Some syntax changes have been changed or made more strict.
EG: Error compiling statement at ../scripts/include/npcutil.inc, Line 20, Error in function 'NpcWander', File: ../scripts/include/npcutil.inc, Line 20
Case statements need brackets around the variable. case Random( 8 ) -> case (Random( 8 )). I had a lot of these.
You can try auto replace them with the regular expression: ^([^\S\r\n]*case )([^(][^\r?\n]*) -> $1($2)

> = operator depricated (need to do .asp files too). Run reg ex a few times.
Deprecated '=' found: did you mean '==' or ':='?
(^[^\S\r\n]*if[^\n]*[^=!><:]=)([^=!><])([^\n\r]*) $1=$2$3
([^\S\r\n]*if.*\([^\n]*[^=!><:]=)([^=!><])([^\n\r]*) $1=$2$3
([^\S\r\n]*while.*\([^\n]*[^=!><:]=)([^=!><])([^\n\r]*) $1=$2$3

> relative includes seemed a bit broken, but it may have been how i was compiling. Either way i refered to the package.
include "../../pkg/opt/folder/file"; include ":folder:file";

> CreateNpcFromTemplate needed an struct instead of an array but compiled fine
var props array;
needed changing to
var props:= struct;

Compilation Summary:
Compiled 1584 scripts in 463110 ms.

Now we are compiling, now we need to get running.

5) If you cant put items into an inventory (This item is too heavy message) Look for
Container 0xFF02
Name WornItemsContainer

and set
MaxItems 0
MaxWeight 0
MaxItems 65535
Maxweight 65535

6) With one of the change Intrinisic value isn't valid anymore so remove it.
^[^\S\r\n]*Intrinsic.*1\S* ->
and then add
Armor 0x1F022
Name intrinsicshield
Graphic 1
MaxHP 1
SaveOnExit 0
to combats itemdesc.cfg

7) To fix spells there are a few things to do.
a) If you have all the spells in a spell book show up as clumsy, the new item type is now a spellbook. Need to open itemdesc.cfg and change Container 0x0EFA to Spellbook 0x0EFA, removed the 'Maxweight 65535', and add 'SpellType Magic' for some reason? Perhaps this was use in the main distro.
b) Because the logic for casting spells in 95 was core but now is handled by scripts we need to add in a new initalizer script that then passes it off to the spell script.
spells.cfg needs changing to remove 'Change' 'Duration' and rename 'Script <spellname>' to 'SpellScript <spellname>' then add in 'Script castSpell'
c) Add in this new start script, each distro will be different but this is what mine looks like, you could possibly use the distro ones but keep in mind all the spells would be wrong: https://github.com/polserver/poldistro/ ... tSpell.src / https://github.com/polserver/poldistro/ ... tSpell.src
https://github.com/polserver/poldistro/ ... tarter.src

In my case i had write one from scratch to work on our server, as we have a TryToCast call logic which checks for regs, mana, movement, etc and then if ok will start the spell script.

d) Also our logic was for TryToCast didnt allow moving when casting so had to add a check in for normal spells.
e) Inscription logic needed changing because EnumerateItemsInContainer(spellbook) was replaced with spellbook.Spells(); and then to get the objecttype var spellobjtype := Hex(spellId + 0x1f2c);
Also instead of adding spells like CreateItemInContainer( book, scroll.objtype, 1 ); , use book.AddSpell(spellId);

8) CreateMultiAtLocation seems to not attach house_serial onto it's components anymore in pol99, so manually do it. We had scripts which would use the property.
// Seems like it doesn't automatically attach house_serial to the components anymore in pol99, do this for legacy reasons.
foreach item in (house.components)
SetObjProperty( item, "house_serial", house.serial);

9) You may have a problem where skills can not be used. We had a lot of skills in skills.cfg which now needs to be attributes.cfg with some changes.
Rename them to attributes.cfg and for each 'Skill 15' should be changed to 'Attribute Enticement' and then removed from another attributes.cfg file.
It means now that any ReadConfigFile("skills"); needs to be changed to attributes but look up the id, we have uoskills which has a look up.
var uoskills := ReadConfigFile(":*:uoskills");
var skillname := uoskills[skillid].Attribute;
var cfg := ReadConfigFile(":*:attributes");
var default_points := cfg[skillname].default_points;

10) Because LOS checks between pol95 and pol99 have changed, i added a special hook so i could try replicate the old pol95 target checks.
Made pol95.inc and replaced all calls to CheckLineOfSight with CheckLineOfSight95 and Target with Target95, also update attackhook with los check if (!CheckLineOfSight95(attacker, defender)) return 1; endif.
This really may not be nessary, but some old spells like wall of stone would be too short in one direction, where in pol95 it would block LOS in the new checks would always allow LOS.
([\s=]Target)(\() -> $195$2
([\s=]CheckLineOfSight)(\() -> $195$2

11) extobj.cfg changes. Either extobj.cfg needs to be updated to contain the same ids as in itemdesc, or itemdesc needs updating to match extobj.cfg.

Make extobj.cfg match itemdesc:

12) We used Polhook for 95, but now there is less need for extra checks and more packets are hookable so was deleted. This included special commands.

13) Update system config files:
Error reading configuration file config/repsys.cfg: Pro
Grab repsys.cfg from https://github.com/polserver/poldistro/ ... repsys.cfg

Execution aborted due to: Intrinsic Shield 0x1f022 must specify SaveOnExit 0
See point 6.

> Option ListenPort in pol.cfg is now only for non-multithreading systems. If you still haven't done it, please read the documentation on how to create a uoclients.cfg.
Pol.cfg is too old, copy https://github.com/polserver/polserver/ ... rt/pol.cfg

> Cant connect
Port no longer in pol.cfg, so Add

Port 5333
Encryption none
AOSResistances 0

to uoclient.cfg, replace 5333 with your port.

14) Generate world files
Modify pol.cfg to point mul files. Open uoconvert.cfg and UseNewHSAFormat 0.
We only worry about britannia.

uoconvert.exe multis && move /Y multis.cfg config\
uoconvert.exe tiles && move /Y tiles.cfg config\
uoconvert.exe landtiles && move /Y landtiles.cfg config\
uoconvert.exe map realm=britannia mapid=0 usedif=1 width=7168 height=4096 //Non Mondain's Legacy use "width=6144" here
uoconvert.exe statics realm=britannia
uoconvert.exe maptile realm=britannia

15) Additional Errors and troubleshooting
> Assertion Failed: graphic < ( config.max_tile_id + 1 ), tiles.cpp, line 33
Change 0x3FFF to MaxTileID=0xFFFF, even though using an older client?

>Error reading configuration file config/tiles.cfg:
> Expected '}' on a blank line after element properties
> Near line: 4478
> Element started on line: 4476
>Server Shutdown: load_tiles_cfg
>Execution aborted due to: Configuration file error.
Make sure UseNewHSAFormat is right

>Server Shutdown: load_weapon_templates
>Execution aborted due to: Objtype 0x1f020 must define a graphic
Make sure extobj.cfg matches the itemdesc

>Error reading configuration file config/repsys.cfg:
> Property 'Invulnerable' was not found.
> Element: NameColoring , found on line 1
>Error reading configuration file config/repsys.cfg:
> Mandatory section type 'General' not found
> Element started on line: 1
Ensure repsys.cfg is correct.

>Compiling: x.src
>Error reading function declaration in module uo
>Error compiling statement at x.src, Line 1
>Compilation Error:
>Near: use uo;
>File: x.src, Line 1
>Execution aborted due to: Error compiling file
Often its due to function redeclared or variable. So in this case function PlaySound() was redeclared when UO.em now has it.

16) Success
Hopefully you should be able to log on and run around without too many differences. Honestly you may encounter many different issues upgrading your distro which I did not run into but I thought id share what I had to do.

Good luck!

Post Reply