Merge branch 'master' into eqstream

This commit is contained in:
KimLS 2017-02-06 21:46:34 -08:00
commit 0736ce43bd
57 changed files with 6422 additions and 2572 deletions

View File

@ -1,5 +1,24 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 01/31/2017 ==
Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.)
== 01/26/2017 ==
Uleat: Change rogue bot behavior to eliminate twirling combat. They will only get behind the mob if they are not the mob's target or if the mob is feared or fleeing. This may lower rogue bot dps a small fraction..but, is more in-line with realistic game mechanics.
== 01/17/2017 ==
Mackal: Combat Revamp
- This change brings melee combat into line with how combat is done on live.
- This correctly applies the PC damage tables and corrects stacking order of many spells
- Given the scope of what had to be rewritten, it was not feasible to preserve the old combat system.
This means you will likely have to rebalance your server, which sucks, but this is very
accurate so shouldn't require any more changes, at least none that would cause you to have
to rebalance your server again.
- For rebalancing, I would recommend running the optional SQL and tweaking from there.
- To help with rebalancing there is a simulator included at utils/combat-sim.
- You can enter the mitigation or offense values you would like to balance around (#showstats will show you them)
a 1 on the sim is min damage 20 is max.
- Quick recommendations for best ways to improve PC DPS, give them some worn (or AA) SE_DamageModifier and/or SE_MinDamageModifier
== 12/03/2016 ==
Uleat: Added hack detection to trade code
- If illegal items are found in trade slots when the 'trade' button is clicked, the trade is cancelled and a message is sent to the offending player
@ -28,7 +47,7 @@ take into account that rogue was sneaking. Now sneaking rogues can see full
inventory on merchants (well, unless an item requires a + faction value).
== 09/12/2016 ==
Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework
Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework
(known as eqemu_update.pl) now known as eqemu_server.pl
- eqemu_server.pl is now a general EQEmu Server management utiltiy framework that can be used
to extend to many purposes. It's main purpose is to simplify server management
@ -49,7 +68,7 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util
- Regular bots database schema changes now happen automatically similarily to the above
- Database checks can also be ran manually via the script menu
- CLI Arguments
- Arguments passed to eqemu_server.pl can execute the same name-based operations that
- Arguments passed to eqemu_server.pl can execute the same name-based operations that
are present in the interactive menu
- Example: "perl eqemu_server.pl opcodes" will download opcodes
- Example: "perl eqemu_server.pl backup_player_tables" will backup and export player tables
@ -64,7 +83,7 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util
- server_start_dev.sh
- server_start.sh
- server_status.sh
- server_stop.sh
- server_stop.sh
- Usage analytics
- eqemu_server.pl now collects usage analytics, this is very helpful for our developers
- Example: We can see how many installs have been performed:
@ -76,10 +95,10 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util
- 'New Server' Utility
- Running 'new_server' from the main menu or 'perl eqemu_server.pl new_server' while in
a completely new folder with just the script present, will allow a server operator
to initiate a full clean PEQ install in that folder. Pulling down all assets and
installing a PEQ database with the name the server operator gives the prompts in the
to initiate a full clean PEQ install in that folder. Pulling down all assets and
installing a PEQ database with the name the server operator gives the prompts in the
script
== 09/10/2016 ==
noudess: Task system experience based on a % of a level did not take into
account the hell levels rule. Now it does.
@ -133,7 +152,7 @@ Kinglykrab: Implemented optional avoidance cap rules.
- Rule Names:
- Character:EnableAvoidanceCap (default is false)
- Character:AvoidanceCap (default is 750, beyond 1,000 seems to make characters dodge all attacks)
== 08/02/2016 ==
Uleat: Changed 'SendZoneSpawnsBulk' behavior to use near/far criteria (live-like) when sending packets.
- Zone-to-Zone client loading will see a small decrease in time (less than 10~15%)
@ -171,7 +190,7 @@ mackal: Fix up the SpellBuff struct
Uleat: Important fix for mob pathing
- This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones
- Changed variable 'gridno' type from int16 to int32 to reflect actual return value of fetch (values do exceed 32767 aka int16.max)
- Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true)
- Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true)
== 06/28/2016 ==
Noudess: Resurrection effects now block certain buffs like on live.
@ -240,7 +259,7 @@ Uleat: Moved database query code out of bot.cpp and into the new BotDatabase cla
== 03/25/2016 ==
Uleat: Fix for heal rotation 'Stack Overflow' error
Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance).
Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance).
Live like modifier added that decreases defensive proc chance if you are higher level then your attacker.
== 03/24/2016 ==
@ -283,7 +302,7 @@ Kinglykrab: Modified #flag so you can refresh your target's account status (GM s
- Just target the person whose flag you want to refresh and type #flag.
Uleat: Added itemlink functionality to the #summonitem command. Current use is limited to extracting the item id from the link.
- Invoking by item link '#summonitem Arrow' produces the same result as by item id '#summonitem 8005'
== 01/12/2016 ==
Athrogate: Adding ClearCompassMark() to Lua.
- Lua didn't have ClearCompassMark(). Perl already had this.
@ -313,7 +332,7 @@ Kinglykrab: Added GetInstanceTimer() to Perl and Lua.
- Note: If you do not provide an instance id in the method it defaults to instance id 0 and returns 0 for time remaining.
- Added UpdateZoneHeader(type, value) to Perl and Lua.
- Note: UpdateZoneHeader allows you to manipulate fog color, fog density, and many other zone header settings on the fly in Perl and Lua.
== 12/21/2015 ==
Natedog: Updated item table fields and added a few missing fields for evolving items
-DO NOT implement Heirloom items till the inventory code is fixed to allow placing NO DROP
@ -322,7 +341,7 @@ Natedog: Updated item table fields and added a few missing fields for evolving i
100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though)
Kinglykrab: Added GetMeleeMitigation() for NPCs and Clients in Perl and Lua.
- This allows you to check total item, spell, and AA melee mitigation contribution.
== 12/19/2015 ==
Kinglykrab: Added many methods to Perl and Lua, list below:
- SeeInvisible()
@ -344,7 +363,7 @@ Kinglykrab: Added many methods to Perl and Lua, list below:
- HasPet()
- IsSilenced()
- IsAmnesiad()
== 12/16/2015 ==
Noudess: Repaired issue with Bind Wounds on someone else. Message was not coming out on client (hold still) and a bind wounds on someone already binding their wounds would interrupt their bind and make them stand. Also removed some duplicate messaging.
@ -353,7 +372,7 @@ Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua.
- Note: Both methods are Mob methods and may be used on NPCs or PCs.
Natedog: Added Discipline functions, UpdateInstanceTimer function, and UnmemSpellBySpellID to lua and perl
-Examples: http://wiki.eqemulator.org/i?M=Pastebin&Paste=BJ0ygmNM
== 12/07/2015 ==
Uleat: Command aliases are no longer handled through the command_add() function.
- To add a command alias, edit the database table `command_settings` - here, you will find three columns: `command`, `access` and `aliases`
@ -366,7 +385,7 @@ Uleat: Command aliases are no longer handled through the command_add() function.
- If you need need more name space for aliases, simply edit the `command_settings` table and increase the size of the `aliases` column
- The old `commands` table has been renamed to `commands_old` for reference
- All of the current 'standard' commands have been added to the new `command_settings` table
- YOU WILL NEED TO VERIFY/IMPORT OLD ACCESS VALUES AS THIS CHANGE REVERTS ALL COMMAND ACCESS VALUES TO THEIR PEQDB DEFAULTS
== 11/30/2015 ==
@ -388,7 +407,7 @@ Akkadius: Performance boost (exponential) - Adjusted default idle cast check tim
- Database version 9089 will take care of this update automatically only if you used the default values
- The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when higher NPC count zones exist (Based off of process profiling)
- Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless npc_spells dictates other values, which most of the time it does not
- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them
- These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max)
@ -396,7 +415,7 @@ Akkadius: Performance boost (exponential) - Adjusted default idle cast check tim
Akkadius: Made many performance optimizing oriented code changes in the source
- Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds)
Akkadius: Added Perl Export Settings which should heavily reduce the Perl footprint
- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
this can make Perl very slow when events are triggered constantly
- The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{})
- qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal()
@ -424,7 +443,7 @@ Akkadius: Added Perl Export Settings which should heavily reduce the Perl footpr
| 4 | EVENT_ATTACK | 0 | 1 | 1 | 0 | 1 |
| 5 | EVENT_COMBAT | 1 | 1 | 1 | 0 | 1 |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
- If a change is made to this table while the server is live and running, you can hot reload all zone process settings via:
#reloadperlexportsettings
- For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as:
@ -433,7 +452,7 @@ Akkadius: Added Perl Export Settings which should heavily reduce the Perl footpr
(export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083
(export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032
(export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141
== 10/16/2015 ==
Uleat: Added command '#bot clearfollowdistance [ <target> | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance
@ -465,7 +484,7 @@ rules:
commands:
'#invsnapshot' - Takes a snapshot of target client's inventory (feature active or inactive)
'#clearinvsnapshots [use rule]' - Clears snapshot entries based on bool argument ([true] - honors the 'InvSnapshotHistoryD' rule, [false] - erases all)
== 08/02/2015 ==
Shendare: VS2013 query StringFormat glitches when "%f" is passed for the int GetRunSpeed().
Shendare: In CreateNewNPCCommand(), the npc_type_id and spawngroupid are created in the database, but never set in the spawn class, so later it can't delete them with #npcspawn remove or #npcspawn delete.

View File

@ -2495,6 +2495,7 @@ struct BookRequest_Struct {
uint8 window; // where to display the text (0xFF means new window)
uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others.
uint32 invslot; // Only used in Sof and later clients;
int16 subslot; // The subslot inside of a bag if it is inside one.
char txtfile[20];
};

View File

@ -5154,6 +5154,7 @@ namespace RoF2
IN(type);
IN(invslot);
IN(subslot);
emu->window = (uint8)eq->window;
strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile));

View File

@ -2826,7 +2826,8 @@ struct BookText_Struct {
struct BookRequest_Struct {
/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window).
/*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway.
/*0008*/ uint32 unknown006; // Seen FFFFFFFF
/*0006*/ int16 subslot; // Inventory sub-slot (0-x)
/*0008*/ uint16 unknown006; // Seen FFFF
/*0010*/ uint16 unknown008; // seen 0000
/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others
/*0016*/ uint32 unknown0012;

File diff suppressed because it is too large Load Diff

View File

@ -113,6 +113,741 @@
#define PLAYER_RACE_ALL_MASK 65535
#define RT_ABHORRENT 193
#define RT_AIR_ELEMENTAL 210
#define RT_AIR_ELEMENTAL_2 475
#define RT_AIR_MEPHIT 291
#define RT_AKHEVA 230
#define RT_AKHEVA_2 722
#define RT_ALARAN 695
#define RT_ALARAN_GHOST 708
#define RT_ALARAN_SENTRY_STONE 703
#define RT_ALLIGATOR 91
#define RT_ALLIGATOR_2 479
#define RT_AMYGDALAN 99
#define RT_AMYGDALAN_2 663
#define RT_ANEUK 395
#define RT_ANIMATED_ARMOR 323
#define RT_ANIMATED_HAND 166
#define RT_ANIMATED_STATUE 442
#define RT_ANIMATED_STATUE_2 448
#define RT_APEXUS 637
#define RT_ARACHNID 326
#define RT_ARCANIST_OF_HATE 352
#define RT_ARMADILLO 87
#define RT_ARMOR_RACK 535
#define RT_AVIAK 13
#define RT_AVIAK_2 558
#define RT_AVIAK_PULL_ALONG 711
#define RT_AYONAE_RO 498
#define RT_BANNER 500
#define RT_BANNER_2 553
#define RT_BANNER_3 554
#define RT_BANNER_4 555
#define RT_BANNER_5 556
#define RT_BANNER_6 557
#define RT_BANNER_7 586
#define RT_BANNER_10TH_ANNIVERSARY 628
#define RT_BANSHEE 250
#define RT_BANSHEE_2 487
#define RT_BANSHEE_3 488
#define RT_BARBARIAN 2
#define RT_BARBARIAN_2 90
#define RT_BARREL 377
#define RT_BARREL_BARGE_SHIP 546
#define RT_BASILISK 436
#define RT_BAT 34
#define RT_BAT_2 260
#define RT_BAT_3 416
#define RT_BAZU 409
#define RT_BEAR 43
#define RT_BEAR_2 305
#define RT_BEAR_3 480
#define RT_BEAR_MOUNT 655
#define RT_BEAR_TRAP 503
#define RT_BEETLE 22
#define RT_BEETLE_2 559
#define RT_BEETLE_3 716
#define RT_BEGGAR 55
#define RT_BELLIKOS 638
#define RT_BERTOXXULOUS 152
#define RT_BERTOXXULOUS_2 255
#define RT_BIXIE 79
#define RT_BIXIE_2 520
#define RT_BLIMP_SHIP 693
#define RT_BLIND_DREAMER 669
#define RT_BLOOD_RAVEN 279
#define RT_BOAT 141
#define RT_BOAT_2 533
#define RT_BOLVIRK 486
#define RT_BONE_GOLEM 362
#define RT_BONE_GOLEM_2 491
#define RT_BONES 383
#define RT_BOOK_DERVISH 660
#define RT_BOT_PORTAL 329
#define RT_BOULDER 585
#define RT_BOX 376
#define RT_BRAXI 688
#define RT_BRAXI_MOUNT 676
#define RT_BRELL 640
#define RT_BRELLS_FIRST_CREATION 639
#define RT_BRISTLEBANE 153
#define RT_BROKEN_CLOCKWORK 274
#define RT_BRONTOTHERIUM 169
#define RT_BROWNIE 15
#define RT_BROWNIE_2 568
#define RT_BUBONIAN 268
#define RT_BUBONIAN_UNDERLING 269
#define RT_BURYNAI 144
#define RT_BURYNAI_2 602
#define RT_CAKE_10TH_ANNIVERSARY 629
#define RT_CAMPFIRE 567
#define RT_CARRIER_HAND 721
#define RT_CAT 713
#define RT_CAZIC_THULE 95
#define RT_CAZIC_THULE_2 670
#define RT_CENTAUR 16
#define RT_CENTAUR_2 521
#define RT_CHEST 378
#define RT_CHEST_2 589
#define RT_CHEST_3 590
#define RT_CHIMERA 412
#define RT_CHIMERA_2 582
#define RT_CHOKIDAI 356
#define RT_CLAM 115
#define RT_CLIKNAR_MOUNT 652
#define RT_CLIKNAR_QUEEN 642
#define RT_CLIKNAR_SOLDIER 643
#define RT_CLIKNAR_WORKER 644
#define RT_CLOCKWORK_BEETLE 276
#define RT_CLOCKWORK_BOAR 472
#define RT_CLOCKWORK_BOMB 504
#define RT_CLOCKWORK_BRAIN 249
#define RT_CLOCKWORK_GNOME 88
#define RT_CLOCKWORK_GOLEM 248
#define RT_CLOCKWORK_GUARDIAN 572
#define RT_COCKATRICE 96
#define RT_COFFIN 382
#define RT_COFFIN_2 592
#define RT_COIN_PURSE 427
#define RT_COLDAIN 183
#define RT_COLDAIN_2 645
#define RT_COLDAIN_3 646
#define RT_CORAL 460
#define RT_CORATHUS 459
#define RT_CRAB 302
#define RT_CRAGBEAST 390
#define RT_CRAGSLITHER 597
#define RT_CROCODILE 259
#define RT_CRYSTAL 591
#define RT_CRYSTAL_SHARD 425
#define RT_CRYSTAL_SPHERE 616
#define RT_CRYSTAL_SPIDER 327
#define RT_CRYSTALSKIN_AMBULOID 641
#define RT_CRYSTALSKIN_SESSILOID 647
#define RT_DAISY_MAN 97
#define RT_DARK_ELF 6
#define RT_DARK_ELF_2 77
#define RT_DARK_LORD 466
#define RT_DEMI_LICH 45
#define RT_DEMON_VULTURE 620
#define RT_DERVISH 100
#define RT_DERVISH_2 372
#define RT_DERVISH_3 431
#define RT_DERVISH_4 704
#define RT_DERVISH_VER_5 726
#define RT_DERVISH_VER_6 727
#define RT_DEVOURER 159
#define RT_DIRE_WOLF 171
#define RT_DISCORD_SHIP 404
#define RT_DISCORDLING 418
#define RT_DISEASED_FIEND 253
#define RT_DJINN 126
#define RT_DRACHNID 57
#define RT_DRACHNID_2 461
#define RT_DRACHNID_COCOON 462
#define RT_DRACOLICH 604
#define RT_DRAGLOCK 132
#define RT_DRAGON 49
#define RT_DRAGON_2 122
#define RT_DRAGON_3 165
#define RT_DRAGON_4 184
#define RT_DRAGON_5 192
#define RT_DRAGON_6 195
#define RT_DRAGON_7 196
#define RT_DRAGON_8 198
#define RT_DRAGON_9 304
#define RT_DRAGON_10 435
#define RT_DRAGON_11 437
#define RT_DRAGON_12 438
#define RT_DRAGON_13 452
#define RT_DRAGON_14 530
#define RT_DRAGON_15 531
#define RT_DRAGON_16 569
#define RT_DRAGON_BONES 423
#define RT_DRAGON_EGG 445
#define RT_DRAGON_STATUE 446
#define RT_DRAGORN 413
#define RT_DRAGORN_BOX 421
#define RT_DRAKE 89
#define RT_DRAKE_2 430
#define RT_DRAKE_3 432
#define RT_DRAKKIN 522
#define RT_DRIXIE 113
#define RT_DROGMORE 348
#define RT_DROLVARG 133
#define RT_DRYAD 243
#define RT_DWARF 8
#define RT_DWARF_2 94
#define RT_DYNAMITE_KEG 505
#define RT_DYNLETH 532
#define RT_EARTH_ELEMENTAL 209
#define RT_EARTH_ELEMENTAL_2 476
#define RT_EARTH_MEPHIT 292
#define RT_EEL 35
#define RT_EFREETI 101
#define RT_EFREETI_2 320
#define RT_ELDDAR 489
#define RT_ELEMENTAL 75
#define RT_ELK_HEAD 714
#define RT_ELVEN_BOAT 544
#define RT_ELVEN_GHOST 587
#define RT_ENCHANTED_ARMOR 175
#define RT_EROLLISI 150
#define RT_ERUDITE 3
#define RT_ERUDITE_2 78
#define RT_ERUDITE_3 678
#define RT_EVAN_TEST 204
#define RT_EVIL_EYE 21
#define RT_EVIL_EYE_2 375
#define RT_EVIL_EYE_3 469
#define RT_EXOSKELETON 570
#define RT_EXPLOSIVE_CART 692
#define RT_EYE 108
#define RT_FAIRY 25
#define RT_FAIRY_2 473
#define RT_FALLEN_KNIGHT 719
#define RT_FAUN 182
#define RT_FAY_DRAKE 154
#define RT_FENNIN_RO 284
#define RT_FERAN 410
#define RT_FERAN_MOUNT 623
#define RT_FIEND 300
#define RT_FIRE_ELEMENTAL 212
#define RT_FIRE_ELEMENTAL_2 477
#define RT_FIRE_MEPHIT 293
#define RT_FISH 24
#define RT_FISH_2 148
#define RT_FLAG 501
#define RT_FLOATING_ISLAND 596
#define RT_FLOATING_SKULL 512
#define RT_FLOATING_TOWER 691
#define RT_FLY 245
#define RT_FLYING_CARPET 720
#define RT_FOREST_GIANT 490
#define RT_FROG 343
#define RT_FROG_2 603
#define RT_FROGLOK 26
#define RT_FROGLOK_2 27
#define RT_FROGLOK_3 330
#define RT_FROGLOK_GHOST 371
#define RT_FROGLOK_SKELETON 349
#define RT_FUNGAL_FIEND 218
#define RT_FUNGUS_PATCH 463
#define RT_FUNGUSMAN 28
#define RT_GALORIAN 228
#define RT_GARGOYLE 29
#define RT_GARGOYLE_2 464
#define RT_GASBAG 30
#define RT_GELATINOUS_CUBE 31
#define RT_GELATINOUS_CUBE_2 712
#define RT_GELIDRAN 417
#define RT_GENARI 648
#define RT_GEONID 178
#define RT_GHOST 32
#define RT_GHOST_2 117
#define RT_GHOST_3 118
#define RT_GHOST_4 334
#define RT_GHOST_SHIP 114
#define RT_GHOST_SHIP_2 552
#define RT_GHOUL 33
#define RT_GHOUL_2 571
#define RT_GIANT 18
#define RT_GIANT_2 140
#define RT_GIANT_3 188
#define RT_GIANT_4 189
#define RT_GIANT_5 306
#define RT_GIANT_6 307
#define RT_GIANT_7 308
#define RT_GIANT_8 309
#define RT_GIANT_9 310
#define RT_GIANT_10 311
#define RT_GIANT_11 312
#define RT_GIANT_12 453
#define RT_GIANT_13 523
#define RT_GIANT_CLOCKWORK 275
#define RT_GIANT_RALLOSIAN_MATS 626
#define RT_GIANT_SHADE 526
#define RT_GIGYN 649
#define RT_GINGERBREAD_MAN 666
#define RT_GIRPLAN 419
#define RT_GNOLL 39
#define RT_GNOLL_2 524
#define RT_GNOLL_3 617
#define RT_GNOME 12
#define RT_GNOMEWORK 457
#define RT_GNOMISH_BALLOON 683
#define RT_GNOMISH_BOAT 545
#define RT_GNOMISH_HOVERING_TRANSPORT 685
#define RT_GNOMISH_ROCKET_PACK 684
#define RT_GOBLIN 40
#define RT_GOBLIN_2 59
#define RT_GOBLIN_3 137
#define RT_GOBLIN_4 369
#define RT_GOBLIN_5 433
#define RT_GOD_LUCLIN_VER_2 728
#define RT_GOD_LUCLIN_VER_3 729
#define RT_GOD_LUCLIN_VER_4 731
#define RT_GOD_OF_DISCORD 622
#define RT_GOLEM 17
#define RT_GOLEM_2 374
#define RT_GOO 145
#define RT_GOO_2 547
#define RT_GOO_3 548
#define RT_GOO_4 549
#define RT_GORAL 687
#define RT_GORAL_MOUNT 673
#define RT_GORGON 121
#define RT_GORILLA 41
#define RT_GORILLA_2 560
#define RT_GRANDFATHER_CLOCK 665
#define RT_GREKEN_YOUNG 651
#define RT_GREKEN_YOUNG_ADULT 650
#define RT_GRENDLAEN 701
#define RT_GRIEG_VENEFICUS 231
#define RT_GRIFFIN 47
#define RT_GRIFFIN_2 525
#define RT_GRIMLING 202
#define RT_GROUND_SHAKER 233
#define RT_GUARD 44
#define RT_GUARD_2 106
#define RT_GUARD_3 112
#define RT_GUARD_4 239
#define RT_GUARD_OF_JUSTICE 251
#define RT_GUARDIAN_CPU 593
#define RT_HADAL 698
#define RT_HAG 185
#define RT_HALF_ELF 7
#define RT_HALFLING 11
#define RT_HALFLING_2 81
#define RT_HARPY 111
#define RT_HARPY_2 527
#define RT_HIGH_ELF 5
#define RT_HIPPOGRIFF 186
#define RT_HOLGRESH 168
#define RT_HOLGRESH_2 715
#define RT_HONEY_POT 536
#define RT_HORSE 216
#define RT_HORSE_2 492
#define RT_HORSE_3 518
#define RT_HOVERING_PLATFORM 699
#define RT_HRAQUIS 261
#define RT_HUMAN 1
#define RT_HUMAN_2 67
#define RT_HUMAN_3 71
#define RT_HUMAN_4 566
#define RT_HUMAN_GHOST 588
#define RT_HUVUL 400
#define RT_HYDRA_CRYSTAL 615
#define RT_HYDRA_MOUNT 631
#define RT_HYDRA_NPC 632
#define RT_HYNID 388
#define RT_ICE_SPECTRE 174
#define RT_IKAAV 394
#define RT_IKSAR 128
#define RT_IKSAR_2 139
#define RT_IKSAR_GHOST 605
#define RT_IKSAR_GOLEM 160
#define RT_IKSAR_SKELETON 606
#define RT_IKSAR_SPIRIT 147
#define RT_IMP 46
#define RT_INNORUUK 123
#define RT_INSECT 370
#define RT_INTERACTIVE_OBJECT 2250
#define RT_INVISIBLE_MAN 127
#define RT_INVISIBLE_MAN_2 681
#define RT_INVISIBLE_MAN_3 690
#define RT_INVISIBLE_MAN_OF_ZOMM 600
#define RT_IXT 393
#define RT_JOKESTER 384
#define RT_JUM_JUM_BUCKET 537
#define RT_JUNK_BEAST 273
#define RT_KANGON 689
#define RT_KANGON_MOUNT 677
#define RT_KARANA 278
#define RT_KEDGE 103
#define RT_KEDGE_2 561
#define RT_KERRAN 23
#define RT_KERRAN_2 562
#define RT_KIRIN 434
#define RT_KIRIN_2 583
#define RT_KNIGHT_OF_HATE 351
#define RT_KNIGHT_OF_PESTILENCE 266
#define RT_KOBOLD 48
#define RT_KOBOLD_2 455
#define RT_KRAKEN 315
#define RT_KYV 396
#define RT_LAUNCH 73
#define RT_LAVA_ROCK 447
#define RT_LAVA_SPIDER 450
#define RT_LAVA_SPIDER_QUEEN 451
#define RT_LEECH 104
#define RT_LEPERTOLOTH 267
#define RT_LIGHTCRAWLER 223
#define RT_LIGHTNING_WARRIOR 407
#define RT_LION 50
#define RT_LIZARD_MAN 51
#define RT_LUCLIN 724
#define RT_LUGGALD 345
#define RT_LUGGALD_2 346
#define RT_LUGGALDS 347
#define RT_MALARIAN 265
#define RT_MAMMOTH 107
#define RT_MAMMOTH_2 528
#define RT_MAN_EATING_PLANT 162
#define RT_MANSION 595
#define RT_MANTICORE 172
#define RT_MANTRAP 573
#define RT_MARIONETTE 659
#define RT_MASTRUQ 402
#define RT_MATA_MURAM 406
#define RT_MEDIUM_PLANT 541
#define RT_MEPHIT 607
#define RT_MERCHANT_SHIP 550
#define RT_MERMAID 110
#define RT_MIMIC 52
#define RT_MINI_POM 252
#define RT_MINOTAUR 53
#define RT_MINOTAUR_2 420
#define RT_MINOTAUR_3 470
#define RT_MINOTAUR_4 574
#define RT_MITHANIEL_MARR 296
#define RT_MORELL_THULE 658
#define RT_MOSQUITO 134
#define RT_MOUTH_OF_INSANITY 281
#define RT_MUDDITE 608
#define RT_MUMMY 368
#define RT_MURAMITE_ARMOR_PILE 424
#define RT_MURKGLIDER 414
#define RT_MURKGLIDER_EGG_SAC 429
#define RT_MUTNA 401
#define RT_NEKHON 614
#define RT_NETHERBIAN 229
#define RT_NIGHTMARE 287
#define RT_NIGHTMARE_GARGOYLE 280
#define RT_NIGHTMARE_GOBLIN 277
#define RT_NIGHTMARE_MEPHIT 294
#define RT_NIGHTMARE_UNICORN 517
#define RT_NIGHTMARE_UNICORN_2 519
#define RT_NIGHTMARE_WRAITH 264
#define RT_NIHIL 385
#define RT_NILBORIEN 317
#define RT_NOC 397
#define RT_NYMPH 242
#define RT_OGRE 10
#define RT_OGRE_2 93
#define RT_OGRE_NPC_MALE 624
#define RT_ORB 730
#define RT_ORC 54
#define RT_ORC_2 458
#define RT_OTHMIR 190
#define RT_OWLBEAR 206
#define RT_PARASITIC_SCAVENGER 700
#define RT_PEGASUS 125
#define RT_PEGASUS_2 493
#define RT_PEGASUS_3 732
#define RT_PHOENIX 303
#define RT_PIRANHA 74
#define RT_PIRATE 335
#define RT_PIRATE_2 336
#define RT_PIRATE_3 337
#define RT_PIRATE_4 338
#define RT_PIRATE_5 339
#define RT_PIRATE_6 340
#define RT_PIRATE_7 341
#define RT_PIRATE_8 342
#define RT_PIRATE_SHIP 551
#define RT_PIXIE 56
#define RT_POISON_FROG 316
#define RT_PORTAL 426
#define RT_POWDER_KEG 636
#define RT_PRESSURE_PLATE 506
#define RT_PUFFER_SPORE 507
#define RT_PUMA 76
#define RT_PUMA_2 439
#define RT_PUMA_3 584
#define RT_PUSLING 270
#define RT_PYRILEN 411
#define RT_RA_TUK 398
#define RT_RABBIT 668
#define RT_RALLOS_ZEK 66
#define RT_RALLOS_ZEK_2 288
#define RT_RALLOS_ZEK_MINION 325
#define RT_RAPTOR 163
#define RT_RAPTOR_2 609
#define RT_RAPTOR_MOUNT 680
#define RT_RAT 36
#define RT_RAT_2 415
#define RT_RAT_MOUNT 656
#define RT_RATMAN 156
#define RT_RATMAN_2 718
#define RT_REANIMATED_HAND 80
#define RT_RECUSO 237
#define RT_REGENERATION_POOL 705
#define RT_RELIC_CASE 707
#define RT_RHINO_BEETLE 207
#define RT_RHINOCEROS 135
#define RT_ROBOCOPTER_OF_ZOMM 601
#define RT_ROCK_PILE 428
#define RT_ROCKHOPPER 200
#define RT_RONNIE_TEST 197
#define RT_ROOT_TENTACLE 509
#define RT_ROT_DOG_MOUNT 672
#define RT_ROTDOG 662
#define RT_ROTOCOPTER 577
#define RT_ROWBOAT 502
#define RT_ROYAL_GUARD 667
#define RT_RUJARKIAN_ORC 361
#define RT_RUJARKIAN_ORC_2 366
#define RT_RUNED_ORB 422
#define RT_RUNIC_SYMBOL 510
#define RT_SABER_TOOTHED_CAT 119
#define RT_SALTPETTER_BOMB 511
#define RT_SAND_ELF 364
#define RT_SANDMAN 664
#define RT_SARNAK 131
#define RT_SARNAK_2 610
#define RT_SARNAK_GOLEM 164
#define RT_SARNAK_SPIRIT 146
#define RT_SARYRN 283
#define RT_SATYR 529
#define RT_SCALED_WOLF 481
#define RT_SCARECROW 82
#define RT_SCARECROW_2 575
#define RT_SCARLET_CHEETAH 221
#define RT_SCLERA_MOUNT 675
#define RT_SCORPION 129
#define RT_SCORPION_2 149
#define RT_SCORPION_3 611
#define RT_SCRYKIN 495
#define RT_SEA_TURTLE 194
#define RT_SEAHORSE 116
#define RT_SELYRAH 686
#define RT_SELYRAH_MOUNT 674
#define RT_SERU 236
#define RT_SERVANT_OF_SHADOW 723
#define RT_SESSILOID_MOUNT 657
#define RT_SHADE 224
#define RT_SHADE_2 373
#define RT_SHADE_3 576
#define RT_SHADEL 205
#define RT_SHAMBLING_MOUND 494
#define RT_SHARK 61
#define RT_SHIKNAR 199
#define RT_SHILISKIN 467
#define RT_SHIP 72
#define RT_SHIP_IN_A_BOTTLE 702
#define RT_SHISSAR 217
#define RT_SHISSAR_2 563
#define RT_SHRIEKER 227
#define RT_SIREN 187
#define RT_SIREN_2 564
#define RT_SKELETAL_HORSE 282
#define RT_SKELETON 60
#define RT_SKELETON_2 367
#define RT_SKELETON_3 484
#define RT_SKUNK 83
#define RT_SKYSTRIDER 709
#define RT_SMALL_PLANT 540
#define RT_SNAKE 37
#define RT_SNAKE_2 468
#define RT_SNAKE_ELEMENTAL 84
#define RT_SNOW_DERVISH 170
#define RT_SNOW_RABBIT 176
#define RT_SOKOKAR 618
#define RT_SOKOKAR_MOUNT 625
#define RT_SOKOKAR_W_SADDLE 627
#define RT_SOLUSEK_RO 58
#define RT_SOLUSEK_RO_2 247
#define RT_SOLUSEK_RO_GUARD 254
#define RT_SONIC_WOLF 232
#define RT_SOUL_DEVOURER 286
#define RT_SPECTRE 85
#define RT_SPECTRE_2 485
#define RT_SPELL_PARTICLE_1 599
#define RT_SPHINX 86
#define RT_SPHINX_2 565
#define RT_SPIDER 38
#define RT_SPIDER_2 440
#define RT_SPIDER_EGG_SACK 449
#define RT_SPIDER_MOUNT 654
#define RT_SPIDER_QUEEN 441
#define RT_SPIKE_TRAP 513
#define RT_SPIRIT_WOLF 483
#define RT_SPORALI 456
#define RT_STONE_JUG 539
#define RT_STONE_PYLON 619
#define RT_STONE_RING 508
#define RT_STONE_WORKER 387
#define RT_STONE_WORKER_2 405
#define RT_STONEGRABBER 220
#define RT_STONEMITE 391
#define RT_STORMRIDER 272
#define RT_SUCCUBUS 408
#define RT_SUCCULENT 167
#define RT_SULLON_ZEK 499
#define RT_SUN_REVENANT 226
#define RT_SUNFLOWER 225
#define RT_SWINETOR 696
#define RT_SWORDFISH 105
#define RT_SYNARCANA 363
#define RT_TABLE 380
#define RT_TADPOLE 102
#define RT_TAELOSIAN 403
#define RT_TALL_PLANT 542
#define RT_TALLON_ZEK 290
#define RT_TANETH 399
#define RT_TAREW_MARR 246
#define RT_TEGI 215
#define RT_TELEPORT_MAN 240
#define RT_TELEPORTATION_STAND 706
#define RT_TELMIRA 653
#define RT_TENTACLE_TERROR 68
#define RT_TENTACLE_TERROR_2 578
#define RT_TERRIS_THULE 257
#define RT_TEST_OBJECT 301
#define RT_THE_RATHE 298
#define RT_THE_TRIBUNAL 256
#define RT_THOUGHT_HORROR 214
#define RT_TIGER 63
#define RT_TIN_SOLDIER 263
#define RT_TOOLBOX 538
#define RT_TOPIARY_LION 661
#define RT_TOPIARY_LION_MOUNT 671
#define RT_TORMENTOR 285
#define RT_TOTEM 173
#define RT_TOTEM_2 514
#define RT_TRAKANON 19
#define RT_TRANQUILION 262
#define RT_TREANT 64
#define RT_TREANT_2 244
#define RT_TREANT_3 496
#define RT_TRIBUNAL 151
#define RT_TRIUMVIRATE 697
#define RT_TROLL 9
#define RT_TROLL_2 92
#define RT_TROLL_3 331
#define RT_TROLL_4 332
#define RT_TROLL_5 333
#define RT_TROLL_ZOMBIE 344
#define RT_TRUSIK 386
#define RT_TSETSIAN 612
#define RT_TUMBLEWEED 694
#define RT_TUNARE 62
#define RT_TUREPTA 389
#define RT_UKUN 392
#define RT_ULTHORK 191
#define RT_UNDEAD_CHOKIDAI 357
#define RT_UNDEAD_FOOTMAN 324
#define RT_UNDEAD_FROGLOK 350
#define RT_UNDEAD_IKSAR 161
#define RT_UNDEAD_KNIGHT 297
#define RT_UNDEAD_SARNAK 155
#define RT_UNDEAD_VEKSAR 358
#define RT_UNDERBULK 201
#define RT_UNICORN 124
#define RT_UNKNOWN_RACE 0
#define RT_UNKNOWN_RACE_2 142
#define RT_UNKNOWN_RACE_3 143
#define RT_UNKNOWN_RACE_4 179
#define RT_UNKNOWN_RACE_5 180
#define RT_UNKNOWN_RACE_6 443
#define RT_UNKNOWN_RACE_7 444
#define RT_VAH_SHIR 130
#define RT_VAH_SHIR_2 238
#define RT_VAH_SHIR_SKELETON 234
#define RT_VALLON_ZEK 289
#define RT_VALORIAN 318
#define RT_VALORIAN_2 322
#define RT_VAMPIRE 65
#define RT_VAMPIRE_2 98
#define RT_VAMPIRE_3 208
#define RT_VAMPIRE_4 219
#define RT_VAMPIRE_5 359
#define RT_VAMPIRE_6 360
#define RT_VAMPIRE_7 365
#define RT_VAMPIRE_8 497
#define RT_VASE 379
#define RT_VEGEROG 258
#define RT_VEKSAR 353
#define RT_VEKSAR_2 354
#define RT_VEKSAR_3 355
#define RT_VENRIL_SATHIR 20
#define RT_VINE_MAW 717
#define RT_WAGON 621
#define RT_WALRUS 177
#define RT_WAR_BOAR 319
#define RT_WAR_BOAR_2 321
#define RT_WAR_WRAITH 313
#define RT_WASP 109
#define RT_WATER_ELEMENTAL 211
#define RT_WATER_ELEMENTAL_2 478
#define RT_WATER_MEPHIT 271
#define RT_WATER_SPOUT 710
#define RT_WEAPON_RACK 381
#define RT_WEAPON_RACK_2 534
#define RT_WEB 515
#define RT_WEDDING_ALTAR 635
#define RT_WEDDING_ARBOR 634
#define RT_WEDDING_FLOWERS 633
#define RT_WEREORC 579
#define RT_WEREWOLF 14
#define RT_WEREWOLF_2 241
#define RT_WEREWOLF_3 454
#define RT_WETFANG_MINNOW 213
#define RT_WHIRLIGIG 682
#define RT_WICKER_BASKET 516
#define RT_WILL_O_WISP 69
#define RT_WINE_CASK 543
#define RT_WINE_CASK_2 630
#define RT_WITHERAN 465
#define RT_WITHERAN_2 474
#define RT_WOLF 42
#define RT_WOLF_2 120
#define RT_WOLF_3 482
#define RT_WOOD_ELF 4
#define RT_WORG 580
#define RT_WORG_2 594
#define RT_WORM 203
#define RT_WRETCH 235
#define RT_WRULON 314
#define RT_WRULON_2 598
#define RT_WURM 158
#define RT_WURM_2 613
#define RT_WURM_MOUNT 679
#define RT_WYVERN 157
#define RT_WYVERN_2 581
#define RT_XALGOZ 136
#define RT_XARIC_THE_UNSPOKEN 725
#define RT_XEGONY 299
#define RT_YAKKAR 181
#define RT_YETI 138
#define RT_ZEBUXORUK 295
#define RT_ZEBUXORUKS_CAGE 328
#define RT_ZELNIAK 222
#define RT_ZOMBIE 70
#define RT_ZOMBIE_2 471
const char* GetRaceIDName(uint16 race_id);
const char* GetPlayerRaceName(uint32 player_race_value);

View File

@ -392,15 +392,13 @@ RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)
RULE_INT(Combat, MeleeBaseCritChance, 0) //The base crit chance for non warriors, NOTE: This will apply to NPCs as well
RULE_INT(Combat, WarBerBaseCritChance, 3) //The base crit chance for warriors and berserkers, only applies to clients
RULE_INT(Combat, BerserkBaseCritChance, 6) //The bonus base crit chance you get when you're berserk
RULE_INT(Combat, PetBaseCritChance, 0) // Pet Base crit chance
RULE_INT(Combat, NPCBashKickLevel, 6) //The level that npcs can KICK/BASH
RULE_INT(Combat, NPCBashKickStunChance, 15) //Percent chance that a bash/kick will stun
RULE_INT(Combat, RogueCritThrowingChance, 25) //Rogue throwing crit bonus
RULE_INT(Combat, RogueDeadlyStrikeChance, 80) //Rogue chance throwing from behind crit becomes a deadly strike
RULE_INT(Combat, RogueDeadlyStrikeMod, 2) //Deadly strike modifier to crit damage
RULE_INT(Combat, ClientBaseCritChance, 0) //The base crit chance for all clients, this will stack with warrior's/zerker's crit chance.
RULE_INT(Combat, MeleeCritDifficulty, 8900) // lower is easier
RULE_INT(Combat, ArcheryCritDifficulty, 3400) // lower is easier
RULE_INT(Combat, ThrowingCritDifficulty, 1100) // lower is easier
RULE_BOOL(Combat, NPCCanCrit, false) // true allows non PC pet NPCs to crit
RULE_BOOL(Combat, UseIntervalAC, true)
RULE_INT(Combat, PetAttackMagicLevel, 30)
RULE_BOOL(Combat, EnableFearPathing, true)
@ -492,6 +490,7 @@ RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist a
RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space
RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF
RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't
RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system
RULE_CATEGORY_END()
RULE_CATEGORY(NPC)

View File

@ -1136,13 +1136,13 @@ const EQEmu::ItemData* SharedDatabase::IterateItems(uint32* id) {
return nullptr;
}
std::string SharedDatabase::GetBook(const char *txtfile)
std::string SharedDatabase::GetBook(const char *txtfile, int16 *language)
{
char txtfile2[20];
std::string txtout;
strcpy(txtfile2, txtfile);
std::string query = StringFormat("SELECT txtfile FROM books WHERE name = '%s'", txtfile2);
std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2);
auto results = QueryDatabase(query);
if (!results.Success()) {
txtout.assign(" ",1);
@ -1157,6 +1157,7 @@ std::string SharedDatabase::GetBook(const char *txtfile)
auto row = results.begin();
txtout.assign(row[0],strlen(row[0]));
*language = static_cast<int16>(atoi(row[1]));
return txtout;
}

View File

@ -94,7 +94,7 @@ class SharedDatabase : public Database
bool SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
std::string GetBook(const char *txtfile);
std::string GetBook(const char *txtfile, int16 *language);
/*
Item Methods

View File

@ -124,6 +124,30 @@ bool EQEmu::skills::IsCastingSkill(SkillType skill)
}
}
int32 EQEmu::skills::GetBaseDamage(SkillType skill)
{
switch (skill) {
case SkillBash:
return 2;
case SkillDragonPunch:
return 12;
case SkillEagleStrike:
return 7;
case SkillFlyingKick:
return 25;
case SkillKick:
return 3;
case SkillRoundKick:
return 5;
case SkillTigerClaw:
return 4;
case SkillFrenzy:
return 10;
default:
return 0;
}
}
const std::map<EQEmu::skills::SkillType, std::string>& EQEmu::skills::GetSkillTypeMap()
{
/* VS2013 code

View File

@ -166,6 +166,7 @@ namespace EQEmu
float GetSkillMeleePushForce(SkillType skill);
bool IsBardInstrumentSkill(SkillType skill);
bool IsCastingSkill(SkillType skill);
int32 GetBaseDamage(SkillType skill);
extern const std::map<SkillType, std::string>& GetSkillTypeMap();

View File

@ -67,11 +67,59 @@ const int SpellTypes_Beneficial = SpellType_Heal|SpellType_Buff|SpellType_Escape
#define SpellType_Any 0xFFFF
// These should not be used to determine spell category..
// They are a graphical affects (effects?) index only
// TODO: import sai list
enum SpellAffectIndex {
SAI_Calm = 12, // Lull and Alliance Spells
SAI_Dispell_Sight = 14, // Dispells and Spells like Bind Sight
SAI_Memory_Blur = 27,
SAI_Calm_Song = 43 // Lull and Alliance Songs
SAI_Summon_Mount_Unclass = -1,
SAI_Direct_Damage = 0,
SAI_Heal_Cure = 1,
SAI_AC_Buff = 2,
SAI_AE_Damage = 3,
SAI_Summon = 4, // Summoned Pets and Items
SAI_Sight = 5,
SAI_Mana_Regen_Resist_Song = 6,
SAI_Stat_Buff = 7,
SAI_Vanish = 9, // Invisibility and Gate/Port
SAI_Appearance = 10, // Illusion and Size
SAI_Enchanter_Pet = 11,
SAI_Calm = 12, // Lull and Alliance Spells
SAI_Fear = 13,
SAI_Dispell_Sight = 14, // Dispells and Spells like Bind Sight
SAI_Stun = 15,
SAI_Haste_Runspeed = 16, // Haste and SoW
SAI_Combat_Slow = 17,
SAI_Damage_Shield = 18,
SAI_Cannibalize_Weapon_Proc = 19,
SAI_Weaken = 20,
SAI_Banish = 21,
SAI_Blind_Poison = 22,
SAI_Cold_DD = 23,
SAI_Poison_Disease_DD = 24,
SAI_Fire_DD = 25,
SAI_Memory_Blur = 27,
SAI_Gravity_Fling = 28,
SAI_Suffocate = 29,
SAI_Lifetap_Over_Time = 30,
SAI_Fire_AE = 31,
SAI_Cold_AE = 33,
SAI_Poison_Disease_AE = 34,
SAI_Teleport = 40,
SAI_Direct_Damage_Song = 41,
SAI_Combat_Buff_Song = 42,
SAI_Calm_Song = 43, // Lull and Alliance Songs
SAI_Firework = 45,
SAI_Firework_AE = 46,
SAI_Weather_Rocket = 47,
SAI_Convert_Vitals = 50,
SAI_NPC_Special_60 = 60,
SAI_NPC_Special_61 = 61,
SAI_NPC_Special_62 = 62,
SAI_NPC_Special_63 = 63,
SAI_NPC_Special_70 = 70,
SAI_NPC_Special_71 = 71,
SAI_NPC_Special_80 = 80,
SAI_Trap_Lock = 88
};
enum RESISTTYPE
{

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9101
#define CURRENT_BINARY_DATABASE_VERSION 9103
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008
#else

115
utils/combat-sim/app.js Normal file
View File

@ -0,0 +1,115 @@
var app = angular.module('app', ['nvd3']);
app.controller('MainCtrl', function($scope, $interval) {
$scope.options = {
chart: {
type: 'discreteBarChart',
height: 450,
margin: {
top: 20,
right: 20,
bottom: 50,
left: 55
},
x: function(d) {
return d.label;
},
y: function(d) {
return d.value + (1e-10);
},
showValues: true,
valueFormat: function(d) {
return d3.format(',.2r')(d);
},
duration: 500,
xAxis: {
axisLabel: 'D1-D20'
},
yAxis: {
axisLabel: 'Count'
}
}
};
$scope.offense = 100;
$scope.mitigation = 100;
$scope.data = [{
key: "Cumulative Return",
values: []
}];
for (var i = 0; i < 20; ++i) {
var value = {
"label": i + 1,
"value": 0
};
$scope.data[0].values.push(value);
}
function addRoll(interval) {
$scope.data[0].values[interval - 1].value += 1;
}
var stop;
$scope.clearData = function() {
console.log('Clearing data');
for (var i = 0; i < 20; ++i) {
$scope.data[0].values[i].value = 0;
}
};
$scope.start = function() {
if (angular.isDefined(stop))
return;
stop = $interval(doCombatRound, 100);
};
$scope.stop = function() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
$scope.$on('$destroy', function() {
$scope.stop();
});
var damage_mods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
function getRandom(min, max) {
return Math.random() * (max - min) + min;
}
function addChance(bucket, chance, value) {
for (var i = 0; i < chance; ++i) {
bucket.push(value);
}
}
function doCombatRound() {
var offense = getRandomInt(0, $scope.offense + 5);
var mitigation = getRandomInt(0, $scope.mitigation + 5);
var avg = parseInt(($scope.offense + $scope.mitigation + 10) / 2);
var index = parseInt((offense - mitigation) + (avg / 2));
if (index < 0) {
index = 0;
}
index = parseInt((index * 20) / avg);
if (index >= 20)
index = 19;
if (index < 0)
index = 0;
var roll = damage_mods[index];
addRoll(roll);
};
});

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>Combat Visualization</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-nvd3/1.0.5/angular-nvd3.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<nvd3 options="options" data="data"></nvd3>
<button ng-click=clearData()>Clear Data</button>
<button ng-click=start()>Start</button>
<button ng-click=stop()>Stop</button>
<div class="input-row">
<label>Offense:</label>
<input type="number" name="Offense" ng-model="offense"></input>
</div>
<div class="input-row">
<label>Mitigation:</label>
<input type="number" name="mitigation" ng-model="mitigation"></input>
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
.input-row {
padding: 8px;
}

View File

@ -0,0 +1,57 @@
DELIMITER $$
DROP FUNCTION IF EXISTS `GetBodyTypeToken`;
-- This function converts a numeric body type to a string label based on server code designations
-- Note: A preceeding '*' indicates a non-client verified token
--
-- example:
-- SELECT `id`, `name`, GetBodyTypeToken(`bodytype`) FROM `npc_types` WHERE `id` IN ('116539', '154086', '164042');
CREATE FUNCTION `GetBodyTypeToken` (`body_type` INT(11)) RETURNS VARCHAR(64)
BEGIN
DECLARE `token` VARCHAR(64) DEFAULT '';
CASE `body_type`
WHEN '1' THEN SET `token` = 'BT_Humanoid';
WHEN '2' THEN SET `token` = 'BT_Lycanthrope';
WHEN '3' THEN SET `token` = 'BT_Undead';
WHEN '4' THEN SET `token` = 'BT_Giant';
WHEN '5' THEN SET `token` = 'BT_Construct';
WHEN '6' THEN SET `token` = 'BT_Extraplanar';
WHEN '7' THEN SET `token` = 'BT_Magical';
WHEN '8' THEN SET `token` = '*BT_SummonedUndead';
WHEN '9' THEN SET `token` = '*BT_RaidGiant';
WHEN '11' THEN SET `token` = '*BT_NoTarget';
WHEN '12' THEN SET `token` = 'BT_Vampyre';
WHEN '13' THEN SET `token` = 'BT_Atenha_Ra';
WHEN '14' THEN SET `token` = 'BT_Greater_Akheva';
WHEN '15' THEN SET `token` = 'BT_Khati_Sha';
WHEN '16' THEN SET `token` = '*BT_Seru';
WHEN '18' THEN SET `token` = 'BT_Draz_Nurakk';
WHEN '19' THEN SET `token` = 'BT_Zek';
WHEN '20' THEN SET `token` = 'BT_Luggald';
WHEN '21' THEN SET `token` = 'BT_Animal';
WHEN '22' THEN SET `token` = 'BT_Insect';
WHEN '23' THEN SET `token` = 'BT_Monster';
WHEN '24' THEN SET `token` = 'BT_Elemental/*BT_Summoned';
WHEN '25' THEN SET `token` = 'BT_Plant';
WHEN '26' THEN SET `token` = 'BT_Dragon';
WHEN '27' THEN SET `token` = '*BT_Summoned2';
WHEN '28' THEN SET `token` = 'BT_Summoned_Creature/*BT_Summoned3';
WHEN '30' THEN SET `token` = '*BT_VeliousDragon';
WHEN '32' THEN SET `token` = '*BT_Dragon3';
WHEN '33' THEN SET `token` = '*BT_Boxes';
WHEN '34' THEN SET `token` = 'BT_Muramite';
WHEN '60' THEN SET `token` = '*BT_NoTarget2';
WHEN '63' THEN SET `token` = '*BT_SwarmPet';
WHEN '66' THEN SET `token` = '*BT_InvisMan';
WHEN '67' THEN SET `token` = '*BT_Special';
ELSE SET `token` = 'BT_UNKNOWN_BODYTYPE';
END CASE;
SET `token` = CONCAT(`token`, '(', `body_type`, ')');
RETURN `token`;
END$$
DELIMITER ;

View File

@ -0,0 +1,756 @@
DELIMITER $$
DROP FUNCTION IF EXISTS `GetRaceToken`;
-- This function converts a numeric race id to a string label based on server code designations
--
-- example:
-- SELECT `id`, `name`, GetRaceToken(`race`) FROM `npc_types` WHERE `id` IN ('644', '105153', '261131');
CREATE FUNCTION `GetRaceToken` (`race_id` INT(11)) RETURNS VARCHAR(64)
BEGIN
DECLARE `token` VARCHAR(64) DEFAULT '';
CASE `race_id`
WHEN '0' THEN SET `token` = 'UNKNOWN RACE';
WHEN '1' THEN SET `token` = 'Human';
WHEN '2' THEN SET `token` = 'Barbarian';
WHEN '3' THEN SET `token` = 'Erudite';
WHEN '4' THEN SET `token` = 'Wood Elf';
WHEN '5' THEN SET `token` = 'High Elf';
WHEN '6' THEN SET `token` = 'Dark Elf';
WHEN '7' THEN SET `token` = 'Half Elf';
WHEN '8' THEN SET `token` = 'Dwarf';
WHEN '9' THEN SET `token` = 'Troll';
WHEN '10' THEN SET `token` = 'Ogre';
WHEN '11' THEN SET `token` = 'Halfling';
WHEN '12' THEN SET `token` = 'Gnome';
WHEN '13' THEN SET `token` = 'Aviak';
WHEN '14' THEN SET `token` = 'Werewolf';
WHEN '15' THEN SET `token` = 'Brownie';
WHEN '16' THEN SET `token` = 'Centaur';
WHEN '17' THEN SET `token` = 'Golem';
WHEN '18' THEN SET `token` = 'Giant';
WHEN '19' THEN SET `token` = 'Trakanon';
WHEN '20' THEN SET `token` = 'Venril Sathir';
WHEN '21' THEN SET `token` = 'Evil Eye';
WHEN '22' THEN SET `token` = 'Beetle';
WHEN '23' THEN SET `token` = 'Kerran';
WHEN '24' THEN SET `token` = 'Fish';
WHEN '25' THEN SET `token` = 'Fairy';
WHEN '26' THEN SET `token` = 'Froglok';
WHEN '27' THEN SET `token` = 'Froglok';
WHEN '28' THEN SET `token` = 'Fungusman';
WHEN '29' THEN SET `token` = 'Gargoyle';
WHEN '30' THEN SET `token` = 'Gasbag';
WHEN '31' THEN SET `token` = 'Gelatinous Cube';
WHEN '32' THEN SET `token` = 'Ghost';
WHEN '33' THEN SET `token` = 'Ghoul';
WHEN '34' THEN SET `token` = 'Bat';
WHEN '35' THEN SET `token` = 'Eel';
WHEN '36' THEN SET `token` = 'Rat';
WHEN '37' THEN SET `token` = 'Snake';
WHEN '38' THEN SET `token` = 'Spider';
WHEN '39' THEN SET `token` = 'Gnoll';
WHEN '40' THEN SET `token` = 'Goblin';
WHEN '41' THEN SET `token` = 'Gorilla';
WHEN '42' THEN SET `token` = 'Wolf';
WHEN '43' THEN SET `token` = 'Bear';
WHEN '44' THEN SET `token` = 'Guard';
WHEN '45' THEN SET `token` = 'Demi Lich';
WHEN '46' THEN SET `token` = 'Imp';
WHEN '47' THEN SET `token` = 'Griffin';
WHEN '48' THEN SET `token` = 'Kobold';
WHEN '49' THEN SET `token` = 'Dragon';
WHEN '50' THEN SET `token` = 'Lion';
WHEN '51' THEN SET `token` = 'Lizard Man';
WHEN '52' THEN SET `token` = 'Mimic';
WHEN '53' THEN SET `token` = 'Minotaur';
WHEN '54' THEN SET `token` = 'Orc';
WHEN '55' THEN SET `token` = 'Beggar';
WHEN '56' THEN SET `token` = 'Pixie';
WHEN '57' THEN SET `token` = 'Drachnid';
WHEN '58' THEN SET `token` = 'Solusek Ro';
WHEN '59' THEN SET `token` = 'Goblin';
WHEN '60' THEN SET `token` = 'Skeleton';
WHEN '61' THEN SET `token` = 'Shark';
WHEN '62' THEN SET `token` = 'Tunare';
WHEN '63' THEN SET `token` = 'Tiger';
WHEN '64' THEN SET `token` = 'Treant';
WHEN '65' THEN SET `token` = 'Vampire';
WHEN '66' THEN SET `token` = 'Rallos Zek';
WHEN '67' THEN SET `token` = 'Human';
WHEN '68' THEN SET `token` = 'Tentacle Terror';
WHEN '69' THEN SET `token` = 'Will-O-Wisp';
WHEN '70' THEN SET `token` = 'Zombie';
WHEN '71' THEN SET `token` = 'Human';
WHEN '72' THEN SET `token` = 'Ship';
WHEN '73' THEN SET `token` = 'Launch';
WHEN '74' THEN SET `token` = 'Piranha';
WHEN '75' THEN SET `token` = 'Elemental';
WHEN '76' THEN SET `token` = 'Puma';
WHEN '77' THEN SET `token` = 'Dark Elf';
WHEN '78' THEN SET `token` = 'Erudite';
WHEN '79' THEN SET `token` = 'Bixie';
WHEN '80' THEN SET `token` = 'Reanimated Hand';
WHEN '81' THEN SET `token` = 'Halfling';
WHEN '82' THEN SET `token` = 'Scarecrow';
WHEN '83' THEN SET `token` = 'Skunk';
WHEN '84' THEN SET `token` = 'Snake Elemental';
WHEN '85' THEN SET `token` = 'Spectre';
WHEN '86' THEN SET `token` = 'Sphinx';
WHEN '87' THEN SET `token` = 'Armadillo';
WHEN '88' THEN SET `token` = 'Clockwork Gnome';
WHEN '89' THEN SET `token` = 'Drake';
WHEN '90' THEN SET `token` = 'Barbarian';
WHEN '91' THEN SET `token` = 'Alligator';
WHEN '92' THEN SET `token` = 'Troll';
WHEN '93' THEN SET `token` = 'Ogre';
WHEN '94' THEN SET `token` = 'Dwarf';
WHEN '95' THEN SET `token` = 'Cazic Thule';
WHEN '96' THEN SET `token` = 'Cockatrice';
WHEN '97' THEN SET `token` = 'Daisy Man';
WHEN '98' THEN SET `token` = 'Vampire';
WHEN '99' THEN SET `token` = 'Amygdalan';
WHEN '100' THEN SET `token` = 'Dervish';
WHEN '101' THEN SET `token` = 'Efreeti';
WHEN '102' THEN SET `token` = 'Tadpole';
WHEN '103' THEN SET `token` = 'Kedge';
WHEN '104' THEN SET `token` = 'Leech';
WHEN '105' THEN SET `token` = 'Swordfish';
WHEN '106' THEN SET `token` = 'Guard';
WHEN '107' THEN SET `token` = 'Mammoth';
WHEN '108' THEN SET `token` = 'Eye';
WHEN '109' THEN SET `token` = 'Wasp';
WHEN '110' THEN SET `token` = 'Mermaid';
WHEN '111' THEN SET `token` = 'Harpy';
WHEN '112' THEN SET `token` = 'Guard';
WHEN '113' THEN SET `token` = 'Drixie';
WHEN '114' THEN SET `token` = 'Ghost Ship';
WHEN '115' THEN SET `token` = 'Clam';
WHEN '116' THEN SET `token` = 'Seahorse';
WHEN '117' THEN SET `token` = 'Ghost';
WHEN '118' THEN SET `token` = 'Ghost';
WHEN '119' THEN SET `token` = 'Saber-toothed Cat';
WHEN '120' THEN SET `token` = 'Wolf';
WHEN '121' THEN SET `token` = 'Gorgon';
WHEN '122' THEN SET `token` = 'Dragon';
WHEN '123' THEN SET `token` = 'Innoruuk';
WHEN '124' THEN SET `token` = 'Unicorn';
WHEN '125' THEN SET `token` = 'Pegasus';
WHEN '126' THEN SET `token` = 'Djinn';
WHEN '127' THEN SET `token` = 'Invisible Man';
WHEN '128' THEN SET `token` = 'Iksar';
WHEN '129' THEN SET `token` = 'Scorpion';
WHEN '130' THEN SET `token` = 'Vah Shir';
WHEN '131' THEN SET `token` = 'Sarnak';
WHEN '132' THEN SET `token` = 'Draglock';
WHEN '133' THEN SET `token` = 'Drolvarg';
WHEN '134' THEN SET `token` = 'Mosquito';
WHEN '135' THEN SET `token` = 'Rhinoceros';
WHEN '136' THEN SET `token` = 'Xalgoz';
WHEN '137' THEN SET `token` = 'Goblin';
WHEN '138' THEN SET `token` = 'Yeti';
WHEN '139' THEN SET `token` = 'Iksar';
WHEN '140' THEN SET `token` = 'Giant';
WHEN '141' THEN SET `token` = 'Boat';
WHEN '142' THEN SET `token` = 'UNKNOWN RACE';
WHEN '143' THEN SET `token` = 'UNKNOWN RACE';
WHEN '144' THEN SET `token` = 'Burynai';
WHEN '145' THEN SET `token` = 'Goo';
WHEN '146' THEN SET `token` = 'Sarnak Spirit';
WHEN '147' THEN SET `token` = 'Iksar Spirit';
WHEN '148' THEN SET `token` = 'Fish';
WHEN '149' THEN SET `token` = 'Scorpion';
WHEN '150' THEN SET `token` = 'Erollisi';
WHEN '151' THEN SET `token` = 'Tribunal';
WHEN '152' THEN SET `token` = 'Bertoxxulous';
WHEN '153' THEN SET `token` = 'Bristlebane';
WHEN '154' THEN SET `token` = 'Fay Drake';
WHEN '155' THEN SET `token` = 'Undead Sarnak';
WHEN '156' THEN SET `token` = 'Ratman';
WHEN '157' THEN SET `token` = 'Wyvern';
WHEN '158' THEN SET `token` = 'Wurm';
WHEN '159' THEN SET `token` = 'Devourer';
WHEN '160' THEN SET `token` = 'Iksar Golem';
WHEN '161' THEN SET `token` = 'Undead Iksar';
WHEN '162' THEN SET `token` = 'Man-Eating Plant';
WHEN '163' THEN SET `token` = 'Raptor';
WHEN '164' THEN SET `token` = 'Sarnak Golem';
WHEN '165' THEN SET `token` = 'Dragon';
WHEN '166' THEN SET `token` = 'Animated Hand';
WHEN '167' THEN SET `token` = 'Succulent';
WHEN '168' THEN SET `token` = 'Holgresh';
WHEN '169' THEN SET `token` = 'Brontotherium';
WHEN '170' THEN SET `token` = 'Snow Dervish';
WHEN '171' THEN SET `token` = 'Dire Wolf';
WHEN '172' THEN SET `token` = 'Manticore';
WHEN '173' THEN SET `token` = 'Totem';
WHEN '174' THEN SET `token` = 'Ice Spectre';
WHEN '175' THEN SET `token` = 'Enchanted Armor';
WHEN '176' THEN SET `token` = 'Snow Rabbit';
WHEN '177' THEN SET `token` = 'Walrus';
WHEN '178' THEN SET `token` = 'Geonid';
WHEN '179' THEN SET `token` = 'UNKNOWN RACE';
WHEN '180' THEN SET `token` = 'UNKNOWN RACE';
WHEN '181' THEN SET `token` = 'Yakkar';
WHEN '182' THEN SET `token` = 'Faun';
WHEN '183' THEN SET `token` = 'Coldain';
WHEN '184' THEN SET `token` = 'Dragon';
WHEN '185' THEN SET `token` = 'Hag';
WHEN '186' THEN SET `token` = 'Hippogriff';
WHEN '187' THEN SET `token` = 'Siren';
WHEN '188' THEN SET `token` = 'Giant';
WHEN '189' THEN SET `token` = 'Giant';
WHEN '190' THEN SET `token` = 'Othmir';
WHEN '191' THEN SET `token` = 'Ulthork';
WHEN '192' THEN SET `token` = 'Dragon';
WHEN '193' THEN SET `token` = 'Abhorrent';
WHEN '194' THEN SET `token` = 'Sea Turtle';
WHEN '195' THEN SET `token` = 'Dragon';
WHEN '196' THEN SET `token` = 'Dragon';
WHEN '197' THEN SET `token` = 'Ronnie Test';
WHEN '198' THEN SET `token` = 'Dragon';
WHEN '199' THEN SET `token` = 'Shik\'Nar';
WHEN '200' THEN SET `token` = 'Rockhopper';
WHEN '201' THEN SET `token` = 'Underbulk';
WHEN '202' THEN SET `token` = 'Grimling';
WHEN '203' THEN SET `token` = 'Worm';
WHEN '204' THEN SET `token` = 'Evan Test';
WHEN '205' THEN SET `token` = 'Shadel';
WHEN '206' THEN SET `token` = 'Owlbear';
WHEN '207' THEN SET `token` = 'Rhino Beetle';
WHEN '208' THEN SET `token` = 'Vampire';
WHEN '209' THEN SET `token` = 'Earth Elemental';
WHEN '210' THEN SET `token` = 'Air Elemental';
WHEN '211' THEN SET `token` = 'Water Elemental';
WHEN '212' THEN SET `token` = 'Fire Elemental';
WHEN '213' THEN SET `token` = 'Wetfang Minnow';
WHEN '214' THEN SET `token` = 'Thought Horror';
WHEN '215' THEN SET `token` = 'Tegi';
WHEN '216' THEN SET `token` = 'Horse';
WHEN '217' THEN SET `token` = 'Shissar';
WHEN '218' THEN SET `token` = 'Fungal Fiend';
WHEN '219' THEN SET `token` = 'Vampire';
WHEN '220' THEN SET `token` = 'Stonegrabber';
WHEN '221' THEN SET `token` = 'Scarlet Cheetah';
WHEN '222' THEN SET `token` = 'Zelniak';
WHEN '223' THEN SET `token` = 'Lightcrawler';
WHEN '224' THEN SET `token` = 'Shade';
WHEN '225' THEN SET `token` = 'Sunflower';
WHEN '226' THEN SET `token` = 'Sun Revenant';
WHEN '227' THEN SET `token` = 'Shrieker';
WHEN '228' THEN SET `token` = 'Galorian';
WHEN '229' THEN SET `token` = 'Netherbian';
WHEN '230' THEN SET `token` = 'Akheva';
WHEN '231' THEN SET `token` = 'Grieg Veneficus';
WHEN '232' THEN SET `token` = 'Sonic Wolf';
WHEN '233' THEN SET `token` = 'Ground Shaker';
WHEN '234' THEN SET `token` = 'Vah Shir Skeleton';
WHEN '235' THEN SET `token` = 'Wretch';
WHEN '236' THEN SET `token` = 'Seru';
WHEN '237' THEN SET `token` = 'Recuso';
WHEN '238' THEN SET `token` = 'Vah Shir';
WHEN '239' THEN SET `token` = 'Guard';
WHEN '240' THEN SET `token` = 'Teleport Man';
WHEN '241' THEN SET `token` = 'Werewolf';
WHEN '242' THEN SET `token` = 'Nymph';
WHEN '243' THEN SET `token` = 'Dryad';
WHEN '244' THEN SET `token` = 'Treant';
WHEN '245' THEN SET `token` = 'Fly';
WHEN '246' THEN SET `token` = 'Tarew Marr';
WHEN '247' THEN SET `token` = 'Solusek Ro';
WHEN '248' THEN SET `token` = 'Clockwork Golem';
WHEN '249' THEN SET `token` = 'Clockwork Brain';
WHEN '250' THEN SET `token` = 'Banshee';
WHEN '251' THEN SET `token` = 'Guard of Justice';
WHEN '252' THEN SET `token` = 'Mini POM';
WHEN '253' THEN SET `token` = 'Diseased Fiend';
WHEN '254' THEN SET `token` = 'Solusek Ro Guard';
WHEN '255' THEN SET `token` = 'Bertoxxulous';
WHEN '256' THEN SET `token` = 'The Tribunal';
WHEN '257' THEN SET `token` = 'Terris Thule';
WHEN '258' THEN SET `token` = 'Vegerog';
WHEN '259' THEN SET `token` = 'Crocodile';
WHEN '260' THEN SET `token` = 'Bat';
WHEN '261' THEN SET `token` = 'Hraquis';
WHEN '262' THEN SET `token` = 'Tranquilion';
WHEN '263' THEN SET `token` = 'Tin Soldier';
WHEN '264' THEN SET `token` = 'Nightmare Wraith';
WHEN '265' THEN SET `token` = 'Malarian';
WHEN '266' THEN SET `token` = 'Knight of Pestilence';
WHEN '267' THEN SET `token` = 'Lepertoloth';
WHEN '268' THEN SET `token` = 'Bubonian';
WHEN '269' THEN SET `token` = 'Bubonian Underling';
WHEN '270' THEN SET `token` = 'Pusling';
WHEN '271' THEN SET `token` = 'Water Mephit';
WHEN '272' THEN SET `token` = 'Stormrider';
WHEN '273' THEN SET `token` = 'Junk Beast';
WHEN '274' THEN SET `token` = 'Broken Clockwork';
WHEN '275' THEN SET `token` = 'Giant Clockwork';
WHEN '276' THEN SET `token` = 'Clockwork Beetle';
WHEN '277' THEN SET `token` = 'Nightmare Goblin';
WHEN '278' THEN SET `token` = 'Karana';
WHEN '279' THEN SET `token` = 'Blood Raven';
WHEN '280' THEN SET `token` = 'Nightmare Gargoyle';
WHEN '281' THEN SET `token` = 'Mouth of Insanity';
WHEN '282' THEN SET `token` = 'Skeletal Horse';
WHEN '283' THEN SET `token` = 'Saryrn';
WHEN '284' THEN SET `token` = 'Fennin Ro';
WHEN '285' THEN SET `token` = 'Tormentor';
WHEN '286' THEN SET `token` = 'Soul Devourer';
WHEN '287' THEN SET `token` = 'Nightmare';
WHEN '288' THEN SET `token` = 'Rallos Zek';
WHEN '289' THEN SET `token` = 'Vallon Zek';
WHEN '290' THEN SET `token` = 'Tallon Zek';
WHEN '291' THEN SET `token` = 'Air Mephit';
WHEN '292' THEN SET `token` = 'Earth Mephit';
WHEN '293' THEN SET `token` = 'Fire Mephit';
WHEN '294' THEN SET `token` = 'Nightmare Mephit';
WHEN '295' THEN SET `token` = 'Zebuxoruk';
WHEN '296' THEN SET `token` = 'Mithaniel Marr';
WHEN '297' THEN SET `token` = 'Undead Knight';
WHEN '298' THEN SET `token` = 'The Rathe';
WHEN '299' THEN SET `token` = 'Xegony';
WHEN '300' THEN SET `token` = 'Fiend';
WHEN '301' THEN SET `token` = 'Test Object';
WHEN '302' THEN SET `token` = 'Crab';
WHEN '303' THEN SET `token` = 'Phoenix';
WHEN '304' THEN SET `token` = 'Dragon';
WHEN '305' THEN SET `token` = 'Bear';
WHEN '306' THEN SET `token` = 'Giant';
WHEN '307' THEN SET `token` = 'Giant';
WHEN '308' THEN SET `token` = 'Giant';
WHEN '309' THEN SET `token` = 'Giant';
WHEN '310' THEN SET `token` = 'Giant';
WHEN '311' THEN SET `token` = 'Giant';
WHEN '312' THEN SET `token` = 'Giant';
WHEN '313' THEN SET `token` = 'War Wraith';
WHEN '314' THEN SET `token` = 'Wrulon';
WHEN '315' THEN SET `token` = 'Kraken';
WHEN '316' THEN SET `token` = 'Poison Frog';
WHEN '317' THEN SET `token` = 'Nilborien';
WHEN '318' THEN SET `token` = 'Valorian';
WHEN '319' THEN SET `token` = 'War Boar';
WHEN '320' THEN SET `token` = 'Efreeti';
WHEN '321' THEN SET `token` = 'War Boar';
WHEN '322' THEN SET `token` = 'Valorian';
WHEN '323' THEN SET `token` = 'Animated Armor';
WHEN '324' THEN SET `token` = 'Undead Footman';
WHEN '325' THEN SET `token` = 'Rallos Zek Minion';
WHEN '326' THEN SET `token` = 'Arachnid';
WHEN '327' THEN SET `token` = 'Crystal Spider';
WHEN '328' THEN SET `token` = 'Zebuxoruk\'s Cage';
WHEN '329' THEN SET `token` = 'BoT Portal';
WHEN '330' THEN SET `token` = 'Froglok';
WHEN '331' THEN SET `token` = 'Troll';
WHEN '332' THEN SET `token` = 'Troll';
WHEN '333' THEN SET `token` = 'Troll';
WHEN '334' THEN SET `token` = 'Ghost';
WHEN '335' THEN SET `token` = 'Pirate';
WHEN '336' THEN SET `token` = 'Pirate';
WHEN '337' THEN SET `token` = 'Pirate';
WHEN '338' THEN SET `token` = 'Pirate';
WHEN '339' THEN SET `token` = 'Pirate';
WHEN '340' THEN SET `token` = 'Pirate';
WHEN '341' THEN SET `token` = 'Pirate';
WHEN '342' THEN SET `token` = 'Pirate';
WHEN '343' THEN SET `token` = 'Frog';
WHEN '344' THEN SET `token` = 'Troll Zombie';
WHEN '345' THEN SET `token` = 'Luggald';
WHEN '346' THEN SET `token` = 'Luggald';
WHEN '347' THEN SET `token` = 'Luggalds';
WHEN '348' THEN SET `token` = 'Drogmore';
WHEN '349' THEN SET `token` = 'Froglok Skeleton';
WHEN '350' THEN SET `token` = 'Undead Froglok';
WHEN '351' THEN SET `token` = 'Knight of Hate';
WHEN '352' THEN SET `token` = 'Arcanist of Hate';
WHEN '353' THEN SET `token` = 'Veksar';
WHEN '354' THEN SET `token` = 'Veksar';
WHEN '355' THEN SET `token` = 'Veksar';
WHEN '356' THEN SET `token` = 'Chokidai';
WHEN '357' THEN SET `token` = 'Undead Chokidai';
WHEN '358' THEN SET `token` = 'Undead Veksar';
WHEN '359' THEN SET `token` = 'Vampire';
WHEN '360' THEN SET `token` = 'Vampire';
WHEN '361' THEN SET `token` = 'Rujarkian Orc';
WHEN '362' THEN SET `token` = 'Bone Golem';
WHEN '363' THEN SET `token` = 'Synarcana';
WHEN '364' THEN SET `token` = 'Sand Elf';
WHEN '365' THEN SET `token` = 'Vampire';
WHEN '366' THEN SET `token` = 'Rujarkian Orc';
WHEN '367' THEN SET `token` = 'Skeleton';
WHEN '368' THEN SET `token` = 'Mummy';
WHEN '369' THEN SET `token` = 'Goblin';
WHEN '370' THEN SET `token` = 'Insect';
WHEN '371' THEN SET `token` = 'Froglok Ghost';
WHEN '372' THEN SET `token` = 'Dervish';
WHEN '373' THEN SET `token` = 'Shade';
WHEN '374' THEN SET `token` = 'Golem';
WHEN '375' THEN SET `token` = 'Evil Eye';
WHEN '376' THEN SET `token` = 'Box';
WHEN '377' THEN SET `token` = 'Barrel';
WHEN '378' THEN SET `token` = 'Chest';
WHEN '379' THEN SET `token` = 'Vase';
WHEN '380' THEN SET `token` = 'Table';
WHEN '381' THEN SET `token` = 'Weapon Rack';
WHEN '382' THEN SET `token` = 'Coffin';
WHEN '383' THEN SET `token` = 'Bones';
WHEN '384' THEN SET `token` = 'Jokester';
WHEN '385' THEN SET `token` = 'Nihil';
WHEN '386' THEN SET `token` = 'Trusik';
WHEN '387' THEN SET `token` = 'Stone Worker';
WHEN '388' THEN SET `token` = 'Hynid';
WHEN '389' THEN SET `token` = 'Turepta';
WHEN '390' THEN SET `token` = 'Cragbeast';
WHEN '391' THEN SET `token` = 'Stonemite';
WHEN '392' THEN SET `token` = 'Ukun';
WHEN '393' THEN SET `token` = 'Ixt';
WHEN '394' THEN SET `token` = 'Ikaav';
WHEN '395' THEN SET `token` = 'Aneuk';
WHEN '396' THEN SET `token` = 'Kyv';
WHEN '397' THEN SET `token` = 'Noc';
WHEN '398' THEN SET `token` = 'Ra`tuk';
WHEN '399' THEN SET `token` = 'Taneth';
WHEN '400' THEN SET `token` = 'Huvul';
WHEN '401' THEN SET `token` = 'Mutna';
WHEN '402' THEN SET `token` = 'Mastruq';
WHEN '403' THEN SET `token` = 'Taelosian';
WHEN '404' THEN SET `token` = 'Discord Ship';
WHEN '405' THEN SET `token` = 'Stone Worker';
WHEN '406' THEN SET `token` = 'Mata Muram';
WHEN '407' THEN SET `token` = 'Lightning Warrior';
WHEN '408' THEN SET `token` = 'Succubus';
WHEN '409' THEN SET `token` = 'Bazu';
WHEN '410' THEN SET `token` = 'Feran';
WHEN '411' THEN SET `token` = 'Pyrilen';
WHEN '412' THEN SET `token` = 'Chimera';
WHEN '413' THEN SET `token` = 'Dragorn';
WHEN '414' THEN SET `token` = 'Murkglider';
WHEN '415' THEN SET `token` = 'Rat';
WHEN '416' THEN SET `token` = 'Bat';
WHEN '417' THEN SET `token` = 'Gelidran';
WHEN '418' THEN SET `token` = 'Discordling';
WHEN '419' THEN SET `token` = 'Girplan';
WHEN '420' THEN SET `token` = 'Minotaur';
WHEN '421' THEN SET `token` = 'Dragorn Box';
WHEN '422' THEN SET `token` = 'Runed Orb';
WHEN '423' THEN SET `token` = 'Dragon Bones';
WHEN '424' THEN SET `token` = 'Muramite Armor Pile';
WHEN '425' THEN SET `token` = 'Crystal Shard';
WHEN '426' THEN SET `token` = 'Portal';
WHEN '427' THEN SET `token` = 'Coin Purse';
WHEN '428' THEN SET `token` = 'Rock Pile';
WHEN '429' THEN SET `token` = 'Murkglider Egg Sac';
WHEN '430' THEN SET `token` = 'Drake';
WHEN '431' THEN SET `token` = 'Dervish';
WHEN '432' THEN SET `token` = 'Drake';
WHEN '433' THEN SET `token` = 'Goblin';
WHEN '434' THEN SET `token` = 'Kirin';
WHEN '435' THEN SET `token` = 'Dragon';
WHEN '436' THEN SET `token` = 'Basilisk';
WHEN '437' THEN SET `token` = 'Dragon';
WHEN '438' THEN SET `token` = 'Dragon';
WHEN '439' THEN SET `token` = 'Puma';
WHEN '440' THEN SET `token` = 'Spider';
WHEN '441' THEN SET `token` = 'Spider Queen';
WHEN '442' THEN SET `token` = 'Animated Statue';
WHEN '443' THEN SET `token` = 'UNKNOWN RACE';
WHEN '444' THEN SET `token` = 'UNKNOWN RACE';
WHEN '445' THEN SET `token` = 'Dragon Egg';
WHEN '446' THEN SET `token` = 'Dragon Statue';
WHEN '447' THEN SET `token` = 'Lava Rock';
WHEN '448' THEN SET `token` = 'Animated Statue';
WHEN '449' THEN SET `token` = 'Spider Egg Sack';
WHEN '450' THEN SET `token` = 'Lava Spider';
WHEN '451' THEN SET `token` = 'Lava Spider Queen';
WHEN '452' THEN SET `token` = 'Dragon';
WHEN '453' THEN SET `token` = 'Giant';
WHEN '454' THEN SET `token` = 'Werewolf';
WHEN '455' THEN SET `token` = 'Kobold';
WHEN '456' THEN SET `token` = 'Sporali';
WHEN '457' THEN SET `token` = 'Gnomework';
WHEN '458' THEN SET `token` = 'Orc';
WHEN '459' THEN SET `token` = 'Corathus';
WHEN '460' THEN SET `token` = 'Coral';
WHEN '461' THEN SET `token` = 'Drachnid';
WHEN '462' THEN SET `token` = 'Drachnid Cocoon';
WHEN '463' THEN SET `token` = 'Fungus Patch';
WHEN '464' THEN SET `token` = 'Gargoyle';
WHEN '465' THEN SET `token` = 'Witheran';
WHEN '466' THEN SET `token` = 'Dark Lord';
WHEN '467' THEN SET `token` = 'Shiliskin';
WHEN '468' THEN SET `token` = 'Snake';
WHEN '469' THEN SET `token` = 'Evil Eye';
WHEN '470' THEN SET `token` = 'Minotaur';
WHEN '471' THEN SET `token` = 'Zombie';
WHEN '472' THEN SET `token` = 'Clockwork Boar';
WHEN '473' THEN SET `token` = 'Fairy';
WHEN '474' THEN SET `token` = 'Witheran';
WHEN '475' THEN SET `token` = 'Air Elemental';
WHEN '476' THEN SET `token` = 'Earth Elemental';
WHEN '477' THEN SET `token` = 'Fire Elemental';
WHEN '478' THEN SET `token` = 'Water Elemental';
WHEN '479' THEN SET `token` = 'Alligator';
WHEN '480' THEN SET `token` = 'Bear';
WHEN '481' THEN SET `token` = 'Scaled Wolf';
WHEN '482' THEN SET `token` = 'Wolf';
WHEN '483' THEN SET `token` = 'Spirit Wolf';
WHEN '484' THEN SET `token` = 'Skeleton';
WHEN '485' THEN SET `token` = 'Spectre';
WHEN '486' THEN SET `token` = 'Bolvirk';
WHEN '487' THEN SET `token` = 'Banshee';
WHEN '488' THEN SET `token` = 'Banshee';
WHEN '489' THEN SET `token` = 'Elddar';
WHEN '490' THEN SET `token` = 'Forest Giant';
WHEN '491' THEN SET `token` = 'Bone Golem';
WHEN '492' THEN SET `token` = 'Horse';
WHEN '493' THEN SET `token` = 'Pegasus';
WHEN '494' THEN SET `token` = 'Shambling Mound';
WHEN '495' THEN SET `token` = 'Scrykin';
WHEN '496' THEN SET `token` = 'Treant';
WHEN '497' THEN SET `token` = 'Vampire';
WHEN '498' THEN SET `token` = 'Ayonae Ro';
WHEN '499' THEN SET `token` = 'Sullon Zek';
WHEN '500' THEN SET `token` = 'Banner';
WHEN '501' THEN SET `token` = 'Flag';
WHEN '502' THEN SET `token` = 'Rowboat';
WHEN '503' THEN SET `token` = 'Bear Trap';
WHEN '504' THEN SET `token` = 'Clockwork Bomb';
WHEN '505' THEN SET `token` = 'Dynamite Keg';
WHEN '506' THEN SET `token` = 'Pressure Plate';
WHEN '507' THEN SET `token` = 'Puffer Spore';
WHEN '508' THEN SET `token` = 'Stone Ring';
WHEN '509' THEN SET `token` = 'Root Tentacle';
WHEN '510' THEN SET `token` = 'Runic Symbol';
WHEN '511' THEN SET `token` = 'Saltpetter Bomb';
WHEN '512' THEN SET `token` = 'Floating Skull';
WHEN '513' THEN SET `token` = 'Spike Trap';
WHEN '514' THEN SET `token` = 'Totem';
WHEN '515' THEN SET `token` = 'Web';
WHEN '516' THEN SET `token` = 'Wicker Basket';
WHEN '517' THEN SET `token` = 'Nightmare/Unicorn';
WHEN '518' THEN SET `token` = 'Horse';
WHEN '519' THEN SET `token` = 'Nightmare/Unicorn';
WHEN '520' THEN SET `token` = 'Bixie';
WHEN '521' THEN SET `token` = 'Centaur';
WHEN '522' THEN SET `token` = 'Drakkin';
WHEN '523' THEN SET `token` = 'Giant';
WHEN '524' THEN SET `token` = 'Gnoll';
WHEN '525' THEN SET `token` = 'Griffin';
WHEN '526' THEN SET `token` = 'Giant Shade';
WHEN '527' THEN SET `token` = 'Harpy';
WHEN '528' THEN SET `token` = 'Mammoth';
WHEN '529' THEN SET `token` = 'Satyr';
WHEN '530' THEN SET `token` = 'Dragon';
WHEN '531' THEN SET `token` = 'Dragon';
WHEN '532' THEN SET `token` = 'Dyn\'Leth';
WHEN '533' THEN SET `token` = 'Boat';
WHEN '534' THEN SET `token` = 'Weapon Rack';
WHEN '535' THEN SET `token` = 'Armor Rack';
WHEN '536' THEN SET `token` = 'Honey Pot';
WHEN '537' THEN SET `token` = 'Jum Jum Bucket';
WHEN '538' THEN SET `token` = 'Toolbox';
WHEN '539' THEN SET `token` = 'Stone Jug';
WHEN '540' THEN SET `token` = 'Small Plant';
WHEN '541' THEN SET `token` = 'Medium Plant';
WHEN '542' THEN SET `token` = 'Tall Plant';
WHEN '543' THEN SET `token` = 'Wine Cask';
WHEN '544' THEN SET `token` = 'Elven Boat';
WHEN '545' THEN SET `token` = 'Gnomish Boat';
WHEN '546' THEN SET `token` = 'Barrel Barge Ship';
WHEN '547' THEN SET `token` = 'Goo';
WHEN '548' THEN SET `token` = 'Goo';
WHEN '549' THEN SET `token` = 'Goo';
WHEN '550' THEN SET `token` = 'Merchant Ship';
WHEN '551' THEN SET `token` = 'Pirate Ship';
WHEN '552' THEN SET `token` = 'Ghost Ship';
WHEN '553' THEN SET `token` = 'Banner';
WHEN '554' THEN SET `token` = 'Banner';
WHEN '555' THEN SET `token` = 'Banner';
WHEN '556' THEN SET `token` = 'Banner';
WHEN '557' THEN SET `token` = 'Banner';
WHEN '558' THEN SET `token` = 'Aviak';
WHEN '559' THEN SET `token` = 'Beetle';
WHEN '560' THEN SET `token` = 'Gorilla';
WHEN '561' THEN SET `token` = 'Kedge';
WHEN '562' THEN SET `token` = 'Kerran';
WHEN '563' THEN SET `token` = 'Shissar';
WHEN '564' THEN SET `token` = 'Siren';
WHEN '565' THEN SET `token` = 'Sphinx';
WHEN '566' THEN SET `token` = 'Human';
WHEN '567' THEN SET `token` = 'Campfire';
WHEN '568' THEN SET `token` = 'Brownie';
WHEN '569' THEN SET `token` = 'Dragon';
WHEN '570' THEN SET `token` = 'Exoskeleton';
WHEN '571' THEN SET `token` = 'Ghoul';
WHEN '572' THEN SET `token` = 'Clockwork Guardian';
WHEN '573' THEN SET `token` = 'Mantrap';
WHEN '574' THEN SET `token` = 'Minotaur';
WHEN '575' THEN SET `token` = 'Scarecrow';
WHEN '576' THEN SET `token` = 'Shade';
WHEN '577' THEN SET `token` = 'Rotocopter';
WHEN '578' THEN SET `token` = 'Tentacle Terror';
WHEN '579' THEN SET `token` = 'Wereorc';
WHEN '580' THEN SET `token` = 'Worg';
WHEN '581' THEN SET `token` = 'Wyvern';
WHEN '582' THEN SET `token` = 'Chimera';
WHEN '583' THEN SET `token` = 'Kirin';
WHEN '584' THEN SET `token` = 'Puma';
WHEN '585' THEN SET `token` = 'Boulder';
WHEN '586' THEN SET `token` = 'Banner';
WHEN '587' THEN SET `token` = 'Elven Ghost';
WHEN '588' THEN SET `token` = 'Human Ghost';
WHEN '589' THEN SET `token` = 'Chest';
WHEN '590' THEN SET `token` = 'Chest';
WHEN '591' THEN SET `token` = 'Crystal';
WHEN '592' THEN SET `token` = 'Coffin';
WHEN '593' THEN SET `token` = 'Guardian CPU';
WHEN '594' THEN SET `token` = 'Worg';
WHEN '595' THEN SET `token` = 'Mansion';
WHEN '596' THEN SET `token` = 'Floating Island';
WHEN '597' THEN SET `token` = 'Cragslither';
WHEN '598' THEN SET `token` = 'Wrulon';
WHEN '599' THEN SET `token` = 'Spell Particle 1';
WHEN '600' THEN SET `token` = 'Invisible Man of Zomm';
WHEN '601' THEN SET `token` = 'Robocopter of Zomm';
WHEN '602' THEN SET `token` = 'Burynai';
WHEN '603' THEN SET `token` = 'Frog';
WHEN '604' THEN SET `token` = 'Dracolich';
WHEN '605' THEN SET `token` = 'Iksar Ghost';
WHEN '606' THEN SET `token` = 'Iksar Skeleton';
WHEN '607' THEN SET `token` = 'Mephit';
WHEN '608' THEN SET `token` = 'Muddite';
WHEN '609' THEN SET `token` = 'Raptor';
WHEN '610' THEN SET `token` = 'Sarnak';
WHEN '611' THEN SET `token` = 'Scorpion';
WHEN '612' THEN SET `token` = 'T THEN SET sian';
WHEN '613' THEN SET `token` = 'Wurm';
WHEN '614' THEN SET `token` = 'Nekhon';
WHEN '615' THEN SET `token` = 'Hydra Crystal';
WHEN '616' THEN SET `token` = 'Crystal Sphere';
WHEN '617' THEN SET `token` = 'Gnoll';
WHEN '618' THEN SET `token` = 'Sokokar';
WHEN '619' THEN SET `token` = 'Stone Pylon';
WHEN '620' THEN SET `token` = 'Demon Vulture';
WHEN '621' THEN SET `token` = 'Wagon';
WHEN '622' THEN SET `token` = 'God of Discord';
WHEN '623' THEN SET `token` = 'Feran Mount';
WHEN '624' THEN SET `token` = 'Ogre NPC - Male';
WHEN '625' THEN SET `token` = 'Sokokar Mount';
WHEN '626' THEN SET `token` = 'Giant (Rallosian mats)';
WHEN '627' THEN SET `token` = 'Sokokar (w saddle)';
WHEN '628' THEN SET `token` = '10th Anniversary Banner';
WHEN '629' THEN SET `token` = '10th Anniversary Cake';
WHEN '630' THEN SET `token` = 'Wine Cask';
WHEN '631' THEN SET `token` = 'Hydra Mount';
WHEN '632' THEN SET `token` = 'Hydra NPC';
WHEN '633' THEN SET `token` = 'Wedding Flowers';
WHEN '634' THEN SET `token` = 'Wedding Arbor';
WHEN '635' THEN SET `token` = 'Wedding Altar';
WHEN '636' THEN SET `token` = 'Powder Keg';
WHEN '637' THEN SET `token` = 'Apexus';
WHEN '638' THEN SET `token` = 'Bellikos';
WHEN '639' THEN SET `token` = 'Brell\'s First Creation';
WHEN '640' THEN SET `token` = 'Brell';
WHEN '641' THEN SET `token` = 'Crystalskin Ambuloid';
WHEN '642' THEN SET `token` = 'Cliknar Queen';
WHEN '643' THEN SET `token` = 'Cliknar Soldier';
WHEN '644' THEN SET `token` = 'Cliknar Worker';
WHEN '645' THEN SET `token` = 'Coldain';
WHEN '646' THEN SET `token` = 'Coldain';
WHEN '647' THEN SET `token` = 'Crystalskin Sessiloid';
WHEN '648' THEN SET `token` = 'Genari';
WHEN '649' THEN SET `token` = 'Gigyn';
WHEN '650' THEN SET `token` = 'Greken - Young Adult';
WHEN '651' THEN SET `token` = 'Greken - Young';
WHEN '652' THEN SET `token` = 'Cliknar Mount';
WHEN '653' THEN SET `token` = 'Telmira';
WHEN '654' THEN SET `token` = 'Spider Mount';
WHEN '655' THEN SET `token` = 'Bear Mount';
WHEN '656' THEN SET `token` = 'Rat Mount';
WHEN '657' THEN SET `token` = 'Sessiloid Mount';
WHEN '658' THEN SET `token` = 'Morell Thule';
WHEN '659' THEN SET `token` = 'Marionette';
WHEN '660' THEN SET `token` = 'Book Dervish';
WHEN '661' THEN SET `token` = 'Topiary Lion';
WHEN '662' THEN SET `token` = 'Rotdog';
WHEN '663' THEN SET `token` = 'Amygdalan';
WHEN '664' THEN SET `token` = 'Sandman';
WHEN '665' THEN SET `token` = 'Grandfather Clock';
WHEN '666' THEN SET `token` = 'Gingerbread Man';
WHEN '667' THEN SET `token` = 'Royal Guard';
WHEN '668' THEN SET `token` = 'Rabbit';
WHEN '669' THEN SET `token` = 'Blind Dreamer';
WHEN '670' THEN SET `token` = 'Cazic Thule';
WHEN '671' THEN SET `token` = 'Topiary Lion Mount';
WHEN '672' THEN SET `token` = 'Rot Dog Mount';
WHEN '673' THEN SET `token` = 'Goral Mount';
WHEN '674' THEN SET `token` = 'Selyrah Mount';
WHEN '675' THEN SET `token` = 'Sclera Mount';
WHEN '676' THEN SET `token` = 'Braxi Mount';
WHEN '677' THEN SET `token` = 'Kangon Mount';
WHEN '678' THEN SET `token` = 'Erudite';
WHEN '679' THEN SET `token` = 'Wurm Mount';
WHEN '680' THEN SET `token` = 'Raptor Mount';
WHEN '681' THEN SET `token` = 'Invisible Man';
WHEN '682' THEN SET `token` = 'Whirligig';
WHEN '683' THEN SET `token` = 'Gnomish Balloon';
WHEN '684' THEN SET `token` = 'Gnomish Rocket Pack';
WHEN '685' THEN SET `token` = 'Gnomish Hovering Transport';
WHEN '686' THEN SET `token` = 'Selyrah';
WHEN '687' THEN SET `token` = 'Goral';
WHEN '688' THEN SET `token` = 'Braxi';
WHEN '689' THEN SET `token` = 'Kangon';
WHEN '690' THEN SET `token` = 'Invisible Man';
WHEN '691' THEN SET `token` = 'Floating Tower';
WHEN '692' THEN SET `token` = 'Explosive Cart';
WHEN '693' THEN SET `token` = 'Blimp Ship';
WHEN '694' THEN SET `token` = 'Tumbleweed';
WHEN '695' THEN SET `token` = 'Alaran';
WHEN '696' THEN SET `token` = 'Swinetor';
WHEN '697' THEN SET `token` = 'Triumvirate';
WHEN '698' THEN SET `token` = 'Hadal';
WHEN '699' THEN SET `token` = 'Hovering Platform';
WHEN '700' THEN SET `token` = 'Parasitic Scavenger';
WHEN '701' THEN SET `token` = 'Grendlaen';
WHEN '702' THEN SET `token` = 'Ship in a Bottle';
WHEN '703' THEN SET `token` = 'Alaran Sentry Stone';
WHEN '704' THEN SET `token` = 'Dervish';
WHEN '705' THEN SET `token` = 'Regeneration Pool';
WHEN '706' THEN SET `token` = 'Teleportation Stand';
WHEN '707' THEN SET `token` = 'Relic Case';
WHEN '708' THEN SET `token` = 'Alaran Ghost';
WHEN '709' THEN SET `token` = 'Skystrider';
WHEN '710' THEN SET `token` = 'Water Spout';
WHEN '711' THEN SET `token` = 'Aviak Pull Along';
WHEN '712' THEN SET `token` = 'Gelatinous Cube';
WHEN '713' THEN SET `token` = 'Cat';
WHEN '714' THEN SET `token` = 'Elk Head';
WHEN '715' THEN SET `token` = 'Holgresh';
WHEN '716' THEN SET `token` = 'Beetle';
WHEN '717' THEN SET `token` = 'Vine Maw';
WHEN '718' THEN SET `token` = 'Ratman';
WHEN '719' THEN SET `token` = 'Fallen Knight';
WHEN '720' THEN SET `token` = 'Flying Carpet';
WHEN '721' THEN SET `token` = 'Carrier Hand';
WHEN '722' THEN SET `token` = 'Akheva';
WHEN '723' THEN SET `token` = 'Servant of Shadow';
WHEN '724' THEN SET `token` = 'Luclin';
WHEN '725' THEN SET `token` = 'Xaric the Unspoken';
WHEN '726' THEN SET `token` = 'Dervish (Ver. 5)';
WHEN '727' THEN SET `token` = 'Dervish (Ver. 6)';
WHEN '728' THEN SET `token` = 'God - Luclin (Ver. 2)';
WHEN '729' THEN SET `token` = 'God - Luclin (Ver. 3)';
WHEN '730' THEN SET `token` = 'Orb';
WHEN '731' THEN SET `token` = 'God - Luclin (Ver. 4)';
WHEN '732' THEN SET `token` = 'Pegasus';
WHEN '2250' THEN SET `token` = 'Interactive Object';
ELSE SET `token` = 'unk';
END CASE;
SET `token` = CONCAT(`token`, '(', `race_id`, ')');
RETURN `token`;
END$$
DELIMITER ;

View File

@ -0,0 +1,71 @@
DELIMITER $$
DROP FUNCTION IF EXISTS `GetSpellAffectIndexToken`;
-- This function converts a numeric spell affect index id to a string label based on server code designations
--
-- example:
-- SELECT `id`, `name`, GetSpellAffectIndexToken(`SpellAffectIndex`) FROM `spells_new` WHERE `id` IN ('73', '2253', '2319');
CREATE FUNCTION `GetSpellAffectIndexToken` (`affect_index_id` INT(11)) RETURNS VARCHAR(64)
BEGIN
DECLARE `token` VARCHAR(64) DEFAULT '';
CASE `affect_index_id`
WHEN '-1' THEN SET `token` = 'SAI_Summon_Mount_Unclass';
WHEN '0' THEN SET `token` = 'SAI_Direct_Damage';
WHEN '1' THEN SET `token` = 'SAI_Heal_Cure';
WHEN '2' THEN SET `token` = 'SAI_AC_Buff';
WHEN '3' THEN SET `token` = 'SAI_AE_Damage';
WHEN '4' THEN SET `token` = 'SAI_Summon';
WHEN '5' THEN SET `token` = 'SAI_Sight';
WHEN '6' THEN SET `token` = 'SAI_Mana_Regen_Resist_Song';
WHEN '7' THEN SET `token` = 'SAI_Stat_Buff';
WHEN '9' THEN SET `token` = 'SAI_Vanish';
WHEN '10' THEN SET `token` = 'SAI_Appearance';
WHEN '11' THEN SET `token` = 'SAI_Enchanter_Pet';
WHEN '12' THEN SET `token` = 'SAI_Calm';
WHEN '13' THEN SET `token` = 'SAI_Fear';
WHEN '14' THEN SET `token` = 'SAI_Dispell_Sight';
WHEN '15' THEN SET `token` = 'SAI_Stun';
WHEN '16' THEN SET `token` = 'SAI_Haste_Runspeed';
WHEN '17' THEN SET `token` = 'SAI_Combat_Slow';
WHEN '18' THEN SET `token` = 'SAI_Damage_Shield';
WHEN '19' THEN SET `token` = 'SAI_Cannibalize_Weapon_Proc';
WHEN '20' THEN SET `token` = 'SAI_Weaken';
WHEN '21' THEN SET `token` = 'SAI_Banish';
WHEN '22' THEN SET `token` = 'SAI_Blind_Poison';
WHEN '23' THEN SET `token` = 'SAI_Cold_DD';
WHEN '24' THEN SET `token` = 'SAI_Poison_Disease_DD';
WHEN '25' THEN SET `token` = 'SAI_Fire_DD';
WHEN '27' THEN SET `token` = 'SAI_Memory_Blur';
WHEN '28' THEN SET `token` = 'SAI_Gravity_Fling';
WHEN '29' THEN SET `token` = 'SAI_Suffocate';
WHEN '30' THEN SET `token` = 'SAI_Lifetap_Over_Time';
WHEN '31' THEN SET `token` = 'SAI_Fire_AE';
WHEN '33' THEN SET `token` = 'SAI_Cold_AE';
WHEN '34' THEN SET `token` = 'SAI_Poison_Disease_AE';
WHEN '40' THEN SET `token` = 'SAI_Teleport';
WHEN '41' THEN SET `token` = 'SAI_Direct_Damage_Song';
WHEN '42' THEN SET `token` = 'SAI_Combat_Buff_Song';
WHEN '43' THEN SET `token` = 'SAI_Calm_Song';
WHEN '45' THEN SET `token` = 'SAI_Firework';
WHEN '46' THEN SET `token` = 'SAI_Firework_AE';
WHEN '47' THEN SET `token` = 'SAI_Weather_Rocket';
WHEN '50' THEN SET `token` = 'SAI_Convert_Vitals';
WHEN '60' THEN SET `token` = 'SAI_NPC_Special_60';
WHEN '61' THEN SET `token` = 'SAI_NPC_Special_61';
WHEN '62' THEN SET `token` = 'SAI_NPC_Special_62';
WHEN '63' THEN SET `token` = 'SAI_NPC_Special_63';
WHEN '70' THEN SET `token` = 'SAI_NPC_Special_70';
WHEN '71' THEN SET `token` = 'SAI_NPC_Special_71';
WHEN '80' THEN SET `token` = 'SAI_NPC_Special_80';
WHEN '88' THEN SET `token` = 'SAI_Lock_Trap';
ELSE SET `token` = 'unk';
END CASE;
SET `token` = CONCAT(`token`, '(', `affect_index_id`, ')');
RETURN `token`;
END$$
DELIMITER ;

View File

@ -0,0 +1,519 @@
DELIMITER $$
DROP FUNCTION IF EXISTS `GetSpellEffectToken`;
-- This function converts a numeric spell effect id to a string label based on server code designations
--
-- example:
-- SELECT `id`, `name`, GetSpellEffectToken(`effectid1`), GetSpellEffectToken(`effectid2`) FROM `spells_new` WHERE `id` IN ('1011', '1602', '11091');
CREATE FUNCTION `GetSpellEffectToken` (`effect_id` INT(11)) RETURNS VARCHAR(64)
BEGIN
DECLARE `token` VARCHAR(64) DEFAULT '';
CASE `effect_id`
WHEN '0' THEN SET `token` = 'SE_CurrentHP';
WHEN '1' THEN SET `token` = 'SE_ArmorClass';
WHEN '2' THEN SET `token` = 'SE_ATK';
WHEN '3' THEN SET `token` = 'SE_MovementSpeed';
WHEN '4' THEN SET `token` = 'SE_STR';
WHEN '5' THEN SET `token` = 'SE_DEX';
WHEN '6' THEN SET `token` = 'SE_AGI';
WHEN '7' THEN SET `token` = 'SE_STA';
WHEN '8' THEN SET `token` = 'SE_INT';
WHEN '9' THEN SET `token` = 'SE_WIS';
WHEN '10' THEN SET `token` = 'SE_CHA';
WHEN '11' THEN SET `token` = 'SE_AttackSpeed';
WHEN '12' THEN SET `token` = 'SE_Invisibility';
WHEN '13' THEN SET `token` = 'SE_SeeInvis';
WHEN '14' THEN SET `token` = 'SE_WaterBreathing';
WHEN '15' THEN SET `token` = 'SE_CurrentMana';
WHEN '16' THEN SET `token` = 'NI_NPCFrenzy';
WHEN '17' THEN SET `token` = 'NI_NPCAwareness';
WHEN '18' THEN SET `token` = 'SE_Lull';
WHEN '19' THEN SET `token` = 'SE_AddFaction';
WHEN '20' THEN SET `token` = 'SE_Blind';
WHEN '21' THEN SET `token` = 'SE_Stun';
WHEN '22' THEN SET `token` = 'SE_Charm';
WHEN '23' THEN SET `token` = 'SE_Fear';
WHEN '24' THEN SET `token` = 'SE_Stamina';
WHEN '25' THEN SET `token` = 'SE_BindAffinity';
WHEN '26' THEN SET `token` = 'SE_Gate';
WHEN '27' THEN SET `token` = 'SE_CancelMagic';
WHEN '28' THEN SET `token` = 'SE_InvisVsUndead';
WHEN '29' THEN SET `token` = 'SE_InvisVsAnimals';
WHEN '30' THEN SET `token` = 'SE_ChangeFrenzyRad';
WHEN '31' THEN SET `token` = 'SE_Mez';
WHEN '32' THEN SET `token` = 'SE_SummonItem';
WHEN '33' THEN SET `token` = 'SE_SummonPet';
WHEN '34' THEN SET `token` = 'NI_Confuse';
WHEN '35' THEN SET `token` = 'SE_DiseaseCounter';
WHEN '36' THEN SET `token` = 'SE_PoisonCounter';
WHEN '37' THEN SET `token` = 'NI_DetectHostile';
WHEN '38' THEN SET `token` = 'NI_DetectMagic';
WHEN '39' THEN SET `token` = 'NI_DetectPoison';
WHEN '40' THEN SET `token` = 'SE_DivineAura';
WHEN '41' THEN SET `token` = 'SE_Destroy';
WHEN '42' THEN SET `token` = 'SE_ShadowStep';
WHEN '43' THEN SET `token` = 'SE_Berserk';
WHEN '44' THEN SET `token` = 'SE_Lycanthropy';
WHEN '45' THEN SET `token` = 'SE_Vampirism';
WHEN '46' THEN SET `token` = 'SE_ResistFire';
WHEN '47' THEN SET `token` = 'SE_ResistCold';
WHEN '48' THEN SET `token` = 'SE_ResistPoison';
WHEN '49' THEN SET `token` = 'SE_ResistDisease';
WHEN '50' THEN SET `token` = 'SE_ResistMagic';
WHEN '51' THEN SET `token` = 'NI_DetectTraps';
WHEN '52' THEN SET `token` = 'SE_SenseDead';
WHEN '53' THEN SET `token` = 'SE_SenseSummoned';
WHEN '54' THEN SET `token` = 'SE_SenseAnimals';
WHEN '55' THEN SET `token` = 'SE_Rune';
WHEN '56' THEN SET `token` = 'SE_TrueNorth';
WHEN '57' THEN SET `token` = 'SE_Levitate';
WHEN '58' THEN SET `token` = 'SE_Illusion';
WHEN '59' THEN SET `token` = 'SE_DamageShield';
WHEN '60' THEN SET `token` = 'NI_TransferItem';
WHEN '61' THEN SET `token` = 'SE_Identify';
WHEN '62' THEN SET `token` = 'NI_ItemID';
WHEN '63' THEN SET `token` = 'SE_WipeHateList';
WHEN '64' THEN SET `token` = 'SE_SpinTarget';
WHEN '65' THEN SET `token` = 'SE_InfraVision';
WHEN '66' THEN SET `token` = 'SE_UltraVision';
WHEN '67' THEN SET `token` = 'SE_EyeOfZomm';
WHEN '68' THEN SET `token` = 'SE_ReclaimPet';
WHEN '69' THEN SET `token` = 'SE_TotalHP';
WHEN '70' THEN SET `token` = 'NI_CorpseBomb';
WHEN '71' THEN SET `token` = 'SE_NecPet';
WHEN '72' THEN SET `token` = 'NI_PreserveCorpse';
WHEN '73' THEN SET `token` = 'SE_BindSight';
WHEN '74' THEN SET `token` = 'SE_FeignDeath';
WHEN '75' THEN SET `token` = 'SE_VoiceGraft';
WHEN '76' THEN SET `token` = 'SE_Sentinel';
WHEN '77' THEN SET `token` = 'SE_LocateCorpse';
WHEN '78' THEN SET `token` = 'SE_AbsorbMagicAtt';
WHEN '79' THEN SET `token` = 'SE_CurrentHPOnce';
WHEN '80' THEN SET `token` = 'NI_EnchantLight';
WHEN '81' THEN SET `token` = 'SE_Revive';
WHEN '82' THEN SET `token` = 'SE_SummonPC';
WHEN '83' THEN SET `token` = 'SE_Teleport';
WHEN '84' THEN SET `token` = 'SE_TossUp';
WHEN '85' THEN SET `token` = 'SE_WeaponProc';
WHEN '86' THEN SET `token` = 'SE_Harmony';
WHEN '87' THEN SET `token` = 'SE_MagnifyVision';
WHEN '88' THEN SET `token` = 'SE_Succor';
WHEN '89' THEN SET `token` = 'SE_ModelSize';
WHEN '90' THEN SET `token` = 'NI_Cloak';
WHEN '91' THEN SET `token` = 'SE_SummonCorpse';
WHEN '92' THEN SET `token` = 'SE_InstantHate';
WHEN '93' THEN SET `token` = 'SE_StopRain';
WHEN '94' THEN SET `token` = 'SE_NegateIfCombat';
WHEN '95' THEN SET `token` = 'SE_Sacrifice';
WHEN '96' THEN SET `token` = 'SE_Silence';
WHEN '97' THEN SET `token` = 'SE_ManaPool';
WHEN '98' THEN SET `token` = 'SE_AttackSpeed2';
WHEN '99' THEN SET `token` = 'SE_Root';
WHEN '100' THEN SET `token` = 'SE_HealOverTime';
WHEN '101' THEN SET `token` = 'SE_CompleteHeal';
WHEN '102' THEN SET `token` = 'SE_Fearless';
WHEN '103' THEN SET `token` = 'SE_CallPet';
WHEN '104' THEN SET `token` = 'SE_Translocate';
WHEN '105' THEN SET `token` = 'SE_AntiGate';
WHEN '106' THEN SET `token` = 'SE_SummonBSTPet';
WHEN '107' THEN SET `token` = 'SE_AlterNPCLevel';
WHEN '108' THEN SET `token` = 'SE_Familiar';
WHEN '109' THEN SET `token` = 'SE_SummonItemIntoBag';
WHEN '110' THEN SET `token` = 'NI_IncreaseArchery';
WHEN '111' THEN SET `token` = 'SE_ResistAll';
WHEN '112' THEN SET `token` = 'SE_CastingLevel';
WHEN '113' THEN SET `token` = 'SE_SummonHorse';
WHEN '114' THEN SET `token` = 'SE_ChangeAggro';
WHEN '115' THEN SET `token` = 'SE_Hunger';
WHEN '116' THEN SET `token` = 'SE_CurseCounter';
WHEN '117' THEN SET `token` = 'SE_MagicWeapon';
WHEN '118' THEN SET `token` = 'SE_Amplification';
WHEN '119' THEN SET `token` = 'SE_AttackSpeed3';
WHEN '120' THEN SET `token` = 'SE_HealRate';
WHEN '121' THEN SET `token` = 'SE_ReverseDS';
WHEN '122' THEN SET `token` = 'NI_ReduceSkill';
WHEN '123' THEN SET `token` = 'SE_Screech';
WHEN '124' THEN SET `token` = 'SE_ImprovedDamage';
WHEN '125' THEN SET `token` = 'SE_ImprovedHeal';
WHEN '126' THEN SET `token` = 'SE_SpellResistReduction';
WHEN '127' THEN SET `token` = 'SE_IncreaseSpellHaste';
WHEN '128' THEN SET `token` = 'SE_IncreaseSpellDuration';
WHEN '129' THEN SET `token` = 'SE_IncreaseRange';
WHEN '130' THEN SET `token` = 'SE_SpellHateMod';
WHEN '131' THEN SET `token` = 'SE_ReduceReagentCost';
WHEN '132' THEN SET `token` = 'SE_ReduceManaCost';
WHEN '133' THEN SET `token` = 'SE_FcStunTimeMod';
WHEN '134' THEN SET `token` = 'SE_LimitMaxLevel';
WHEN '135' THEN SET `token` = 'SE_LimitResist';
WHEN '136' THEN SET `token` = 'SE_LimitTarget';
WHEN '137' THEN SET `token` = 'SE_LimitEffect';
WHEN '138' THEN SET `token` = 'SE_LimitSpellType';
WHEN '139' THEN SET `token` = 'SE_LimitSpell';
WHEN '140' THEN SET `token` = 'SE_LimitMinDur';
WHEN '141' THEN SET `token` = 'SE_LimitInstant';
WHEN '142' THEN SET `token` = 'SE_LimitMinLevel';
WHEN '143' THEN SET `token` = 'SE_LimitCastTimeMin';
WHEN '144' THEN SET `token` = 'SE_LimitCastTimeMax';
WHEN '145' THEN SET `token` = 'SE_Teleport2';
WHEN '146' THEN SET `token` = 'NI_ElectricityResist';
WHEN '147' THEN SET `token` = 'SE_PercentalHeal';
WHEN '148' THEN SET `token` = 'SE_StackingCommand_Block';
WHEN '149' THEN SET `token` = 'SE_StackingCommand_Overwrite';
WHEN '150' THEN SET `token` = 'SE_DeathSave';
WHEN '151' THEN SET `token` = 'SE_SuspendPet';
WHEN '152' THEN SET `token` = 'SE_TemporaryPets';
WHEN '153' THEN SET `token` = 'SE_BalanceHP';
WHEN '154' THEN SET `token` = 'SE_DispelDetrimental';
WHEN '155' THEN SET `token` = 'SE_SpellCritDmgIncrease';
WHEN '156' THEN SET `token` = 'SE_IllusionCopy';
WHEN '157' THEN SET `token` = 'SE_SpellDamageShield';
WHEN '158' THEN SET `token` = 'SE_Reflect';
WHEN '159' THEN SET `token` = 'SE_AllStats';
WHEN '160' THEN SET `token` = 'NI_MakeDrunk';
WHEN '161' THEN SET `token` = 'SE_MitigateSpellDamage';
WHEN '162' THEN SET `token` = 'SE_MitigateMeleeDamage';
WHEN '163' THEN SET `token` = 'SE_NegateAttacks';
WHEN '164' THEN SET `token` = 'SE_AppraiseLDonChest';
WHEN '165' THEN SET `token` = 'SE_DisarmLDoNTrap';
WHEN '166' THEN SET `token` = 'SE_UnlockLDoNChest';
WHEN '167' THEN SET `token` = 'SE_PetPowerIncrease';
WHEN '168' THEN SET `token` = 'SE_MeleeMitigation';
WHEN '169' THEN SET `token` = 'SE_CriticalHitChance';
WHEN '170' THEN SET `token` = 'SE_SpellCritChance';
WHEN '171' THEN SET `token` = 'SE_CrippBlowChance';
WHEN '172' THEN SET `token` = 'SE_AvoidMeleeChance';
WHEN '173' THEN SET `token` = 'SE_RiposteChance';
WHEN '174' THEN SET `token` = 'SE_DodgeChance';
WHEN '175' THEN SET `token` = 'SE_ParryChance';
WHEN '176' THEN SET `token` = 'SE_DualWieldChance';
WHEN '177' THEN SET `token` = 'SE_DoubleAttackChance';
WHEN '178' THEN SET `token` = 'SE_MeleeLifetap';
WHEN '179' THEN SET `token` = 'SE_AllInstrumentMod';
WHEN '180' THEN SET `token` = 'SE_ResistSpellChance';
WHEN '181' THEN SET `token` = 'SE_ResistFearChance';
WHEN '182' THEN SET `token` = 'SE_HundredHands';
WHEN '183' THEN SET `token` = 'SE_MeleeSkillCheck';
WHEN '184' THEN SET `token` = 'SE_HitChance';
WHEN '185' THEN SET `token` = 'SE_DamageModifier';
WHEN '186' THEN SET `token` = 'SE_MinDamageModifier';
WHEN '187' THEN SET `token` = 'SE_BalanceMana';
WHEN '188' THEN SET `token` = 'SE_IncreaseBlockChance';
WHEN '189' THEN SET `token` = 'SE_CurrentEndurance';
WHEN '190' THEN SET `token` = 'SE_EndurancePool';
WHEN '191' THEN SET `token` = 'SE_Amnesia';
WHEN '192' THEN SET `token` = 'SE_Hate';
WHEN '193' THEN SET `token` = 'SE_SkillAttack';
WHEN '194' THEN SET `token` = 'SE_FadingMemories';
WHEN '195' THEN SET `token` = 'SE_StunResist';
WHEN '196' THEN SET `token` = 'SE_StrikeThrough';
WHEN '197' THEN SET `token` = 'SE_SkillDamageTaken';
WHEN '198' THEN SET `token` = 'SE_CurrentEnduranceOnce';
WHEN '199' THEN SET `token` = 'SE_Taunt';
WHEN '200' THEN SET `token` = 'SE_ProcChance';
WHEN '201' THEN SET `token` = 'SE_RangedProc';
WHEN '202' THEN SET `token` = 'SE_IllusionOther';
WHEN '203' THEN SET `token` = 'SE_MassGroupBuff';
WHEN '204' THEN SET `token` = 'SE_GroupFearImmunity';
WHEN '205' THEN SET `token` = 'SE_Rampage';
WHEN '206' THEN SET `token` = 'SE_AETaunt';
WHEN '207' THEN SET `token` = 'SE_FleshToBone';
WHEN '208' THEN SET `token` = 'NI_PurgePoison';
WHEN '209' THEN SET `token` = 'SE_DispelBeneficial';
WHEN '210' THEN SET `token` = 'NI_PetShield';
WHEN '211' THEN SET `token` = 'SE_AEMelee';
WHEN '212' THEN SET `token` = 'SE_FrenziedDevastation';
WHEN '213' THEN SET `token` = 'SE_PetMaxHP';
WHEN '214' THEN SET `token` = 'SE_MaxHPChange';
WHEN '215' THEN SET `token` = 'SE_PetAvoidance';
WHEN '216' THEN SET `token` = 'SE_Accuracy';
WHEN '217' THEN SET `token` = 'SE_HeadShot';
WHEN '218' THEN SET `token` = 'SE_PetCriticalHit';
WHEN '219' THEN SET `token` = 'SE_SlayUndead';
WHEN '220' THEN SET `token` = 'SE_SkillDamageAmount';
WHEN '221' THEN SET `token` = 'SE_Packrat';
WHEN '222' THEN SET `token` = 'SE_BlockBehind';
WHEN '223' THEN SET `token` = 'SE_DoubleRiposte';
WHEN '224' THEN SET `token` = 'SE_GiveDoubleRiposte';
WHEN '225' THEN SET `token` = 'SE_GiveDoubleAttack';
WHEN '226' THEN SET `token` = 'SE_TwoHandBash';
WHEN '227' THEN SET `token` = 'SE_ReduceSkillTimer';
WHEN '228' THEN SET `token` = 'SE_ReduceFallDamage';
WHEN '229' THEN SET `token` = 'SE_PersistantCasting';
WHEN '230' THEN SET `token` = 'SE_ExtendedShielding';
WHEN '231' THEN SET `token` = 'SE_StunBashChance';
WHEN '232' THEN SET `token` = 'SE_DivineSave';
WHEN '233' THEN SET `token` = 'SE_Metabolism';
WHEN '234' THEN SET `token` = 'SE_ReduceApplyPoisonTime';
WHEN '235' THEN SET `token` = 'SE_ChannelChanceSpells';
WHEN '236' THEN SET `token` = 'NI_FreePet';
WHEN '237' THEN SET `token` = 'SE_GivePetGroupTarget';
WHEN '238' THEN SET `token` = 'SE_IllusionPersistence';
WHEN '239' THEN SET `token` = 'SE_FeignedCastOnChance';
WHEN '240' THEN SET `token` = 'NI_StringUnbreakable';
WHEN '241' THEN SET `token` = 'SE_ImprovedReclaimEnergy';
WHEN '242' THEN SET `token` = 'SE_IncreaseChanceMemwipe';
WHEN '243' THEN SET `token` = 'SE_CharmBreakChance';
WHEN '244' THEN SET `token` = 'SE_RootBreakChance';
WHEN '245' THEN SET `token` = 'SE_TrapCircumvention';
WHEN '246' THEN SET `token` = 'SE_SetBreathLevel';
WHEN '247' THEN SET `token` = 'SE_RaiseSkillCap';
WHEN '248' THEN SET `token` = 'SE_SecondaryForte';
WHEN '249' THEN SET `token` = 'SE_SecondaryDmgInc';
WHEN '250' THEN SET `token` = 'SE_SpellProcChance';
WHEN '251' THEN SET `token` = 'SE_ConsumeProjectile';
WHEN '252' THEN SET `token` = 'SE_FrontalBackstabChance';
WHEN '253' THEN SET `token` = 'SE_FrontalBackstabMinDmg';
WHEN '254' THEN SET `token` = 'SE_Blank';
WHEN '255' THEN SET `token` = 'SE_ShieldDuration';
WHEN '256' THEN SET `token` = 'SE_ShroudofStealth';
WHEN '257' THEN SET `token` = 'SE_PetDiscipline';
WHEN '258' THEN SET `token` = 'SE_TripleBackstab';
WHEN '259' THEN SET `token` = 'SE_CombatStability';
WHEN '260' THEN SET `token` = 'SE_AddSingingMod';
WHEN '261' THEN SET `token` = 'SE_SongModCap';
WHEN '262' THEN SET `token` = 'SE_RaiseStatCap';
WHEN '263' THEN SET `token` = 'SE_TradeSkillMastery';
WHEN '264' THEN SET `token` = 'SE_HastenedAASkill';
WHEN '265' THEN SET `token` = 'SE_MasteryofPast';
WHEN '266' THEN SET `token` = 'SE_ExtraAttackChance';
WHEN '267' THEN SET `token` = 'SE_PetDiscipline2';
WHEN '268' THEN SET `token` = 'SE_ReduceTradeskillFail';
WHEN '269' THEN SET `token` = 'SE_MaxBindWound';
WHEN '270' THEN SET `token` = 'SE_BardSongRange';
WHEN '271' THEN SET `token` = 'SE_BaseMovementSpeed';
WHEN '272' THEN SET `token` = 'SE_CastingLevel2';
WHEN '273' THEN SET `token` = 'SE_CriticalDoTChance';
WHEN '274' THEN SET `token` = 'SE_CriticalHealChance';
WHEN '275' THEN SET `token` = 'SE_CriticalMend';
WHEN '276' THEN SET `token` = 'SE_Ambidexterity';
WHEN '277' THEN SET `token` = 'SE_UnfailingDivinity';
WHEN '278' THEN SET `token` = 'SE_FinishingBlow';
WHEN '279' THEN SET `token` = 'SE_Flurry';
WHEN '280' THEN SET `token` = 'SE_PetFlurry';
WHEN '281' THEN SET `token` = 'SE_FeignedMinion';
WHEN '282' THEN SET `token` = 'SE_ImprovedBindWound';
WHEN '283' THEN SET `token` = 'SE_DoubleSpecialAttack';
WHEN '284' THEN SET `token` = 'NI_LoHSetHeal';
WHEN '285' THEN SET `token` = 'SE_NimbleEvasion';
WHEN '286' THEN SET `token` = 'SE_FcDamageAmt';
WHEN '287' THEN SET `token` = 'SE_SpellDurationIncByTic';
WHEN '288' THEN SET `token` = 'SE_SkillAttackProc';
WHEN '289' THEN SET `token` = 'SE_CastOnFadeEffect';
WHEN '290' THEN SET `token` = 'SE_IncreaseRunSpeedCap';
WHEN '291' THEN SET `token` = 'SE_Purify';
WHEN '292' THEN SET `token` = 'SE_StrikeThrough2';
WHEN '293' THEN SET `token` = 'SE_FrontalStunResist';
WHEN '294' THEN SET `token` = 'SE_CriticalSpellChance';
WHEN '295' THEN SET `token` = 'NI_ReduceTimerSpecial';
WHEN '296' THEN SET `token` = 'SE_FcSpellVulnerability';
WHEN '297' THEN SET `token` = 'SE_FcDamageAmtIncoming';
WHEN '298' THEN SET `token` = 'SE_ChangeHeight';
WHEN '299' THEN SET `token` = 'SE_WakeTheDead';
WHEN '300' THEN SET `token` = 'SE_Doppelganger';
WHEN '301' THEN SET `token` = 'SE_ArcheryDamageModifier';
WHEN '302' THEN SET `token` = 'SE_FcDamagePctCrit';
WHEN '303' THEN SET `token` = 'SE_FcDamageAmtCrit';
WHEN '304' THEN SET `token` = 'SE_OffhandRiposteFail';
WHEN '305' THEN SET `token` = 'SE_MitigateDamageShield';
WHEN '306' THEN SET `token` = 'NI_ArmyOfTheDead';
WHEN '307' THEN SET `token` = 'NI_Appraisal';
WHEN '308' THEN SET `token` = 'SE_SuspendMinion';
WHEN '309' THEN SET `token` = 'SE_GateCastersBindpoint';
WHEN '310' THEN SET `token` = 'SE_ReduceReuseTimer';
WHEN '311' THEN SET `token` = 'SE_LimitCombatSkills';
WHEN '312' THEN SET `token` = 'SE_Sanctuary';
WHEN '313' THEN SET `token` = 'SE_ForageAdditionalItems';
WHEN '314' THEN SET `token` = 'SE_Invisibility2';
WHEN '315' THEN SET `token` = 'SE_InvisVsUndead2';
WHEN '316' THEN SET `token` = 'NI_ImprovedInvisAnimals';
WHEN '317' THEN SET `token` = 'SE_ItemHPRegenCapIncrease';
WHEN '318' THEN SET `token` = 'SE_ItemManaRegenCapIncrease';
WHEN '319' THEN SET `token` = 'SE_CriticalHealOverTime';
WHEN '320' THEN SET `token` = 'SE_ShieldBlock';
WHEN '321' THEN SET `token` = 'SE_ReduceHate';
WHEN '322' THEN SET `token` = 'SE_GateToHomeCity';
WHEN '323' THEN SET `token` = 'SE_DefensiveProc';
WHEN '324' THEN SET `token` = 'SE_HPToMana';
WHEN '325' THEN SET `token` = 'SE_NoBreakAESneak';
WHEN '326' THEN SET `token` = 'SE_SpellSlotIncrease';
WHEN '327' THEN SET `token` = 'SE_MysticalAttune';
WHEN '328' THEN SET `token` = 'SE_DelayDeath';
WHEN '329' THEN SET `token` = 'SE_ManaAbsorbPercentDamage';
WHEN '330' THEN SET `token` = 'SE_CriticalDamageMob';
WHEN '331' THEN SET `token` = 'SE_Salvage';
WHEN '332' THEN SET `token` = 'SE_SummonToCorpse';
WHEN '333' THEN SET `token` = 'SE_CastOnRuneFadeEffect';
WHEN '334' THEN SET `token` = 'SE_BardAEDot';
WHEN '335' THEN SET `token` = 'SE_BlockNextSpellFocus';
WHEN '336' THEN SET `token` = 'NI_IllusionaryTarget';
WHEN '337' THEN SET `token` = 'SE_PercentXPIncrease';
WHEN '338' THEN SET `token` = 'SE_SummonAndResAllCorpses';
WHEN '339' THEN SET `token` = 'SE_TriggerOnCast';
WHEN '340' THEN SET `token` = 'SE_SpellTrigger';
WHEN '341' THEN SET `token` = 'SE_ItemAttackCapIncrease';
WHEN '342' THEN SET `token` = 'SE_ImmuneFleeing';
WHEN '343' THEN SET `token` = 'SE_InterruptCasting';
WHEN '344' THEN SET `token` = 'SE_ChannelChanceItems';
WHEN '345' THEN SET `token` = 'SE_AssassinateLevel';
WHEN '346' THEN SET `token` = 'SE_HeadShotLevel';
WHEN '347' THEN SET `token` = 'SE_DoubleRangedAttack';
WHEN '348' THEN SET `token` = 'SE_LimitManaMin';
WHEN '349' THEN SET `token` = 'SE_ShieldEquipDmgMod';
WHEN '350' THEN SET `token` = 'SE_ManaBurn';
WHEN '351' THEN SET `token` = 'NI_PersistentEffect';
WHEN '352' THEN SET `token` = 'NI_IncreaseTrapCount';
WHEN '353' THEN SET `token` = 'NI_AdditionalAura';
WHEN '354' THEN SET `token` = 'NI_DeactivateAllTraps';
WHEN '355' THEN SET `token` = 'NI_LearnTrap';
WHEN '356' THEN SET `token` = 'NI_ChangeTriggerType';
WHEN '357' THEN SET `token` = 'SE_FcMute';
WHEN '358' THEN SET `token` = 'SE_CurrentManaOnce';
WHEN '359' THEN SET `token` = 'NI_PassiveSenseTrap';
WHEN '360' THEN SET `token` = 'SE_ProcOnKillShot';
WHEN '361' THEN SET `token` = 'SE_SpellOnDeath';
WHEN '362' THEN SET `token` = 'SE_PotionBeltSlots';
WHEN '363' THEN SET `token` = 'SE_BandolierSlots';
WHEN '364' THEN SET `token` = 'SE_TripleAttackChance';
WHEN '365' THEN SET `token` = 'SE_ProcOnSpellKillShot';
WHEN '366' THEN SET `token` = 'SE_GroupShielding';
WHEN '367' THEN SET `token` = 'SE_SetBodyType';
WHEN '368' THEN SET `token` = 'NI_FactionMod';
WHEN '369' THEN SET `token` = 'SE_CorruptionCounter';
WHEN '370' THEN SET `token` = 'SE_ResistCorruption';
WHEN '371' THEN SET `token` = 'SE_AttackSpeed4';
WHEN '372' THEN SET `token` = 'SE_ForageSkill';
WHEN '373' THEN SET `token` = 'SE_CastOnFadeEffectAlways';
WHEN '374' THEN SET `token` = 'SE_ApplyEffect';
WHEN '375' THEN SET `token` = 'SE_DotCritDmgIncrease';
WHEN '376' THEN SET `token` = 'NI_Fling';
WHEN '377' THEN SET `token` = 'SE_CastOnFadeEffectNPC';
WHEN '378' THEN SET `token` = 'SE_SpellEffectResistChance';
WHEN '379' THEN SET `token` = 'SE_ShadowStepDirectional';
WHEN '380' THEN SET `token` = 'SE_Knockdown';
WHEN '381' THEN SET `token` = 'NI_KnockTowardCaster';
WHEN '382' THEN SET `token` = 'SE_NegateSpellEffect';
WHEN '383' THEN SET `token` = 'SE_SympatheticProc';
WHEN '384' THEN SET `token` = 'SE_Leap';
WHEN '385' THEN SET `token` = 'SE_LimitSpellGroup';
WHEN '386' THEN SET `token` = 'SE_CastOnCurer';
WHEN '387' THEN SET `token` = 'SE_CastOnCure';
WHEN '388' THEN SET `token` = 'NI_SummonCorpseZone';
WHEN '389' THEN SET `token` = 'SE_FcTimerRefresh';
WHEN '390' THEN SET `token` = 'NI_FcTimerLockout';
WHEN '391' THEN SET `token` = 'SE_LimitManaMax';
WHEN '392' THEN SET `token` = 'SE_FcHealAmt';
WHEN '393' THEN SET `token` = 'SE_FcHealPctIncoming';
WHEN '394' THEN SET `token` = 'SE_FcHealAmtIncoming';
WHEN '395' THEN SET `token` = 'SE_FcHealPctCritIncoming';
WHEN '396' THEN SET `token` = 'SE_FcHealAmtCrit';
WHEN '397' THEN SET `token` = 'SE_PetMeleeMitigation';
WHEN '398' THEN SET `token` = 'SE_SwarmPetDuration';
WHEN '399' THEN SET `token` = 'SE_FcTwincast';
WHEN '400' THEN SET `token` = 'SE_HealGroupFromMana';
WHEN '401' THEN SET `token` = 'SE_ManaDrainWithDmg';
WHEN '402' THEN SET `token` = 'SE_EndDrainWithDmg';
WHEN '403' THEN SET `token` = 'SE_LimitSpellClass';
WHEN '404' THEN SET `token` = 'SE_LimitSpellSubclass';
WHEN '405' THEN SET `token` = 'SE_TwoHandBluntBlock';
WHEN '406' THEN SET `token` = 'SE_CastonNumHitFade';
WHEN '407' THEN SET `token` = 'SE_CastonFocusEffect';
WHEN '408' THEN SET `token` = 'SE_LimitHPPercent';
WHEN '409' THEN SET `token` = 'SE_LimitManaPercent';
WHEN '410' THEN SET `token` = 'SE_LimitEndPercent';
WHEN '411' THEN SET `token` = 'SE_LimitClass';
WHEN '412' THEN SET `token` = 'SE_LimitRace';
WHEN '413' THEN SET `token` = 'SE_FcBaseEffects';
WHEN '414' THEN SET `token` = 'SE_LimitCastingSkill';
WHEN '415' THEN SET `token` = 'NI_FFItemClass';
WHEN '416' THEN SET `token` = 'SE_ACv2';
WHEN '417' THEN SET `token` = 'SE_ManaRegen_v2';
WHEN '418' THEN SET `token` = 'SE_SkillDamageAmount2';
WHEN '419' THEN SET `token` = 'SE_AddMeleeProc';
WHEN '420' THEN SET `token` = 'SE_FcLimitUse';
WHEN '421' THEN SET `token` = 'SE_FcIncreaseNumHits';
WHEN '422' THEN SET `token` = 'SE_LimitUseMin';
WHEN '423' THEN SET `token` = 'SE_LimitUseType';
WHEN '424' THEN SET `token` = 'SE_GravityEffect';
WHEN '425' THEN SET `token` = 'NI_Display';
WHEN '426' THEN SET `token` = 'SE_IncreaseExtTargetWindow';
WHEN '427' THEN SET `token` = 'SE_SkillProc';
WHEN '428' THEN SET `token` = 'SE_LimitToSkill';
WHEN '429' THEN SET `token` = 'SE_SkillProcSuccess';
WHEN '430' THEN SET `token` = 'NI_PostEffect';
WHEN '431' THEN SET `token` = 'NI_PostEffectData';
WHEN '432' THEN SET `token` = 'NI_ExpandMaxActiveTrophyBen';
WHEN '433' THEN SET `token` = 'SE_CriticalDotDecay';
WHEN '434' THEN SET `token` = 'SE_CriticalHealDecay';
WHEN '435' THEN SET `token` = 'SE_CriticalRegenDecay';
WHEN '436' THEN SET `token` = 'NI_BeneficialCountDownHold';
WHEN '437' THEN SET `token` = 'NI_TeleporttoAnchor';
WHEN '438' THEN SET `token` = 'NI_TranslocatetoAnchor';
WHEN '439' THEN SET `token` = 'SE_Assassinate';
WHEN '440' THEN SET `token` = 'SE_FinishingBlowLvl';
WHEN '441' THEN SET `token` = 'SE_DistanceRemoval';
WHEN '442' THEN SET `token` = 'SE_TriggerOnReqTarget';
WHEN '443' THEN SET `token` = 'SE_TriggerOnReqCaster';
WHEN '444' THEN SET `token` = 'SE_ImprovedTaunt';
WHEN '445' THEN SET `token` = 'NI_AddMercSlot';
WHEN '446' THEN SET `token` = 'SE_AStacker';
WHEN '447' THEN SET `token` = 'SE_BStacker';
WHEN '448' THEN SET `token` = 'SE_CStacker';
WHEN '449' THEN SET `token` = 'SE_DStacker';
WHEN '450' THEN SET `token` = 'SE_MitigateDotDamage';
WHEN '451' THEN SET `token` = 'SE_MeleeThresholdGuard';
WHEN '452' THEN SET `token` = 'SE_SpellThresholdGuard';
WHEN '453' THEN SET `token` = 'SE_TriggerMeleeThreshold';
WHEN '454' THEN SET `token` = 'SE_TriggerSpellThreshold';
WHEN '455' THEN SET `token` = 'SE_AddHatePct';
WHEN '456' THEN SET `token` = 'SE_AddHateOverTimePct';
WHEN '457' THEN SET `token` = 'SE_ResourceTap';
WHEN '458' THEN SET `token` = 'SE_FactionModPct';
WHEN '459' THEN SET `token` = 'SE_DamageModifier2';
WHEN '460' THEN SET `token` = 'NI_Ff_Override_NotFocusable';
WHEN '461' THEN SET `token` = 'SE_ImprovedDamage2';
WHEN '462' THEN SET `token` = 'SE_FcDamageAmt2';
WHEN '463' THEN SET `token` = 'NI_Shield_Target';
WHEN '464' THEN SET `token` = 'SE_PC_Pet_Rampage';
WHEN '465' THEN SET `token` = 'NI_PC_Pet_AE_Rampage';
WHEN '466' THEN SET `token` = 'SE_PC_Pet_Flurry_Chance';
WHEN '467' THEN SET `token` = 'NI_DS_Mitigation_Amount';
WHEN '468' THEN SET `token` = 'NI_DS_Mitigation_Percentage';
WHEN '469' THEN SET `token` = 'NI_Chance_Best_in_Spell_Grp';
WHEN '470' THEN SET `token` = 'NI_Trigger_Best_in_Spell_Grp';
WHEN '471' THEN SET `token` = 'NI_Double_Melee_Round';
-- these are not defined
WHEN '472' THEN SET `token` = 'NI_Buy_AA_Rank';
WHEN '473' THEN SET `token` = 'NI_Double_Backstab_From_Front';
WHEN '474' THEN SET `token` = 'NI_Pet_Crit_Melee_Damage_Pct';
WHEN '475' THEN SET `token` = 'NI_Trigger_Spell_Non_Item';
WHEN '476' THEN SET `token` = 'NI_Weapon_Stance';
WHEN '477' THEN SET `token` = 'NI_Hatelist_To_Top_Index';
WHEN '478' THEN SET `token` = 'NI_Hatelist_To_Tail_Index';
WHEN '479' THEN SET `token` = 'NI_Ff_Value_Min';
WHEN '480' THEN SET `token` = 'NI_Ff_Value_Max';
WHEN '481' THEN SET `token` = 'NI_Fc_Cast_Spell_On_Land';
WHEN '482' THEN SET `token` = 'NI_Skill_Base_Damage_Mod';
WHEN '483' THEN SET `token` = 'NI_Fc_Spell_Damage_Pct_IncomingPC';
WHEN '484' THEN SET `token` = 'NI_Fc_Spell_Damage_Amt_IncomingPC';
WHEN '485' THEN SET `token` = 'NI_Ff_CasterClass';
WHEN '486' THEN SET `token` = 'NI_Ff_Same_Caster';
WHEN '487' THEN SET `token` = 'NI_Extend_Tradeskill_Cap';
WHEN '488' THEN SET `token` = 'NI_Defender_Melee_Force_Pct';
WHEN '489' THEN SET `token` = 'NI_Worn_Endurance_Regen_Cap';
WHEN '490' THEN SET `token` = 'NI_Ff_ReuseTimeMin';
WHEN '491' THEN SET `token` = 'NI_Ff_ReuseTimeMax';
WHEN '492' THEN SET `token` = 'NI_Ff_Endurance_Min';
WHEN '493' THEN SET `token` = 'NI_Ff_Endurance_Max';
WHEN '494' THEN SET `token` = 'NI_Pet_Add_Atk';
WHEN '495' THEN SET `token` = 'NI_Ff_DurationMax';
ELSE SET `token` = 'unk';
END CASE;
SET `token` = CONCAT(`token`, '(', `effect_id`, ')');
RETURN `token`;
END$$
DELIMITER ;

View File

@ -0,0 +1,171 @@
DELIMITER $$
DROP FUNCTION IF EXISTS `GetSpellTargetTypeToken`;
-- This function converts a numeric spell target type to a string label based on server code designations
-- Note: `cast_restriction` data taken from MacroQuest2 definitions
--
-- example:
-- SELECT `id`, `name`, GetSpellTargetTypeToken(`targettype`, `CastRestriction`) FROM `spells_new` WHERE `id` IN ('6836', '10763', '25039');
CREATE FUNCTION `GetSpellTargetTypeToken` (`target_type` INT(11), `cast_restriction` INT(11)) RETURNS VARCHAR(128)
BEGIN
DECLARE `token` VARCHAR(128) DEFAULT '';
DECLARE `token2` VARCHAR(64) DEFAULT '';
CASE `target_type`
WHEN '1' THEN SET `token` = 'ST_TargetOptional';
WHEN '2' THEN SET `token` = 'ST_AEClientV1';
WHEN '3' THEN SET `token` = 'ST_GroupTeleport';
WHEN '4' THEN SET `token` = 'ST_AECaster';
WHEN '5' THEN SET `token` = 'ST_Target';
WHEN '6' THEN SET `token` = 'ST_Self';
WHEN '8' THEN SET `token` = 'ST_AETarget';
WHEN '9' THEN SET `token` = 'ST_Animal';
WHEN '10' THEN SET `token` = 'ST_Undead';
WHEN '11' THEN SET `token` = 'ST_Summoned';
WHEN '13' THEN SET `token` = 'ST_Tap';
WHEN '14' THEN SET `token` = 'ST_Pet';
WHEN '15' THEN SET `token` = 'ST_Corpse';
WHEN '16' THEN SET `token` = 'ST_Plant';
WHEN '17' THEN SET `token` = 'ST_Giant';
WHEN '18' THEN SET `token` = 'ST_Dragon';
WHEN '20' THEN SET `token` = 'ST_TargetAETap';
WHEN '24' THEN SET `token` = 'ST_UndeadAE';
WHEN '25' THEN SET `token` = 'ST_SummonedAE';
WHEN '32' THEN SET `token` = 'ST_AETargetHateList';
WHEN '33' THEN SET `token` = 'ST_HateList';
WHEN '34' THEN SET `token` = 'ST_LDoNChest_Cursed';
WHEN '35' THEN SET `token` = 'ST_Muramite';
WHEN '36' THEN SET `token` = 'ST_AreaClientOnly';
WHEN '37' THEN SET `token` = 'ST_AreaNPCOnly';
WHEN '38' THEN SET `token` = 'ST_SummonedPet';
WHEN '39' THEN SET `token` = 'ST_GroupNoPets';
WHEN '40' THEN SET `token` = 'ST_AEBard';
WHEN '41' THEN SET `token` = 'ST_Group';
WHEN '42' THEN SET `token` = 'ST_Directional';
WHEN '43' THEN SET `token` = 'ST_GroupClientAndPet';
WHEN '44' THEN SET `token` = 'ST_Beam';
WHEN '45' THEN SET `token` = 'ST_Ring';
WHEN '46' THEN SET `token` = 'ST_TargetsTarget';
WHEN '47' THEN SET `token` = 'ST_PetMaster';
WHEN '50' THEN SET `token` = 'ST_TargetAENoPlayersPets';
ELSE SET `token` = 'unk';
END CASE;
SET `token` = CONCAT(`token`, '(', `target_type`, ')');
CASE `cast_restriction`
WHEN '0' THEN SET `token2` = 'None';
WHEN '100' THEN SET `token2` = 'Only works on Animal or Humanoid';
WHEN '101' THEN SET `token2` = 'Only works on Dragon';
WHEN '102' THEN SET `token2` = 'Only works on Animal or Insect';
WHEN '104' THEN SET `token2` = 'Only works on Animal';
WHEN '105' THEN SET `token2` = 'Only works on Plant';
WHEN '106' THEN SET `token2` = 'Only works on Giant';
WHEN '108' THEN SET `token2` = 'Doesn\'t work on Animals or Humanoids';
WHEN '109' THEN SET `token2` = 'Only works on Bixie';
WHEN '110' THEN SET `token2` = 'Only works on Harpy';
WHEN '111' THEN SET `token2` = 'Only works on Gnoll';
WHEN '112' THEN SET `token2` = 'Only works on Sporali';
WHEN '113' THEN SET `token2` = 'Only works on Kobold';
WHEN '114' THEN SET `token2` = 'Only works on Shade';
WHEN '115' THEN SET `token2` = 'Only works on Drakkin';
WHEN '117' THEN SET `token2` = 'Only works on Animals or Plants';
WHEN '118' THEN SET `token2` = 'Only works on Summoned';
WHEN '119' THEN SET `token2` = 'Only works on Fire_Pet';
WHEN '120' THEN SET `token2` = 'Only works on Undead';
WHEN '121' THEN SET `token2` = 'Only works on Living';
WHEN '122' THEN SET `token2` = 'Only works on Fairy';
WHEN '123' THEN SET `token2` = 'Only works on Humanoid';
WHEN '124' THEN SET `token2` = 'Undead HP Less Than 10%';
WHEN '125' THEN SET `token2` = 'Clockwork HP Less Than 45%';
WHEN '126' THEN SET `token2` = 'Wisp HP Less Than 10%';
WHEN '190' THEN SET `token2` = 'Doesn\'t work on Raid Bosses';
WHEN '191' THEN SET `token2` = 'Only works on Raid Bosses';
WHEN '201' THEN SET `token2` = 'HP Above 75%';
WHEN '203' THEN SET `token2` = 'HP Less Than 20%';
WHEN '204' THEN SET `token2` = 'HP Less Than 50%';
WHEN '216' THEN SET `token2` = 'Not In Combat';
WHEN '221' THEN SET `token2` = 'At Least 1 Pet On Hatelist';
WHEN '222' THEN SET `token2` = 'At Least 2 Pets On Hatelist';
WHEN '223' THEN SET `token2` = 'At Least 3 Pets On Hatelist';
WHEN '224' THEN SET `token2` = 'At Least 4 Pets On Hatelist';
WHEN '225' THEN SET `token2` = 'At Least 5 Pets On Hatelist';
WHEN '226' THEN SET `token2` = 'At Least 6 Pets On Hatelist';
WHEN '227' THEN SET `token2` = 'At Least 7 Pets On Hatelist';
WHEN '228' THEN SET `token2` = 'At Least 8 Pets On Hatelist';
WHEN '229' THEN SET `token2` = 'At Least 9 Pets On Hatelist';
WHEN '230' THEN SET `token2` = 'At Least 10 Pets On Hatelist';
WHEN '231' THEN SET `token2` = 'At Least 11 Pets On Hatelist';
WHEN '232' THEN SET `token2` = 'At Least 12 Pets On Hatelist';
WHEN '233' THEN SET `token2` = 'At Least 13 Pets On Hatelist';
WHEN '234' THEN SET `token2` = 'At Least 14 Pets On Hatelist';
WHEN '235' THEN SET `token2` = 'At Least 15 Pets On Hatelist';
WHEN '236' THEN SET `token2` = 'At Least 16 Pets On Hatelist';
WHEN '237' THEN SET `token2` = 'At Least 17 Pets On Hatelist';
WHEN '238' THEN SET `token2` = 'At Least 18 Pets On Hatelist';
WHEN '239' THEN SET `token2` = 'At Least 19 Pets On Hatelist';
WHEN '240' THEN SET `token2` = 'At Least 20 Pets On Hatelist';
WHEN '250' THEN SET `token2` = 'HP Less Than 35%';
WHEN '304' THEN SET `token2` = 'Chain Plate Classes';
WHEN '399' THEN SET `token2` = 'HP Between 15 and 25%';
WHEN '400' THEN SET `token2` = 'HP Between 1 and 25%';
WHEN '401' THEN SET `token2` = 'HP Between 25 and 35%';
WHEN '402' THEN SET `token2` = 'HP Between 35 and 45%';
WHEN '403' THEN SET `token2` = 'HP Between 45 and 55%';
WHEN '404' THEN SET `token2` = 'HP Between 55 and 65%';
WHEN '412' THEN SET `token2` = 'HP Above 99%';
WHEN '501' THEN SET `token2` = 'HP Below 5%';
WHEN '502' THEN SET `token2` = 'HP Below 10%';
WHEN '503' THEN SET `token2` = 'HP Below 15%';
WHEN '504' THEN SET `token2` = 'HP Below 20%';
WHEN '505' THEN SET `token2` = 'HP Below 25%';
WHEN '506' THEN SET `token2` = 'HP Below 30%';
WHEN '507' THEN SET `token2` = 'HP Below 35%';
WHEN '508' THEN SET `token2` = 'HP Below 40%';
WHEN '509' THEN SET `token2` = 'HP Below 45%';
WHEN '510' THEN SET `token2` = 'HP Below 50%';
WHEN '511' THEN SET `token2` = 'HP Below 55%';
WHEN '512' THEN SET `token2` = 'HP Below 60%';
WHEN '513' THEN SET `token2` = 'HP Below 65%';
WHEN '514' THEN SET `token2` = 'HP Below 70%';
WHEN '515' THEN SET `token2` = 'HP Below 75%';
WHEN '516' THEN SET `token2` = 'HP Below 80%';
WHEN '517' THEN SET `token2` = 'HP Below 85%';
WHEN '518' THEN SET `token2` = 'HP Below 90%';
WHEN '519' THEN SET `token2` = 'HP Below 95%';
WHEN '521' THEN SET `token2` = 'Mana Below X%';
WHEN '522' THEN SET `token2` = 'End Below 40%';
WHEN '523' THEN SET `token2` = 'Mana Below 40%';
WHEN '603' THEN SET `token2` = 'Only works on Undead2';
WHEN '608' THEN SET `token2` = 'Only works on Undead3';
WHEN '624' THEN SET `token2` = 'Only works on Summoned2';
WHEN '701' THEN SET `token2` = 'Doesn\'t work on Pets';
WHEN '818' THEN SET `token2` = 'Only works on Undead4';
WHEN '819' THEN SET `token2` = 'Doesn\'t work on Undead4';
WHEN '825' THEN SET `token2` = 'End Below 21%';
WHEN '826' THEN SET `token2` = 'End Below 25%';
WHEN '827' THEN SET `token2` = 'End Below 29%';
WHEN '836' THEN SET `token2` = 'Only works on Regular Servers';
WHEN '837' THEN SET `token2` = 'Doesn\'t work on Progression Servers';
WHEN '842' THEN SET `token2` = 'Only works on Humanoid Level 84 Max';
WHEN '843' THEN SET `token2` = 'Only works on Humanoid Level 86 Max';
WHEN '844' THEN SET `token2` = 'Only works on Humanoid Level 88 Max';
WHEN '1000' THEN SET `token2` = 'Between Level 1 and 75';
WHEN '1001' THEN SET `token2` = 'Between Level 76 and 85';
WHEN '1002' THEN SET `token2` = 'Between Level 86 and 95';
WHEN '1003' THEN SET `token2` = 'Between Level 96 and 100';
WHEN '1004' THEN SET `token2` = 'HP Less Than 80%';
WHEN '38311' THEN SET `token2` = 'Mana Below 20%';
WHEN '38312' THEN SET `token2` = 'Mana Below 10%';
ELSE SET `token2` = 'unk';
END CASE;
SET `token2` = CONCAT(`token2`, '(', `cast_restriction`, ')');
SET `token` = CONCAT(`token`, ':', `token2`);
RETURN `token`;
END$$
DELIMITER ;

View File

@ -355,6 +355,8 @@
9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty|
9100|2016_08_27_object_display_name.sql|SHOW COLUMNS FROM `object` LIKE 'display_name'|empty|
9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty|
9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty|
9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,25 @@
update npc_types set attack_speed=0, atk=ceil(1.7*level), accuracy=ceil(1.7*level) where (name like 'Swarm%' or name like '%skel%' or name like 'BLpet%' or name like 'Sum%')
and id >510 and id <860;
update npc_types set attack_speed=0, atk=ceil(0.5*level), accuracy=ceil(0.5*level) where name like 'SumFire%';
update npc_types set attack_speed=0, atk=ceil(1.775*level), accuracy=ceil(1.775*level) where name like 'SumAir%';
update npc_types set attack_speed=0, atk=ceil(1.775*level), accuracy=ceil(1.775*level) where name like 'SumEarth%';
update npc_types set attack_speed=0, atk=ceil(2.26*level), accuracy=ceil(2.26*level),gender=2,size=3 where name like 'BestialAid%';
update npc_types set attack_speed=0, atk=ceil(2.26*level), accuracy=ceil(2.26*level),gender=2,size=3 where name like 'RagingServant%';
update npc_types n
set ac=
ceil(case
when level < 3 then level*2+2
when level < 15 and level >=3 then level*3
when id >= 200000 and id < 224000 then 200*.5+level
else level * 4.1 end
* (case when raid_target=1 then 1.4 else 1 end) + (case when raid_target=1 then level*1.4 else 0 end))
+ 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,str=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,sta=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,agi=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,_int=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,dex=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,wis=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5)
,cha=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5);

View File

@ -0,0 +1,2 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:LevelToStopDamageCaps', '0', '1 will effectively disable them, 20 should give basically same results as old incorrect system.');

View File

@ -0,0 +1,15 @@
alter table books add language int not null default 0;
drop table if exists reading_is_fundamental;
create table reading_is_fundamental
(
filename varchar(32),
language int
);
insert into reading_is_fundamental (select items.filename, items.booktype from items where items.filename != "" group by filename);
update books set books.language = (select language from reading_is_fundamental r where r.filename = books.name);
drop table reading_is_fundamental;

View File

@ -0,0 +1,4 @@
UPDATE `books` SET `language` = '0' WHERE `language` IS NULL;
ALTER TABLE `books` MODIFY COLUMN `language` INT NOT NULL DEFAULT '0';

File diff suppressed because it is too large Load Diff

View File

@ -35,9 +35,9 @@ public:
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; }
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr, int special = 0) { return false; }
ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }

View File

@ -46,6 +46,7 @@ void Mob::CalcBonuses()
CalcMaxHP();
CalcMaxMana();
SetAttackTimer();
CalcAC();
rooted = FindType(SE_Root);
}
@ -669,6 +670,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
}
switch (effect) {
case SE_ACv2:
case SE_ArmorClass:
newbon->AC += base1;
break;
// Note: AA effects that use accuracy are skill limited, while spell effect is not.
case SE_Accuracy:
// Bad data or unsupported new skill
@ -1308,8 +1313,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
}
case SE_HeadShotLevel: {
if (newbon->HSLevel < base1)
newbon->HSLevel = base1;
if (newbon->HSLevel[0] < base1)
newbon->HSLevel[0] = base1;
newbon->HSLevel[1] = base2;
break;
}
@ -1322,8 +1328,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
}
case SE_AssassinateLevel: {
if (newbon->AssassinateLevel < base1)
newbon->AssassinateLevel = base1;
if (newbon->AssassinateLevel[0] < base1) {
newbon->AssassinateLevel[0] = base1;
newbon->AssassinateLevel[1] = base2;
}
break;
}
@ -1381,7 +1389,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
}
case SE_MeleeMitigation:
newbon->MeleeMitigationEffect -= base1;
newbon->MeleeMitigationEffect += base1;
break;
case SE_ATK:
@ -1527,9 +1535,6 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
}
}
// THIS IS WRONG, leaving for now
//this prolly suffer from roundoff error slightly...
newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client.
if (GetClass() == BARD)
newbon->ManaRegen = 0; // Bards do not get mana regen from spells.
}
@ -1927,8 +1932,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
break;
case SE_MeleeMitigation:
//for some reason... this value is negative for increased mitigation
new_bonus->MeleeMitigationEffect -= effect_value;
// This value is negative because it counteracts another SPA :P
new_bonus->MeleeMitigationEffect += effect_value;
break;
case SE_CriticalHitChance:
@ -3024,8 +3029,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
case SE_HeadShotLevel:
{
if(new_bonus->HSLevel < effect_value)
new_bonus->HSLevel = effect_value;
if(new_bonus->HSLevel[0] < effect_value) {
new_bonus->HSLevel[0] = effect_value;
new_bonus->HSLevel[1] = base2;
}
break;
}
@ -3040,8 +3047,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
case SE_AssassinateLevel:
{
if(new_bonus->AssassinateLevel < effect_value)
new_bonus->AssassinateLevel = effect_value;
if(new_bonus->AssassinateLevel[0] < effect_value) {
new_bonus->AssassinateLevel[0] = effect_value;
new_bonus->AssassinateLevel[1] = base2;
}
break;
}
@ -4647,9 +4656,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_HeadShotLevel:
spellbonuses.HSLevel = effect_value;
aabonuses.HSLevel = effect_value;
itembonuses.HSLevel = effect_value;
spellbonuses.HSLevel[0] = effect_value;
aabonuses.HSLevel[0] = effect_value;
itembonuses.HSLevel[0] = effect_value;
spellbonuses.HSLevel[1] = effect_value;
aabonuses.HSLevel[1] = effect_value;
itembonuses.HSLevel[1] = effect_value;
break;
case SE_Assassinate:
@ -4662,9 +4674,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_AssassinateLevel:
spellbonuses.AssassinateLevel = effect_value;
aabonuses.AssassinateLevel = effect_value;
itembonuses.AssassinateLevel = effect_value;
spellbonuses.AssassinateLevel[0] = effect_value;
aabonuses.AssassinateLevel[0] = effect_value;
itembonuses.AssassinateLevel[0] = effect_value;
spellbonuses.AssassinateLevel[1] = effect_value;
aabonuses.AssassinateLevel[1] = effect_value;
itembonuses.AssassinateLevel[1] = effect_value;
break;
case SE_FinishingBlow:

File diff suppressed because it is too large Load Diff

View File

@ -206,9 +206,9 @@ public:
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr, int special = 0);
ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return (GetRaid() ? true : false); }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); }
@ -239,7 +239,7 @@ public:
uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; }
virtual float GetProcChances(float ProcBonus, uint16 hand);
virtual int GetHandToHandDamage(void);
virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse);
virtual bool TryFinishingBlow(Mob *defender, int &damage);
virtual void DoRiposte(Mob* defender);
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
@ -248,13 +248,12 @@ public:
uint16 GetPrimarySkillValue();
uint16 MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const;
inline uint16 MaxSkill(EQEmu::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
virtual int GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target = nullptr);
virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false);
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
virtual void RogueAssassinate(Mob* other);
virtual void DoClassAttacks(Mob *target, bool IsRiposte=false);
virtual bool TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse);
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0);
virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg);
bool CanDoSpecialAttack(Mob *other);
virtual int32 CheckAggroAmount(uint16 spellid);
@ -294,6 +293,7 @@ public:
bool UseDiscipline(uint32 spell_id, uint32 target);
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
bool GetNeedsCured(Mob *tar);
bool GetNeedsHateRedux(Mob *tar);
bool HasOrMayGetAggro();
void SetDefaultBotStance();
void CalcChanceToCast();
@ -503,7 +503,6 @@ public:
bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;}
bool GetShowHelm() { return _showhelm; }
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetSTR() const { return STR; }
inline virtual int32 GetSTA() const { return STA; }
inline virtual int32 GetDEX() const { return DEX; }
@ -672,6 +671,8 @@ private:
glm::vec3 m_PreSummonLocation;
uint8 _spellCastingChances[MaxStances][MaxSpellTypes];
Timer evade_timer;
std::shared_ptr<HealRotation> m_member_of_heal_rotation;
std::map<uint32, BotAA> botAAs;

View File

@ -436,6 +436,8 @@ public:
case 10:
if (spells[spell_id].effectdescnum != 65)
break;
if (IsEffectInSpell(spell_id, SE_NegateIfCombat))
break;
entry_prototype = new STMovementSpeedEntry();
entry_prototype->SafeCastToMovementSpeed()->group = BCSpells::IsGroupType(target_type);
break;

View File

@ -617,7 +617,8 @@ bool BotDatabase::LoadBuffs(Bot* bot_inst)
" `caston_x`,"
" `caston_y`,"
" `caston_z`,"
" `extra_di_chance`"
" `extra_di_chance`,"
" `instrument_mod`"
" FROM `bot_buffs`"
" WHERE `bot_id` = '%u'",
bot_inst->GetBotID()
@ -657,6 +658,7 @@ bool BotDatabase::LoadBuffs(Bot* bot_inst)
bot_buffs[buff_count].caston_y = atoi(row[14]);
bot_buffs[buff_count].caston_z = atoi(row[15]);
bot_buffs[buff_count].ExtraDIChance = atoi(row[16]);
bot_buffs[buff_count].instrument_mod = atoi(row[17]);
bot_buffs[buff_count].casterid = 0;
++buff_count;
}

View File

@ -33,6 +33,7 @@ extern volatile bool RunLoops;
#include "../common/eqemu_logsys.h"
#include "../common/features.h"
#include "../common/emu_legacy.h"
#include "../common/spdat.h"
#include "../common/guilds.h"
#include "../common/rulesys.h"
@ -1997,6 +1998,7 @@ void Client::SetGM(bool toggle) {
}
void Client::ReadBook(BookRequest_Struct *book) {
int16 book_language=0;
char *txtfile = book->txtfile;
if(txtfile[0] == '0' && txtfile[1] == '\0') {
@ -2004,7 +2006,7 @@ void Client::ReadBook(BookRequest_Struct *book) {
return;
}
std::string booktxt2 = database.GetBook(txtfile);
std::string booktxt2 = database.GetBook(txtfile, &book_language);
int length = booktxt2.length();
if (booktxt2[0] != '\0') {
@ -2015,21 +2017,47 @@ void Client::ReadBook(BookRequest_Struct *book) {
BookText_Struct *out = (BookText_Struct *) outapp->pBuffer;
out->window = book->window;
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF)
{
const EQEmu::ItemInstance *inst = m_inv[book->invslot];
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) {
// Find out what slot the book was read from.
// SoF+ need to look up book type for the output message.
int16 read_from_slot;
if (book->subslot >= 0) {
uint16 offset;
offset = (book->invslot-23) * 10; // How many packs to skip.
read_from_slot = 251 + offset + book->subslot;
}
else {
read_from_slot = book->invslot -1;
}
const EQEmu::ItemInstance *inst = 0;
if (read_from_slot <= EQEmu::legacy::SLOT_PERSONAL_BAGS_END)
{
inst = m_inv[read_from_slot];
}
if(inst)
out->type = inst->GetItem()->Book;
else
out->type = book->type;
}
else
{
else {
out->type = book->type;
}
out->invslot = book->invslot;
memcpy(out->booktext, booktxt2.c_str(), length);
if (book_language > 0 && book_language < MAX_PP_LANGUAGE) {
if (m_pp.languages[book_language] < 100) {
GarbleMessage(out->booktext, (100 - m_pp.languages[book_language]));
}
}
QueuePacket(outapp);
safe_delete(outapp);
}
@ -6861,16 +6889,46 @@ void Client::SendStatsWindow(Client* client, bool use_window)
indP + "Wind: " + itoa(GetWindMod()) + "<br>";
}
EQEmu::skills::SkillType skill = EQEmu::skills::SkillHandtoHand;
auto *inst = GetInv().GetItem(EQEmu::inventory::slotPrimary);
if (inst && inst->IsClassCommon()) {
switch (inst->GetItem()->ItemType) {
case EQEmu::item::ItemType1HSlash:
skill = EQEmu::skills::Skill1HSlashing;
break;
case EQEmu::item::ItemType2HSlash:
skill = EQEmu::skills::Skill2HSlashing;
break;
case EQEmu::item::ItemType1HPiercing:
skill = EQEmu::skills::Skill1HPiercing;
break;
case EQEmu::item::ItemType1HBlunt:
skill = EQEmu::skills::Skill1HBlunt;
break;
case EQEmu::item::ItemType2HBlunt:
skill = EQEmu::skills::Skill2HBlunt;
break;
case EQEmu::item::ItemType2HPiercing:
if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2)
skill = EQEmu::skills::Skill1HPiercing;
else
skill = EQEmu::skills::Skill2HPiercing;
break;
default:
break;
}
}
std::ostringstream final_string;
final_string <<
/* C/L/R */ indP << "Class: " << class_Name << indS << "Level: " << static_cast<int>(GetLevel()) << indS << "Race: " << race_Name << "<br>" <<
/* Runes */ indP << "Rune: " << rune_number << indL << indS << "Spell Rune: " << magic_rune_number << "<br>" <<
/* HP/M/E */ HME_row <<
/* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")<br>" <<
/* Atk */ indP << "<c \"#CCFF00\">ATK: " << GetTotalATK() << "</c><br>" <<
/* Atk2 */ indP << "- Base: " << GetATKRating() << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "<br>" <<
/* AC */ indP << "<c \"#CCFF00\">AC: " << CalcAC() << "</c><br>" <<
/* AC2 */ indP << "- Mit: " << GetACMit() << " | Avoid: " << GetACAvoid() << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "<br>" <<
/* Atk */ indP << "<c \"#CCFF00\">tohit: " << compute_tohit(skill) << " / " << GetTotalToHit(skill, 0) << "</c><br>" <<
/* Atk2 */ indP << "- Offense: " << offense(skill) << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "<br>" <<
/* AC */ indP << "<c \"#CCFF00\">mitigation AC: " << GetMitigationAC() << "</c><br>" <<
/* AC2 */ indP << "- defense: " << compute_defense() << " / " << GetTotalDefense() << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "<br>" <<
/* Haste */ indP << "<c \"#CCFF00\">Haste: " << GetHaste() << "</c><br>" <<
/* Haste2 */ indP << " - Item: " << itembonuses.haste << " + Spell: " << (spellbonuses.haste + spellbonuses.hastetype2) << " (Cap: " << RuleI(Character, HasteCap) << ") | Over: " << (spellbonuses.hastetype3 + ExtraHaste) << "<br>" <<
/* RunSpeed*/ indP << "<c \"#CCFF00\">Runspeed: " << GetRunspeed() << "</c><br>" <<
@ -6908,7 +6966,9 @@ void Client::SendStatsWindow(Client* client, bool use_window)
client->Message(15, "~~~~~ %s %s ~~~~~", GetCleanName(), GetLastName());
client->Message(0, " Level: %i Class: %i Race: %i DS: %i/%i Size: %1.1f Weight: %.1f/%d ", GetLevel(), GetClass(), GetRace(), GetDS(), RuleI(Character, ItemDamageShieldCap), GetSize(), (float)CalcCurrentWeight() / 10.0f, GetSTR());
client->Message(0, " HP: %i/%i HP Regen: %i/%i",GetHP(), GetMaxHP(), CalcHPRegen(), CalcHPRegenCap());
client->Message(0, " AC: %i ( Mit.: %i + Avoid.: %i + Spell: %i ) | Shield AC: %i", CalcAC(), GetACMit(), GetACAvoid(), spellbonuses.AC, shield_ac);
client->Message(0, " compute_tohit: %i TotalToHit: %i", compute_tohit(skill), GetTotalToHit(skill, 0));
client->Message(0, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense());
client->Message(0, " offense: %i mitigation ac: %i", offense(skill), GetMitigationAC());
if(CalcMaxMana() > 0)
client->Message(0, " Mana: %i/%i Mana Regen: %i/%i", GetMana(), GetMaxMana(), CalcManaRegen(), CalcManaRegenCap());
client->Message(0, " End.: %i/%i End. Regen: %i/%i",GetEndurance(), GetMaxEndurance(), CalcEnduranceRegen(), CalcEnduranceRegenCap());

View File

@ -221,18 +221,18 @@ public:
//abstract virtual function implementations required by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr, int special = 0);
ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return (GetRaid() ? true : false); }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); }
virtual Group* GetGroup() { return entity_list.GetGroupByClient(this); }
virtual inline bool IsBerserk() { return berserk; }
virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
virtual void SetAttackTimer();
int GetQuiverHaste(int delay);
void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false);
int DoDamageCaps(int base_damage);
void AI_Init();
void AI_Start(uint32 iMoveDelay = 0);
@ -418,8 +418,6 @@ public:
virtual void CalcBonuses();
//these are all precalculated now
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
inline virtual int GetHaste() const { return Haste; }
int GetRawACNoShield(int &shield_ac) const;
@ -1292,7 +1290,7 @@ private:
void OPGMEndTraining(const EQApplicationPacket *app);
void OPGMTrainSkill(const EQApplicationPacket *app);
void OPGMSummon(const EQApplicationPacket *app);
void OPCombatAbility(const EQApplicationPacket *app);
void OPCombatAbility(const CombatAbility_Struct *ca_atk);
// Bandolier Methods
void CreateBandolier(const EQApplicationPacket *app);
@ -1301,9 +1299,6 @@ private:
void HandleTraderPriceUpdate(const EQApplicationPacket *app);
int32 CalcAC();
int32 GetACMit();
int32 GetACAvoid();
int32 CalcATK();
int32 CalcItemATKCap();
int32 CalcHaste();

View File

@ -1025,111 +1025,6 @@ int32 Client::acmod()
return 0;
};
// This is a testing formula for AC, the value this returns should be the same value as the one the client shows...
// ac1 and ac2 are probably the damage migitation and damage avoidance numbers, not sure which is which.
// I forgot to include the iksar defense bonus and i cant find my notes now...
// AC from spells are not included (cant even cast spells yet..)
int32 Client::CalcAC()
{
// new formula
int avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9);
if (avoidance < 0) {
avoidance = 0;
}
if (RuleB(Character, EnableAvoidanceCap)) {
if (avoidance > RuleI(Character, AvoidanceCap)) {
avoidance = RuleI(Character, AvoidanceCap);
}
}
int mitigation = 0;
if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) {
//something is wrong with this, naked casters have the wrong natural AC
// mitigation = (spellbonuses.AC/3) + (GetSkill(DEFENSE)/2) + (itembonuses.AC+1);
mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1);
//this might be off by 4..
mitigation -= 4;
}
else {
// mitigation = (spellbonuses.AC/4) + (GetSkill(DEFENSE)/3) + ((itembonuses.AC*4)/3);
mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3);
if (m_pp.class_ == MONK) {
mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close...
}
}
int displayed = 0;
displayed += ((avoidance + mitigation) * 1000) / 847; //natural AC
//Iksar AC, untested
if (GetRace() == IKSAR) {
displayed += 12;
int iksarlevel = GetLevel();
iksarlevel -= 10;
if (iksarlevel > 25) {
iksarlevel = 25;
}
if (iksarlevel > 0) {
displayed += iksarlevel * 12 / 10;
}
}
// Shield AC bonus for HeroicSTR
if (itembonuses.HeroicSTR) {
bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary);
if (equiped) {
uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType;
if (shield == EQEmu::item::ItemTypeShield) {
displayed += itembonuses.HeroicSTR / 2;
}
}
}
//spell AC bonuses are added directly to natural total
displayed += spellbonuses.AC;
AC = displayed;
return (AC);
}
int32 Client::GetACMit()
{
int mitigation = 0;
if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) {
mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1);
mitigation -= 4;
}
else {
mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3);
if (m_pp.class_ == MONK) {
mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close...
}
}
// Shield AC bonus for HeroicSTR
if (itembonuses.HeroicSTR) {
bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary);
if (equiped) {
uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType;
if (shield == EQEmu::item::ItemTypeShield) {
mitigation += itembonuses.HeroicSTR / 2;
}
}
}
return (mitigation * 1000 / 847);
}
int32 Client::GetACAvoid()
{
int32 avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9);
if (avoidance < 0) {
avoidance = 0;
}
if (RuleB(Character, EnableAvoidanceCap)) {
if ((avoidance * 1000 / 847) > RuleI(Character, AvoidanceCap)) {
return RuleI(Character, AvoidanceCap);
}
}
return (avoidance * 1000 / 847);
}
int32 Client::CalcMaxMana()
{
switch (GetCasterClass()) {

View File

@ -4621,7 +4621,8 @@ void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
std::cout << "Wrong size on OP_CombatAbility. Got: " << app->size << ", Expected: " << sizeof(CombatAbility_Struct) << std::endl;
return;
}
OPCombatAbility(app);
auto ca_atk = (CombatAbility_Struct *)app->pBuffer;
OPCombatAbility(ca_atk);
return;
}

View File

@ -35,6 +35,13 @@
#define CON_YELLOW 15
#define CON_RED 13
#define DMG_BLOCKED -1
#define DMG_PARRIED -2
#define DMG_RIPOSTED -3
#define DMG_DODGED -4
#define DMG_INVULNERABLE -5
#define DMG_RUNE -6
//Spell specialization parameters, not sure of a better place for them
#define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized
#define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized
@ -464,9 +471,9 @@ struct StatBonuses {
int8 CriticalMend; // chance critical monk mend
int32 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy
uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg
uint8 HSLevel; // Max Level Headshot will be effective at.
uint8 HSLevel[2]; // Max Level Headshot will be effective at. and chance mod
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
uint8 AssassinateLevel[2]; // Max Level Assassinate will be effective at.
int32 PetMeleeMitigation; // Add AC to owner's pet.
bool IllusionPersistence; // Causes illusions not to fade.
uint16 extra_xtargets; // extra xtarget entries
@ -638,5 +645,23 @@ struct ExtraAttackOptions {
};
struct DamageTable {
int32 max_extra; // max extra damage
int32 chance; // chance not to apply?
int32 minusfactor; // difficulty of rolling
};
struct DamageHitInfo {
//uint16 attacker; // id
//uint16 defender; // id
int base_damage;
int min_damage;
int damage_done;
int offense;
int tohit;
int hand;
EQEmu::skills::SkillType skill;
};
#endif

View File

@ -52,8 +52,8 @@ class Corpse : public Mob {
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; }
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; }
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }

View File

@ -35,9 +35,9 @@ public:
//abstract virtual function implementations required by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; }
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr, int special = 0) {
ExtraAttackOptions *opts = nullptr) {
return false;
}
virtual bool HasRaid() { return false; }

View File

@ -553,7 +553,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
auto mob = entity_list.GetMobID(id);
if (mob) {
++hit_count;
caster->ProcessAttackRounds(mob, opts, 1);
caster->ProcessAttackRounds(mob, opts);
}
}

View File

@ -332,8 +332,10 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch
CastToMob()->AddProcToWeapon(item2->Proc.Effect, true);
eslot = EQEmu::textures::weaponPrimary;
if (item2->Damage > 0)
if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::PrimaryWeaponEquipped);
SetFacestab(true);
}
if (item2->IsType2HWeapon())
SetTwoHanderEquipped(true);
}

View File

@ -1270,12 +1270,6 @@ void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, in
self->DoSpecialAttackDamage(other, static_cast<EQEmu::skills::SkillType>(skill), max_damage, min_damage, hate_override, reuse_time);
}
void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time,
bool hit_chance) {
Lua_Safe_Call_Void();
self->DoSpecialAttackDamage(other, static_cast<EQEmu::skills::SkillType>(skill), max_damage, min_damage, hate_override, reuse_time, hit_chance);
}
void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other) {
Lua_Safe_Call_Void();
self->DoThrowingAttackDmg(other);
@ -2218,7 +2212,6 @@ luabind::scope lua_register_mob() {
.def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int))&Lua_Mob::DoSpecialAttackDamage)
.def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int))&Lua_Mob::DoSpecialAttackDamage)
.def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int,int))&Lua_Mob::DoSpecialAttackDamage)
.def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int,int,bool))&Lua_Mob::DoSpecialAttackDamage)
.def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::DoThrowingAttackDmg)
.def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob,Lua_ItemInst))&Lua_Mob::DoThrowingAttackDmg)
.def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob,Lua_ItemInst,Lua_Item))&Lua_Mob::DoThrowingAttackDmg)

View File

@ -267,7 +267,6 @@ public:
void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage);
void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override);
void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time);
void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time, bool hit_chance);
void DoThrowingAttackDmg(Lua_Mob other);
void DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon);
void DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_Item item);

View File

@ -4426,20 +4426,10 @@ void Merc::DoClassAttacks(Mob *target) {
if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
{
DoAnim(animKick);
int32 dmg = 0;
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){
dmg = -5;
}
else{
if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetKickDamage();
else
dmg = zone->random.Int(1, GetKickDamage());
}
}
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
dmg = DMG_INVULNERABLE;
reuse = KickReuseTime * 1000;
DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse);
@ -4448,19 +4438,10 @@ void Merc::DoClassAttacks(Mob *target) {
else
{
DoAnim(animTailRake);
int32 dmg = 0;
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){
dmg = -5;
}
else{
if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetBashDamage();
else
dmg = zone->random.Int(1, GetBashDamage());
}
}
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
dmg = DMG_INVULNERABLE;
reuse = BashReuseTime * 1000;
DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse);
@ -4474,7 +4455,7 @@ void Merc::DoClassAttacks(Mob *target) {
classattack_timer.Start(reuse / HasteModifier);
}
bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special)
bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts)
{
if (!other) {
SetTarget(nullptr);
@ -4485,7 +4466,7 @@ bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, boo
return NPC::Attack(other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts);
}
void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special)
void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special)
{
if(IsDead() || IsCorpse())
return;

View File

@ -65,9 +65,9 @@ public:
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0);
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return 0; }
@ -197,7 +197,6 @@ public:
virtual void CalcBonuses();
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); }
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetATK() const { return ATK; }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
int32 GetRawACNoShield(int &shield_ac) const;

View File

@ -110,7 +110,9 @@ Mob::Mob(const char* in_name,
m_TargetV(glm::vec3()),
flee_timer(FLEE_CHECK_TIMER),
m_Position(position),
tmHidden(-1)
tmHidden(-1),
mitigation_ac(0),
m_specialattacks(eSpecialAttacks::None)
{
targeted = 0;
tar_ndx=0;
@ -212,6 +214,7 @@ Mob::Mob(const char* in_name,
has_shieldequiped = false;
has_twohandbluntequiped = false;
has_twohanderequipped = false;
can_facestab = false;
has_numhits = false;
has_MGB = false;
has_ProjectIllusion = false;
@ -285,6 +288,8 @@ Mob::Mob(const char* in_name,
armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color;
}
std::fill(std::begin(m_spellHitsLeft), std::end(m_spellHitsLeft), 0);
m_Delta = glm::vec4();
animation = 0;
@ -1497,6 +1502,10 @@ void Mob::ShowStats(Client* client)
if (IsAIControlled()) {
client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange());
}
client->Message(0, " compute_tohit: %i TotalToHit: %i", compute_tohit(EQEmu::skills::SkillHandtoHand), GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0));
client->Message(0, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense());
client->Message(0, " offense: %i mitigation ac: %i", offense(EQEmu::skills::SkillHandtoHand), GetMitigationAC());
}
}
@ -2773,7 +2782,22 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client)
wc->material = GetEquipmentMaterial(material_slot);
wc->elite_material = IsEliteMaterialItem(material_slot);
wc->hero_forge_model = GetHerosForgeModel(material_slot);
#ifdef BOTS
if (IsBot()) {
auto item_inst = CastToBot()->GetBotItem(EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot));
if (item_inst)
wc->color.Color = item_inst->GetColor();
else
wc->color.Color = 0;
}
else {
wc->color.Color = GetEquipmentColor(material_slot);
}
#else
wc->color.Color = GetEquipmentColor(material_slot);
#endif
wc->wear_slot_id = material_slot;
if (!one_client)
@ -4644,7 +4668,7 @@ void Mob::SetRaidGrouped(bool v)
}
}
int16 Mob::GetCriticalChanceBonus(uint16 skill)
int Mob::GetCriticalChanceBonus(uint16 skill)
{
int critical_chance = 0;

View File

@ -54,6 +54,13 @@ namespace EQEmu
class ItemInstance;
}
enum class eSpecialAttacks : int {
None,
Rampage,
AERampage,
ChaoticStab
};
class Mob : public Entity {
public:
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
@ -152,45 +159,54 @@ public:
float HeadingAngleToMob(Mob *other); // to keep consistent with client generated messages
virtual void RangedAttack(Mob* other) { }
virtual void ThrowingAttack(Mob* other) { }
uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg);
// 13 = Primary (default), 14 = secondary
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0;
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0;
void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
int MonkSpecialAttack(Mob* other, uint8 skill_used);
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
bool AvoidDamage(Mob* attacker, int32 &damage, int hand);
bool AvoidDamage(Mob *attacker, DamageHitInfo &hit);
int compute_tohit(EQEmu::skills::SkillType skillinuse);
int GetTotalToHit(EQEmu::skills::SkillType skill, int chance_mod); // compute_tohit + spell bonuses
int compute_defense();
virtual bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0);
virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr);
void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage);
virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse);
uint32 TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse);
uint32 TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime);
int GetTotalDefense(); // compute_defense + spell bonuses
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
virtual bool TryFinishingBlow(Mob *defender, int &damage);
int TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse);
int TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse);
virtual void DoRiposte(Mob* defender);
void ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts = nullptr);
virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr);
virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
void ApplyMeleeDamageMods(uint16 skill, int &damage, Mob * defender = nullptr, ExtraAttackOptions *opts = nullptr);
int ACSum();
int offense(EQEmu::skills::SkillType skill);
void CalcAC() { mitigation_ac = ACSum(); }
int GetACSoftcap();
double GetSoftcapReturns();
int GetClassRaceACBonus();
inline int GetMitigationAC() { return mitigation_ac; }
void MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
double RollD20(int offense, int mitigation); // CALL THIS FROM THE DEFENDER
bool CombatRange(Mob* other);
virtual inline bool IsBerserk() { return false; } // only clients
void RogueEvade(Mob *other);
void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr);
void CommonOutgoingHitSuccess(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
void BreakInvisibleSpells();
virtual void CancelSneakHide();
void CommonBreakInvisible();
void CommonBreakInvisibleFromCombat();
bool HasDied();
virtual bool CheckDualWield();
void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0);
void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0);
void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr);
void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr);
virtual bool CheckDoubleAttack();
// inline process for places where we need to do them outside of the AI_Process
void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0)
void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr)
{
if (target) {
DoMainHandAttackRounds(target, opts, special);
DoMainHandAttackRounds(target, opts);
if (CanThisClassDualWield())
DoOffHandAttackRounds(target, opts, special);
DoOffHandAttackRounds(target, opts);
}
return;
}
@ -357,6 +373,8 @@ public:
inline void SetTwoHandBluntEquiped(bool val) { has_twohandbluntequiped = val; }
bool HasTwoHanderEquipped() { return has_twohanderequipped; }
void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; }
bool CanFacestab() { return can_facestab; }
void SetFacestab(bool val) { can_facestab = val; }
virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { return 0; }
virtual uint32 GetEquipment(uint8 material_slot) const { return(0); }
virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
@ -367,7 +385,7 @@ public:
bool AffectedBySpellExcludingSlot(int slot, int effect);
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) = 0;
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill,
bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) = 0;
bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0;
inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;}
bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false);
inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;}
@ -404,9 +422,10 @@ public:
strn0cpy(name, GetName(), 64); return; };
inline Mob* GetTarget() const { return target; }
virtual void SetTarget(Mob* mob);
inline bool HasTargetReflection() const { return (target && target != this && target->target == this); }
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); }
virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast<int>(cur_hp * 100 / max_hp); }
inline virtual int32 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; }
inline int32 GetAC() const { return AC; }
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
inline virtual int32 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; }
@ -673,7 +692,7 @@ public:
int16 GetMeleeMinDamageMod_SE(uint16 skill);
int16 GetCrippBlowChance();
int16 GetSkillReuseTime(uint16 skill);
int16 GetCriticalChanceBonus(uint16 skill);
int GetCriticalChanceBonus(uint16 skill);
int16 GetSkillDmgAmt(uint16 skill);
bool TryReflectSpell(uint32 spell_id);
bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); }
@ -778,7 +797,8 @@ public:
int32 GetMeleeMitigation();
uint8 GetWeaponDamageBonus(const EQEmu::ItemData* weapon, bool offhand = false);
uint16 GetDamageTable(EQEmu::skills::SkillType skillinuse);
const DamageTable &GetDamageTable() const;
void ApplyDamageTable(DamageHitInfo &hit);
virtual int GetHandToHandDamage(void);
bool CanThisClassDoubleAttack(void) const;
@ -801,9 +821,9 @@ public:
int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker);
int32 ReduceAllDamage(int32 damage);
virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true);
void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10);
virtual void DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemData* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f);
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0);
void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0);
virtual void DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemInstance* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f);
bool TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, int AmmoSlot, float speed);
void ProjectileAttack();
@ -816,6 +836,7 @@ public:
bool AddRampage(Mob*);
void ClearRampage();
void AreaRampage(ExtraAttackOptions *opts);
inline bool IsSpecialAttack(eSpecialAttacks in) { return m_specialattacks == in; }
void StartEnrage();
void ProcessEnrage();
@ -1042,7 +1063,7 @@ public:
#endif
protected:
void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0);
void CommonDamage(Mob* other, int &damage, const uint16 spell_id, const EQEmu::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
float _GetMovementSpeed(int mod) const;
int _GetWalkSpeed() const;
@ -1079,6 +1100,7 @@ protected:
bool multitexture;
int AC;
int mitigation_ac; // cached Mob::ACSum
int32 ATK;
int32 STR;
int32 STA;
@ -1150,6 +1172,7 @@ protected:
int base_walkspeed;
int base_fearspeed;
int current_speed;
eSpecialAttacks m_specialattacks;
uint32 pLastChange;
bool held;
@ -1168,15 +1191,14 @@ protected:
void ExecWeaponProc(const EQEmu::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1);
virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::inventory::slotPrimary);
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::inventory::slotPrimary, Mob *on = nullptr);
virtual float GetSpecialProcChances(uint16 hand);
virtual float GetAssassinateProcChances(uint16 ReuseTime);
virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm?
uint16 GetWeaponSpeedbyHand(uint16 hand);
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
int GetKickDamage();
int GetBashDamage();
virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg);
#ifdef BOTS
virtual
#endif
int GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target = nullptr);
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
@ -1211,7 +1233,7 @@ protected:
Timer attack_dw_timer;
Timer ranged_timer;
float attack_speed; //% increase/decrease in attack speed (not haste)
int8 attack_delay; //delay between attacks in 10ths of seconds
int attack_delay; //delay between attacks in 10ths of seconds
int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
Timer tic_timer;
Timer mana_timer;
@ -1278,6 +1300,7 @@ protected:
bool has_shieldequiped;
bool has_twohandbluntequiped;
bool has_twohanderequipped;
bool can_facestab;
bool has_numhits;
bool has_MGB;
bool has_ProjectIllusion;
@ -1394,7 +1417,8 @@ protected:
glm::vec3 m_TargetRing;
uint32 m_spellHitsLeft[38]; // Used to track which spells will have their numhits incremented when spell finishes casting, 38 Buffslots
// we might want to do this differently, we gotta do max NPC buffs ... which is 97
uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting
int flymode;
bool m_targetable;
int QGVarDuration(const char *fmt);

View File

@ -1160,11 +1160,8 @@ void Mob::AI_Process() {
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){
if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] || aabonuses.PC_Pet_Rampage[0]){
int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] + aabonuses.PC_Pet_Rampage[0];
int dmg_mod = spellbonuses.PC_Pet_Rampage[1] + itembonuses.PC_Pet_Rampage[1] + aabonuses.PC_Pet_Rampage[1];
if(zone->random.Roll(chance)) {
ExtraAttackOptions opts;
opts.damage_percent = dmg_mod / 100.0f;
Rampage(&opts);
Rampage(nullptr);
}
}
}
@ -1175,12 +1172,7 @@ void Mob::AI_Process() {
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
if(cur > 0) {
opts.damage_percent = cur / 100.0f;
}
cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3);
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3);
if(cur > 0) {
opts.damage_flat = cur;
}
@ -1215,12 +1207,7 @@ void Mob::AI_Process() {
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
if(cur > 0) {
opts.damage_percent = cur / 100.0f;
}
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3);
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3);
if(cur > 0) {
opts.damage_flat = cur;
}
@ -1992,6 +1979,8 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
rampage_targets = RuleI(Combat, DefaultRampageTargets);
if (rampage_targets > RuleI(Combat, MaxRampageTargets))
rampage_targets = RuleI(Combat, MaxRampageTargets);
m_specialattacks = eSpecialAttacks::Rampage;
for (int i = 0; i < RampageArray.size(); i++) {
if (index_hit >= rampage_targets)
break;
@ -2001,14 +1990,16 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
if (m_target == GetTarget())
continue;
if (CombatRange(m_target)) {
ProcessAttackRounds(m_target, opts, 2);
ProcessAttackRounds(m_target, opts);
index_hit++;
}
}
}
if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets)
ProcessAttackRounds(GetTarget(), opts, 2);
ProcessAttackRounds(GetTarget(), opts);
m_specialattacks = eSpecialAttacks::None;
return true;
}
@ -2024,10 +2015,12 @@ void Mob::AreaRampage(ExtraAttackOptions *opts)
int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1);
rampage_targets = rampage_targets > 0 ? rampage_targets : -1;
m_specialattacks = eSpecialAttacks::AERampage;
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
if(index_hit == 0)
ProcessAttackRounds(GetTarget(), opts, 1);
ProcessAttackRounds(GetTarget(), opts);
m_specialattacks = eSpecialAttacks::None;
}
uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) {

View File

@ -201,6 +201,9 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
CalcNPCDamage();
}
base_damage = round((max_dmg - min_dmg) / 1.9);
min_damage = min_dmg - round(base_damage / 10.0);
accuracy_rating = d->accuracy_rating;
avoidance_rating = d->avoidance_rating;
ATK = d->ATK;
@ -1054,7 +1057,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->WIS = 150;
npc_type->CHA = 150;
npc_type->attack_delay = 30;
npc_type->attack_delay = 3000;
npc_type->prim_melee_type = 28;
npc_type->sec_melee_type = 28;
@ -1956,10 +1959,10 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
id[i] = std::tolower(id[i]);
}
if(id == "ac") { AC = atoi(val.c_str()); return; }
if(id == "ac") { AC = atoi(val.c_str()); CalcAC(); return; }
else if(id == "str") { STR = atoi(val.c_str()); return; }
else if(id == "sta") { STA = atoi(val.c_str()); return; }
else if(id == "agi") { AGI = atoi(val.c_str()); return; }
else if(id == "agi") { AGI = atoi(val.c_str()); CalcAC(); return; }
else if(id == "dex") { DEX = atoi(val.c_str()); return; }
else if(id == "wis") { WIS = atoi(val.c_str()); CalcMaxMana(); return; }
else if(id == "int" || id == "_int") { INT = atoi(val.c_str()); CalcMaxMana(); return; }
@ -1984,13 +1987,25 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
else if(id == "special_attacks") { NPCSpecialAttacks(val.c_str(), 0, 1); return; }
else if(id == "special_abilities") { ProcessSpecialAbilities(val.c_str()); return; }
else if(id == "attack_speed") { attack_speed = (float)atof(val.c_str()); CalcBonuses(); return; }
else if(id == "attack_delay") { attack_delay = atoi(val.c_str()); CalcBonuses(); return; }
else if(id == "attack_delay") { /* TODO: fix DB */attack_delay = atoi(val.c_str()) * 100; CalcBonuses(); return; }
else if(id == "atk") { ATK = atoi(val.c_str()); return; }
else if(id == "accuracy") { accuracy_rating = atoi(val.c_str()); return; }
else if(id == "avoidance") { avoidance_rating = atoi(val.c_str()); return; }
else if(id == "trackable") { trackable = atoi(val.c_str()); return; }
else if(id == "min_hit") { min_dmg = atoi(val.c_str()); return; }
else if(id == "max_hit") { max_dmg = atoi(val.c_str()); return; }
else if(id == "min_hit") {
min_dmg = atoi(val.c_str());
// TODO: fix DB
base_damage = round((max_dmg - min_dmg) / 1.9);
min_damage = min_dmg - round(base_damage / 10.0);
return;
}
else if(id == "max_hit") {
max_dmg = atoi(val.c_str());
// TODO: fix DB
base_damage = round((max_dmg - min_dmg) / 1.9);
min_damage = min_dmg - round(base_damage / 10.0);
return;
}
else if(id == "attack_count") { attack_count = atoi(val.c_str()); return; }
else if(id == "see_invis") { see_invis = atoi(val.c_str()); return; }
else if(id == "see_invis_undead") { see_invis_undead = atoi(val.c_str()); return; }

View File

@ -109,9 +109,9 @@ public:
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0);
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
@ -259,9 +259,11 @@ public:
uint32 GetMaxDMG() const {return max_dmg;}
uint32 GetMinDMG() const {return min_dmg;}
int GetBaseDamage() const { return base_damage; }
int GetMinDamage() const { return min_damage; }
float GetSlowMitigation() const { return slow_mitigation; }
float GetAttackSpeed() const {return attack_speed;}
uint8 GetAttackDelay() const {return attack_delay;}
int GetAttackDelay() const {return attack_delay;}
bool IsAnimal() const { return(bodytype == BT_Animal); }
uint16 GetPetSpellID() const {return pet_spell_id;}
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
@ -463,6 +465,8 @@ protected:
uint32 max_dmg;
uint32 min_dmg;
int base_damage;
int min_damage;
int32 accuracy_rating;
int32 avoidance_rating;
int16 attack_count;

View File

@ -225,8 +225,7 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint
{
user = nullptr;
last_user = nullptr;
EQEmu::ItemInstance* inst = nullptr;
inst = new EQEmu::ItemInstance(ItemInstWorldContainer);
EQEmu::ItemInstance* inst = new EQEmu::ItemInstance(ItemInstWorldContainer);
// Initialize members
m_id = 0;
@ -257,6 +256,8 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint
strcpy(m_data.object_name, model);
else
strcpy(m_data.object_name, "IT64_ACTORDEF"); //default object name if model isn't specified for some unknown reason
safe_delete(inst);
}
Object::~Object()

File diff suppressed because it is too large Load Diff

View File

@ -5566,6 +5566,7 @@ void Client::InitializeBuffSlots()
for(int x = 0; x < max_slots; ++x)
{
buffs[x].spellid = SPELL_UNKNOWN;
buffs[x].UpdateClient = false;
}
current_buff_count = 0;
}
@ -5582,6 +5583,7 @@ void NPC::InitializeBuffSlots()
for(int x = 0; x < max_slots; ++x)
{
buffs[x].spellid = SPELL_UNKNOWN;
buffs[x].UpdateClient = false;
}
current_buff_count = 0;
}

View File

@ -486,7 +486,7 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh
}
damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating);
//damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating);
}
if (damage < 0)
@ -539,7 +539,7 @@ int32 Client::Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 mi
float mit_rating, float atk_rating)
{
if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules))
return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating);
return 0; //Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating);
int d = 10;
// floats for the rounding issues
float dmg_interval = (damage - minhit) / 19.0;
@ -613,7 +613,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage)
}
int min_hit = 1;
int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100;
int max_hit = 2;//(2*weapon_damage*GetDamageTable(skillinuse)) / 100;
if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10))
max_hit = (RuleI(Combat, HitCapPre10));
@ -1086,4 +1086,4 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, EQEmu::skills::Skil
}
return(chancetohit);
}
}

View File

@ -2133,7 +2133,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
temp_npctype_data->healscale = atoi(row[87]);
temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true: false;
temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false: true;
temp_npctype_data->attack_delay = atoi(row[90]);
temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB
temp_npctype_data->light = (atoi(row[91]) & 0x0F);
temp_npctype_data->armtexture = atoi(row[92]);

View File

@ -110,7 +110,7 @@ struct NPCType
uint8 spawn_limit; //only this many may be in zone at a time (0=no limit)
uint8 mount_color; //only used by horse class
float attack_speed; //%+- on attack delay of the mob.
uint8 attack_delay; //delay between attacks in 10ths of a second
int attack_delay; //delay between attacks in ms
int accuracy_rating; // flat bonus before mods
int avoidance_rating; // flat bonus before mods
bool findable; //can be found with find command