PDA

View Full Version : Auto NPC Scale Engine/System (Must Read for Server Devs)


Akkadius
12-25-2013, 12:02 AM
WARNING: Before you read this, prepare to absorb a bunch of information and understand this before trying to paste it into your source and try and make it work without reading.

Here is another mod that I've spent a lot of time baking, making sure that it works using in running a live server. It was a seriously amazing thing once I got this built to where this was realistic and now I am sharing it with everyone.

Akka's Funhouse has ran entirely successfully in every single zone using this system, it is the bread and butter to saving yourself tons of development time by using very accuracte and precise math to scale your encounters. It gives a lot of options even for being a system I built for a lot of proprietary purposes, it is extremely flexible.

This system has a lot to it, however once you understand it, it is very easy to maintain and WILL save you many many hours. I will try to break it down the best that I can.

----------------------------
Required: Perl DBI - See Google for installing Perl DBI/DBD for Mysql, until I create an article explaining otherwise.
Required: plugin::LoadMysql(); - See thread HERE (http://www.eqemulator.org/forums/showthread.php?p=227039#post227039)
Required: Mysql tables cust_npc_scaling & cust_npc_scale_static & cust_npc_zonescale_static - DOWNLOAD HERE (http://eoc.akkadius.com/dl/cust_npc_scale_tables.sql)
----------------------------

It allows you to insert your own 'definitions' data for the way NPC's are scaled on the fly. You can adjust values, reload the zone and your scaling takes effective IMMEDIATELY.

There are 3 custom Mysql tables involved

cust_npc_scaling - This has the 'base' NPC data for Trash/Named/Raid encounters
cust_npc_scale_static - This table contains 'static' entries that override scaling for all of the dynamic scaling. The values in this table are NOT multipliers
cust_npc_zonescale_static - This table is topical to that of cust_npc_scaling, entries that are in this table are multipliers of the base data that exists in cust_npc_scaling. More on this later.


High Level Breakdown:

In each zone there is an invisible NPC that gets spawned, this is called your zonecontroller, this NPC simply sits and listens for signals and NPC pops and responds to them accordingly. This NPC and script is responsible for all of the magic that occurs here.
When the zonecontroller pops, the first step it takes is to load scaling data from all three tables, this is pushed into memory and stays in memory until Perl is reloaded with #reloadpl
Within the first 5 seconds that the zonecontroller is spawned, it will load everything into memory, and then iterate through all of the spawned entities in the zone and scale them with all of the data presented in the Mysql tables
Whenever an NPC spawns, it will signal the zonecontroller to say 'Hey, scale me' and the zonecontroller will respond to the request by scaling only that NPC that had just popped, given the exact criteria that is once again presented in the tables



Rules:

Keep in mind when this system is active, it assumes the place of scaling every single NPC in every zone. There are other methods explained later that will allow you to bypass the normal scaling system. There is currently no way to just say 'Don't scale' currently. If you truly wanted to over ride, you could do the same thing the zonecontroller script is doing inside the NPC script itself by setting the stats on the fly
Any invisible NPC is set to invulnerable, not attack
Any invisible NPC that is NOT a shadowed man, their name is set to blank or ""


Datasets:

The zonecontroller once again is fed a list of scaling data, this base scaling data is retrieved from `cust_npc_scaling` and the copy I have made for everyone today contains 300 entries, representing 1-100 NPC's based on data queried from averages of the current PEQ `npc_types` table, this is not the table that I use but should work relatively similar to current PEQ scaling. My server supported 250 levels so I had 750 entries.
There are 100 entries for each NPC TYPE, I have broken down NPC types into Trash, Named and Raid encounters


Typically, trash NPC's do not have a # in their name, so that zonecontroller literally will categorize a target end NPC by their name. The convention is as follows:

Trash - No # in the name
Named - Only 1 # in the name
Raid - 2 x '##' in the NPC Name


In PEQ's database table, currently raid targets do not go by the raid convention that I had made up, so this part is improvised due to a lack of a better way to differentiate a raid target given the data that we have. You could try to match special attack flags but that is also unreliable. This is up to you as the content creator to understand this and manipulate this to your advantage.

Here is a visual example of what data in `cust_npc_scaling` looks like:

Keys: Level, Type
Once again this is the base dataset, there are other tables I will explain that can multiply these values depending on your desire to scale content.

+-------+------+---------+------+--------+--------+--------------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------+------------+-----------+-----------------+
| level | type | hp | mana | mindmg | maxdmg | attack_speed | AC | STR | STA | DEX | AGI | _INT | WIS | CHA | MR | CR | DR | FR | PR | hp_regen | spellscale | healscale | npcspecialattks |
+-------+------+---------+------+--------+--------+--------------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------+------------+-----------+-----------------+
| 1 | 0 | 11 | 0 | 1 | 2 | 0 | 25 | 79 | 79 | 79 | 79 | 79 | 79 | 79 | 1 | 1 | 1 | 1 | 1 | 0 | 100 | 100 | |
| 2 | 0 | 24 | 0 | 1 | 4 | 0 | 32 | 81 | 81 | 81 | 81 | 81 | 81 | 81 | 1 | 1 | 1 | 1 | 1 | 0 | 100 | 100 | |
| 3 | 0 | 39 | 0 | 1 | 6 | 0 | 38 | 84 | 84 | 84 | 84 | 84 | 84 | 84 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 4 | 0 | 56 | 0 | 1 | 8 | 0 | 45 | 86 | 86 | 86 | 86 | 86 | 86 | 86 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 5 | 0 | 75 | 0 | 1 | 10 | 0 | 51 | 87 | 87 | 87 | 87 | 87 | 87 | 87 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 6 | 0 | 96 | 0 | 1 | 12 | 0 | 58 | 89 | 89 | 89 | 89 | 89 | 89 | 89 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 7 | 0 | 119 | 0 | 1 | 14 | 0 | 64 | 91 | 91 | 91 | 91 | 91 | 91 | 91 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 8 | 0 | 144 | 0 | 1 | 16 | 0 | 71 | 92 | 92 | 92 | 92 | 92 | 92 | 92 | 3 | 3 | 3 | 3 | 3 | 0 | 100 | 100 | |
| 9 | 0 | 171 | 0 | 1 | 18 | 0 | 77 | 93 | 93 | 93 | 93 | 93 | 93 | 93 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 10 | 0 | 200 | 0 | 1 | 20 | 0 | 84 | 94 | 94 | 94 | 94 | 94 | 94 | 94 | 4 | 4 | 4 | 4 | 4 | 1 | 100 | 100 | |
| 11 | 0 | 231 | 0 | 1 | 22 | 0 | 90 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 1 | 100 | 100 | |
| 12 | 0 | 264 | 0 | 1 | 24 | 0 | 97 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 13 | 0 | 299 | 0 | 1 | 26 | 0 | 103 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 5 | 5 | 5 | 5 | 5 | 1 | 100 | 100 | |
| 14 | 0 | 336 | 0 | 1 | 28 | 0 | 110 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 15 | 0 | 375 | 0 | 1 | 30 | 0 | 116 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 2 | 100 | 100 | |
| 16 | 0 | 416 | 0 | 1 | 32 | 0 | 123 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 17 | 0 | 459 | 0 | 1 | 34 | 0 | 129 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 7 | 7 | 7 | 7 | 7 | 0 | 100 | 100 | |
| 18 | 0 | 504 | 0 | 1 | 36 | 0 | 136 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 11 | 11 | 11 | 11 | 11 | 0 | 100 | 100 | |
| 19 | 0 | 551 | 0 | 1 | 38 | 0 | 142 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 20 | 0 | 600 | 0 | 1 | 40 | 0 | 149 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 21 | 0 | 651 | 0 | 1 | 42 | 0 | 155 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 22 | 0 | 704 | 0 | 1 | 44 | 0 | 162 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 9 | 9 | 9 | 9 | 9 | 4 | 100 | 100 | |
| 23 | 0 | 759 | 0 | 1 | 46 | 0 | 168 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 9 | 9 | 9 | 9 | 9 | 0 | 100 | 100 | |
| 24 | 0 | 816 | 0 | 1 | 48 | 0 | 175 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 10 | 10 | 10 | 10 | 10 | 4 | 100 | 100 | |
| 25 | 0 | 875 | 0 | 1 | 50 | 0 | 181 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 10 | 10 | 10 | 10 | 10 | 1 | 100 | 100 | |
| 26 | 0 | 936 | 0 | 1 | 52 | 0 | 188 | 102 | 102 | 102 | 102 | 102 | 102 | 102 | 10 | 10 | 10 | 10 | 10 | 1 | 100 | 100 | |
| 27 | 0 | 999 | 0 | 1 | 54 | 0 | 194 | 103 | 103 | 103 | 103 | 103 | 103 | 103 | 11 | 11 | 11 | 11 | 11 | 5 | 100 | 100 | |
| 28 | 0 | 1064 | 0 | 11 | 56 | 0 | 201 | 104 | 104 | 104 | 104 | 104 | 104 | 104 | 11 | 11 | 11 | 11 | 11 | 5 | 100 | 100 | |
| 29 | 0 | 1131 | 0 | 11 | 58 | 0 | 207 | 105 | 105 | 105 | 105 | 105 | 105 | 105 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 30 | 0 | 1200 | 0 | 12 | 60 | -7 | 214 | 106 | 106 | 106 | 106 | 106 | 106 | 106 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 31 | 0 | 1271 | 0 | 13 | 62 | -7 | 220 | 108 | 108 | 108 | 108 | 108 | 108 | 108 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 32 | 0 | 1344 | 0 | 13 | 64 | -7 | 227 | 109 | 109 | 109 | 109 | 109 | 109 | 109 | 13 | 13 | 13 | 13 | 13 | 7 | 100 | 100 | |
| 33 | 0 | 1419 | 0 | 13 | 66 | -7 | 233 | 111 | 111 | 111 | 111 | 111 | 111 | 111 | 13 | 13 | 13 | 13 | 13 | 1 | 100 | 100 | |
| 34 | 0 | 1496 | 0 | 14 | 68 | -8 | 240 | 113 | 113 | 113 | 113 | 113 | 113 | 113 | 14 | 14 | 14 | 14 | 14 | 7 | 100 | 100 | |
| 35 | 0 | 1575 | 0 | 14 | 70 | -8 | 246 | 116 | 116 | 116 | 116 | 116 | 116 | 116 | 14 | 14 | 14 | 14 | 14 | 8 | 100 | 100 | |
| 36 | 0 | 1656 | 0 | 14 | 72 | -8 | 253 | 118 | 118 | 118 | 118 | 118 | 118 | 118 | 14 | 14 | 14 | 14 | 14 | 8 | 100 | 100 | |
| 37 | 0 | 1739 | 0 | 14 | 74 | -8 | 259 | 121 | 121 | 121 | 121 | 121 | 121 | 121 | 14 | 14 | 14 | 14 | 14 | 9 | 100 | 100 | |
| 38 | 0 | 1824 | 0 | 15 | 76 | -8 | 266 | 124 | 124 | 124 | 124 | 124 | 124 | 124 | 15 | 15 | 15 | 15 | 15 | 9 | 100 | 100 | |
| 39 | 0 | 1911 | 0 | 16 | 78 | -9 | 272 | 128 | 128 | 128 | 128 | 128 | 128 | 128 | 15 | 15 | 15 | 15 | 15 | 1 | 100 | 100 | |
| 40 | 0 | 2000 | 0 | 32 | 120 | -9 | 279 | 132 | 132 | 132 | 132 | 132 | 132 | 132 | 16 | 16 | 16 | 16 | 16 | 1 | 100 | 100 | |
| 41 | 0 | 2091 | 0 | 33 | 123 | -9 | 285 | 136 | 136 | 136 | 136 | 136 | 136 | 136 | 16 | 16 | 16 | 16 | 16 | 10 | 100 | 100 | |
| 42 | 0 | 2184 | 0 | 34 | 126 | -9 | 292 | 140 | 140 | 140 | 140 | 140 | 140 | 140 | 17 | 17 | 17 | 17 | 17 | 2 | 100 | 100 | |
| 43 | 0 | 2279 | 0 | 34 | 129 | -10 | 298 | 145 | 145 | 145 | 145 | 145 | 145 | 145 | 18 | 18 | 18 | 18 | 18 | 1 | 100 | 100 | |
| 44 | 0 | 4900 | 0 | 35 | 132 | -10 | 381 | 151 | 151 | 151 | 151 | 151 | 151 | 151 | 18 | 18 | 18 | 18 | 18 | 3 | 100 | 100 | |
| 45 | 0 | 2475 | 0 | 36 | 135 | -10 | 311 | 156 | 156 | 156 | 156 | 156 | 156 | 156 | 18 | 18 | 18 | 18 | 18 | 12 | 100 | 100 | |
| 46 | 0 | 6000 | 0 | 37 | 138 | -10 | 318 | 162 | 162 | 162 | 162 | 162 | 162 | 162 | 18 | 18 | 18 | 18 | 18 | 4 | 100 | 100 | |
| 47 | 0 | 6500 | 0 | 38 | 141 | -10 | 324 | 169 | 169 | 169 | 169 | 169 | 169 | 169 | 18 | 18 | 18 | 18 | 18 | 32 | 100 | 100 | |
| 48 | 0 | 7000 | 0 | 38 | 144 | -11 | 331 | 176 | 176 | 176 | 176 | 176 | 176 | 176 | 19 | 19 | 19 | 19 | 19 | 35 | 100 | 100 | |
| 49 | 0 | 7500 | 0 | 39 | 147 | -11 | 421 | 183 | 183 | 183 | 183 | 183 | 183 | 183 | 19 | 19 | 19 | 19 | 19 | 4 | 100 | 100 | |
| 50 | 0 | 8750 | 0 | 74 | 200 | -15 | 344 | 191 | 191 | 191 | 191 | 191 | 191 | 191 | 20 | 20 | 20 | 20 | 20 | 6 | 100 | 100 | |
| 51 | 0 | 9750 | 0 | 75 | 203 | -16 | 350 | 200 | 100 | 200 | 200 | 200 | 200 | 200 | 21 | 21 | 21 | 21 | 21 | 6 | 100 | 100 | |
| 52 | 0 | 10750 | 0 | 76 | 206 | -16 | 446 | 209 | 209 | 209 | 209 | 209 | 209 | 209 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 53 | 0 | 11750 | 0 | 77 | 209 | -16 | 454 | 218 | 218 | 218 | 218 | 218 | 218 | 218 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 54 | 0 | 12750 | 0 | 78 | 212 | -16 | 462 | 228 | 228 | 228 | 228 | 228 | 228 | 228 | 21 | 21 | 21 | 21 | 21 | 9 | 100 | 100 | |
| 55 | 0 | 13750 | 0 | 78 | 215 | -17 | 376 | 239 | 139 | 239 | 239 | 239 | 239 | 239 | 22 | 22 | 22 | 22 | 22 | 8 | 100 | 100 | |
| 56 | 0 | 14750 | 0 | 79 | 218 | -17 | 478 | 250 | 250 | 250 | 250 | 250 | 250 | 250 | 22 | 22 | 22 | 22 | 22 | 10 | 100 | 100 | |
| 57 | 0 | 15750 | 0 | 80 | 221 | -17 | 486 | 261 | 261 | 261 | 261 | 261 | 261 | 261 | 22 | 22 | 22 | 22 | 22 | 11 | 100 | 100 | |
| 58 | 0 | 16750 | 0 | 81 | 224 | -18 | 494 | 274 | 274 | 274 | 274 | 274 | 274 | 274 | 23 | 23 | 23 | 23 | 23 | 12 | 100 | 100 | |
| 59 | 0 | 17000 | 0 | 62 | 177 | 0 | 402 | 287 | 287 | 287 | 287 | 287 | 287 | 287 | 24 | 24 | 24 | 24 | 24 | 7 | 100 | 100 | |
| 60 | 0 | 19000 | 0 | 142 | 280 | -19 | 409 | 300 | 300 | 300 | 300 | 300 | 300 | 300 | 24 | 24 | 24 | 24 | 24 | 11 | 100 | 100 | |
| 61 | 0 | 20000 | 0 | 143 | 283 | -19 | 415 | 314 | 314 | 314 | 314 | 314 | 314 | 314 | 24 | 24 | 24 | 24 | 24 | 100 | 100 | 100 | |
| 62 | 0 | 23000 | 0 | 450 | 1400 | -26 | 1328 | 225 | 225 | 225 | 225 | 225 | 225 | 225 | 65 | 65 | 65 | 65 | 65 | 15 | 100 | 100 | |
| 63 | 0 | 23500 | 0 | 450 | 1400 | -26 | 1348 | 225 | 225 | 225 | 225 | 225 | 225 | 225 | 65 | 65 | 65 | 65 | 65 | 15 | 100 | 100 | |
| 64 | 0 | 24000 | 0 | 450 | 1400 | -26 | 1369 | 225 | 225 | 225 | 225 | 225 | 225 | 225 | 87 | 87 | 87 | 87 | 87 | 15 | 100 | 100 | |
| 65 | 0 | 28500 | 0 | 226 | 445 | -24 | 441 | 378 | 378 | 378 | 378 | 378 | 378 | 378 | 26 | 26 | 26 | 26 | 26 | 142 | 100 | 100 | |
| 66 | 0 | 25000 | 0 | 450 | 1400 | -26 | 1410 | 225 | 225 | 225 | 225 | 225 | 225 | 225 | 65 | 65 | 65 | 65 | 65 | 15 | 100 | 100 | |
| 67 | 0 | 28000 | 0 | 360 | 800 | -18 | 568 | 314 | 314 | 314 | 314 | 314 | 314 | 314 | 27 | 27 | 27 | 27 | 27 | 250 | 100 | 100 | |
| 68 | 0 | 21760 | 0 | 272 | 524 | -22 | 1266 | 452 | 452 | 372 | 452 | 222 | 372 | 222 | 36 | 36 | 36 | 36 | 36 | 15 | 100 | 100 | |
| 69 | 0 | 28000 | 0 | 360 | 800 | -18 | 584 | 314 | 314 | 314 | 314 | 314 | 314 | 314 | 27 | 27 | 27 | 27 | 27 | 250 | 100 | 100 | |
| 70 | 0 | 30000 | 0 | 262 | 445 | 0 | 474 | 378 | 378 | 378 | 378 | 378 | 378 | 378 | 26 | 26 | 26 | 26 | 26 | 14 | 100 | 100 | |
| 71 | 0 | 10000 | 0 | 1 | 1 | 0 | 600 | 192 | 192 | 192 | 192 | 192 | 192 | 192 | 28 | 28 | 28 | 28 | 28 | 500 | 100 | 100 | |
| 72 | 0 | 82800 | 0 | 162 | 731 | -25 | 1216 | 347 | 347 | 72 | 222 | 72 | 347 | 347 | 38 | 38 | 38 | 38 | 38 | 10 | 100 | 100 | |
| 73 | 0 | 60000 | 0 | 675 | 2125 | -22 | 1479 | 325 | 325 | 325 | 325 | 325 | 325 | 325 | 38 | 38 | 38 | 38 | 38 | 35 | 100 | 100 | |
| 74 | 0 | 61000 | 0 | 675 | 2125 | -22 | 1499 | 325 | 325 | 325 | 325 | 325 | 325 | 325 | 39 | 39 | 39 | 39 | 39 | 35 | 100 | 100 | |
| 75 | 0 | 10875 | 0 | 234 | 750 | -33 | 759 | 590 | 590 | 590 | 590 | 590 | 590 | 590 | 40 | 40 | 40 | 40 | 40 | 8 | 100 | 100 | |
| 76 | 0 | 49046 | 0 | 406 | 1360 | -21 | 1187 | 412 | 412 | 359 | 387 | 362 | 414 | 417 | 36 | 36 | 36 | 36 | 36 | 62 | 100 | 100 | |
| 77 | 0 | 51373 | 0 | 417 | 1432 | -21 | 1228 | 423 | 423 | 366 | 396 | 371 | 426 | 431 | 36 | 36 | 36 | 36 | 36 | 52 | 100 | 100 | |
| 78 | 0 | 53700 | 0 | 429 | 1505 | -21 | 1270 | 434 | 434 | 373 | 404 | 381 | 438 | 446 | 36 | 36 | 36 | 36 | 36 | 43 | 100 | 100 | |
| 79 | 0 | 56027 | 0 | 441 | 1578 | -21 | 1312 | 444 | 444 | 380 | 412 | 391 | 450 | 461 | 36 | 36 | 36 | 36 | 36 | 34 | 100 | 100 | |
| 80 | 0 | 58354 | 0 | 453 | 1651 | -22 | 1354 | 455 | 455 | 387 | 421 | 401 | 462 | 476 | 36 | 36 | 36 | 36 | 36 | 25 | 100 | 100 | |
| 81 | 0 | 60681 | 0 | 465 | 1724 | -22 | 1396 | 465 | 465 | 394 | 429 | 410 | 474 | 490 | 36 | 36 | 36 | 36 | 36 | 16 | 100 | 100 | |
| 82 | 0 | 63007 | 0 | 477 | 1797 | -22 | 1437 | 476 | 476 | 401 | 437 | 420 | 486 | 505 | 36 | 36 | 36 | 36 | 36 | 7 | 100 | 100 | |
| 83 | 0 | 65334 | 0 | 489 | 1870 | -23 | 1479 | 486 | 486 | 408 | 445 | 430 | 498 | 520 | 36 | 36 | 36 | 36 | 36 | -2 | 100 | 100 | |
| 84 | 0 | 67661 | 0 | 500 | 1942 | -23 | 1521 | 497 | 497 | 415 | 454 | 439 | 510 | 534 | 36 | 36 | 36 | 36 | 36 | -11 | 100 | 100 | |
| 85 | 0 | 69988 | 0 | 512 | 2015 | -23 | 1563 | 507 | 507 | 422 | 462 | 449 | 522 | 549 | 36 | 36 | 36 | 36 | 36 | -20 | 100 | 100 | |
| 86 | 0 | 72315 | 0 | 524 | 2088 | -23 | 1604 | 518 | 518 | 429 | 470 | 459 | 534 | 564 | 36 | 36 | 36 | 36 | 36 | -29 | 100 | 100 | |
| 87 | 0 | 74642 | 0 | 536 | 2161 | -24 | 1646 | 529 | 529 | 436 | 479 | 469 | 546 | 579 | 36 | 36 | 36 | 36 | 36 | -38 | 100 | 100 | |
| 88 | 0 | 76969 | 0 | 548 | 2234 | -24 | 1688 | 539 | 539 | 443 | 487 | 478 | 558 | 593 | 36 | 36 | 36 | 36 | 36 | -47 | 100 | 100 | |
| 89 | 0 | 79295 | 0 | 560 | 2307 | -24 | 1730 | 550 | 550 | 450 | 495 | 488 | 570 | 608 | 36 | 36 | 36 | 36 | 36 | -56 | 100 | 100 | |
| 90 | 0 | 81622 | 0 | 572 | 2380 | -24 | 1771 | 560 | 560 | 457 | 503 | 498 | 582 | 623 | 36 | 36 | 36 | 36 | 36 | -65 | 100 | 100 | |
| 91 | 0 | 83949 | 0 | 584 | 2453 | -25 | 1813 | 571 | 571 | 464 | 512 | 508 | 594 | 638 | 36 | 36 | 36 | 36 | 36 | -74 | 100 | 100 | |
| 92 | 0 | 86276 | 0 | 595 | 2525 | -25 | 1855 | 581 | 581 | 471 | 520 | 517 | 606 | 652 | 36 | 36 | 36 | 36 | 36 | -83 | 100 | 100 | |
| 93 | 0 | 88603 | 0 | 607 | 2598 | -25 | 1897 | 592 | 592 | 478 | 528 | 527 | 618 | 667 | 36 | 36 | 36 | 36 | 36 | -92 | 100 | 100 | |
| 94 | 0 | 90930 | 0 | 619 | 2671 | -25 | 1939 | 602 | 602 | 485 | 536 | 537 | 630 | 682 | 36 | 36 | 36 | 36 | 36 | -101 | 100 | 100 | |
| 95 | 0 | 93257 | 0 | 631 | 2744 | -26 | 1980 | 613 | 613 | 492 | 545 | 547 | 642 | 697 | 36 | 36 | 36 | 36 | 36 | -110 | 100 | 100 | |
| 96 | 0 | 95583 | 0 | 643 | 2817 | -26 | 2022 | 624 | 624 | 499 | 553 | 556 | 654 | 711 | 36 | 36 | 36 | 36 | 36 | -119 | 100 | 100 | |
| 97 | 0 | 97910 | 0 | 655 | 2890 | -26 | 2064 | 634 | 634 | 506 | 561 | 566 | 666 | 726 | 36 | 36 | 36 | 36 | 36 | -128 | 100 | 100 | |
| 98 | 0 | 100237 | 0 | 667 | 2963 | -26 | 2106 | 645 | 645 | 513 | 570 | 576 | 678 | 741 | 36 | 36 | 36 | 36 | 36 | -137 | 100 | 100 | |
| 99 | 0 | 102564 | 0 | 679 | 3035 | -27 | 2147 | 655 | 655 | 520 | 578 | 586 | 690 | 756 | 37 | 37 | 37 | 37 | 37 | -147 | 100 | 100 | |
| 100 | 0 | 104891 | 0 | 690 | 3108 | -27 | 2189 | 666 | 666 | 527 | 586 | 595 | 702 | 770 | 37 | 37 | 37 | 37 | 37 | -156 | 100 | 100 | |
| 1 | 1 | 11 | 0 | 1 | 2 | 0 | 34 | 79 | 79 | 79 | 79 | 79 | 79 | 79 | 1 | 1 | 1 | 1 | 1 | 0 | 100 | 100 | |
| 2 | 1 | 60 | 0 | 1 | 10 | 0 | 35 | 93 | 93 | 93 | 93 | 93 | 93 | 93 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 3 | 1 | 39 | 0 | 1 | 6 | 0 | 52 | 84 | 84 | 84 | 84 | 84 | 84 | 84 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 4 | 1 | 58 | 0 | 1 | 10 | 0 | 49 | 75 | 75 | 75 | 75 | 20 | 20 | 75 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 5 | 1 | 75 | 0 | 2 | 12 | 0 | 56 | 75 | 75 | 75 | 75 | 80 | 75 | 75 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 6 | 1 | 96 | 0 | 1 | 12 | 0 | 63 | 89 | 89 | 89 | 89 | 89 | 89 | 89 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 7 | 1 | 119 | 0 | 1 | 14 | 0 | 70 | 91 | 91 | 91 | 91 | 91 | 91 | 91 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 8 | 1 | 144 | 0 | 1 | 16 | 0 | 78 | 92 | 92 | 92 | 92 | 92 | 92 | 92 | 3 | 3 | 3 | 3 | 3 | 0 | 100 | 100 | |
| 9 | 1 | 171 | 0 | 9 | 20 | 0 | 85 | 82 | 82 | 77 | 82 | 76 | 77 | 72 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 10 | 1 | 200 | 0 | 1 | 20 | 0 | 92 | 94 | 94 | 94 | 94 | 94 | 94 | 94 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 11 | 1 | 231 | 0 | 1 | 22 | 0 | 124 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 12 | 1 | 264 | 0 | 1 | 24 | 0 | 106 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 13 | 1 | 299 | 0 | 1 | 26 | 0 | 113 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 14 | 1 | 336 | 0 | 1 | 28 | 0 | 120 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 15 | 1 | 375 | 0 | 1 | 30 | 0 | 128 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 16 | 1 | 416 | 0 | 1 | 32 | 0 | 135 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 17 | 1 | 459 | 0 | 1 | 34 | 0 | 142 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 7 | 7 | 7 | 7 | 7 | 0 | 100 | 100 | |
| 18 | 1 | 504 | 0 | 8 | 36 | 0 | 186 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 7 | 7 | 7 | 7 | 7 | 0 | 100 | 100 | |
| 19 | 1 | 551 | 0 | 1 | 38 | 0 | 156 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 20 | 1 | 600 | 0 | 8 | 42 | -5 | 163 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 21 | 1 | 651 | 0 | 1 | 42 | 0 | 213 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 22 | 1 | 704 | 0 | 1 | 44 | 0 | 178 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 9 | 9 | 9 | 9 | 9 | 0 | 100 | 100 | |
| 23 | 1 | 759 | 0 | 1 | 46 | 0 | 185 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 9 | 9 | 9 | 9 | 9 | 1 | 100 | 100 | |
| 24 | 1 | 816 | 0 | 1 | 48 | 0 | 192 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 25 | 1 | 875 | 0 | 1 | 50 | 0 | 199 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 10 | 10 | 10 | 10 | 10 | 1 | 100 | 100 | |
| 26 | 1 | 936 | 0 | 1 | 52 | 0 | 206 | 102 | 102 | 102 | 102 | 102 | 102 | 102 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 27 | 1 | 999 | 0 | 1 | 54 | 0 | 213 | 103 | 103 | 103 | 103 | 103 | 103 | 103 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 28 | 1 | 1064 | 0 | 11 | 56 | 0 | 221 | 104 | 104 | 104 | 104 | 104 | 104 | 104 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 29 | 1 | 1131 | 0 | 11 | 58 | 0 | 228 | 105 | 105 | 105 | 105 | 105 | 105 | 105 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 30 | 1 | 1200 | 0 | 12 | 60 | -7 | 235 | 106 | 106 | 106 | 106 | 106 | 106 | 106 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 31 | 1 | 1271 | 0 | 13 | 62 | -7 | 242 | 108 | 108 | 108 | 108 | 108 | 108 | 108 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 32 | 1 | 1344 | 0 | 13 | 64 | -7 | 249 | 109 | 109 | 109 | 109 | 109 | 109 | 109 | 13 | 13 | 13 | 13 | 13 | 1 | 100 | 100 | |
| 33 | 1 | 1419 | 0 | 13 | 66 | -7 | 256 | 111 | 111 | 111 | 111 | 111 | 111 | 111 | 13 | 13 | 13 | 13 | 13 | 1 | 100 | 100 | |
| 34 | 1 | 1496 | 0 | 14 | 68 | -8 | 263 | 113 | 113 | 113 | 113 | 113 | 113 | 113 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | |
| 35 | 1 | 559 | 0 | 2 | 32 | -8 | 271 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 14 | 14 | 14 | 14 | 14 | 0 | 100 | 100 | |
| 36 | 1 | 1656 | 0 | 14 | 72 | -8 | 278 | 118 | 118 | 118 | 118 | 118 | 118 | 118 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | |
| 37 | 1 | 1739 | 0 | 14 | 74 | -8 | 285 | 121 | 121 | 121 | 121 | 121 | 121 | 121 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | |
| 38 | 1 | 1824 | 0 | 15 | 76 | -8 | 365 | 124 | 124 | 124 | 124 | 124 | 124 | 124 | 15 | 15 | 15 | 15 | 15 | 1 | 100 | 100 | |
| 39 | 1 | 1911 | 0 | 16 | 78 | -9 | 374 | 128 | 128 | 128 | 128 | 128 | 128 | 128 | 15 | 15 | 15 | 15 | 15 | 1 | 100 | 100 | |
| 40 | 1 | 3250 | 0 | 32 | 120 | 0 | 306 | 132 | 132 | 132 | 132 | 132 | 132 | 132 | 16 | 16 | 16 | 16 | 16 | 2 | 100 | 100 | |
| 41 | 1 | 2091 | 0 | 33 | 123 | -9 | 314 | 136 | 136 | 136 | 136 | 136 | 136 | 136 | 16 | 16 | 16 | 16 | 16 | 1 | 100 | 100 | |
| 42 | 1 | 2184 | 0 | 34 | 126 | -9 | 401 | 140 | 140 | 140 | 140 | 140 | 140 | 140 | 17 | 17 | 17 | 17 | 17 | 1 | 100 | 100 | |
| 43 | 1 | 2279 | 0 | 34 | 129 | -10 | 410 | 145 | 145 | 145 | 145 | 145 | 145 | 145 | 18 | 18 | 18 | 18 | 18 | 2 | 100 | 100 | |
| 44 | 1 | 2376 | 0 | 35 | 132 | -10 | 419 | 151 | 151 | 151 | 151 | 151 | 151 | 151 | 18 | 18 | 18 | 18 | 18 | 2 | 100 | 100 | |
| 45 | 1 | 2475 | 0 | 36 | 135 | -10 | 428 | 156 | 156 | 156 | 156 | 156 | 156 | 156 | 18 | 18 | 18 | 18 | 18 | 2 | 100 | 100 | |
| 46 | 1 | 6000 | 0 | 37 | 138 | -10 | 349 | 162 | 162 | 162 | 162 | 162 | 162 | 162 | 18 | 18 | 18 | 18 | 18 | 4 | 100 | 100 | |
| 47 | 1 | 6500 | 0 | 38 | 141 | -10 | 446 | 169 | 169 | 169 | 169 | 169 | 169 | 169 | 18 | 18 | 18 | 18 | 18 | 5 | 100 | 100 | |
| 48 | 1 | 759 | 0 | 6 | 42 | -11 | 364 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 19 | 19 | 19 | 19 | 19 | 0 | 100 | 100 | |
| 49 | 1 | 7500 | 0 | 39 | 147 | -11 | 463 | 183 | 183 | 183 | 183 | 183 | 183 | 183 | 19 | 19 | 19 | 19 | 19 | 5 | 100 | 100 | |
| 50 | 1 | 8750 | 0 | 74 | 200 | -15 | 378 | 191 | 191 | 191 | 191 | 191 | 191 | 191 | 20 | 20 | 20 | 20 | 20 | 4 | 100 | 100 | |
| 51 | 1 | 9750 | 0 | 75 | 203 | -16 | 481 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 21 | 21 | 21 | 21 | 21 | 7 | 100 | 100 | |
| 52 | 1 | 10750 | 0 | 76 | 206 | -16 | 490 | 209 | 209 | 209 | 209 | 209 | 209 | 209 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 53 | 1 | 11000 | 0 | 57 | 159 | 0 | 399 | 218 | 218 | 218 | 218 | 218 | 218 | 218 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 54 | 1 | 12000 | 0 | 58 | 162 | 0 | 406 | 228 | 228 | 228 | 228 | 228 | 228 | 228 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 55 | 1 | 13750 | 0 | 78 | 215 | -17 | 414 | 239 | 239 | 239 | 239 | 239 | 239 | 239 | 22 | 22 | 22 | 22 | 22 | 10 | 100 | 100 | |
| 56 | 1 | 14000 | 0 | 59 | 168 | 0 | 421 | 250 | 250 | 250 | 250 | 250 | 250 | 250 | 22 | 22 | 22 | 22 | 22 | 10 | 100 | 100 | |
| 57 | 1 | 15750 | 0 | 80 | 221 | -17 | 535 | 261 | 261 | 261 | 261 | 261 | 261 | 261 | 22 | 22 | 22 | 22 | 22 | 8 | 100 | 100 | |
| 58 | 1 | 16000 | 0 | 61 | 174 | 0 | 435 | 274 | 274 | 274 | 274 | 274 | 274 | 274 | 23 | 23 | 23 | 23 | 23 | 6 | 100 | 100 | |
| 59 | 1 | 17000 | 0 | 62 | 177 | 0 | 442 | 287 | 287 | 287 | 287 | 287 | 287 | 287 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 60 | 1 | 19000 | 0 | 142 | 280 | -19 | 449 | 300 | 300 | 300 | 300 | 300 | 300 | 300 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 61 | 1 | 20000 | 0 | 143 | 283 | -19 | 457 | 314 | 314 | 314 | 314 | 314 | 314 | 314 | 24 | 24 | 24 | 24 | 24 | 100 | 100 | 100 | |
| 62 | 1 | 21000 | 0 | 144 | 286 | -20 | 580 | 329 | 329 | 329 | 329 | 329 | 329 | 329 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 63 | 1 | 32000 | 0 | 164 | 255 | -25 | 471 | 305 | 305 | 305 | 305 | 305 | 305 | 305 | 25 | 25 | 25 | 25 | 25 | 22 | 100 | 100 | |
| 64 | 1 | 36000 | 0 | 156 | 420 | -25 | 478 | 350 | 350 | 350 | 350 | 350 | 350 | 350 | 26 | 26 | 26 | 26 | 26 | 25 | 100 | 100 | |
| 65 | 1 | 28500 | 0 | 226 | 445 | -24 | 485 | 378 | 378 | 378 | 378 | 378 | 378 | 378 | 26 | 26 | 26 | 26 | 26 | 20 | 100 | 100 | |
| 66 | 1 | 31500 | 0 | 161 | 414 | -22 | 615 | 396 | 396 | 396 | 396 | 396 | 396 | 396 | 26 | 26 | 26 | 26 | 26 | 22 | 100 | 100 | |
| 67 | 1 | 35817 | 0 | 215 | 455 | -29 | 543 | 396 | 396 | 396 | 396 | 396 | 396 | 396 | 27 | 27 | 27 | 27 | 27 | 31 | 100 | 100 | |
| 68 | 1 | 38024 | 0 | 229 | 484 | -31 | 551 | 410 | 410 | 410 | 410 | 410 | 410 | 410 | 27 | 27 | 27 | 27 | 27 | 33 | 100 | 100 | |
| 69 | 1 | 40232 | 0 | 244 | 513 | -33 | 560 | 423 | 423 | 423 | 423 | 423 | 423 | 423 | 28 | 28 | 28 | 28 | 28 | 34 | 100 | 100 | |
| 70 | 1 | 42439 | 0 | 259 | 542 | -35 | 569 | 437 | 437 | 437 | 437 | 437 | 437 | 437 | 28 | 28 | 28 | 28 | 28 | 36 | 100 | 100 | |
| 71 | 1 | 44647 | 0 | 273 | 571 | -38 | 578 | 451 | 451 | 451 | 451 | 451 | 451 | 451 | 28 | 28 | 28 | 28 | 28 | 38 | 100 | 100 | |
| 72 | 1 | 46855 | 0 | 288 | 599 | -40 | 586 | 465 | 465 | 465 | 465 | 465 | 465 | 465 | 29 | 29 | 29 | 29 | 29 | 39 | 100 | 100 | |
| 73 | 1 | 49062 | 0 | 303 | 628 | -42 | 595 | 479 | 479 | 479 | 479 | 479 | 479 | 479 | 29 | 29 | 29 | 29 | 29 | 41 | 100 | 100 | |
| 74 | 1 | 51270 | 0 | 317 | 657 | -44 | 604 | 493 | 493 | 493 | 493 | 493 | 493 | 493 | 30 | 30 | 30 | 30 | 30 | 42 | 100 | 100 | |
| 75 | 1 | 53477 | 0 | 332 | 686 | -46 | 612 | 507 | 507 | 507 | 507 | 507 | 507 | 507 | 30 | 30 | 30 | 30 | 30 | 44 | 100 | 100 | |
| 76 | 1 | 55685 | 0 | 347 | 715 | -48 | 621 | 520 | 520 | 520 | 520 | 520 | 520 | 520 | 31 | 31 | 31 | 31 | 31 | 45 | 100 | 100 | |
| 77 | 1 | 57892 | 0 | 361 | 744 | -51 | 630 | 534 | 534 | 534 | 534 | 534 | 534 | 534 | 31 | 31 | 31 | 31 | 31 | 47 | 100 | 100 | |
| 78 | 1 | 60100 | 0 | 376 | 773 | -53 | 639 | 548 | 548 | 548 | 548 | 548 | 548 | 548 | 31 | 31 | 31 | 31 | 31 | 49 | 100 | 100 | |
| 79 | 1 | 62308 | 0 | 391 | 802 | -55 | 647 | 562 | 562 | 562 | 562 | 562 | 562 | 562 | 32 | 32 | 32 | 32 | 32 | 50 | 100 | 100 | |
| 80 | 1 | 64515 | 0 | 405 | 831 | -57 | 656 | 576 | 576 | 576 | 576 | 576 | 576 | 576 | 32 | 32 | 32 | 32 | 32 | 52 | 100 | 100 | |
| 81 | 1 | 66723 | 0 | 420 | 860 | -59 | 665 | 590 | 590 | 590 | 590 | 590 | 590 | 590 | 33 | 33 | 33 | 33 | 33 | 53 | 100 | 100 | |
| 82 | 1 | 68930 | 0 | 435 | 889 | -61 | 673 | 604 | 604 | 604 | 604 | 604 | 604 | 604 | 33 | 33 | 33 | 33 | 33 | 55 | 100 | 100 | |
| 83 | 1 | 71138 | 0 | 449 | 918 | -64 | 682 | 618 | 618 | 618 | 618 | 618 | 618 | 618 | 34 | 34 | 34 | 34 | 34 | 56 | 100 | 100 | |
| 84 | 1 | 73345 | 0 | 464 | 947 | -66 | 691 | 631 | 631 | 631 | 631 | 631 | 631 | 631 | 34 | 34 | 34 | 34 | 34 | 58 | 100 | 100 | |
| 85 | 1 | 75553 | 0 | 479 | 976 | -68 | 700 | 645 | 645 | 645 | 645 | 645 | 645 | 645 | 34 | 34 | 34 | 34 | 34 | 60 | 100 | 100 | |
| 86 | 1 | 77761 | 0 | 493 | 1005 | -70 | 708 | 659 | 659 | 659 | 659 | 659 | 659 | 659 | 35 | 35 | 35 | 35 | 35 | 61 | 100 | 100 | |
| 87 | 1 | 79968 | 0 | 508 | 1034 | -72 | 717 | 673 | 673 | 673 | 673 | 673 | 673 | 673 | 35 | 35 | 35 | 35 | 35 | 63 | 100 | 100 | |
| 88 | 1 | 82176 | 0 | 523 | 1063 | -74 | 726 | 687 | 687 | 687 | 687 | 687 | 687 | 687 | 36 | 36 | 36 | 36 | 36 | 64 | 100 | 100 | |
| 89 | 1 | 84383 | 0 | 537 | 1092 | -77 | 735 | 701 | 701 | 701 | 701 | 701 | 701 | 701 | 36 | 36 | 36 | 36 | 36 | 66 | 100 | 100 | |
| 90 | 1 | 86591 | 0 | 552 | 1121 | -79 | 743 | 715 | 715 | 715 | 715 | 715 | 715 | 715 | 36 | 36 | 36 | 36 | 36 | 67 | 100 | 100 | |
| 91 | 1 | 88798 | 0 | 567 | 1150 | -81 | 752 | 728 | 728 | 728 | 728 | 728 | 728 | 728 | 37 | 37 | 37 | 37 | 37 | 69 | 100 | 100 | |
| 92 | 1 | 91006 | 0 | 581 | 1179 | -83 | 761 | 742 | 742 | 742 | 742 | 742 | 742 | 742 | 37 | 37 | 37 | 37 | 37 | 71 | 100 | 100 | |
| 93 | 1 | 93214 | 0 | 596 | 1207 | -85 | 769 | 756 | 756 | 756 | 756 | 756 | 756 | 756 | 38 | 38 | 38 | 38 | 38 | 72 | 100 | 100 | |
| 94 | 1 | 95421 | 0 | 611 | 1236 | -87 | 778 | 770 | 770 | 770 | 770 | 770 | 770 | 770 | 38 | 38 | 38 | 38 | 38 | 74 | 100 | 100 | |
| 95 | 1 | 97629 | 0 | 625 | 1265 | -90 | 787 | 784 | 784 | 784 | 784 | 784 | 784 | 784 | 39 | 39 | 39 | 39 | 39 | 75 | 100 | 100 | |
| 96 | 1 | 99836 | 0 | 640 | 1294 | -92 | 796 | 798 | 798 | 798 | 798 | 798 | 798 | 798 | 39 | 39 | 39 | 39 | 39 | 77 | 100 | 100 | |
| 97 | 1 | 102044 | 0 | 655 | 1323 | -94 | 804 | 812 | 812 | 812 | 812 | 812 | 812 | 812 | 39 | 39 | 39 | 39 | 39 | 78 | 100 | 100 | |
| 98 | 1 | 104252 | 0 | 669 | 1352 | -96 | 813 | 826 | 826 | 826 | 826 | 826 | 826 | 826 | 40 | 40 | 40 | 40 | 40 | 80 | 100 | 100 | |
| 99 | 1 | 106459 | 0 | 684 | 1381 | -98 | 822 | 839 | 839 | 839 | 839 | 839 | 839 | 839 | 40 | 40 | 40 | 40 | 40 | 82 | 100 | 100 | |
| 100 | 1 | 108667 | 0 | 699 | 1410 | -100 | 830 | 853 | 853 | 853 | 853 | 853 | 853 | 853 | 41 | 41 | 41 | 41 | 41 | 83 | 100 | 100 | |
| 1 | 2 | 11 | 0 | 1 | 2500 | 0 | 28 | 79 | 79 | 79 | 79 | 79 | 79 | 79 | 1 | 1 | 1 | 1 | 1 | 0 | 100 | 100 | ABH |
| 2 | 2 | 60 | 0 | 1 | 10 | 0 | 35 | 93 | 93 | 93 | 93 | 93 | 93 | 93 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 3 | 2 | 39 | 0 | 1 | 6 | 0 | 52 | 84 | 84 | 84 | 84 | 84 | 84 | 84 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 4 | 2 | 56 | 0 | 1 | 8 | 0 | 61 | 86 | 86 | 86 | 86 | 86 | 86 | 86 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | S |
| 5 | 2 | 75 | 0 | 2 | 12 | 0 | 56 | 75 | 75 | 75 | 75 | 80 | 75 | 75 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 6 | 2 | 96 | 0 | 1 | 12 | 0 | 63 | 89 | 89 | 89 | 89 | 89 | 89 | 89 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 7 | 2 | 119 | 0 | 1 | 14 | 0 | 70 | 91 | 91 | 91 | 91 | 91 | 91 | 91 | 2 | 2 | 2 | 2 | 2 | 0 | 100 | 100 | |
| 8 | 2 | 144 | 0 | 1 | 16 | 0 | 78 | 92 | 92 | 92 | 92 | 92 | 92 | 92 | 3 | 3 | 3 | 3 | 3 | 0 | 100 | 100 | f |
| 9 | 2 | 171 | 0 | 9 | 20 | 0 | 85 | 82 | 82 | 77 | 82 | 76 | 77 | 72 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 10 | 2 | 200 | 0 | 1 | 20 | 0 | 92 | 94 | 94 | 94 | 94 | 94 | 94 | 94 | 4 | 4 | 4 | 4 | 4 | 0 | 100 | 100 | |
| 11 | 2 | 231 | 0 | 1 | 22 | 0 | 124 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 12 | 2 | 264 | 0 | 1 | 24 | 0 | 106 | 95 | 95 | 95 | 95 | 95 | 95 | 95 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 13 | 2 | 299 | 0 | 1 | 26 | 0 | 113 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 5 | 5 | 5 | 5 | 5 | 0 | 100 | 100 | |
| 14 | 2 | 336 | 0 | 1 | 28 | 0 | 120 | 96 | 96 | 96 | 96 | 96 | 96 | 96 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 15 | 2 | 375 | 0 | 1 | 30 | 0 | 128 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 16 | 2 | 416 | 0 | 1 | 32 | 0 | 135 | 97 | 97 | 97 | 97 | 97 | 97 | 97 | 6 | 6 | 6 | 6 | 6 | 0 | 100 | 100 | |
| 17 | 2 | 459 | 0 | 1 | 34 | 0 | 142 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 7 | 7 | 7 | 7 | 7 | 0 | 100 | 100 | |
| 18 | 2 | 504 | 0 | 8 | 36 | 0 | 186 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 7 | 7 | 7 | 7 | 7 | 0 | 100 | 100 | |
| 19 | 2 | 551 | 0 | 1 | 38 | 0 | 156 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 20 | 2 | 600 | 0 | 8 | 42 | -5 | 163 | 98 | 98 | 98 | 98 | 98 | 98 | 98 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 21 | 2 | 651 | 0 | 1 | 42 | 0 | 213 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 8 | 8 | 8 | 8 | 8 | 0 | 100 | 100 | |
| 22 | 2 | 704 | 0 | 1 | 44 | 0 | 178 | 99 | 99 | 99 | 99 | 99 | 99 | 99 | 9 | 9 | 9 | 9 | 9 | 0 | 100 | 100 | |
| 23 | 2 | 759 | 0 | 1 | 46 | 0 | 185 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 9 | 9 | 9 | 9 | 9 | 1 | 100 | 100 | |
| 24 | 2 | 816 | 0 | 1 | 48 | 0 | 192 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 25 | 2 | 875 | 0 | 1 | 50 | 0 | 199 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 10 | 10 | 10 | 10 | 10 | 1 | 100 | 100 | |
| 26 | 2 | 936 | 0 | 1 | 52 | 0 | 206 | 102 | 102 | 102 | 102 | 102 | 102 | 102 | 10 | 10 | 10 | 10 | 10 | 0 | 100 | 100 | |
| 27 | 2 | 999 | 0 | 1 | 54 | 0 | 213 | 103 | 103 | 103 | 103 | 74 | 103 | 103 | 11 | 11 | 11 | 11 | 11 | 0 | 100 | 100 | f |
| 28 | 2 | 1064 | 0 | 11 | 56 | 0 | 221 | 104 | 104 | 104 | 104 | 104 | 104 | 104 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 29 | 2 | 1131 | 0 | 11 | 58 | 0 | 228 | 105 | 105 | 105 | 105 | 105 | 105 | 105 | 11 | 11 | 11 | 11 | 11 | 1 | 100 | 100 | |
| 30 | 2 | 1200 | 0 | 12 | 60 | -7 | 235 | 106 | 106 | 106 | 106 | 106 | 106 | 106 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 31 | 2 | 1271 | 0 | 13 | 62 | -7 | 242 | 108 | 108 | 108 | 108 | 108 | 108 | 108 | 12 | 12 | 12 | 12 | 12 | 1 | 100 | 100 | |
| 32 | 2 | 1344 | 0 | 13 | 64 | -7 | 249 | 109 | 109 | 109 | 109 | 109 | 109 | 109 | 13 | 13 | 13 | 13 | 13 | 1 | 100 | 100 | |
| 33 | 2 | 1419 | 0 | 13 | 66 | -7 | 256 | 111 | 111 | 111 | 111 | 74 | 111 | 111 | 13 | 13 | 13 | 13 | 13 | 1 | 100 | 100 | f |
| 34 | 2 | 1496 | 0 | 14 | 68 | -8 | 263 | 113 | 113 | 113 | 113 | 113 | 113 | 113 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | |
| 35 | 2 | 559 | 0 | 2 | 32 | -8 | 271 | 101 | 101 | 101 | 101 | 101 | 101 | 101 | 14 | 14 | 14 | 14 | 14 | 0 | 100 | 100 | |
| 36 | 2 | 1656 | 0 | 14 | 72 | -8 | 278 | 118 | 118 | 118 | 118 | 118 | 118 | 118 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | |
| 37 | 2 | 1739 | 0 | 14 | 74 | -8 | 285 | 121 | 121 | 121 | 121 | 121 | 121 | 121 | 14 | 14 | 14 | 14 | 14 | 1 | 100 | 100 | I |
| 38 | 2 | 1824 | 0 | 15 | 76 | -8 | 365 | 124 | 124 | 124 | 124 | 124 | 124 | 124 | 15 | 15 | 15 | 15 | 15 | 1 | 100 | 100 | |
| 39 | 2 | 1911 | 0 | 16 | 78 | -9 | 374 | 128 | 128 | 128 | 128 | 128 | 128 | 128 | 15 | 15 | 15 | 15 | 15 | 1 | 100 | 100 | |
| 40 | 2 | 3250 | 0 | 32 | 120 | 0 | 306 | 132 | 132 | 132 | 132 | 132 | 132 | 132 | 16 | 16 | 16 | 16 | 16 | 2 | 100 | 100 | |
| 41 | 2 | 2091 | 0 | 33 | 123 | -9 | 314 | 136 | 136 | 136 | 136 | 136 | 136 | 136 | 16 | 16 | 16 | 16 | 16 | 1 | 100 | 100 | |
| 42 | 2 | 2184 | 0 | 34 | 126 | -9 | 321 | 140 | 140 | 140 | 140 | 140 | 140 | 140 | 17 | 17 | 17 | 17 | 17 | 1 | 100 | 100 | I |
| 43 | 2 | 2279 | 0 | 34 | 129 | -10 | 410 | 145 | 145 | 145 | 145 | 145 | 145 | 145 | 18 | 18 | 18 | 18 | 18 | 2 | 100 | 100 | N |
| 44 | 2 | 2376 | 0 | 35 | 132 | -10 | 335 | 151 | 151 | 151 | 151 | 151 | 151 | 151 | 18 | 18 | 18 | 18 | 18 | 1 | 100 | 100 | I |
| 45 | 2 | 2475 | 0 | 36 | 135 | -10 | 428 | 156 | 156 | 156 | 156 | 156 | 156 | 156 | 18 | 18 | 18 | 18 | 18 | 2 | 100 | 100 | |
| 46 | 2 | 8000 | 0 | 80 | 130 | 15 | 349 | 169 | 169 | 169 | 169 | 169 | 169 | 169 | 18 | 18 | 18 | 18 | 18 | 6 | 100 | 100 | MCID |
| 47 | 2 | 6500 | 0 | 38 | 141 | -10 | 446 | 169 | 169 | 169 | 169 | 169 | 169 | 169 | 18 | 18 | 18 | 18 | 18 | 5 | 100 | 100 | |
| 48 | 2 | 7000 | 0 | 38 | 144 | -11 | 331 | 176 | 176 | 176 | 176 | 74 | 176 | 176 | 19 | 19 | 19 | 19 | 19 | 35 | 100 | 100 | f |
| 49 | 2 | 7500 | 0 | 39 | 147 | -11 | 463 | 183 | 183 | 183 | 183 | 183 | 183 | 183 | 19 | 19 | 19 | 19 | 19 | 5 | 100 | 100 | |
| 50 | 2 | 8750 | 0 | 74 | 200 | -15 | 378 | 191 | 191 | 191 | 191 | 191 | 191 | 191 | 20 | 20 | 20 | 20 | 20 | 4 | 100 | 100 | |
| 51 | 2 | 9750 | 0 | 75 | 203 | -16 | 481 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 21 | 21 | 21 | 21 | 21 | 7 | 100 | 100 | |
| 52 | 2 | 10750 | 0 | 76 | 206 | -16 | 490 | 209 | 209 | 209 | 209 | 209 | 209 | 209 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 53 | 2 | 11000 | 0 | 57 | 159 | 0 | 399 | 218 | 218 | 218 | 218 | 218 | 218 | 218 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 54 | 2 | 12000 | 0 | 58 | 162 | 0 | 406 | 228 | 228 | 228 | 228 | 228 | 228 | 228 | 21 | 21 | 21 | 21 | 21 | 8 | 100 | 100 | |
| 55 | 2 | 13750 | 0 | 78 | 215 | -17 | 414 | 239 | 239 | 239 | 239 | 239 | 239 | 239 | 22 | 22 | 22 | 22 | 22 | 10 | 100 | 100 | |
| 56 | 2 | 14000 | 0 | 59 | 168 | 0 | 421 | 250 | 250 | 250 | 250 | 250 | 250 | 250 | 22 | 22 | 22 | 22 | 22 | 10 | 100 | 100 | |
| 57 | 2 | 15750 | 0 | 80 | 221 | -17 | 535 | 261 | 261 | 261 | 261 | 261 | 261 | 261 | 22 | 22 | 22 | 22 | 22 | 8 | 100 | 100 | |
| 58 | 2 | 16000 | 0 | 61 | 174 | 0 | 435 | 274 | 274 | 274 | 274 | 274 | 274 | 274 | 23 | 23 | 23 | 23 | 23 | 6 | 100 | 100 | |
| 59 | 2 | 17000 | 0 | 62 | 177 | 0 | 442 | 287 | 287 | 287 | 287 | 287 | 287 | 287 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 60 | 2 | 19000 | 0 | 142 | 280 | -19 | 449 | 300 | 300 | 300 | 300 | 300 | 300 | 300 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 61 | 2 | 20000 | 0 | 143 | 283 | -19 | 457 | 314 | 314 | 314 | 314 | 314 | 314 | 314 | 24 | 24 | 24 | 24 | 24 | 100 | 100 | 100 | |
| 62 | 2 | 21000 | 0 | 144 | 286 | -20 | 580 | 329 | 329 | 329 | 329 | 329 | 329 | 329 | 24 | 24 | 24 | 24 | 24 | 8 | 100 | 100 | |
| 63 | 2 | 20750 | 0 | 28 | 200 | -25 | 471 | 239 | 239 | 239 | 239 | 239 | 239 | 239 | 25 | 25 | 25 | 25 | 25 | 8 | 100 | 100 | SE |
| 64 | 2 | 22542 | 0 | 320 | 900 | -21 | 478 | 361 | 361 | 361 | 361 | 361 | 361 | 361 | 74 | 74 | 74 | 74 | 74 | 386 | 100 | 100 | SEUMCfS |
| 65 | 2 | 23561 | 0 | 226 | 445 | -24 | 485 | 378 | 378 | 378 | 378 | 378 | 378 | 378 | 26 | 26 | 26 | 26 | 26 | 20 | 100 | 100 | |
| 66 | 2 | 24580 | 0 | 161 | 414 | -22 | 615 | 396 | 396 | 396 | 396 | 396 | 396 | 396 | 26 | 26 | 26 | 26 | 26 | 22 | 100 | 100 | SEFTMCNID |
| 67 | 2 | 25599 | 0 | 273 | 924 | -22 | 624 | 414 | 414 | 414 | 414 | 74 | 414 | 414 | 59 | 59 | 59 | 59 | 59 | 25 | 100 | 100 | SERNDf |
| 68 | 2 | 26619 | 0 | 636 | 1344 | -40 | 1266 | 450 | 450 | 450 | 450 | 450 | 450 | 450 | 51 | 51 | 77 | 51 | 77 | 70 | 100 | 100 | SEMCIDf |
| 69 | 2 | 27638 | 0 | 286 | 984 | -23 | 642 | 453 | 453 | 453 | 453 | 74 | 453 | 453 | 60 | 60 | 60 | 60 | 60 | 30 | 100 | 100 | SFf |
| 70 | 2 | 28657 | 0 | 440 | 2000 | -35 | 521 | 473 | 473 | 473 | 473 | 473 | 473 | 473 | 27 | 27 | 27 | 27 | 27 | 5 | 100 | 100 | |
| 71 | 2 | 1007751 | 0 | 560 | 3000 | -25 | 1663 | 496 | 496 | 496 | 496 | 496 | 496 | 496 | 283 | 283 | 283 | 283 | 283 | 5 | 100 | 100 | ERUMCIf |
| 72 | 2 | 1207751 | 0 | 520 | 1875 | -25 | 1070 | 518 | 518 | 518 | 518 | 74 | 518 | 518 | 298 | 298 | 298 | 298 | 298 | 186 | 100 | 100 | SERTMCNIDf |
| 73 | 2 | 1407751 | 0 | 1625 | 3600 | -15 | 2096 | 355 | 355 | 355 | 355 | 355 | 355 | 355 | 136 | 136 | 136 | 136 | 136 | 0 | 100 | 100 | SERFQUMCNIDf |
| 74 | 2 | 1607751 | 0 | 1072 | 1942 | -24 | 1648 | 565 | 565 | 565 | 565 | 565 | 565 | 565 | 90 | 90 | 90 | 90 | 90 | 600 | 100 | 100 | SEFTMCNIDf |
| 75 | 2 | 1657451 | 0 | 248 | 750 | -33 | 696 | 590 | 590 | 590 | 590 | 590 | 590 | 590 | 144 | 144 | 144 | 144 | 144 | 52 | 100 | 100 | |
| 76 | 2 | 1707151 | 0 | 918 | 1670 | -40 | 1550 | 616 | 616 | 616 | 616 | 616 | 616 | 616 | 362 | 362 | 362 | 362 | 362 | 72 | 100 | 100 | STMCNDf |
| 77 | 2 | 1756851 | 0 | 788 | 2050 | -32 | 1570 | 637 | 637 | 637 | 637 | 637 | 637 | 637 | 110 | 110 | 110 | 110 | 110 | 500 | 100 | 100 | SERrFQMCNIDf |
| 78 | 2 | 1806551 | 0 | 195 | 546 | -29 | 2235 | 670 | 670 | 670 | 670 | 670 | 670 | 670 | 87 | 87 | 87 | 87 | 87 | 7 | 100 | 100 | If |
| 79 | 2 | 1856251 | 0 | 563 | 2440 | -35 | 2181 | 729 | 729 | 729 | 729 | 729 | 729 | 729 | 205 | 205 | 205 | 205 | 205 | 800 | 100 | 100 | SERTQMCNIDf |
| 80 | 2 | 1905951 | 0 | 82 | 340 | -25 | 1256 | 891 | 891 | 891 | 891 | 891 | 891 | 891 | 45 | 45 | 45 | 45 | 45 | 6 | 100 | 100 | |
| 81 | 2 | 1955651 | 0 | -60 | 728 | -24 | 1765 | 901 | 901 | 901 | 901 | 901 | 901 | 901 | 0 | 0 | 0 | 0 | 0 | 327 | 100 | 100 | SERFTQUMCNIDf |
| 82 | 2 | 2005351 | 0 | -250 | 501 | -21 | 1768 | 965 | 965 | 965 | 965 | 965 | 965 | 965 | -54 | -54 | -54 | -54 | -54 | 344 | 100 | 100 | SERFTQUMCNIDf |
| 83 | 2 | 2055051 | 0 | -439 | 274 | -19 | 1770 | 1030 | 1030 | 1030 | 1030 | 1030 | 1030 | 1030 | -108 | -108 | -108 | -108 | -108 | 361 | 100 | 100 | SERFTQUMCNIDf |
| 84 | 2 | 2104751 | 0 | -629 | 47 | -16 | 1772 | 1094 | 1094 | 1094 | 1094 | 1094 | 1094 | 1094 | -162 | -162 | -162 | -162 | -162 | 378 | 100 | 100 | SERFTQUMCNIDf |
| 85 | 2 | 2154451 | 0 | -819 | -180 | -13 | 1775 | 1158 | 1158 | 1158 | 1158 | 1158 | 1158 | 1158 | -216 | -216 | -216 | -216 | -216 | 395 | 100 | 100 | SERFTQUMCNIDf |
| 86 | 2 | 2204151 | 0 | -1008 | -407 | -11 | 1777 | 1222 | 1222 | 1222 | 1222 | 1222 | 1222 | 1222 | -269 | -269 | -269 | -269 | -269 | 411 | 100 | 100 | SERFTQUMCNIDf |
| 87 | 2 | 2253851 | 0 | -1198 | -634 | -8 | 1779 | 1286 | 1286 | 1286 | 1286 | 1286 | 1286 | 1286 | -323 | -323 | -323 | -323 | -323 | 428 | 100 | 100 | SERFTQUMCNIDf |
| 88 | 2 | 2303551 | 0 | -1388 | -861 | -5 | 1781 | 1351 | 1351 | 1351 | 1351 | 1351 | 1351 | 1351 | -377 | -377 | -377 | -377 | -377 | 445 | 100 | 100 | SERFTQUMCNIDf |
| 89 | 2 | 2353251 | 0 | -1578 | -1088 | -3 | 1784 | 1415 | 1415 | 1415 | 1415 | 1415 | 1415 | 1415 | -431 | -431 | -431 | -431 | -431 | 462 | 100 | 100 | SERFTQUMCNIDf |
| 90 | 2 | 2402951 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDf |
| 91 | 2 | 2452651 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 92 | 2 | 2502351 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 93 | 2 | 2552051 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 94 | 2 | 2601751 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 95 | 2 | 2651451 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 96 | 2 | 2701151 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 97 | 2 | 2750851 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 98 | 2 | 2800551 | 0 | 86 | 360 | -26 | 1328 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1079 | 1033 | 1033 | 1033 | 1033 | 1033 | 210 | 100 | 100 | SERFTQUMCNIDfW |
| 99 | 2 | 3500000 | 0 | 2000 | 6999 | -50 | 696 | 590 | 590 | 590 | 590 | 590 | 590 | 590 | 192 | 192 | 192 | 192 | 192 | 500 | 100 | 100 | SERFTQUMCNIDfW |
| 100 | 2 | 3500000 | 0 | 2000 | 6999 | -50 | 696 | 590 | 590 | 590 | 590 | 590 | 590 | 590 | 192 | 192 | 192 | 192 | 192 | 500 | 100 | 100 | SERFTQUMCNIDfW |
+-------+------+---------+------+--------+--------+--------------+------+------+------+------+------+------+------+------+------+------+------+------+------+----------+------------+-----------+-----------------+
300 rows in set


Now, this is what NPC's in any zone will recieve, they will get this base scaling data as long as they have a level and their name follows one of the conventions. You could create a brand new NPC, give it level 90, save, repop the zone and the zonecontroller will take care of its scaling numbers within about 5 seconds.

Topical Multipliers

You can set per zone multipliers by simply creating an entry in the table `cust_npc_zonescale_static`, this information is keyed with some simple information:

zonesn - This is the zones short name in which you want to set custom multipliers for
Version - the Version (Instance) in which you want these rules to apply, meaning you could have varied difficulties of a zone
Type - The convention that was listed above with names


This is an example of the table from my server. The beauty of this is that when you start to know what feels right to your players, you can use the similar multipliers for another zone but adjust the numbers up a bit.

To give you an idea, if you had a NPC that was level 90, and had a named name (#Boogabooga). Not only would he get base scaling data for Type 1, you could then add multipliers to his type in the zone. Let's say this guy is in crushbone, and I set the maxdmg multiplier for this zone to 6, it would be whatever the base data is for that dataset, multiplied by 6. Pretty easy to understand. To narrow it down, #Boogabooga would be affected by this row value here:

+----------------+---------+----+------+--------+--------+--------------+----+-----------+------------+---------+----------------+------+----------+
| zonesn | version | hp | mana | mindmg | maxdmg | attack_speed | ac | healscale | spellscale | hpregen | specialattacks | type | accuracy |
+----------------+---------+----+------+--------+--------+--------------+----+-----------+------------+---------+----------------+------+----------+
| crushbone | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 1 | 100 |

The only field that obviously isn't a multiplier is the accuracy field and the special attacks field, that is pretty self explanatory. If this is empty, it will let the existing NPC special attacks exist. I'm not sure how the special attacks will work with the new system since it was all changed up, you might be able to simply replace the field with the new convention values and it would be set the same way.


mysql> SELECT * FROM `cust_npc_zonescale_static` order by type, zonesn
;
+----------------+---------+----+------+--------+--------+--------------+----+-----------+------------+---------+----------------+------+----------+
| zonesn | version | hp | mana | mindmg | maxdmg | attack_speed | ac | healscale | spellscale | hpregen | specialattacks | type | accuracy |
+----------------+---------+----+------+--------+--------+--------------+----+-----------+------------+---------+----------------+------+----------+
| alkabormare | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 0 |
| atiiki | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 0 |
| crushbone | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 100 |
| gukbottom | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 200 |
| karnor | 1 | 2 | 1 | 2 | 7 | 1 | 2 | 1 | 1 | 3 | | 0 | 300 |
| oldblackburrow | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 100 |
| soldungb | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 0 |
| soldungb | 2 | 5 | 1 | 4 | 9 | 1 | 2 | 5 | 5 | 8 | | 0 | 100 |
| somnium | 0 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 0 |
| thulelibrary | 1 | 2 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 0 | 0 |
| alkabormare | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 1 | 0 |
| atiiki | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 3 | | 1 | 0 |
| crushbone | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 1 | 100 |
| gukbottom | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 3 | | 1 | 200 |
| karnor | 1 | 5 | 1 | 2 | 8 | 1 | 2 | 1 | 1 | 8 | | 1 | 100 |
| oldblackburrow | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 1 | 100 |
| soldungb | 2 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 3 | | 1 | 100 |
| soldungb | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 3 | | 1 | 0 |
| somnium | 0 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 3 | | 1 | 0 |
| thulelibrary | 1 | 3 | 1 | 2 | 6 | 1 | 2 | 1 | 1 | 5 | | 1 | 0 |
| soldungb | 2 | 3 | 1 | 1 | 1 | 1 | 2 | 10 | 10 | 3 | | 2 | 0 |
| somnium | 0 | 3 | 1 | 3 | 1 | 2 | 2 | 1 | 1 | 3 | SERFTQUMCNDf | 2 | 0 |
+----------------+---------+----+------+--------+--------+--------------+----+-----------+------------+---------+----------------+------+----------+
22 rows in set

The last table I will explain is an under used one by myself, but may come in useful for others. It is a table that allows someone to set manual static entries for an NPC that will be placed very last in the scaling process. You could set a raid mob to be set at special numbers with this table using very similar rules of the table before it.

mysql> SELECT * FROM `cust_npc_scale_static`
order by zonesn;
+-------------+--------+------+------+--------+--------+--------------+------+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+----------+------------+-----------+-----------------+---------------+----------------+
| name | zonesn | hp | mana | mindmg | maxdmg | attack_speed | AC | STR | STA | DEX | AGI | _INT | WIS | CHA | MR | CR | DR | FR | PR | hp_regen | spellscale | healscale | npcspecialattks | usediabloloot | localloottable |
+-------------+--------+------+------+--------+--------+--------------+------+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+----------+------------+-----------+-----------------+---------------+----------------+
| Storm_Fury | atiiki | 4545 | 100 | 100 | 998458 | 1 | 1000 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 2000 | 100 | 100 | SEFMCNIDf | 0 | 331 |
+-------------+--------+------+------+--------+--------+--------------+------+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+----------+------------+-----------+-----------------+---------------+----------------+
1 row in set

----------------------------------------------

The Code:

You will need to have an entry in global_player.pl that essentially spawns the zonecontroller if it doesn't already exist.

First, here is the zonecontroller npc_types data, it assumed NPC ID 50 since it is not used in PEQ.

INSERT INTO `npc_types` (`id`, `name`, `lastname`, `level`, `race`, `class`, `bodytype`, `hp`, `mana`, `gender`, `texture`, `helmtexture`, `size`, `hp_regen_rate`, `mana_regen_rate`, `loottable_id`, `merchant_id`, `alt_currency_id`,
`npc_spells_id`, `npc_faction_id`, `adventure_template_id`, `trap_template`, `mindmg`, `maxdmg`, `attack_count`, `npcspecialattks`, `aggroradius`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`, `luclin_beardcolor`,
`luclin_beard`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `armortint_id`, `armortint_red`, `armortint_green`, `armortint_blue`, `d_meele_texture1`, `d_meele_texture2`, `prim_melee_type`, `sec_melee_type`, `runspeed`, `MR`, `CR`,
`DR`, `FR`, `PR`, `Corrup`, `see_invis`, `see_invis_undead`, `qglobal`, `AC`, `npc_aggro`, `spawn_limit`, `attack_speed`, `findable`, `STR`, `STA`, `DEX`, `AGI`, `_INT`, `WIS`, `CHA`, `see_hide`, `see_improved_hide`, `trackable`, `isbot`,
`exclude`, `ATK`, `Accuracy`, `slow_mitigation`, `version`, `maxlevel`, `scalerate`, `private_corpse`, `unique_spawn_by_name`, `underwater`, `isquest`, `emoteid`) VALUES (50, 'zonecontroller', NULL, 1, 240, 1, 11, 31, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 'ZiGH', 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 1.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, 75, 80, 75, 75, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0);



global_player.pl :: This makes sure the controller is spawned when a player enters the zone, if not, spawn it.

sub EVENT_ENTERZONE{
if(!$entity_list->GetNPCByNPCTypeID(50)){ quest::spawn2(50, 0, 0, 0, 0, 0, 0); $client->NPCSpawn($entity_list->GetNPCByNPCTypeID(50), "add", 1); } #::: Automatic Scaling
}

zonecontroller.pl :: This goes in your global or templates folder

#::: Akkadius
#::: Zonecontroller
#::: This Entity sits in every zone ready to accept signals to handle scaling requests
#::: First use of this will be to handle automatic scaling of the zone if desired

#::: Insert Zone Controller into database
#::: SQL: (Assumes NPC ID 50)
#::: INSERT INTO `npc_types` (`id`, `name`, `lastname`, `level`, `race`, `class`, `bodytype`, `hp`, `mana`, `gender`, `texture`, `helmtexture`, `size`, `hp_regen_rate`, `mana_regen_rate`, `loottable_id`, `merchant_id`, `alt_currency_id`,
`npc_spells_id`, `npc_faction_id`, `adventure_template_id`, `trap_template`, `mindmg`, `maxdmg`, `attack_count`, `npcspecialattks`, `aggroradius`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`, `luclin_beardcolor`,
`luclin_beard`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `armortint_id`, `armortint_red`, `armortint_green`, `armortint_blue`, `d_meele_texture1`, `d_meele_texture2`, `prim_melee_type`, `sec_melee_type`, `runspeed`, `MR`, `CR`,
`DR`, `FR`, `PR`, `Corrup`, `see_invis`, `see_invis_undead`, `qglobal`, `AC`, `npc_aggro`, `spawn_limit`, `attack_speed`, `findable`, `STR`, `STA`, `DEX`, `AGI`, `_INT`, `WIS`, `CHA`, `see_hide`, `see_improved_hide`, `trackable`, `isbot`,
`exclude`, `ATK`, `Accuracy`, `slow_mitigation`, `version`, `maxlevel`, `scalerate`, `private_corpse`, `unique_spawn_by_name`, `underwater`, `isquest`, `emoteid`) VALUES (50, 'zonecontroller', NULL, 1, 240, 1, 11, 31, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 'ZiGH', 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 1.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, 75, 80, 75, 75, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0);



sub EVENT_SPAWN{
$npc->TempName("");
#$Debug = " ";
quest::gmsay("[Zonecontroller] [ALIVE] Zone: $zonesn Instance Version: $instanceversion InstID $instanceversion", 15);
LoadStaticNPCScaling($zonesn); #::: Load NPC Static Scaling
LoadStaticZoneScaling(); #::: Load Zone Static Scaling
quest::settimer("scaleall", 1); #::: Run Scaling routine
quest::settimer("scaleall", 3); #::: Run Scaling routine
$ScalingLoaded = "";
}

sub EVENT_TIMER{
if($timer eq "scaleall"){ ScaleProcedure(); quest::stoptimer("scaleall"); quest::gmsay("Scaling routine complete", 15); }
if($timer eq "levelset"){
@ent = $entity_list->GetNPCList();
$Level = $npc->GetEntityVariable("queuesetlevel2");
$Variance = $npc->GetEntityVariable("queuesetlevel3");
foreach $NPC (@ent){
if($NPC->GetNPCTypeID() > 1000){
if($Variance > 0){ } else{ $Variance = 0; }
$NPC->SetLevel($Level + (RandomRange(0 - $Variance, $Variance)));
}
}
$npc->SetEntityVariable("queuesetlevel", 0);
$npc->SetEntityVariable("queuesetlevel2", 0);
$npc->SetEntityVariable("queuesetlevel3", 0);
quest::gmsay("Level Scaling Done...", 15);
quest::stoptimer("levelset");
}
}

sub EVENT_SIGNAL{
if($signal == 10){ ScaleProcedure(); }
if($signal == 11){ $npc->SetEntityVariable("queuesetlevel", 1); return; }
if($npc->GetEntityVariable("queuesetlevel") > 0 && $npc->GetEntityVariable("queuesetlevel2") == 0){ $npc->SetEntityVariable("queuesetlevel2", $signal); quest::settimer("levelset", 1); }
if($npc->GetEntityVariable("queuesetlevel2") > 0){ $npc->SetEntityVariable("queuesetlevel3", $signal); }
#::: Getting Signal from Spawned NPC #:::
if($signal == 21){ $npc->SetEntityVariable("queuesetnpc", 1); return; }
if($npc->GetEntityVariable("queuesetnpc") eq "1" && $ScalingLoaded == 3){ $npc->SetEntityVariable("queuesetnpc", 0); ScaleProcedure($signal); }
if($signal == 23){ $Debug = 1; }
}

sub ScaleProcedure{
#::: Read from DB
if(!$SD[1][0][0]){ LoadScaling(); } #::: Scaling Vars Empty, reload them from DB
$NPC = 0; $pop = "";

if($_[0]){
@ent = $entity_list->GetNPCByNPCTypeID($_[0]);
$pop = " POP";
# quest::gmsay("Scaling NPC ID " . $_[0], 15);
}
else{ @ent = $entity_list->GetNPCList(); $ScalingLoaded = 2; }
foreach $NPC (@ent){
#::: Hide Invis NPC Names
if(($NPC->GetRace() == 127 || $NPC->GetRace() == 240) && $NPC->GetLevel() < 100 && $NPC->GetNPCTypeID() > 1000){ if($NPC->GetCleanName()=~/shadowed/i){} else{ $NPC->TempName(""); $NPC->ModifyNPCStat("special_attacks", "AZ"); } }
if($NPC->GetEntityVariable("Scaled") != 1){
#Static NPC Scaling
$n_name = $NPC->GetCleanName(); $n_name =~ tr/ /_/;
if($N_SD{$n_name}[0]){ ScaleNPCStatic($NPC, $n_name); }
}
#::: SCALING
if($NPC->GetPetSpellID() == 0 && $NPC->GetRace() != 127 && $NPC->GetRace() != 240 && $NPC->GetClass() < 20 && $NPC->GetNPCTypeID() > 1000 && $NPC->GetEntityVariable("Scaled") != 1){
$NTYPE = 0; $NN = "NPC";
if(substr($NPC->GetName(), 0, 1) eq "#" && substr($NPC->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($NPC->GetName(), 0, 2) eq "##" && substr($NPC->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$NPC->ModifyNPCStat("max_hp", $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2]);
$NPC->ModifyNPCStat("max_mana", $SD[$NPC->GetLevel()][$NTYPE][3] * $SZD{$zonesn}[$instanceversion][$NTYPE][3]);
$NPC->ModifyNPCStat("min_hit", $SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]);
$NPC->ModifyNPCStat("max_hit", $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]);
$NPC->ModifyNPCStat("attack_speed", $SD[$NPC->GetLevel()][$NTYPE][6] * $SZD{$zonesn}[$instanceversion][$NTYPE][6]);
$NPC->ModifyNPCStat("ac", $SD[$NPC->GetLevel()][$NTYPE][7] * $SZD{$zonesn}[$instanceversion][$NTYPE][7]);
$NPC->ModifyNPCStat("str", $SD[$NPC->GetLevel()][$NTYPE][8]);
$NPC->ModifyNPCStat("sta", $SD[$NPC->GetLevel()][$NTYPE][9]);
$NPC->ModifyNPCStat("dex", $SD[$NPC->GetLevel()][$NTYPE][10]);
$NPC->ModifyNPCStat("agi", $SD[$NPC->GetLevel()][$NTYPE][11]);
$NPC->ModifyNPCStat("int", $SD[$NPC->GetLevel()][$NTYPE][12]);
$NPC->ModifyNPCStat("wis", $SD[$NPC->GetLevel()][$NTYPE][13]);
$NPC->ModifyNPCStat("cha", $SD[$NPC->GetLevel()][$NTYPE][14]);
$NPC->ModifyNPCStat("mr", $SD[$NPC->GetLevel()][$NTYPE][15]);
$NPC->ModifyNPCStat("cr", $SD[$NPC->GetLevel()][$NTYPE][16]);
$NPC->ModifyNPCStat("dr", $SD[$NPC->GetLevel()][$NTYPE][17]);
$NPC->ModifyNPCStat("fr", $SD[$NPC->GetLevel()][$NTYPE][18]);
$NPC->ModifyNPCStat("pr", $SD[$NPC->GetLevel()][$NTYPE][19]);
if($SZD{$zonesn}[$instanceversion][$NTYPE][13]){
$NPC->ModifyNPCStat("accuracy", $SZD{$zonesn}[$instanceversion][$NTYPE][13]);
}
#::: Is there a static zone entry?
if($SZD{$zonesn}[$instanceversion][$NTYPE][11] != 1){
$NPC->ModifyNPCStat("special_attacks", $SZD{$zonesn}[$instanceversion][$NTYPE][11]);
}else{
$NPC->ModifyNPCStat("special_attacks", $SD[$NPC->GetLevel()][$NTYPE][21]);
}
$NPC->ModifyNPCStat("hp_regen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->SetEntityVariable("hpregen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->ModifyNPCStat("spellscale", $SD[$NPC->GetLevel()][$NTYPE][22] * $SZD{$zonesn}[$instanceversion][$NTYPE][9]);
$NPC->ModifyNPCStat("healscale", $SD[$NPC->GetLevel()][$NTYPE][23] * $SZD{$zonesn}[$instanceversion][$NTYPE][8]);

#::: Proprietary Loot Assignment - Leaving here for others reference
# $LID = (200000 + ($NTYPE * 1000) + $NPC->GetLevel());
# if($NPC->GetLoottableID() != $LID){
# $NPC->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
# $NPC->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
# }
$NPC->SetHP($NPC->GetMaxHP());
$NPC->SetEntityVariable("Scaled", 1); if($Debug){ $NPC->SetEntityVariable("ScaledType", 1); }

if($Debug){
quest::gmsay("Scaling $pop $NN [" . $NPC->GetCleanName() . "]
HP:[". $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2] . "]
hp_regen:[". ($SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]) . "]
min_hit:[". ($SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]) . "]
max_hit:[".( $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]) . "]
spec:[". $SD[$NPC->GetLevel()][$NTYPE][21] . "]
NTYPE:[". $NTYPE . "]
", 15);
}
if(!$SD[$NPC->GetLevel()][$NTYPE][0]){ quest::gmsay($NPC->GetCleanName() . ": ERROR! Missing Scaling Entry! For level " . $NPC->GetLevel() . " Type: $NTYPE", 13); }
}
# Level 255 NPC's are considered quest NPC's and shall not be attacked #
if($NPC->GetLevel() == 255){ $NPC->ModifyNPCStat("special_attacks", "AHGZ"); $NPC->SetEntityVariable("max_hp", 100000); }
}
if($ScalingLoaded == 2){ $ScalingLoaded = 3; }
}

#::: Loading routines....

sub LoadScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scaling.level,
cust_npc_scaling.type,
cust_npc_scaling.hp,
cust_npc_scaling.mana,
cust_npc_scaling.mindmg,
cust_npc_scaling.maxdmg,
cust_npc_scaling.attack_speed,
cust_npc_scaling.AC,
cust_npc_scaling.STR,
cust_npc_scaling.STA,
cust_npc_scaling.DEX,
cust_npc_scaling.AGI,
cust_npc_scaling._INT,
cust_npc_scaling.WIS,
cust_npc_scaling.CHA,
cust_npc_scaling.MR,
cust_npc_scaling.CR,
cust_npc_scaling.DR,
cust_npc_scaling.FR,
cust_npc_scaling.PR,
cust_npc_scaling.hp_regen,
cust_npc_scaling.npcspecialattks,
cust_npc_scaling.spellscale,
cust_npc_scaling.healscale
FROM
cust_npc_scaling
ORDER BY cust_npc_scaling.level, cust_npc_scaling.type";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $SD[$row[0]][$row[1]] = [@row]; }
}

sub LoadStaticZoneScaling{
#::: Load Static Zone Scaling Data #:::
$connect = plugin::LoadMysql();
#::: Default empty values to 1
for($i = 2; $i < 17; $i++){
for($t = 0; $t < 3; $t++){
if(!$SZD{$zonesn}[$instanceversion][$t][$i] || $SZD{$zonesn}[$instanceversion][$t][$i] == 0){
$SZD{$zonesn}[$instanceversion][$t][$i] = 1;
}
}
}

$query = "SELECT `zonesn`, `version`, `hp`, `mana`, `mindmg`, `maxdmg`, `attack_speed`, `ac`, `healscale`, `spellscale`, `hpregen`, `specialattacks`, `type`, `accuracy` FROM `cust_npc_zonescale_static` WHERE `zonesn` = '" . $zonesn . "'"; $query_handle = $connect->prepare($query); $query_handle->execute(); my @SZD;
while (@row = $query_handle->fetchrow_array()){
$SZD{$row[0]}[$row[1]][$row[12]] = [@row];
if($SZD{$zonesn}[$instanceversion][0]){
$Mod = $SZD{$zonesn}[$instanceversion][2]; $npc->SetEntityVariable("ScaleMod", $Mod);
quest::gmsay("[Zonecontroller] (Static Data) [Type] : " . $row[12] . " Zone Data: HP=" . ($SZD{$zonesn}[$instanceversion][$row[12]][2] * 100) . "(%%) Mana=" . ($SZD{$zonesn}[$instanceversion][$row[12]][3] * 100) . "(%%) MINDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][4] * 100) . "(%%) MAXDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][5] * 100) . "(%%) ATK_SPD=" . ($SZD{$zonesn}[$instanceversion][$row[12]][6] * 100) . "(%%) AC=" . ($SZD{$zonesn}[$instanceversion][$row[12]][7] * 100) . "(%%) SPELLSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][8] * 100) . "(%%) HEALSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][9] * 100) . "(%%) HPREGEN=" . ($SZD{$zonesn}[$instanceversion][$row[12]][10] * 100) . "(%%)", 15);

}
}
}

sub LoadStaticNPCScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scale_static.`name`,
cust_npc_scale_static.zonesn,
cust_npc_scale_static.hp,
cust_npc_scale_static.mana,
cust_npc_scale_static.mindmg,
cust_npc_scale_static.maxdmg,
cust_npc_scale_static.attack_speed,
cust_npc_scale_static.AC,
cust_npc_scale_static.STR,
cust_npc_scale_static.STA,
cust_npc_scale_static.DEX,
cust_npc_scale_static.AGI,
cust_npc_scale_static._INT,
cust_npc_scale_static.WIS,
cust_npc_scale_static.CHA,
cust_npc_scale_static.MR,
cust_npc_scale_static.CR,
cust_npc_scale_static.DR,
cust_npc_scale_static.FR,
cust_npc_scale_static.PR,
cust_npc_scale_static.hp_regen,
cust_npc_scale_static.spellscale,
cust_npc_scale_static.healscale,
cust_npc_scale_static.npcspecialattks,
cust_npc_scale_static.usediabloloot,
cust_npc_scale_static.localloottable
FROM
cust_npc_scale_static
WHERE cust_npc_scale_static.zonesn = '" . $_[0] . "' OR cust_npc_scale_static.zonesn = 'global'";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $N_SD{$row[0]} = [@row]; quest::gmsay("[Zonecontroller]: Loading static NPC data for NPC: '" . $row[0] ."'", 15); }
}

sub ScaleNPCStatic{
my $SS = $_[0];
quest::shout("Found data for NPC " . $SS->GetCleanName() . ' - ' . $_[1]);
$NTYPE = 0; $NN = "NPC";
if(substr($SS->GetName(), 0, 1) eq "#" && substr($SS->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($SS->GetName(), 0, 2) eq "##" && substr($SS->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$SS->ModifyNPCStat("max_hp", $N_SD{$_[1]}[2]);
$SS->ModifyNPCStat("max_mana", $N_SD{$_[1]}[3]);
$SS->ModifyNPCStat("min_hit", $N_SD{$_[1]}[4]);
$SS->ModifyNPCStat("max_hit", $N_SD{$_[1]}[5]);
$SS->ModifyNPCStat("attack_speed", $N_SD{$_[1]}[6]);
$SS->ModifyNPCStat("ac", $N_SD{$_[1]}[7]);
$SS->ModifyNPCStat("str", $N_SD{$_[1]}[8]);
$SS->ModifyNPCStat("sta", $N_SD{$_[1]}[9]);
$SS->ModifyNPCStat("dex", $N_SD{$_[1]}[10]);
$SS->ModifyNPCStat("agi", $N_SD{$_[1]}[11]);
$SS->ModifyNPCStat("int", $N_SD{$_[1]}[12]);
$SS->ModifyNPCStat("wis", $N_SD{$_[1]}[13]);
$SS->ModifyNPCStat("cha", $N_SD{$_[1]}[14]);
$SS->ModifyNPCStat("mr", $N_SD{$_[1]}[15]);
$SS->ModifyNPCStat("cr", $N_SD{$_[1]}[16]);
$SS->ModifyNPCStat("dr", $N_SD{$_[1]}[17]);
$SS->ModifyNPCStat("fr", $N_SD{$_[1]}[18]);
$SS->ModifyNPCStat("pr", $N_SD{$_[1]}[19]);
$SS->ModifyNPCStat("hp_regen", $N_SD{$_[1]}[20]);
$SS->ModifyNPCStat("spellscale", $N_SD{$_[1]}[21]);
$SS->ModifyNPCStat("healscale", $N_SD{$_[1]}[22]);
$SS->ModifyNPCStat("special_attacks", $N_SD{$_[1]}[23]);

#::: Dynamic Loot assignment, proprietary
# if($N_SD{$_[1]}[24] == 1){ #::: Tells Static Entry to use Diablo Loot
# $LID = (200000 + ($NTYPE * 1000) + $SS->GetLevel());
# if($SS->GetLoottableID() != $LID){
# $SS->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
# $SS->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
# }
# }

if($N_SD{$_[1]}[25] > 0){ #::: Add an additional Loot table
$SS->ModifyNPCStat("loottable_id", $N_SD{$_[1]}[25]); $SS->AddLootTable();
}
$SS->SetEntityVariable("Scaled", 1); if($Debug){ $SS->SetEntityVariable("ScaledType", 2); }
}

sub RandomRange {
my $MinRandom = $_[0];
my $MaxRandom = $_[1];
my $RandomResult = int(rand(($MaxRandom + 1) - $MinRandom)) + $MinRandom;
if ($RandomResult > $MaxRandom) { return $MaxRandom; }
return $RandomResult;
}

global_npc.pl :: Tells zonecontroller to scale NPC upon spawn


sub EVENT_SPAWN{
if($npc->GetEntityVariable("Scaled") != 1){ #::: If not flagged as scaled, then scale the NPC
quest::signalwith(50, 21, 0);
quest::signalwith(50, $npc->GetNPCTypeID(), 0);
}
}


Enjoy!

Let me know if you have questions.

Secrets
12-25-2013, 02:03 AM
I have a question: How many percentage are you?

Akkadius
12-25-2013, 02:59 AM
I have a question: How many percentage are you?

200

/10 char

Splose
04-30-2014, 12:40 AM
For anybody interested in using decimals in the cust_npc_zonescale_static table. (The table that overrides and multiplies the baseline of the original scaling table).

Simply go to Design Table and go to the "Fields" tab.. There you will see a column called "Type". Change whatever you want to scale as a decimal to "float" and change "Decimals" to 1.

pennywse
09-01-2014, 10:30 PM
Is there something special that I need to do to get this to work with DiabloLoot? One works without the other and vise versa, but not together.

Akkadius
09-01-2014, 10:42 PM
What are you running into?

pennywse
09-02-2014, 04:09 PM
No errors or anything, scaling works perfect, but when it is on there is no random loot on the npcs via diablo loot. If I don't have scaling, the npcs have all the random loot.

Akkadius
09-02-2014, 04:16 PM
No errors or anything, scaling works perfect, but when it is on there is no random loot on the npcs via diablo loot. If I don't have scaling, the npcs have all the random loot.

How are you applying random loot?

pennywse
09-02-2014, 05:17 PM
I used your DiabloLoot script. I made no changes after that.

Akkadius
09-02-2014, 05:20 PM
I used your DiabloLoot script. I made no changes after that.

Yes but you need to actually apply the loot to NPC's are you doing that via the global_npc.pl ?

pennywse
09-02-2014, 05:27 PM
Yes but you need to actually apply the loot to NPC's are you doing that via the global_npc.pl ?

Yes I am

global_npc.pl

sub EVENT_SPAWN{
#::: START: Akka's Diablo Loot Handler :::#
$NTYPE = 0; #::: TRASH
if(substr($npc->GetName(), 0, 1) eq "#" && substr($npc->GetName(), 1, 2) ne "#"){ $NTYPE = 1; } #::: NAMED
if(substr($npc->GetName(), 0, 2) eq "##" && substr($npc->GetName(), 2, 3) ne "#"){ $NTYPE = 2; } #::: RAID
$LID = (200000 + ($NTYPE * 1000) + $npc->GetLevel());
if($npc->GetLoottableID() != $LID){
$npc->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $npc->GetLevel())); $npc->AddLootTable();
$npc->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $npc->GetLevel())); $npc->AddLootTable();
}
#::: END: Akka's Diablo Loot Handler :::#
}

sub EVENT_SPAWN{
if($npc->GetEntityVariable("Scaled") != 1){ #::: If not flagged as scaled, then scale the NPC
quest::signalwith(50, 21, 0);
quest::signalwith(50, $npc->GetNPCTypeID(), 0);
}
}

global_player.pl

sub EVENT_ENTERZONE { #message only appears in Cities / Pok and wherever the Wayfarer Camps (LDON) is in. This message won't appear in the player's home city.
if($ulevel >= 15 && !defined($qglobals{Wayfarer})) {
if($client->GetStartZone()!=$zoneid && ($zoneid == 1 || $zoneid == 2 || $zoneid == 3 || $zoneid == 8 || $zoneid == 9 || $zoneid == 10 || $zoneid == 19 || $zoneid == 22 || $zoneid == 23 || $zoneid == 24 || $zoneid == 29 || $zoneid == 30 || $zoneid == 34 || $zoneid == 35 || $zoneid == 40 || $zoneid == 41 || $zoneid == 42 || $zoneid == 45 || $zoneid == 49 || $zoneid == 52 || $zoneid == 54 || $zoneid == 55 || $zoneid == 60 || $zoneid == 61 || $zoneid == 62 || $zoneid == 67 || $zoneid == 68 || $zoneid == 75 || $zoneid == 82 || $zoneid == 106 || $zoneid == 155 || $zoneid == 202 || $zoneid == 382 || $zoneid == 383 || $zoneid == 392 || $zoneid == 393 || $zoneid == 408)) {
$client->Message(15,"A mysterious voice whispers to you, 'If you can feel me in your thoughts, know this -- something is changing in the world and I reckon you should be a part of it. I do not know much, but I do know that in every home city and the wilds there are agents of an organization called the Wayfarers Brotherhood. They are looking for recruits . . . If you can hear this message, you are one of the chosen. Rush to your home city, or search the West Karanas and Rathe Mountains for a contact if you have been exiled from your home for your deeds, and find out more. Adventure awaits you, my friend.'");
}
}
}

sub EVENT_COMBINE_SUCCESS
{
if ($recipe_id =~ /^1090[4-7]$/) {
$client->Message(1,
"The gem resonates with power as the shards placed within glow unlocking some of the stone's power. ".
"You were successful in assembling most of the stone but there are four slots left to fill, ".
"where could those four pieces be?"
);
}
elsif ($recipe_id =~ /^10(903|346|334)$/) {
my %reward = (
melee => {
10903 => 67665,
10346 => 67660,
10334 => 67653
},
hybrid => {
10903 => 67666,
10346 => 67661,
10334 => 67654
},
priest => {
10903 => 67667,
10346 => 67662,
10334 => 67655
},
caster => {
10903 => 67668,
10346 => 67663,
10334 => 67656
}
);
my $type = plugin::ClassType($class);
quest::summonitem($reward{$type}{$recipe_id});
quest::summonitem(67704);
$client->Message(1,"Success");
}
}

sub EVENT_ENTERZONE{
if(!$entity_list->GetNPCByNPCTypeID(50)){ quest::spawn2(50, 0, 0, 0, 0, 0, 0); $client->NPCSpawn($entity_list->GetNPCByNPCTypeID(50), "add", 1); } #::: Automatic Scaling
}

Akkadius
09-02-2014, 05:28 PM
You can't have two sub EVENT_SPAWN's, you need the code inside of each to be combined. That would be your issue.

pennywse
09-02-2014, 05:30 PM
You can't have two sub EVENT_SPAWN's, you need the code inside of each to be combined. That would be your issue.

Awesome, I will give that a try. Thank you very much. That was the problem.

Akkadius
09-02-2014, 06:50 PM
Awesome, I will give that a try. Thank you very much. That was the problem.

Very good.

/10 char

dpjaf4t
09-23-2014, 01:43 PM
Getting into this a bit late, maybe ...

Is there any point to updating the npcspecialattks field(s) to the 07/11/2013 'n^1' format and/or adding such as special_abilities field(s)?

freewind1
12-26-2014, 07:29 PM
i feel dumb but i cant seem to make this work, i copied and pasted
all 3 of the code snippets into their respective .pl and then placed all 3 in quest/global folder and also sourced the zonecontroller NPC & tables to the database, but for some reason this is not doing anything... (no editing has been done to the imported tables)

this is loadmysql.pl
sub LoadMysql_Old{
use DBI;
use DBD::mysql;
# CONFIG VARIABLES
my $confile = "eqemu_config.xml"; #default
open(F, "<$confile") or die "Unable to open config: $confile\n";
my $indb = 0;

while(<F>) {
s/\r//g;
if(/<database>/i) {
$indb = 1;
}
next unless($indb == 1);
if(/<\/database>/i) {
$indb = 0;
last;
}
if(/<host>(.*)<\/host>/i) {
$host = $1;
} elsif(/<username>(.*)<\/username>/i) {
$user = $1;
} elsif(/<password>(.*)<\/password>/i) {
$pass = $1;
} elsif(/<db>(.*)<\/db>/i) {
$db = $1;
}
}
# DATA SOURCE NAME
$dsn = "dbi:mysql:$db:localhost:3306";
# PERL DBI CONNECT
$connect = DBI->connect($dsn, $user, $pass);
}

sub LoadMysql{
use DBI;
use DBD::mysql;
# CONFIG VARIABLES
$host = 127.0.0.1;
$user = "root";
$pass = "Mypassword";
$db = "peq";
$dsn = "dbi:mysql:$db:localhost:3306";
return DBI->connect($dsn, $user, $pass);
}

im using Akka's PEQ Server Repack


thanks for the help!

Akkadius
12-26-2014, 08:02 PM
Do you know that your DBI is even working?

freewind1
12-26-2014, 10:12 PM
yes it is working i used
sub EVENT_SAY {
if($text=~/Hail/i){
if(!$connect){ $connect = plugin::LoadMysql(); }
$query = "SELECT
cust_npc_scaling.level,
cust_npc_scaling.type,
cust_npc_scaling.hp,
cust_npc_scaling.mana,
cust_npc_scaling.mindmg,
cust_npc_scaling.maxdmg,
cust_npc_scaling.attack_speed,
cust_npc_scaling.AC,
cust_npc_scaling.STR,
cust_npc_scaling.STA,
cust_npc_scaling.DEX,
cust_npc_scaling.AGI,
cust_npc_scaling._INT,
cust_npc_scaling.WIS,
cust_npc_scaling.CHA,
cust_npc_scaling.MR,
cust_npc_scaling.CR,
cust_npc_scaling.DR,
cust_npc_scaling.FR,
cust_npc_scaling.PR,
cust_npc_scaling.hp_regen,
cust_npc_scaling.npcspecialattks,
cust_npc_scaling.spellscale,
cust_npc_scaling.healscale
FROM
cust_npc_scaling
ORDER BY cust_npc_scaling.level, cust_npc_scaling.type";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0; my @SD;
while (@row = $query_handle->fetchrow_array()){
$SD[$row[0]][$row[1]] = [@row];
quest::say($SD[$row[0]][$row[1]])
}
}
}

to test it

--------
Sorry for this post i found out why it wasn't working the copy and paste of the zonecontroller did not have #### in front of the insert into field for the zonecontroller NPC i failed miserably and sorry for wasting everyones time

Akkadius
12-26-2014, 11:03 PM
You're not wasting anybody's time when you're consciously making an effort to help yourself.

It's good you got it figured out

freewind1
12-27-2014, 12:37 AM
#::: INSERT INTO `npc_types` (`id`, `name`, `lastname`, `level`, `race`, `class`, `bodytype`, `hp`, `mana`, `gender`, `texture`, `helmtexture`, `size`, `hp_regen_rate`, `mana_regen_rate`, `loottable_id`, `merchant_id`, `alt_currency_id`,
`npc_spells_id`, `npc_faction_id`, `adventure_template_id`, `trap_template`, `mindmg`, `maxdmg`, `attack_count`, `npcspecialattks`, `aggroradius`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`, `luclin_beardcolor`,
`luclin_beard`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `armortint_id`, `armortint_red`, `armortint_green`, `armortint_blue`, `d_meele_texture1`, `d_meele_texture2`, `prim_melee_type`, `sec_melee_type`, `runspeed`, `MR`, `CR`,
`DR`, `FR`, `PR`, `Corrup`, `see_invis`, `see_invis_undead`, `qglobal`, `AC`, `npc_aggro`, `spawn_limit`, `attack_speed`, `findable`, `STR`, `STA`, `DEX`, `AGI`, `_INT`, `WIS`, `CHA`, `see_hide`, `see_improved_hide`, `trackable`, `isbot`,
`exclude`, `ATK`, `Accuracy`, `slow_mitigation`, `version`, `maxlevel`, `scalerate`, `private_corpse`, `unique_spawn_by_name`, `underwater`, `isquest`, `emoteid`) VALUES (50, 'zonecontroller', NULL, 1, 240, 1, 11, 31, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 'ZiGH', 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 1.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, 75, 80, 75, 75, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0);

This is the segment that was causing the zonecontroller.pl not to work do the multiple lines without a # in front of them, hope this helps the next person who tries this script and doesn't find it right off :)

Akkadius
12-27-2014, 12:39 AM
#::: INSERT INTO `npc_types` (`id`, `name`, `lastname`, `level`, `race`, `class`, `bodytype`, `hp`, `mana`, `gender`, `texture`, `helmtexture`, `size`, `hp_regen_rate`, `mana_regen_rate`, `loottable_id`, `merchant_id`, `alt_currency_id`,
`npc_spells_id`, `npc_faction_id`, `adventure_template_id`, `trap_template`, `mindmg`, `maxdmg`, `attack_count`, `npcspecialattks`, `aggroradius`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`, `luclin_beardcolor`,
`luclin_beard`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `armortint_id`, `armortint_red`, `armortint_green`, `armortint_blue`, `d_meele_texture1`, `d_meele_texture2`, `prim_melee_type`, `sec_melee_type`, `runspeed`, `MR`, `CR`,
`DR`, `FR`, `PR`, `Corrup`, `see_invis`, `see_invis_undead`, `qglobal`, `AC`, `npc_aggro`, `spawn_limit`, `attack_speed`, `findable`, `STR`, `STA`, `DEX`, `AGI`, `_INT`, `WIS`, `CHA`, `see_hide`, `see_improved_hide`, `trackable`, `isbot`,
`exclude`, `ATK`, `Accuracy`, `slow_mitigation`, `version`, `maxlevel`, `scalerate`, `private_corpse`, `unique_spawn_by_name`, `underwater`, `isquest`, `emoteid`) VALUES (50, 'zonecontroller', NULL, 1, 240, 1, 11, 31, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 'ZiGH', 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 1.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 75, 75, 75, 80, 75, 75, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0);

This is the segment that was causing the zonecontroller.pl not to work do the multiple lines without a # in front of them, hope this helps the next person who tries this script and doesn't find it right off :)

Yes you have to manually insert the NPC yourself.

Greyhelm
02-18-2015, 04:56 AM
I am having trouble with your zone scaling script.

Debug tells me

[Quests] Use of uninitialized value $qst_npc_50::ScalingLoaded in numeric eq (==) at quests/fhalls/zonecontroller.pl line 54

I assume that if I put zonecontroller.pl into global this will try to call up in every zone by what I read. So I am trying to just do one zone at the moment. Any idea as to what I missed out on? I triple checked the code and reread the posts. Any help on the debug would be appreciated.

Splose
07-23-2016, 10:58 PM
I noticed when using GetNPCTypeID in my global_npc that it wasn't scaling repops.. I've changed it to work by entity ID and it is now scaling repops properly.. but after a slight delay.

Under EVENT_SIGNAL in Zonecontroller I've added the following debug:
quest::gmsay("got signal from " . $entity_list->GetNPCByID($signal)->GetCleanName() . "(scaled: " . $entity_list->GetNPCByID($signal)->GetEntityVariable("Scaled") . ") : $signal");

I noticed that whenever I enter a zone my ZC is getting SPAMMED with signals that from what I see he shouldn't be getting (scaled entity variable = 1 but npcs are randomly sending signals, they aren't even spawning while they do this) see here:

https://i.gyazo.com/62934b73e994b676979fcf8b9b4ecacc.png

After about 5 minutes or so (depending on how many mobs are in the zone) this spam will stop. This script was working 2 years ago so I'm wondering if there have been any source changes that have affected this system.

Akkadius
07-24-2016, 12:44 AM
I've got a completely different setup for this now with the new zone controller setup.

You'll have to figure out how to make what is here work for the current source.

Splose
07-24-2016, 01:15 AM
I've got a completely different setup for this now with the new zone controller setup.

You'll have to figure out how to make what is here work for the current source.

Not very helpful.. I asked if there were new source changes that would affect this the answer to that would have been yes.. Thanks anyway though.

Anyone looking to use this stock this should work:

Remove the signals from your global_npc and change zonecontroller.pl to zone_controller.pl

Line 120 will make sure Diabloloot is not assigned to the zones in the array. If you don't use that you can just remove that whole block entirely.

zone_controller.pl

sub EVENT_SPAWN {
quest::gmsay("Zone Scaling Sequence Initiated.", 18);
quest::gmsay("Zone: $zonesn", 18);
quest::gmsay("Instance Version: $instanceversion", 18);
quest::gmsay("Instance ID: $instanceversion", 18);

LoadStaticNPCScaling($zonesn); #::: Load NPC Static Scaling
LoadStaticZoneScaling(); #::: Load Zone Static Scaling


quest::settimer("scaleall", 1); #::: Run Scaling routine
quest::settimer("scaleall", 3); #::: Run Scaling routine
$ScalingLoaded = "";
}

sub EVENT_SPAWN_ZONE {
quest::shout("Mob spawned. - " . $spawned_entity_id ."");
ScaleProcedure($spawned_entity_id);
}

sub EVENT_TIMER{
if($timer eq "scaleall"){ ScaleProcedure(); quest::stoptimer("scaleall"); quest::gmsay("Scaling Sequence SUCCESSFUL (TEST)", 14); }
}


sub ScaleMob {
my $npc_ent = $entity_list->GetNPCByID($_[0]);
#quest::shout("found NPC: " . $npc_ent->GetCleanName() . "");
}

sub ScaleProcedure{

#::: Read from DB
if(!$SD[1][0][0]){ LoadScaling(); } #::: Scaling Vars Empty, reload them from DB
$NPC = 0; $pop = "";

if($_[0]){
@ent = $entity_list->GetNPCByID($_[0]);
$pop = " POP";
#quest::gmsay("Scaling NPC ID " . $_[0], 15);
}
else{ @ent = $entity_list->GetNPCList(); $ScalingLoaded = 2; }
foreach $NPC (@ent){
#::: Hide Invis NPC Names
if(($NPC->GetRace() == 127 || $NPC->GetRace() == 240) && $NPC->GetLevel() < 100 && $NPC->GetNPCTypeID() > 1000){ if($NPC->GetCleanName()=~/shadowed/i){} else{ $NPC->TempName(""); $NPC->ModifyNPCStat("special_attacks", "AZ"); } }

if($NPC->GetEntityVariable("Scaled") != 1){
#Static NPC Scaling
$n_name = $NPC->GetCleanName(); $n_name =~ tr/ /_/;
if($N_SD{$n_name}[0]){ ScaleNPCStatic($NPC, $n_name); }
}
#::: SCALING
#$NPC->Say("Scaling...");
if($NPC->GetPetSpellID() == 0 && $NPC->GetRace() != 127 && $NPC->GetRace() != 240 && $NPC->GetClass() < 20 && $NPC->GetNPCTypeID() > 1000 && $NPC->GetEntityVariable("Scaled") != 1){


$NTYPE = 0; $NN = "NPC";
if(substr($NPC->GetName(), 0, 1) eq "#" && substr($NPC->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($NPC->GetName(), 0, 2) eq "##" && substr($NPC->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$NPC->ModifyNPCStat("max_hp", $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2]);
$NPC->ModifyNPCStat("max_mana", $SD[$NPC->GetLevel()][$NTYPE][3] * $SZD{$zonesn}[$instanceversion][$NTYPE][3]);
$NPC->ModifyNPCStat("min_hit", $SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]);
$NPC->ModifyNPCStat("max_hit", $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]);
$NPC->ModifyNPCStat("attack_speed", $SD[$NPC->GetLevel()][$NTYPE][6] * $SZD{$zonesn}[$instanceversion][$NTYPE][6]);
$NPC->ModifyNPCStat("ac", $SD[$NPC->GetLevel()][$NTYPE][7] * $SZD{$zonesn}[$instanceversion][$NTYPE][7]);
$NPC->ModifyNPCStat("str", $SD[$NPC->GetLevel()][$NTYPE][8]);
$NPC->ModifyNPCStat("sta", $SD[$NPC->GetLevel()][$NTYPE][9]);
$NPC->ModifyNPCStat("dex", $SD[$NPC->GetLevel()][$NTYPE][10]);
$NPC->ModifyNPCStat("agi", $SD[$NPC->GetLevel()][$NTYPE][11]);
$NPC->ModifyNPCStat("int", $SD[$NPC->GetLevel()][$NTYPE][12]);
$NPC->ModifyNPCStat("wis", $SD[$NPC->GetLevel()][$NTYPE][13]);
$NPC->ModifyNPCStat("cha", $SD[$NPC->GetLevel()][$NTYPE][14]);
$NPC->ModifyNPCStat("mr", $SD[$NPC->GetLevel()][$NTYPE][15]);
$NPC->ModifyNPCStat("cr", $SD[$NPC->GetLevel()][$NTYPE][16]);
$NPC->ModifyNPCStat("dr", $SD[$NPC->GetLevel()][$NTYPE][17]);
$NPC->ModifyNPCStat("fr", $SD[$NPC->GetLevel()][$NTYPE][18]);
$NPC->ModifyNPCStat("pr", $SD[$NPC->GetLevel()][$NTYPE][19]);
if($SZD{$zonesn}[$instanceversion][$NTYPE][13]){
$NPC->ModifyNPCStat("accuracy", $SZD{$zonesn}[$instanceversion][$NTYPE][13]);
}

if($Debug){
$NPC->SetEntityVariable("max_hp", $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2]);
$NPC->SetEntityVariable("max_mana", $SD[$NPC->GetLevel()][$NTYPE][3] * $SZD{$zonesn}[$instanceversion][$NTYPE][3]);
$NPC->SetEntityVariable("min_hit", $SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]);
$NPC->SetEntityVariable("max_hit", $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]);
$NPC->SetEntityVariable("attack_speed", $SD[$NPC->GetLevel()][$NTYPE][6] * $SZD{$zonesn}[$instanceversion][$NTYPE][6]);
$NPC->SetEntityVariable("ac", $SD[$NPC->GetLevel()][$NTYPE][7] * $SZD{$zonesn}[$instanceversion][$NTYPE][7]);
$NPC->SetEntityVariable("str", $SD[$NPC->GetLevel()][$NTYPE][8]);
$NPC->SetEntityVariable("sta", $SD[$NPC->GetLevel()][$NTYPE][9]);
$NPC->SetEntityVariable("dex", $SD[$NPC->GetLevel()][$NTYPE][10]);
$NPC->SetEntityVariable("agi", $SD[$NPC->GetLevel()][$NTYPE][11]);
$NPC->SetEntityVariable("int", $SD[$NPC->GetLevel()][$NTYPE][12]);
$NPC->SetEntityVariable("wis", $SD[$NPC->GetLevel()][$NTYPE][13]);
$NPC->SetEntityVariable("cha", $SD[$NPC->GetLevel()][$NTYPE][14]);
$NPC->SetEntityVariable("mr", $SD[$NPC->GetLevel()][$NTYPE][15]);
$NPC->SetEntityVariable("cr", $SD[$NPC->GetLevel()][$NTYPE][16]);
$NPC->SetEntityVariable("dr", $SD[$NPC->GetLevel()][$NTYPE][17]);
$NPC->SetEntityVariable("fr", $SD[$NPC->GetLevel()][$NTYPE][18]);
$NPC->SetEntityVariable("pr", $SD[$NPC->GetLevel()][$NTYPE][19]);
if($SZD{$zonesn}[$instanceversion][$NTYPE][13]){
$NPC->SetEntityVariable("accuracy", $SZD{$zonesn}[$instanceversion][$NTYPE][13]);
}
}

#::: Is there a static zone entry?
if($SZD{$zonesn}[$instanceversion][$NTYPE][11] != 1){
$NPC->ModifyNPCStat("special_attacks", $SZD{$zonesn}[$instanceversion][$NTYPE][11]);
}else{
$NPC->ModifyNPCStat("special_attacks", $SD[$NPC->GetLevel()][$NTYPE][21]);
}
$NPC->ModifyNPCStat("hp_regen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->SetEntityVariable("hpregen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->ModifyNPCStat("spellscale", $SD[$NPC->GetLevel()][$NTYPE][22] * $SZD{$zonesn}[$instanceversion][$NTYPE][9]);
$NPC->ModifyNPCStat("healscale", $SD[$NPC->GetLevel()][$NTYPE][23] * $SZD{$zonesn}[$instanceversion][$NTYPE][8]);

$LID = (200000 + ($NTYPE * 1000) + $NPC->GetLevel());
if($NPC->GetLoottableID() != $LID){
my @nodiabloloot = (175,112,427,36,294,495);
my $zid = $NPC->GetZoneID();
if($NPC->GetZoneID == 396 && $instanceversion == 1) {
}
if(grep( /^$zid$/i, @nodiabloloot)) {
}
else {
$NPC->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
$NPC->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
}
}
$NPC->SetHP($NPC->GetMaxHP());
$NPC->SetEntityVariable("Scaled", 1); if($Debug){ $NPC->SetEntityVariable("ScaledType", 1); }

if($Debug){
quest::gmsay("Scaling $pop $NN [" . $NPC->GetCleanName() . "]
HP:[". $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2] . "]
hp_regen:[". ($SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]) . "]
min_hit:[". ($SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]) . "]
max_hit:[".( $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]) . "]
spec:[". $SD[$NPC->GetLevel()][$NTYPE][21] . "]
NTYPE:[". $NTYPE . "]
", 15);
}

if(!$SD[$NPC->GetLevel()][$NTYPE][0]){ quest::gmsay($NPC->GetCleanName() . ": ERROR! Missing Scaling Entry! For level " . $NPC->GetLevel() . " Type: $NTYPE", 13); }
}
# Level 255 NPC's are considered quest NPC's and shall not be attacked #
if($NPC->GetLevel() == 255){ $NPC->ModifyNPCStat("special_attacks", "AHGZ"); $NPC->SetEntityVariable("max_hp", 100000); }
}
if($ScalingLoaded == 2){ $ScalingLoaded = 3; }
}

sub LoadScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scaling.level,
cust_npc_scaling.type,
cust_npc_scaling.hp,
cust_npc_scaling.mana,
cust_npc_scaling.mindmg,
cust_npc_scaling.maxdmg,
cust_npc_scaling.attack_speed,
cust_npc_scaling.AC,
cust_npc_scaling.STR,
cust_npc_scaling.STA,
cust_npc_scaling.DEX,
cust_npc_scaling.AGI,
cust_npc_scaling._INT,
cust_npc_scaling.WIS,
cust_npc_scaling.CHA,
cust_npc_scaling.MR,
cust_npc_scaling.CR,
cust_npc_scaling.DR,
cust_npc_scaling.FR,
cust_npc_scaling.PR,
cust_npc_scaling.hp_regen,
cust_npc_scaling.npcspecialattks,
cust_npc_scaling.spellscale,
cust_npc_scaling.healscale
FROM
cust_npc_scaling
ORDER BY cust_npc_scaling.level, cust_npc_scaling.type";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $SD[$row[0]][$row[1]] = [@row]; }
}

sub LoadStaticZoneScaling{
#::: Load Static Zone Scaling Data #:::
$connect = plugin::LoadMysql();
#::: Default empty values to 1
for($i = 2; $i < 17; $i++){
for($t = 0; $t < 3; $t++){
if(!$SZD{$zonesn}[$instanceversion][$t][$i] || $SZD{$zonesn}[$instanceversion][$t][$i] == 0){
$SZD{$zonesn}[$instanceversion][$t][$i] = 1;
}
}
}

$query = "SELECT `zonesn`, `version`, `hp`, `mana`, `mindmg`, `maxdmg`, `attack_speed`, `ac`, `healscale`, `spellscale`, `hpregen`, `specialattacks`, `type`, `accuracy` FROM `cust_npc_zonescale_static` WHERE `zonesn` = '" . $zonesn . "'"; $query_handle = $connect->prepare($query); $query_handle->execute(); my @SZD;
while (@row = $query_handle->fetchrow_array()){
$SZD{$row[0]}[$row[1]][$row[12]] = [@row];
if($SZD{$zonesn}[$instanceversion][0]){
$Mod = $SZD{$zonesn}[$instanceversion][2]; $npc->SetEntityVariable("ScaleMod", $Mod);
quest::gmsay("[Zonecontroller] (Static Data) [Type] : " . $row[12] . " Zone Data: HP=" . ($SZD{$zonesn}[$instanceversion][$row[12]][2] * 100) . "(%%) Mana=" . ($SZD{$zonesn}[$instanceversion][$row[12]][3] * 100) . "(%%) MINDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][4] * 100) . "(%%) MAXDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][5] * 100) . "(%%) ATK_SPD=" . ($SZD{$zonesn}[$instanceversion][$row[12]][6] * 100) . "(%%) AC=" . ($SZD{$zonesn}[$instanceversion][$row[12]][7] * 100) . "(%%) SPELLSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][8] * 100) . "(%%) HEALSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][9] * 100) . "(%%) HPREGEN=" . ($SZD{$zonesn}[$instanceversion][$row[12]][10] * 100) . "(%%)", 15);

}
}
}

sub LoadStaticNPCScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scale_static.`name`,
cust_npc_scale_static.zonesn,
cust_npc_scale_static.hp,
cust_npc_scale_static.mana,
cust_npc_scale_static.mindmg,
cust_npc_scale_static.maxdmg,
cust_npc_scale_static.attack_speed,
cust_npc_scale_static.AC,
cust_npc_scale_static.STR,
cust_npc_scale_static.STA,
cust_npc_scale_static.DEX,
cust_npc_scale_static.AGI,
cust_npc_scale_static._INT,
cust_npc_scale_static.WIS,
cust_npc_scale_static.CHA,
cust_npc_scale_static.MR,
cust_npc_scale_static.CR,
cust_npc_scale_static.DR,
cust_npc_scale_static.FR,
cust_npc_scale_static.PR,
cust_npc_scale_static.hp_regen,
cust_npc_scale_static.spellscale,
cust_npc_scale_static.healscale,
cust_npc_scale_static.npcspecialattks,
cust_npc_scale_static.usediabloloot,
cust_npc_scale_static.localloottable
FROM
cust_npc_scale_static
WHERE cust_npc_scale_static.zonesn = '" . $_[0] . "' OR cust_npc_scale_static.zonesn = 'global'";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $N_SD{$row[0]} = [@row]; quest::gmsay("[Zonecontroller]: Loading static NPC data for NPC: '" . $row[0] ."'", 15); }
}

sub ScaleNPCStatic{
my $SS = $_[0];
quest::shout("Found data for NPC " . $SS->GetCleanName() . ' - ' . $_[1]);
$NTYPE = 0; $NN = "NPC";
if(substr($SS->GetName(), 0, 1) eq "#" && substr($SS->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($SS->GetName(), 0, 2) eq "##" && substr($SS->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$SS->ModifyNPCStat("max_hp", $N_SD{$_[1]}[2]);
$SS->ModifyNPCStat("max_mana", $N_SD{$_[1]}[3]);
$SS->ModifyNPCStat("min_hit", $N_SD{$_[1]}[4]);
$SS->ModifyNPCStat("max_hit", $N_SD{$_[1]}[5]);
$SS->ModifyNPCStat("attack_speed", $N_SD{$_[1]}[6]);
$SS->ModifyNPCStat("ac", $N_SD{$_[1]}[7]);
$SS->ModifyNPCStat("str", $N_SD{$_[1]}[8]);
$SS->ModifyNPCStat("sta", $N_SD{$_[1]}[9]);
$SS->ModifyNPCStat("dex", $N_SD{$_[1]}[10]);
$SS->ModifyNPCStat("agi", $N_SD{$_[1]}[11]);
$SS->ModifyNPCStat("int", $N_SD{$_[1]}[12]);
$SS->ModifyNPCStat("wis", $N_SD{$_[1]}[13]);
$SS->ModifyNPCStat("cha", $N_SD{$_[1]}[14]);
$SS->ModifyNPCStat("mr", $N_SD{$_[1]}[15]);
$SS->ModifyNPCStat("cr", $N_SD{$_[1]}[16]);
$SS->ModifyNPCStat("dr", $N_SD{$_[1]}[17]);
$SS->ModifyNPCStat("fr", $N_SD{$_[1]}[18]);
$SS->ModifyNPCStat("pr", $N_SD{$_[1]}[19]);
$SS->ModifyNPCStat("hp_regen", $N_SD{$_[1]}[20]);
$SS->ModifyNPCStat("spellscale", $N_SD{$_[1]}[21]);
$SS->ModifyNPCStat("healscale", $N_SD{$_[1]}[22]);
$SS->ModifyNPCStat("special_attacks", $N_SD{$_[1]}[23]);

if($N_SD{$_[1]}[24] == 1){ #::: Tells Static Entry to use Diablo Loot
$LID = (200000 + ($NTYPE * 1000) + $SS->GetLevel());
if($SS->GetLoottableID() != $LID){
$SS->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
$SS->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
}
}

if($N_SD{$_[1]}[25] > 0){ #::: Add an additional Loot table
$SS->ModifyNPCStat("loottable_id", $N_SD{$_[1]}[25]); $SS->AddLootTable();
}

$SS->SetEntityVariable("Scaled", 1); if($Debug){ $SS->SetEntityVariable("ScaledType", 2); }
}

sub RandomRange {

my $MinRandom = $_[0];
my $MaxRandom = $_[1];

my $RandomResult = int(rand(($MaxRandom + 1) - $MinRandom)) + $MinRandom;
if ($RandomResult > $MaxRandom)
{
return $MaxRandom;
}
return $RandomResult;

}

jpyou127
04-13-2017, 03:06 PM
Akkadius, do you have this available for use with the current EMU/DB?

Celestial

Akkadius
04-13-2017, 03:07 PM
Currently - it does not.

Documentation and plugin refresh is coming within the next month or so

jpyou127
04-13-2017, 03:09 PM
Awesome!! Love your work man!

Will this also work with instances?


Celestial

kugbok
05-20-2017, 07:46 PM
very interested in this :-) thanks for all your work

eldarian
05-23-2017, 12:48 AM
This is amazing!

Aardil
02-21-2018, 01:00 PM
Questions

According to what I Read, this used DBD
What I want to know is this:
I have an existing DB, not sure if its DBD or not.

If I create the tables in my old DB then it seems logical that I should not need to load DBD or alter the eqemu_config since it is all in the original DB.

plug_in From what I read all it does is alter the eqemu_config

Am I wrong?

Aardil

c0ncrete
02-21-2018, 01:41 PM
DBI is a database independent interface for perl. DBD are the drivers it uses to connect (DBD::mysql, etc).

Marmosa
04-02-2018, 02:25 PM
Does anyone have the required sql for the tables? The link seems to be broken.

deladriendil
04-27-2018, 02:43 PM
This is really cool. opens up tons of opportunities
how does the scaling work exactly for Raid mobs? i'm basically looking for a way to scale raid content down to a single 6 man group as far as difficulty. also, are these instructions still representative in the current peq database or would tweaks need to be made?

Splose
04-27-2018, 08:48 PM
I will post a fix for this sometime this weekend for you guys.

jpyou127
04-30-2018, 06:47 AM
Most excellent Splose!

Splose
05-11-2018, 11:16 AM
Most excellent Splose!

I completely forgot about this!

A quick disclaimer I have a HEAVILY modified zone_controller.pl and had to quickly go through and remove everything that's not "stock" as far as the auto scaling goes. A quick test has this working on my server. If any of you have any issues I will try and fix them to the best of my ability.

Make sure you have the rule Zone::UseZoneController enabled. Place the following code into a file named zone_controller.pl in your quests/global folder.


sub EVENT_SPAWN {
#$Debug = " ";

quest::gmsay("Zone Scaling Sequence Initiated.", 18);
quest::gmsay("Zone: $zonesn", 18);
quest::gmsay("Instance Version: $instanceversion", 18);
quest::gmsay("Instance ID: $instanceversion", 18);

LoadStaticNPCScaling($zonesn); #::: Load NPC Static Scaling
LoadStaticZoneScaling(); #::: Load Zone Static Scaling


quest::settimer("scaleall", 1); #::: Run Scaling routine
quest::settimer("scaleall", 3); #::: Run Scaling routine
$ScalingLoaded = "";
}

sub EVENT_SIGNAL {
ScaleProcedure($signal);
}


sub EVENT_SPAWN_ZONE {
my $Pet = $entity_list->GetNPCByID($spawned_entity_id)->GetPetSpellID();
if(!$Pet) {ScaleProcedure($spawned_entity_id);}
else {
quest::settimer("scale",1);
}
}


sub EVENT_TIMER{
if($timer eq "scaleall"){ ScaleProcedure(); quest::stoptimer("scaleall"); quest::gmsay("Scaling Sequence SUCCESSFUL (TEST)", 14); }
if($timer eq "scale"){quest::stoptimer("scale"); ScaleProcedure($spawned_entity_id);}
}



sub ScaleMob {
my $npc_ent = $entity_list->GetNPCByID($_[0]);
}

sub ScaleProcedure{
#quest::shout("scaling " . $_[0] . "");
#::: Read from DB
if(!$SD[1][0][0]){ LoadScaling(); } #::: Scaling Vars Empty, reload them from DB
$NPC = 0; $pop = "";

if($_[0]){
@ent = $entity_list->GetNPCByID($_[0]);
$pop = " POP";
#quest::gmsay("Scaling NPC ID " . $_[0], 15);
}
else{ @ent = $entity_list->GetNPCList(); $ScalingLoaded = 2; }
foreach $NPC (@ent){
#::: Hide Invis NPC Names
if(($NPC->GetRace() == 127 || $NPC->GetRace() == 240) && $NPC->GetLevel() < 100 && $NPC->GetNPCTypeID() > 1000){ if($NPC->GetCleanName()=~/shadowed/i){} else{ $NPC->TempName(""); $NPC->ModifyNPCStat("special_attacks", "AZ"); } }

if($NPC->GetEntityVariable("Scaled") != 1){
#Static NPC Scaling
$n_name = $NPC->GetCleanName(); $n_name =~ tr/ /_/;
if($N_SD{$n_name}[0]){ ScaleNPCStatic($NPC, $n_name); }
}
#::: SCALING
#$NPC->Say("Scaling...");
if($NPC->GetPetSpellID() == 0 && $NPC->GetRace() != 127 && $NPC->GetRace() != 240 && $NPC->GetClass() < 20 && $NPC->GetNPCTypeID() > 1000 && $NPC->GetEntityVariable("Scaled") != 1){


$NTYPE = 0; $NN = "NPC";
if(substr($NPC->GetName(), 0, 1) eq "#" && substr($NPC->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($NPC->GetName(), 0, 2) eq "##" && substr($NPC->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$NPC->ModifyNPCStat("max_hp", $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2]);
$NPC->ModifyNPCStat("max_mana", $SD[$NPC->GetLevel()][$NTYPE][3] * $SZD{$zonesn}[$instanceversion][$NTYPE][3]);
$NPC->ModifyNPCStat("min_hit", $SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]);
$NPC->ModifyNPCStat("max_hit", $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]);
$NPC->ModifyNPCStat("attack_speed", $SD[$NPC->GetLevel()][$NTYPE][6] * $SZD{$zonesn}[$instanceversion][$NTYPE][6]);
$NPC->ModifyNPCStat("ac", $SD[$NPC->GetLevel()][$NTYPE][7] * $SZD{$zonesn}[$instanceversion][$NTYPE][7]);
$NPC->ModifyNPCStat("str", $SD[$NPC->GetLevel()][$NTYPE][8]);
$NPC->ModifyNPCStat("sta", $SD[$NPC->GetLevel()][$NTYPE][9]);
$NPC->ModifyNPCStat("dex", $SD[$NPC->GetLevel()][$NTYPE][10]);
$NPC->ModifyNPCStat("agi", $SD[$NPC->GetLevel()][$NTYPE][11]);
$NPC->ModifyNPCStat("int", $SD[$NPC->GetLevel()][$NTYPE][12]);
$NPC->ModifyNPCStat("wis", $SD[$NPC->GetLevel()][$NTYPE][13]);
$NPC->ModifyNPCStat("cha", $SD[$NPC->GetLevel()][$NTYPE][14]);
$NPC->ModifyNPCStat("mr", $SD[$NPC->GetLevel()][$NTYPE][15]);
$NPC->ModifyNPCStat("cr", $SD[$NPC->GetLevel()][$NTYPE][16]);
$NPC->ModifyNPCStat("dr", $SD[$NPC->GetLevel()][$NTYPE][17]);
$NPC->ModifyNPCStat("fr", $SD[$NPC->GetLevel()][$NTYPE][18]);
$NPC->ModifyNPCStat("pr", $SD[$NPC->GetLevel()][$NTYPE][19]);
$NPC->ModifyNPCStat("accuracy", 100);
if($SZD{$zonesn}[$instanceversion][$NTYPE][13]){
$NPC->ModifyNPCStat("accuracy", $SZD{$zonesn}[$instanceversion][$NTYPE][13]);
}

if($Debug){
$NPC->SetEntityVariable("max_hp", $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2]);
$NPC->SetEntityVariable("max_mana", $SD[$NPC->GetLevel()][$NTYPE][3] * $SZD{$zonesn}[$instanceversion][$NTYPE][3]);
$NPC->SetEntityVariable("min_hit", $SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]);
$NPC->SetEntityVariable("max_hit", $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]);
$NPC->SetEntityVariable("attack_speed", $SD[$NPC->GetLevel()][$NTYPE][6] * $SZD{$zonesn}[$instanceversion][$NTYPE][6]);
$NPC->SetEntityVariable("ac", $SD[$NPC->GetLevel()][$NTYPE][7] * $SZD{$zonesn}[$instanceversion][$NTYPE][7]);
$NPC->SetEntityVariable("str", $SD[$NPC->GetLevel()][$NTYPE][8]);
$NPC->SetEntityVariable("sta", $SD[$NPC->GetLevel()][$NTYPE][9]);
$NPC->SetEntityVariable("dex", $SD[$NPC->GetLevel()][$NTYPE][10]);
$NPC->SetEntityVariable("agi", $SD[$NPC->GetLevel()][$NTYPE][11]);
$NPC->SetEntityVariable("int", $SD[$NPC->GetLevel()][$NTYPE][12]);
$NPC->SetEntityVariable("wis", $SD[$NPC->GetLevel()][$NTYPE][13]);
$NPC->SetEntityVariable("cha", $SD[$NPC->GetLevel()][$NTYPE][14]);
$NPC->SetEntityVariable("mr", $SD[$NPC->GetLevel()][$NTYPE][15]);
$NPC->SetEntityVariable("cr", $SD[$NPC->GetLevel()][$NTYPE][16]);
$NPC->SetEntityVariable("dr", $SD[$NPC->GetLevel()][$NTYPE][17]);
$NPC->SetEntityVariable("fr", $SD[$NPC->GetLevel()][$NTYPE][18]);
$NPC->SetEntityVariable("pr", $SD[$NPC->GetLevel()][$NTYPE][19]);
if($SZD{$zonesn}[$instanceversion][$NTYPE][13]){
$NPC->SetEntityVariable("accuracy", $SZD{$zonesn}[$instanceversion][$NTYPE][13]);
}
}

#::: Is there a static zone entry?
if($SZD{$zonesn}[$instanceversion][$NTYPE][11] != 1){
$NPC->ModifyNPCStat("special_attacks", $SZD{$zonesn}[$instanceversion][$NTYPE][11]);
}else{
$NPC->ModifyNPCStat("special_attacks", $SD[$NPC->GetLevel()][$NTYPE][21]);
}
$NPC->ModifyNPCStat("hp_regen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->SetEntityVariable("hpregen", $SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]);
$NPC->ModifyNPCStat("spellscale", $SD[$NPC->GetLevel()][$NTYPE][22] * $SZD{$zonesn}[$instanceversion][$NTYPE][9]);
$NPC->ModifyNPCStat("healscale", $SD[$NPC->GetLevel()][$NTYPE][23] * $SZD{$zonesn}[$instanceversion][$NTYPE][8]);

$LID = (200000 + ($NTYPE * 1000) + $NPC->GetLevel());
if($NPC->GetLoottableID() != $LID){
$NPC->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
$NPC->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $NPC->GetLevel())); $NPC->AddLootTable();
}
$NPC->SetHP($NPC->GetMaxHP());
$NPC->SetEntityVariable("Scaled", 1); if($Debug){ $NPC->SetEntityVariable("ScaledType", 1); }

if($Debug){
quest::gmsay("Scaling $pop $NN [" . $NPC->GetCleanName() . "]
HP:[". $SD[$NPC->GetLevel()][$NTYPE][2] * $SZD{$zonesn}[$instanceversion][$NTYPE][2] . "]
hp_regen:[". ($SD[$NPC->GetLevel()][$NTYPE][20] * $SZD{$zonesn}[$instanceversion][$NTYPE][10]) . "]
min_hit:[". ($SD[$NPC->GetLevel()][$NTYPE][4] * $SZD{$zonesn}[$instanceversion][$NTYPE][4]) . "]
max_hit:[".( $SD[$NPC->GetLevel()][$NTYPE][5] * $SZD{$zonesn}[$instanceversion][$NTYPE][5]) . "]
spec:[". $SD[$NPC->GetLevel()][$NTYPE][21] . "]
NTYPE:[". $NTYPE . "]
", 15);
}

if(!$SD[$NPC->GetLevel()][$NTYPE][0]){ quest::gmsay($NPC->GetCleanName() . ": ERROR! Missing Scaling Entry! For level " . $NPC->GetLevel() . " Type: $NTYPE", 13); }
}
# Level 255 NPC's are considered quest NPC's and shall not be attacked #
if($NPC->GetLevel() == 255){ $NPC->ModifyNPCStat("special_attacks", "AHGZ"); $NPC->SetEntityVariable("max_hp", 100000); }
}
if($ScalingLoaded == 2){ $ScalingLoaded = 3; }
}

sub LoadScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scaling.level,
cust_npc_scaling.type,
cust_npc_scaling.hp,
cust_npc_scaling.mana,
cust_npc_scaling.mindmg,
cust_npc_scaling.maxdmg,
cust_npc_scaling.attack_speed,
cust_npc_scaling.AC,
cust_npc_scaling.STR,
cust_npc_scaling.STA,
cust_npc_scaling.DEX,
cust_npc_scaling.AGI,
cust_npc_scaling._INT,
cust_npc_scaling.WIS,
cust_npc_scaling.CHA,
cust_npc_scaling.MR,
cust_npc_scaling.CR,
cust_npc_scaling.DR,
cust_npc_scaling.FR,
cust_npc_scaling.PR,
cust_npc_scaling.hp_regen,
cust_npc_scaling.npcspecialattks,
cust_npc_scaling.spellscale,
cust_npc_scaling.healscale
FROM
cust_npc_scaling
ORDER BY cust_npc_scaling.level, cust_npc_scaling.type";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $SD[$row[0]][$row[1]] = [@row]; }
}

sub LoadStaticZoneScaling{
#::: Load Static Zone Scaling Data #:::
$connect = plugin::LoadMysql();
#::: Default empty values to 1
for($i = 2; $i < 17; $i++){
for($t = 0; $t < 3; $t++){
if(!$SZD{$zonesn}[$instanceversion][$t][$i] || $SZD{$zonesn}[$instanceversion][$t][$i] == 0){
$SZD{$zonesn}[$instanceversion][$t][$i] = 1;
}
}
}

$query = "SELECT `zonesn`, `version`, `hp`, `mana`, `mindmg`, `maxdmg`, `attack_speed`, `ac`, `healscale`, `spellscale`, `hpregen`, `specialattacks`, `type`, `accuracy` FROM `cust_npc_zonescale_static` WHERE `zonesn` = '" . $zonesn . "'"; $query_handle = $connect->prepare($query); $query_handle->execute(); my @SZD;
while (@row = $query_handle->fetchrow_array()){
$SZD{$row[0]}[$row[1]][$row[12]] = [@row];
if($SZD{$zonesn}[$instanceversion][0]){
$Mod = $SZD{$zonesn}[$instanceversion][2]; $npc->SetEntityVariable("ScaleMod", $Mod);
quest::gmsay("[Zonecontroller] (Static Data) [Type] : " . $row[12] . " Zone Data: HP=" . ($SZD{$zonesn}[$instanceversion][$row[12]][2] * 100) . "(%%) Mana=" . ($SZD{$zonesn}[$instanceversion][$row[12]][3] * 100) . "(%%) MINDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][4] * 100) . "(%%) MAXDMG=" . ($SZD{$zonesn}[$instanceversion][$row[12]][5] * 100) . "(%%) ATK_SPD=" . ($SZD{$zonesn}[$instanceversion][$row[12]][6] * 100) . "(%%) AC=" . ($SZD{$zonesn}[$instanceversion][$row[12]][7] * 100) . "(%%) SPELLSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][8] * 100) . "(%%) HEALSCALE=" . ($SZD{$zonesn}[$instanceversion][$row[12]][9] * 100) . "(%%) HPREGEN=" . ($SZD{$zonesn}[$instanceversion][$row[12]][10] * 100) . "(%%)", 15);

}
}
}

sub LoadStaticNPCScaling{
$connect = plugin::LoadMysql();
$query = "SELECT
cust_npc_scale_static.`name`,
cust_npc_scale_static.zonesn,
cust_npc_scale_static.hp,
cust_npc_scale_static.mana,
cust_npc_scale_static.mindmg,
cust_npc_scale_static.maxdmg,
cust_npc_scale_static.attack_speed,
cust_npc_scale_static.AC,
cust_npc_scale_static.STR,
cust_npc_scale_static.STA,
cust_npc_scale_static.DEX,
cust_npc_scale_static.AGI,
cust_npc_scale_static._INT,
cust_npc_scale_static.WIS,
cust_npc_scale_static.CHA,
cust_npc_scale_static.MR,
cust_npc_scale_static.CR,
cust_npc_scale_static.DR,
cust_npc_scale_static.FR,
cust_npc_scale_static.PR,
cust_npc_scale_static.hp_regen,
cust_npc_scale_static.spellscale,
cust_npc_scale_static.healscale,
cust_npc_scale_static.npcspecialattks,
cust_npc_scale_static.usediabloloot,
cust_npc_scale_static.localloottable
FROM
cust_npc_scale_static
WHERE cust_npc_scale_static.zonesn = '" . $_[0] . "' OR cust_npc_scale_static.zonesn = 'global'";
$query_handle = $connect->prepare($query);
$query_handle->execute();
$NTYPE = 0;
while (@row = $query_handle->fetchrow_array()){ $N_SD{$row[0]} = [@row]; quest::gmsay("[Zonecontroller]: Loading static NPC data for NPC: '" . $row[0] ."'", 15); }
}


sub ScaleNPCStatic{
my $SS = $_[0];
quest::shout("Found data for NPC " . $SS->GetCleanName() . ' - ' . $_[1]);
$NTYPE = 0; $NN = "NPC";
if(substr($SS->GetName(), 0, 1) eq "#" && substr($SS->GetName(), 1, 2) ne "#"){ $NTYPE = 1; $NN = "Named"; }
if(substr($SS->GetName(), 0, 2) eq "##" && substr($SS->GetName(), 2, 3) ne "#"){ $NTYPE = 2; $NN = "Raid"; }

$SS->ModifyNPCStat("max_hp", $N_SD{$_[1]}[2]);
$SS->ModifyNPCStat("max_mana", $N_SD{$_[1]}[3]);
$SS->ModifyNPCStat("min_hit", $N_SD{$_[1]}[4]);
$SS->ModifyNPCStat("max_hit", $N_SD{$_[1]}[5]);
$SS->ModifyNPCStat("attack_speed", $N_SD{$_[1]}[6]);
$SS->ModifyNPCStat("ac", $N_SD{$_[1]}[7]);
$SS->ModifyNPCStat("str", $N_SD{$_[1]}[8]);
$SS->ModifyNPCStat("sta", $N_SD{$_[1]}[9]);
$SS->ModifyNPCStat("dex", $N_SD{$_[1]}[10]);
$SS->ModifyNPCStat("agi", $N_SD{$_[1]}[11]);
$SS->ModifyNPCStat("int", $N_SD{$_[1]}[12]);
$SS->ModifyNPCStat("wis", $N_SD{$_[1]}[13]);
$SS->ModifyNPCStat("cha", $N_SD{$_[1]}[14]);
$SS->ModifyNPCStat("mr", $N_SD{$_[1]}[15]);
$SS->ModifyNPCStat("cr", $N_SD{$_[1]}[16]);
$SS->ModifyNPCStat("dr", $N_SD{$_[1]}[17]);
$SS->ModifyNPCStat("fr", $N_SD{$_[1]}[18]);
$SS->ModifyNPCStat("pr", $N_SD{$_[1]}[19]);
$SS->ModifyNPCStat("hp_regen", $N_SD{$_[1]}[20]);
$SS->ModifyNPCStat("spellscale", $N_SD{$_[1]}[21]);
$SS->ModifyNPCStat("healscale", $N_SD{$_[1]}[22]);
$SS->ModifyNPCStat("special_attacks", $N_SD{$_[1]}[23]);

if($N_SD{$_[1]}[24] == 1){ #::: Tells Static Entry to use Diablo Loot
$LID = (200000 + ($NTYPE * 1000) + $SS->GetLevel());
if($SS->GetLoottableID() != $LID){
$SS->ModifyNPCStat("loottable_id", (210000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
$SS->ModifyNPCStat("loottable_id", (200000 + ($NTYPE * 1000) + $SS->GetLevel())); $SS->AddLootTable();
}
}

if($N_SD{$_[1]}[25] > 0){ #::: Add an additional Loot table
$SS->ModifyNPCStat("loottable_id", $N_SD{$_[1]}[25]); $SS->AddLootTable();
}

$SS->SetEntityVariable("Scaled", 1); if($Debug){ $SS->SetEntityVariable("ScaledType", 2); }
}


sub RandomRange {

my $MinRandom = $_[0];
my $MaxRandom = $_[1];

my $RandomResult = int(rand(($MaxRandom + 1) - $MinRandom)) + $MinRandom;
if ($RandomResult > $MaxRandom)
{
return $MaxRandom;
}
return $RandomResult;

}

deladriendil
05-11-2018, 01:20 PM
splose is this all that we need? the original links to download the custom tables are gone. don't want to start messing with this if its a partial fix.

Splose
05-11-2018, 01:38 PM
splose is this all that we need? the original links to download the custom tables are gone. don't want to start messing with this if its a partial fix.

Didn't realize the links were dead. You may have to balance these a bit I'm not sure how different they are to the ones provided in the op.

Download here. (https://www.dropbox.com/s/oyw67lxkgvk82zt/Scaling%20Tables.rar?dl=0)

Akkadius
05-11-2018, 02:05 PM
Also need to take into consideration that special attacks are no longer handled the same anymore

Splose
05-11-2018, 02:12 PM
Also need to take into consideration that special attacks are no longer handled the same anymore

Ahh that is right.

Just to clarify.. you are still able to use either system you just lose the increased functionality of the new one if you do it this way...correct?

Either way an easy fix but I'll have to get it done after work. Will update soon.

Akkadius
05-11-2018, 02:55 PM
Thanks for taking this on bud - I'm sure many people will appreciate it

If you want to pretty it up and make sure it all works and is tested that would be great.

Swap out special attacks for the new hotness and make sure that works and things should be good

I will make sure that all of this gets into our new docs we've been working on for 2018

deladriendil
05-11-2018, 03:19 PM
will the LoadMySQL() stuff work as advertised in the .json world as presented here?

http://www.eqemulator.org/forums/showthread.php?p=227039#post227039

Akkadius
05-11-2018, 03:20 PM
Yes as long as you have the latest plugins from the PEQ repo

https://github.com/ProjectEQ/projecteqquests/blob/master/plugins/MySQL.pl

deladriendil
05-13-2018, 02:42 PM
any chance I could get an example in JSON?

i put this at the end after the last }
file loads but I see the following in world

[Update] No script update necessary...
garbage after JSON object, at character offset 1977 (before "ub Loadmysql{\t\n\tu..."} at eqemu_server.pl line 1147

Splose
05-14-2018, 09:36 AM
@deladriendil

This is what I use:

Server Folder/plugins/MYSQL.pl

#::: Akkadius
#::: Description: These plugins are MySQL loaders in use with Perl DBI
#::: For plug and play, LoadMysql will load your database credentials from eqemu_config.json

sub LoadMysql {
use DBI;
use DBD::mysql;
use JSON;

my $json = new JSON();

#::: Load Config
my $content;
open(my $fh, '<', "eqemu_config.json") or die "cannot open file $filename"; {
local $/;
$content = <$fh>;
}
close($fh);

#::: Decode
$config = $json->decode($content);

#::: Set MySQL Connection vars
$db = $config->{"server"}{"database"}{"db"};
$host = $config->{"server"}{"database"}{"host"};
$user = $config->{"server"}{"database"}{"username"};
$pass = $config->{"server"}{"database"}{"password"};

#::: Map DSN
$dsn = "dbi:mysql:$db:$host:3306";

#::: Connect and return
$connect = DBI->connect($dsn, $user, $pass);

return $connect;
}

Thanks for taking this on bud - I'm sure many people will appreciate it

If you want to pretty it up and make sure it all works and is tested that would be great.

Swap out special attacks for the new hotness and make sure that works and things should be good

I will make sure that all of this gets into our new docs we've been working on for 2018

Not a problem. It's something I've wanted to do for a little while. I would assume I'm the best person other than yourself to get it done since I've used it for years now and I am pretty familiar with the inner workings.

Current plans:


Update code to take advantage of the new special_abilities system
Migrate code to the plugins folder to free up space in zone_controller.pl
Clean up my existing pet scaling code that works with this system
Simple boolean option to use pet scaling or not
Add a way to not scale entire zones
Add a "don't scale me" option for specific NPCs while still scaling the rest of the zone

deladriendil
05-14-2018, 12:06 PM
awesome. sorry, i misunderstood where that chunk of code went. got it now.
So we are just waiting on the change for the new special abilities then this is ready to test? or am I missing something.

Splose
05-14-2018, 01:41 PM
No what you have now should work I briefly tested it. When I get everything I want done it'll be a simple drag and drop into the appropriate folders and you won't have to do anything further assuming you have no other customizations in your zone_controller.pl

Since I'm trying to migrate to the plugins folder any added functionality past my list will be drag an drop as well.

Techungry
02-07-2019, 11:14 PM
Hi. I first wanted to thank you for coming up with such an awesome approach to scaling. I am using it to setup a solo tuned server for my family and friends and have been playing with it for a bit. One thing I am unsure of is whether this approach will scale spells/procs of NPC's and how that works? What effect does the spell_scale column have on the NPC's?

Splose
02-08-2019, 06:51 AM
Hi. I first wanted to thank you for coming up with such an awesome approach to scaling. I am using it to setup a solo tuned server for my family and friends and have been playing with it for a bit. One thing I am unsure of is whether this approach will scale spells/procs of NPC's and how that works? What effect does the spell_scale column have on the NPC's?

Yes it will.. the sp dmg and healing work the same way.

Spell Damage Scaling (100 = 100% or normal, <100 is weaker, >100 is stronger)


I still work on this from time to time.. I need to take some time out to just completely rewrite it in a cleaner way, it is so dirty atm.

Techungry
02-08-2019, 11:22 AM
Thanks Splose. Does it also affect procs? I tested with #Korucust in chardokb. He has a 1600 dmg life tap proc. It seemed he was classified as a type '1' NPC based on that was the type he inherited his other scaling from. I set spell_scale to 30 and he still had a full dmg proc, so I am wondering if procs are a special case?

Techungry
02-08-2019, 05:20 PM
It seems that editing the values on the NPC itself in the npc_types table works for scaling the proc, but setting the spell_scale and heal_scale to 0 does not result in the npc_scale_global_base value applying. It could be working fine for the standard casting spells but the NPC I am testing with casts nothing not lifetap and dots. I will find an NPC that casts something besides a DOT and see if that is working.

superpally1
02-08-2019, 06:34 PM
there is also this now. https://github.com/EQEmu/Server/wiki/NPC-Scaling

Techungry
02-08-2019, 06:58 PM
Yes I am very familiar with it, thanks. That was actually very helpful once I found it, but the behavior seems to be different from described. I suspect its specific to procs or the lifetap for this NPC or something. I'll try testing a few more NPC's, maybe I am just unlucky.

Techungry
02-08-2019, 09:54 PM
Ok, spell_scale from the npc_scale_global_base is it is definitely not being applied when the NPC's spellscale and healscale are 0. For now i will work around it by updating the npc_types table directly which appears to work but you might want to check the code around that area as there is a bug somewhere.

Splose
02-10-2019, 05:17 AM
Ok, spell_scale from the npc_scale_global_base is it is definitely not being applied when the NPC's spellscale and healscale are 0. For now i will work around it by updating the npc_types table directly which appears to work but you might want to check the code around that area as there is a bug somewhere.

It is working on older compiles.. I haven't tried on a recent compile but I would assume things have been updated/changed and that's why its broken.

I recommend going to link by superpally (https://github.com/EQEmu/Server/wiki/NPC-Scaling).

Huge improvement and it is being done source side rather than through Perl.