aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dep/CMakeLists.txt2
-rw-r--r--dep/PackageList.txt8
-rw-r--r--dep/StormLib/CMakeLists.txt272
-rw-r--r--dep/StormLib/doc/History.txt62
-rw-r--r--dep/StormLib/doc/Sector Offset MD5.txt25
-rw-r--r--dep/StormLib/doc/The MoPaQ File Format 0.9.txt318
-rw-r--r--dep/StormLib/doc/The MoPaQ File Format 1.0.txt433
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-deDE.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-enGB.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-enSG.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-enUS.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-esES.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-esMX.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-frFR.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-itIT.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-koKR.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-plPL.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-ptBR.txt1
-rw-r--r--dep/StormLib/doc/d3-authenticationcode-zhTW.txt1
-rw-r--r--dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob49
-rw-r--r--dep/StormLib/doc/diablo3_urls.txt14
-rw-r--r--dep/StormLib/src/FileStream.cpp2294
-rw-r--r--dep/StormLib/src/FileStream.h189
-rw-r--r--dep/StormLib/src/SBaseCommon.cpp1700
-rw-r--r--dep/StormLib/src/SBaseDumpData.cpp144
-rw-r--r--dep/StormLib/src/SBaseFileTable.cpp2550
-rw-r--r--dep/StormLib/src/SCompression.cpp1135
-rw-r--r--dep/StormLib/src/SFileAddFile.cpp1286
-rw-r--r--dep/StormLib/src/SFileAttributes.cpp477
-rw-r--r--dep/StormLib/src/SFileCompactArchive.cpp765
-rw-r--r--dep/StormLib/src/SFileCreateArchive.cpp255
-rw-r--r--dep/StormLib/src/SFileExtractFile.cpp67
-rw-r--r--dep/StormLib/src/SFileFindFile.cpp446
-rw-r--r--dep/StormLib/src/SFileListFile.cpp557
-rw-r--r--dep/StormLib/src/SFileOpenArchive.cpp470
-rw-r--r--dep/StormLib/src/SFileOpenFileEx.cpp469
-rw-r--r--dep/StormLib/src/SFilePatchArchives.cpp587
-rw-r--r--dep/StormLib/src/SFileReadFile.cpp1183
-rw-r--r--dep/StormLib/src/SFileVerify.cpp921
-rw-r--r--dep/StormLib/src/StormCommon.h274
-rw-r--r--dep/StormLib/src/StormLib.h984
-rw-r--r--dep/StormLib/src/StormPort.h235
-rw-r--r--dep/StormLib/src/adpcm/adpcm.cpp358
-rw-r--r--dep/StormLib/src/adpcm/adpcm.h22
-rw-r--r--dep/StormLib/src/bzip2/blocksort.c1094
-rw-r--r--dep/StormLib/src/bzip2/bzlib.c1573
-rw-r--r--dep/StormLib/src/bzip2/bzlib.h282
-rw-r--r--dep/StormLib/src/bzip2/bzlib_private.h509
-rw-r--r--dep/StormLib/src/bzip2/compress.c672
-rw-r--r--dep/StormLib/src/bzip2/crctable.c104
-rw-r--r--dep/StormLib/src/bzip2/decompress.c626
-rw-r--r--dep/StormLib/src/bzip2/huffman.c205
-rw-r--r--dep/StormLib/src/bzip2/randtable.c84
-rw-r--r--dep/StormLib/src/huffman/huff.cpp1303
-rw-r--r--dep/StormLib/src/huffman/huff.h142
-rw-r--r--dep/StormLib/src/huffman/huff_patch.cpp1120
-rw-r--r--dep/StormLib/src/huffman/huff_patch.h145
-rw-r--r--dep/StormLib/src/jenkins/lookup.h24
-rw-r--r--dep/StormLib/src/jenkins/lookup3.c1003
-rw-r--r--dep/StormLib/src/libtomcrypt/src/hashes/hash_memory.c69
-rw-r--r--dep/StormLib/src/libtomcrypt/src/hashes/md5.c368
-rw-r--r--dep/StormLib/src/libtomcrypt/src/hashes/sha1.c288
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt.h87
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h38
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h136
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h891
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h424
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h378
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h384
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h424
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h500
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h23
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h558
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h89
-rw-r--r--dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h199
-rw-r--r--dep/StormLib/src/libtomcrypt/src/math/ltm_desc.c483
-rw-r--r--dep/StormLib/src/libtomcrypt/src/math/multi.c61
-rw-r--r--dep/StormLib/src/libtomcrypt/src/math/rand_prime.c87
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/base64_decode.c104
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c30
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c40
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c41
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c27
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c36
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_libc.c43
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c13
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c26
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c36
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c54
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c54
-rw-r--r--dep/StormLib/src/libtomcrypt/src/misc/zeromem.c34
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c102
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c47
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c182
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c96
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c110
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c99
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c91
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c96
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c287
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c386
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c139
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c68
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c127
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c111
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c54
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c35
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c194
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c82
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c89
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c53
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c166
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c169
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c70
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c46
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c83
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c65
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c76
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c207
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c222
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c60
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c196
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c147
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c108
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c189
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c177
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c110
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c113
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c34
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c143
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c112
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c167
-rw-r--r--dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c87
-rw-r--r--dep/StormLib/src/libtommath/bn_fast_mp_invmod.c148
-rw-r--r--dep/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c172
-rw-r--r--dep/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c107
-rw-r--r--dep/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c98
-rw-r--r--dep/StormLib/src/libtommath/bn_fast_s_mp_sqr.c114
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_2expt.c48
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_abs.c43
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_add.c53
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_add_d.c112
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_addmod.c41
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_and.c57
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_clamp.c44
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_clear.c44
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_clear_multi.c34
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_cmp.c43
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_cmp_d.c44
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_cmp_mag.c55
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_cnt_lsb.c53
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_copy.c68
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_count_bits.c45
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_div.c292
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_div_2.c68
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_div_2d.c97
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_div_3.c79
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_div_d.c115
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_dr_is_modulus.c43
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_dr_reduce.c94
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_dr_setup.c32
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_exch.c34
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_expt_d.c57
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_exptmod.c112
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_exptmod_fast.c321
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_exteuclid.c82
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_fread.c67
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_fwrite.c52
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_gcd.c105
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_get_int.c45
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_grow.c57
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init.c46
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init_copy.c32
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init_multi.c59
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init_set.c32
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init_set_int.c31
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_init_size.c48
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_invmod.c43
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_invmod_slow.c175
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_is_square.c109
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_jacobi.c105
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_karatsuba_mul.c167
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c121
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_lcm.c60
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_lshd.c67
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mod.c48
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mod_2d.c55
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mod_d.c27
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c59
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_montgomery_reduce.c118
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_montgomery_setup.c59
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mul.c66
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mul_2.c82
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mul_2d.c85
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mul_d.c79
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_mulmod.c40
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_n_root.c132
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_neg.c40
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_or.c50
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_fermat.c62
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_is_divisible.c50
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_is_prime.c83
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c103
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_next_prime.c170
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c52
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_prime_random_ex.c125
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_radix_size.c78
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_radix_smap.c24
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_rand.c55
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_read_radix.c85
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_read_signed_bin.c41
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c55
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce.c100
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_2k.c61
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_2k_l.c62
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c47
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c44
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_is_2k.c52
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c44
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_reduce_setup.c34
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_rshd.c72
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_set.c29
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_set_int.c48
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_shrink.c35
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_signed_bin_size.c27
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_sqr.c58
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_sqrmod.c41
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_sqrt.c81
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_sub.c59
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_sub_d.c93
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_submod.c42
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_to_signed_bin.c33
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c31
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c48
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c31
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_toom_mul.c284
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_toom_sqr.c226
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_toradix.c75
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_toradix_n.c88
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c28
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_xor.c51
-rw-r--r--dep/StormLib/src/libtommath/bn_mp_zero.c36
-rw-r--r--dep/StormLib/src/libtommath/bn_prime_tab.c61
-rw-r--r--dep/StormLib/src/libtommath/bn_reverse.c39
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_add.c109
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_exptmod.c252
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_mul_digs.c90
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c81
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_sqr.c84
-rw-r--r--dep/StormLib/src/libtommath/bn_s_mp_sub.c89
-rw-r--r--dep/StormLib/src/libtommath/bncore.c36
-rw-r--r--dep/StormLib/src/libtommath/tommath.h584
-rw-r--r--dep/StormLib/src/libtommath/tommath_class.h999
-rw-r--r--dep/StormLib/src/libtommath/tommath_superclass.h76
-rw-r--r--dep/StormLib/src/lzma/C/LzFind.c761
-rw-r--r--dep/StormLib/src/lzma/C/LzFind.h115
-rw-r--r--dep/StormLib/src/lzma/C/LzFindMt.c793
-rw-r--r--dep/StormLib/src/lzma/C/LzFindMt.h105
-rw-r--r--dep/StormLib/src/lzma/C/LzHash.h54
-rw-r--r--dep/StormLib/src/lzma/C/LzmaDec.c999
-rw-r--r--dep/StormLib/src/lzma/C/LzmaDec.h231
-rw-r--r--dep/StormLib/src/lzma/C/LzmaEnc.c2268
-rw-r--r--dep/StormLib/src/lzma/C/LzmaEnc.h80
-rw-r--r--dep/StormLib/src/lzma/C/Threads.c84
-rw-r--r--dep/StormLib/src/lzma/C/Threads.h59
-rw-r--r--dep/StormLib/src/lzma/C/Types.h236
-rw-r--r--dep/StormLib/src/lzma/info.txt1
-rw-r--r--dep/StormLib/src/pklib/crc32.c66
-rw-r--r--dep/StormLib/src/pklib/explode.c522
-rw-r--r--dep/StormLib/src/pklib/implode.c769
-rw-r--r--dep/StormLib/src/pklib/pklib.h148
-rw-r--r--dep/StormLib/src/sparse/sparse.cpp292
-rw-r--r--dep/StormLib/src/sparse/sparse.h19
-rw-r--r--dep/StormLib/src/zlib/adler32.c149
-rw-r--r--dep/StormLib/src/zlib/compress2.c79
-rw-r--r--dep/StormLib/src/zlib/crc32.c423
-rw-r--r--dep/StormLib/src/zlib/crc32.h441
-rw-r--r--dep/StormLib/src/zlib/deflate.c1736
-rw-r--r--dep/StormLib/src/zlib/deflate.h331
-rw-r--r--dep/StormLib/src/zlib/inffast.c318
-rw-r--r--dep/StormLib/src/zlib/inffast.h11
-rw-r--r--dep/StormLib/src/zlib/inffixed.h94
-rw-r--r--dep/StormLib/src/zlib/inflate.c1368
-rw-r--r--dep/StormLib/src/zlib/inflate.h115
-rw-r--r--dep/StormLib/src/zlib/inftrees.c329
-rw-r--r--dep/StormLib/src/zlib/inftrees.h55
-rw-r--r--dep/StormLib/src/zlib/trees.c1219
-rw-r--r--dep/StormLib/src/zlib/trees.h128
-rw-r--r--dep/StormLib/src/zlib/zconf.h332
-rw-r--r--dep/StormLib/src/zlib/zlib.h1357
-rw-r--r--dep/StormLib/src/zlib/zutil.c318
-rw-r--r--dep/StormLib/src/zlib/zutil.h269
-rw-r--r--dep/StormLib/storm_dll/storm_dll.cpp117
-rw-r--r--dep/StormLib/storm_dll/storm_dll.def25
-rw-r--r--dep/StormLib/storm_dll/storm_dll.h67
-rw-r--r--dep/StormLib/stormlib_dll/DllMain.c24
-rw-r--r--dep/StormLib/stormlib_dll/StormLib.def76
-rw-r--r--dep/StormLib/stormlib_dll/StormLib.exp75
-rw-r--r--dep/StormLib/test/Test.cpp1892
-rw-r--r--dep/StormLib/test/x86_ripped_code.asm1231
-rw-r--r--dep/StormLib/test/x86_starcraft_lzma.asm11066
-rw-r--r--dep/libmpq/AUTHORS10
-rw-r--r--dep/libmpq/CMakeLists.txt34
-rw-r--r--dep/libmpq/COPYING339
-rw-r--r--dep/libmpq/FAQ68
-rw-r--r--dep/libmpq/INSTALL182
-rw-r--r--dep/libmpq/Makefile.am26
-rw-r--r--dep/libmpq/NEWS76
-rw-r--r--dep/libmpq/README34
-rw-r--r--dep/libmpq/THANKS21
-rw-r--r--dep/libmpq/TODO10
-rw-r--r--dep/libmpq/autogen.sh19
-rw-r--r--dep/libmpq/bindings/Makefile.am6
-rw-r--r--dep/libmpq/bindings/d/Makefile.am6
-rw-r--r--dep/libmpq/bindings/d/dsss.conf2
-rw-r--r--dep/libmpq/bindings/d/mpq.d318
-rw-r--r--dep/libmpq/bindings/python/Makefile.am5
-rw-r--r--dep/libmpq/bindings/python/mpq-info16
-rw-r--r--dep/libmpq/bindings/python/mpq.py322
-rw-r--r--dep/libmpq/config.h74
-rw-r--r--dep/libmpq/configure.ac84
-rw-r--r--dep/libmpq/debian/changelog35
-rw-r--r--dep/libmpq/debian/compat1
-rw-r--r--dep/libmpq/debian/control50
-rw-r--r--dep/libmpq/debian/copyright23
-rw-r--r--dep/libmpq/debian/libmpq-dev.dirs6
-rw-r--r--dep/libmpq/debian/libmpq-dev.install6
-rw-r--r--dep/libmpq/debian/libmpq0.dirs1
-rw-r--r--dep/libmpq/debian/libmpq0.docs6
-rw-r--r--dep/libmpq/debian/libmpq0.install1
-rw-r--r--dep/libmpq/debian/python-mpq.install1
-rw-r--r--dep/libmpq/debian/rules112
-rw-r--r--dep/libmpq/doc/Makefile.am5
-rw-r--r--dep/libmpq/doc/man1/Makefile.am9
-rw-r--r--dep/libmpq/doc/man1/libmpq-config.169
-rw-r--r--dep/libmpq/doc/man3/Makefile.am31
-rw-r--r--dep/libmpq/doc/man3/libmpq.3207
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_close.357
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_files.350
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_offset.351
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_open.371
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_packed_size.351
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_unpacked_size.351
-rw-r--r--dep/libmpq/doc/man3/libmpq__archive_version.348
-rw-r--r--dep/libmpq/doc/man3/libmpq__block_close_offset.353
-rw-r--r--dep/libmpq/doc/man3/libmpq__block_open_offset.365
-rw-r--r--dep/libmpq/doc/man3/libmpq__block_read.378
-rw-r--r--dep/libmpq/doc/man3/libmpq__block_unpacked_size.359
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_blocks.354
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_compressed.354
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_encrypted.354
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_imploded.354
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_number.352
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_offset.355
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_packed_size.355
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_read.377
-rw-r--r--dep/libmpq/doc/man3/libmpq__file_unpacked_size.355
-rw-r--r--dep/libmpq/doc/man3/libmpq__strerror.345
-rw-r--r--dep/libmpq/doc/man3/libmpq__version.345
-rw-r--r--dep/libmpq/libmpq-config.in57
-rw-r--r--dep/libmpq/libmpq.pc.in10
-rw-r--r--dep/libmpq/libmpq/Makefile.am23
-rw-r--r--dep/libmpq/libmpq/common.c220
-rw-r--r--dep/libmpq/libmpq/common.h61
-rw-r--r--dep/libmpq/libmpq/crypt_buf.h217
-rw-r--r--dep/libmpq/libmpq/explode.c602
-rw-r--r--dep/libmpq/libmpq/explode.h87
-rw-r--r--dep/libmpq/libmpq/extract.c361
-rw-r--r--dep/libmpq/libmpq/extract.h106
-rw-r--r--dep/libmpq/libmpq/huffman.c1101
-rw-r--r--dep/libmpq/libmpq/huffman.h151
-rw-r--r--dep/libmpq/libmpq/mpq-internal.h145
-rw-r--r--dep/libmpq/libmpq/mpq.c1004
-rw-r--r--dep/libmpq/libmpq/mpq.h101
-rw-r--r--dep/libmpq/libmpq/pack_begin.h34
-rw-r--r--dep/libmpq/libmpq/pack_end.h31
-rw-r--r--dep/libmpq/libmpq/platform.h28
-rw-r--r--dep/libmpq/libmpq/wave.c250
-rw-r--r--dep/libmpq/libmpq/wave.h45
-rw-r--r--dep/libmpq/tools/Makefile.am8
-rw-r--r--dep/libmpq/tools/crypt_buf_gen.c85
-rw-r--r--dep/libmpq/win/config.h81
-rw-r--r--dep/libmpq/win/dirent.h230
-rw-r--r--dep/libmpq/win/stdint.h247
-rw-r--r--sql/base/auth_database.sql8
-rw-r--r--sql/base/characters_database.sql259
-rw-r--r--sql/old/3.3.5a/2011_12_13_02_creature_template_addon.sql2
-rw-r--r--sql/old/3.3.5a/2011_12_14_01_gameobject_template.sql1
-rw-r--r--sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_13_00_world_misc.sql2
-rw-r--r--sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_creature_template.sql2
-rw-r--r--sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_spell_bonus_data.sql2
-rw-r--r--sql/old/3.3.5a/TDB48_to_TDB49_updates/world/2012_09_09_02_world_spell_script_names.sql14
-rw-r--r--sql/old/3.3.5a/TDB49_to_TDB50_updates/world/2012_12_18_00_characters_worldstates.sql5
-rw-r--r--sql/old/4.2.2/2011_11_24_01_world_command_4x.sql2
-rw-r--r--sql/old/4.2.2/2011_11_24_02_world_player_xp_for_level_4x.sql7
-rw-r--r--sql/old/4.2.2/2011_11_25_00_characters_character_stats_4x.sql5
-rw-r--r--sql/old/4.2.2/2011_11_25_01_characters_characters_4x.sql5
-rw-r--r--sql/old/4.2.2/2011_11_25_02_characters_character_pet_4x.sql1
-rw-r--r--sql/old/4.2.2/2011_11_25_02_world_item_script_names_4x.sql17
-rw-r--r--sql/old/4.2.2/2011_11_25_02_world_item_template_4x.sql43
-rw-r--r--sql/old/4.2.2/2011_11_25_02_world_item_template_addon_4x.sql43
-rw-r--r--sql/old/4.2.2/2011_11_25_03_characters_character_stats_4x.sql7
-rw-r--r--sql/old/4.2.2/2011_11_25_03_characters_characters_4x.sql9
-rw-r--r--sql/old/4.2.2/2011_11_25_03_characters_corpse_4x.sql1
-rw-r--r--sql/old/4.2.2/2011_11_26_00_characters_characters_4x.sql5
-rw-r--r--sql/old/4.2.2/2011_11_26_02_world_quest_template_4x.sql31
-rw-r--r--sql/old/4.2.2/2011_11_26_03_world_disenchant_loot_template_4x.sql225
-rw-r--r--sql/old/4.2.2/2011_11_26_07_world_startinfo_4x.sql4730
-rw-r--r--sql/old/4.2.2/2011_11_26_08_world_creature_template_4x.sql2
-rw-r--r--sql/old/4.2.2/2011_11_27_00_world_player_levelstats_4x.sql66
-rw-r--r--sql/old/4.2.2/2011_11_28_00_world_gameobject_template_4x.sql9
-rw-r--r--sql/old/4.2.2/2011_12_18_01_world_player_classlevelstats_4x.sql64
-rw-r--r--sql/old/4.2.2/2011_12_18_02_world_player_levelstats_4x.sql1920
-rw-r--r--sql/old/4.2.2/2011_12_21_00_world_locales_quest_4x.sql34
-rw-r--r--sql/old/4.2.2/2011_12_26_00_world_achievement_criteria_data_4x.sql3
-rw-r--r--sql/old/4.2.2/2012_01_10_00_auth_account_4x.sql1
-rw-r--r--sql/old/4.2.2/2012_01_29_00_characters_characters_4x.sql1
-rw-r--r--sql/old/4.2.2/2012_01_29_01_characters_characters_4x.sql2
-rw-r--r--sql/old/4.2.2/2012_01_31_01_world_hotfix_data_4x.sql42
-rw-r--r--sql/old/4.2.2/2012_01_31_02_world_hotfix_data_4x.sql5
-rw-r--r--sql/old/4.2.2/2012_05_30_00_characters_characters_4x.sql2
-rw-r--r--sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_4x.sql24
-rw-r--r--sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_progress_4x.sql25
-rw-r--r--sql/old/4.2.2/2012_07_14_00_world_item_template_4x.sql4
-rw-r--r--sql/old/4.2.2/2012_07_19_00_world_item_template_4x.sql3
-rw-r--r--sql/old/4.3.4/2012_07_03_00_world_item_template_addon_434.sql1
-rw-r--r--sql/old/4.3.4/2012_07_05_00_world_item_template_addon_434.sql1
-rw-r--r--sql/old/4.3.4/2012_07_10_00_characters_character_glyphs_434.sql4
-rw-r--r--sql/old/4.3.4/2012_07_18_00_characters_characters_434.sql1
-rw-r--r--sql/old/4.3.4/2012_07_23_00_auth_realmlist_434.sql1
-rw-r--r--sql/old/4.3.4/2012_07_24_00_characters_various_434.sql3
-rw-r--r--sql/old/4.3.4/2012_07_30_00_characters_void_storage_434.sql11
-rw-r--r--sql/old/4.3.4/2012_07_30_01_characters_void_storage_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_01_00_characters_item_instance_434.sql11
-rw-r--r--sql/old/4.3.4/2012_08_04_01_world_player_classlevelstats_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_05_01_world_item_set_names_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_05_02_world_command_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_06_00_world_classlevelstats_434.sql7
-rw-r--r--sql/old/4.3.4/2012_08_06_00_world_command_434.sql4
-rw-r--r--sql/old/4.3.4/2012_08_06_01_world_classlevelstats_434.sql6
-rw-r--r--sql/old/4.3.4/2012_08_07_00_characters_characters_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_07_01_characters_void_storage_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_08_00_world_creature_template_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_12_00_world_misc_434.sql59
-rw-r--r--sql/old/4.3.4/2012_08_12_03_world_misc_434.sql38
-rw-r--r--sql/old/4.3.4/2012_08_13_00_world_quest_template_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_14_00_world_event_ai_434.sql3
-rw-r--r--sql/old/4.3.4/2012_08_14_00_world_reputation_spillover_template_434.sql13
-rw-r--r--sql/old/4.3.4/2012_08_14_01_world_commands_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_14_02_world_npc_vendor_434.sql6
-rw-r--r--sql/old/4.3.4/2012_08_15_00_world_quest_template_434.sql2
-rw-r--r--sql/old/4.3.4/2012_08_15_01_world_misc_434.sql3
-rw-r--r--sql/old/4.3.4/2012_08_15_01_world_spell_script_names_434.sql5
-rw-r--r--sql/old/4.3.4/2012_08_15_02_world_quest_template_434.sql5
-rw-r--r--sql/old/4.3.4/2012_08_15_03_world_rep_spillover_template_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_20_00_world_quest_template_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_22_00_characters_characters_434.sql1
-rw-r--r--sql/old/4.3.4/2012_08_23_00_characters_guild_member434.sql4
-rw-r--r--sql/old/4.3.4/2012_08_26_00_world_spell_script_names_434.sql3
-rw-r--r--sql/old/4.3.4/2012_08_27_00_characters_guild_bank_eventlog.sql1
-rw-r--r--sql/old/4.3.4/2012_09_03_00_characters_currency_434.sql8
-rw-r--r--sql/old/4.3.4/2012_09_03_01_characters_currency_434.sql3
-rw-r--r--sql/old/4.3.4/2012_09_03_02_characters_characters_434.sql2
-rw-r--r--sql/old/4.3.4/2012_09_04_00_characters_character_cuf_profiles_434.sql19
-rw-r--r--sql/old/4.3.4/2012_09_07_00_characters_guild_434.sql3
-rw-r--r--sql/old/4.3.4/2012_09_09_00_characters_guild_news_434.sql11
-rw-r--r--sql/old/4.3.4/2012_09_09_00_world_guild_xp_for_level.sql33
-rw-r--r--sql/old/4.3.4/2012_09_09_01_world_spell_script_names.sql5
-rw-r--r--sql/old/4.3.4/2012_09_09_02_world_spell_script_names_434.sql4
-rw-r--r--sql/old/4.3.4/2012_09_09_05_world_guild_rewards_434.sql53
-rw-r--r--sql/old/4.3.4/2012_09_10_00_characters_guild_finder_434.sql40
-rw-r--r--sql/old/4.3.4/2012_10_15_00_world_phase_definitions_434.sql66
-rw-r--r--sql/old/4.3.4/2012_10_15_01_world_spell_script_names_434.sql2
-rw-r--r--sql/old/4.3.4/2012_10_15_02_world_spell_script_names_434.sql1
-rw-r--r--sql/old/4.3.4/2012_11_07_00_characters_guild_newslog_434.sql21
-rw-r--r--sql/old/4.3.4/2012_11_17_00_world_spell_script_names_434.sql4
-rw-r--r--sql/old/4.3.4/2012_11_20_00_world_misc_434.sql39
-rw-r--r--sql/old/4.3.4/2012_11_21_00_characters_worldstates_434.sql1
-rw-r--r--sql/old/4.3.4/2012_11_21_00_world_misc_434.sql3
-rw-r--r--sql/old/4.3.4/2012_11_22_00_world_command_434.sql6
-rw-r--r--sql/old/4.3.4/2012_11_25_02_world_spell_script_names_434.sql9
-rw-r--r--sql/old/4.3.4/2012_12_01_00_world_spell_script_names_434.sql16
-rw-r--r--sql/old/4.3.4/2012_12_02_00_world_spell_group_misc_434.sql22
-rw-r--r--sql/old/4.3.4/2012_12_24_00_world_spell_script_names_434.sql1
-rw-r--r--sql/old/4.3.4/2012_12_24_09_world_halls_of_origination_434.sql50
-rw-r--r--sql/old/4.3.4/2012_12_25_01_world_halls_of_origination_434.sql55
-rw-r--r--sql/old/4.3.4/2012_12_26_00_world_spell_script_names_434.sql39
-rw-r--r--sql/old/4.3.4/2012_12_27_00_world_spelldifficulty_dbc_434.sql1
-rw-r--r--sql/old/4.3.4/2012_12_27_01_world_achievement_dbc_434.sql418
-rw-r--r--sql/old/4.3.4/2012_12_30_00_world_zul_gurub_434.sql26
-rw-r--r--sql/old/4.3.4/2013_01_03_00_world_spell_area_434.sql1
-rw-r--r--sql/old/4.3.4/2013_01_03_01_world_spell_area_434.sql13
-rw-r--r--sql/old/4.3.4/2013_01_04_00_world_halls_of_origination_434.sql51
-rw-r--r--sql/old/4.3.4/2013_01_05_00_world_firelands_434.sql113
-rw-r--r--sql/old/4.3.4/2013_01_21_00_world_misc_434.sql22
-rw-r--r--sql/old/4.3.4/2013_01_21_01_world_misc_434.sql4
-rw-r--r--sql/old/4.3.4/2013_01_22_00_world_spell_proc_event_434.sql6
-rw-r--r--sql/old/4.3.4/2013_01_22_01_world_spell_script_names_434.sql4
-rw-r--r--sql/old/4.3.4/2013_01_24_00_world_instance_template_434.sql1
-rw-r--r--sql/old/4.3.4/2013_01_25_00_world_spell_linked_spell_434.sql3
-rw-r--r--sql/old/4.3.4/2013_01_26_00_world_spell_script_names_434.sql7
-rw-r--r--sql/old/4.3.4/2013_01_29_00_world_creature_template_434.sql1
-rw-r--r--sql/old/4.3.4/2013_01_30_00_characters_characters_434.sql2
-rw-r--r--sql/old/4.3.4/2013_01_31_00_world_spell_script_names_434.sql6
-rw-r--r--sql/old/4.3.4/2013_02_04_00_world_graveyard_orientation_434.sql1025
-rw-r--r--sql/old/4.3.4/2013_02_06_00_world_spell_proc_event_434.sql6
-rw-r--r--sql/updates/world/2013_01_26_01_world_misc_434.sql7
-rw-r--r--sql/updates/world/2013_02_27_00_world_creature_summon_groups_434.sql10
-rw-r--r--sql/updates/world/2013_03_15_01_world_keychain_db2_434.sql43
-rw-r--r--sql/updates/world/2013_03_23_00_world_playercreateinfo_spell.sql777
-rw-r--r--sql/updates/world/2013_04_03_00_world_playercreateinfo_button_434.sql4
-rw-r--r--sql/updates/world/2013_05_09_00_world_spell_dbc_434.sql138
-rw-r--r--sql/updates/world/2013_05_09_01_world_spelleffect_dbc_434.sql105
-rw-r--r--sql/updates/world/2013_05_11_00_world_spelleffect_dbc_434.sql75
-rw-r--r--sql/updates/world/2013_05_12_00_world_spell_learn_spell_434.sql16
-rw-r--r--sql/updates/world/2013_05_21_00_world_trinity_string_434.sql4
-rw-r--r--src/server/collision/Maps/TileAssembler.cpp11
-rw-r--r--src/server/game/AI/CreatureAIRegistry.cpp2
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAI.cpp1339
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAI.h643
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAIMgr.cpp694
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAIMgr.h46
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp16
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h1
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h1
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp2760
-rw-r--r--src/server/game/Achievements/AchievementMgr.h89
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp17
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h2
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp14
-rw-r--r--src/server/game/Battlefield/Battlefield.h6
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp9
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.h1
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h2
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp128
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h60
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.cpp56
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.h2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp118
-rw-r--r--src/server/game/Battlegrounds/Battleground.h33
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp793
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h14
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp36
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.h40
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp36
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.h40
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp4
-rw-r--r--src/server/game/CMakeLists.txt2
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp8
-rw-r--r--src/server/game/Calendar/CalendarMgr.h3
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.cpp1
-rw-r--r--src/server/game/Chat/Chat.cpp18
-rw-r--r--src/server/game/Chat/Chat.h2
-rw-r--r--src/server/game/Chat/ChatLink.cpp29
-rw-r--r--src/server/game/Chat/ChatLink.h2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp51
-rw-r--r--src/server/game/Conditions/ConditionMgr.h6
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp138
-rw-r--r--src/server/game/DataStores/DB2Stores.h35
-rw-r--r--src/server/game/DataStores/DB2Structure.h156
-rw-r--r--src/server/game/DataStores/DB2Utility.cpp171
-rw-r--r--src/server/game/DataStores/DB2Utility.h40
-rw-r--r--src/server/game/DataStores/DB2fmt.h27
-rw-r--r--src/server/game/DataStores/DBCEnums.h146
-rw-r--r--src/server/game/DataStores/DBCStores.cpp618
-rw-r--r--src/server/game/DataStores/DBCStores.h72
-rw-r--r--src/server/game/DataStores/DBCStructure.h1283
-rw-r--r--src/server/game/DataStores/DBCfmt.h184
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h2
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp108
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h46
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp20
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp75
-rw-r--r--src/server/game/Entities/Creature/Creature.h27
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp220
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp8
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp18
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp7
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h1
-rw-r--r--src/server/game/Entities/Item/Item.cpp378
-rw-r--r--src/server/game/Entities/Item/Item.h225
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.h231
-rw-r--r--src/server/game/Entities/Object/Object.cpp582
-rw-r--r--src/server/game/Entities/Object/Object.h90
-rw-r--r--src/server/game/Entities/Object/ObjectDefines.h53
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.cpp97
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.h39
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp1388
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFieldFlags.h1
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.h902
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp70
-rw-r--r--src/server/game/Entities/Pet/Pet.h3
-rw-r--r--src/server/game/Entities/Player/Player.cpp5111
-rw-r--r--src/server/game/Entities/Player/Player.h747
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp1
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp9
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp425
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp3403
-rw-r--r--src/server/game/Entities/Unit/Unit.h242
-rw-r--r--[-rwxr-xr-x]src/server/game/Entities/Vehicle/Vehicle.cpp5
-rw-r--r--src/server/game/Entities/Vehicle/VehicleDefines.h24
-rw-r--r--src/server/game/Events/GameEventMgr.cpp11
-rw-r--r--src/server/game/Events/GameEventMgr.h1
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp9
-rw-r--r--src/server/game/Globals/ObjectAccessor.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp2042
-rw-r--r--src/server/game/Globals/ObjectMgr.h107
-rw-r--r--src/server/game/Grids/GridDefines.h7
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp1
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h35
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiersImpl.h49
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp3
-rw-r--r--src/server/game/Grids/ObjectGridLoader.h1
-rw-r--r--src/server/game/Groups/Group.cpp62
-rw-r--r--src/server/game/Groups/Group.h58
-rw-r--r--src/server/game/Guilds/Guild.cpp1304
-rw-r--r--src/server/game/Guilds/Guild.h254
-rw-r--r--src/server/game/Guilds/GuildFinderMgr.cpp333
-rw-r--r--src/server/game/Guilds/GuildFinderMgr.h274
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp206
-rw-r--r--src/server/game/Guilds/GuildMgr.h15
-rw-r--r--src/server/game/Handlers/ArenaTeamHandler.cpp73
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp176
-rw-r--r--src/server/game/Handlers/AuthHandler.cpp26
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp546
-rw-r--r--src/server/game/Handlers/BattlefieldHandler.cpp302
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp9
-rw-r--r--src/server/game/Handlers/ChannelHandler.cpp100
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp313
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp463
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp554
-rw-r--r--src/server/game/Handlers/GuildFinderHandler.cpp442
-rw-r--r--src/server/game/Handlers/GuildHandler.cpp666
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp786
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp13
-rw-r--r--src/server/game/Handlers/LootHandler.cpp13
-rw-r--r--src/server/game/Handlers/MailHandler.cpp126
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp437
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp216
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp59
-rw-r--r--src/server/game/Handlers/PetHandler.cpp31
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp12
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp12
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp169
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp32
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp95
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp13
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp229
-rw-r--r--src/server/game/Handlers/VehicleHandler.cpp50
-rw-r--r--src/server/game/Handlers/VoiceChatHandler.cpp4
-rw-r--r--src/server/game/Handlers/VoidStorageHandler.cpp618
-rw-r--r--src/server/game/Instances/InstanceScript.cpp18
-rw-r--r--src/server/game/Instances/InstanceScript.h22
-rw-r--r--src/server/game/Loot/LootMgr.cpp26
-rw-r--r--src/server/game/Mails/Mail.h16
-rw-r--r--src/server/game/Maps/Map.cpp16
-rw-r--r--src/server/game/Maps/Map.h1
-rw-r--r--src/server/game/Maps/MapManager.cpp2
-rw-r--r--src/server/game/Maps/PhaseMgr.cpp382
-rw-r--r--src/server/game/Maps/PhaseMgr.h175
-rw-r--r--src/server/game/Miscellaneous/Formulas.h23
-rw-r--r--src/server/game/Miscellaneous/Language.h22
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h1161
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp19
-rwxr-xr-x[-rw-r--r--]src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp0
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp3
-rw-r--r--src/server/game/Movement/MovementStructures.cpp5179
-rw-r--r--src/server/game/Movement/MovementStructures.h158
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp13
-rw-r--r--src/server/game/Movement/Spline/MoveSplineFlag.h99
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp58
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.h22
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.cpp129
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.h8
-rw-r--r--src/server/game/Movement/Spline/MovementTypedefs.h2
-rw-r--r--src/server/game/Movement/Spline/MovementUtil.cpp162
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.h5
-rw-r--r--src/server/game/Quests/QuestDef.cpp229
-rw-r--r--src/server/game/Quests/QuestDef.h132
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp3
-rw-r--r--src/server/game/Scripting/MapScripts.cpp6
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp57
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp6
-rw-r--r--src/server/game/Scripting/ScriptMgr.h13
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2958
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2753
-rw-r--r--src/server/game/Server/WorldPacket.cpp106
-rw-r--r--src/server/game/Server/WorldPacket.h (renamed from src/server/shared/Packets/WorldPacket.h)24
-rw-r--r--src/server/game/Server/WorldSession.cpp444
-rw-r--r--src/server/game/Server/WorldSession.h128
-rw-r--r--src/server/game/Server/WorldSocket.cpp128
-rw-r--r--src/server/game/Server/WorldSocket.h1
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h98
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp474
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h10
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp368
-rw-r--r--src/server/game/Spells/Spell.cpp553
-rw-r--r--src/server/game/Spells/Spell.h15
-rw-r--r--src/server/game/Spells/SpellEffects.cpp556
-rw-r--r--src/server/game/Spells/SpellInfo.cpp557
-rw-r--r--src/server/game/Spells/SpellInfo.h67
-rw-r--r--src/server/game/Spells/SpellMgr.cpp467
-rw-r--r--src/server/game/Spells/SpellMgr.h4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp12
-rw-r--r--src/server/game/Tickets/TicketMgr.cpp5
-rw-r--r--src/server/game/Tools/PlayerDump.cpp19
-rw-r--r--src/server/game/Tools/PlayerDump.h3
-rw-r--r--src/server/game/Weather/Weather.cpp1
-rw-r--r--src/server/game/Weather/Weather.h2
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp1
-rw-r--r--src/server/game/World/World.cpp298
-rw-r--r--src/server/game/World/World.h57
-rw-r--r--src/server/scripts/CMakeLists.txt2
-rw-r--r--src/server/scripts/Commands/cs_character.cpp4
-rw-r--r--src/server/scripts/Commands/cs_cheat.cpp15
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp45
-rw-r--r--src/server/scripts/Commands/cs_gm.cpp15
-rw-r--r--src/server/scripts/Commands/cs_go.cpp2
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp4
-rw-r--r--src/server/scripts/Commands/cs_guild.cpp1
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp25
-rw-r--r--src/server/scripts/Commands/cs_list.cpp2
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp465
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp21
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp106
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp14
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp178
-rw-r--r--src/server/scripts/Commands/cs_reset.cpp7
-rw-r--r--src/server/scripts/Commands/cs_titles.cpp6
-rw-r--r--src/server/scripts/Commands/cs_wp.cpp64
-rw-r--r--src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h47
-rw-r--r--src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp271
-rw-r--r--src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp171
-rw-r--r--src/server/scripts/EasternKingdoms/CMakeLists.txt21
-rw-r--r--src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp455
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp54
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp180
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp59
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp298
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp288
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp108
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_kilnara.cpp (renamed from src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp)71
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp815
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp266
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp125
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp571
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp212
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp44
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_zanzil.cpp109
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp223
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h88
-rw-r--r--src/server/scripts/EasternKingdoms/boss_kruul.cpp163
-rw-r--r--src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp63
-rw-r--r--src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp129
-rw-r--r--src/server/scripts/EasternKingdoms/zone_ghostlands.cpp40
-rw-r--r--src/server/scripts/EasternKingdoms/zone_hinterlands.cpp202
-rw-r--r--src/server/scripts/EasternKingdoms/zone_ironforge.cpp67
-rw-r--r--src/server/scripts/EasternKingdoms/zone_loch_modan.cpp74
-rw-r--r--src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp146
-rw-r--r--src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp185
-rw-r--r--src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp626
-rw-r--r--src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp134
-rw-r--r--src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp196
-rw-r--r--src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp3
-rw-r--r--src/server/scripts/Kalimdor/CMakeLists.txt8
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp4
-rw-r--r--src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp704
-rw-r--r--src/server/scripts/Kalimdor/Firelands/firelands.h74
-rw-r--r--src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp59
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp571
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp346
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp404
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h126
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp282
-rw-r--r--src/server/scripts/Kalimdor/zone_azshara.cpp517
-rw-r--r--src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp4
-rw-r--r--src/server/scripts/Kalimdor/zone_darkshore.cpp373
-rw-r--r--src/server/scripts/Kalimdor/zone_desolace.cpp104
-rw-r--r--src/server/scripts/Kalimdor/zone_durotar.cpp450
-rw-r--r--src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp15
-rw-r--r--src/server/scripts/Kalimdor/zone_felwood.cpp72
-rw-r--r--src/server/scripts/Kalimdor/zone_feralas.cpp232
-rw-r--r--src/server/scripts/Kalimdor/zone_moonglade.cpp10
-rw-r--r--src/server/scripts/Kalimdor/zone_mulgore.cpp122
-rw-r--r--src/server/scripts/Kalimdor/zone_orgrimmar.cpp222
-rw-r--r--src/server/scripts/Kalimdor/zone_silithus.cpp8
-rw-r--r--src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp158
-rw-r--r--src/server/scripts/Kalimdor/zone_tanaris.cpp107
-rw-r--r--src/server/scripts/Kalimdor/zone_the_barrens.cpp12
-rw-r--r--src/server/scripts/Kalimdor/zone_thousand_needles.cpp442
-rw-r--r--src/server/scripts/Kalimdor/zone_thunder_bluff.cpp24
-rw-r--r--src/server/scripts/Kalimdor/zone_ungoro_crater.cpp327
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp4
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp1
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp8
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp16
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp5
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp24
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp3
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp10
-rw-r--r--src/server/scripts/Northrend/zone_dalaran.cpp45
-rw-r--r--src/server/scripts/Northrend/zone_zuldrak.cpp3
-rw-r--r--src/server/scripts/OutdoorPvP/CMakeLists.txt2
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp785
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPEP.h331
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp4
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp126
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp256
-rw-r--r--src/server/scripts/Spells/spell_item.cpp3
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp724
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp112
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp18
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp152
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp76
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp310
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp240
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp93
-rw-r--r--src/server/scripts/World/item_scripts.cpp12
-rw-r--r--src/server/scripts/World/npc_professions.cpp8
-rw-r--r--src/server/scripts/World/npcs_special.cpp14
-rw-r--r--src/server/shared/Common.h17
-rw-r--r--src/server/shared/DataStores/DB2FileLoader.cpp408
-rw-r--r--src/server/shared/DataStores/DB2FileLoader.h107
-rw-r--r--src/server/shared/DataStores/DB2Store.h233
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.cpp9
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.h15
-rw-r--r--src/server/shared/DataStores/DBCStore.h2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp96
-rwxr-xr-x[-rw-r--r--]src/server/shared/Database/Implementation/CharacterDatabase.h35
-rw-r--r--src/server/shared/Database/Implementation/WorldDatabase.cpp8
-rw-r--r--src/server/shared/Define.h14
-rw-r--r--src/server/shared/Packets/ByteBuffer.h137
-rw-r--r--src/server/shared/Utilities/Util.cpp6
-rw-r--r--src/server/shared/Utilities/Util.h2
-rw-r--r--src/server/worldserver/CMakeLists.txt3
-rw-r--r--src/server/worldserver/worldserver.conf.dist230
-rw-r--r--src/tools/CMakeLists.txt6
-rw-r--r--src/tools/map_extractor/CMakeLists.txt21
-rw-r--r--src/tools/map_extractor/System.cpp587
-rw-r--r--src/tools/map_extractor/adt.cpp23
-rw-r--r--src/tools/map_extractor/adt.h13
-rw-r--r--src/tools/map_extractor/dbcfile.cpp74
-rw-r--r--src/tools/map_extractor/dbcfile.h211
-rw-r--r--src/tools/map_extractor/loadlib.cpp25
-rw-r--r--src/tools/map_extractor/loadlib/loadlib.h5
-rw-r--r--src/tools/map_extractor/mpq_libmpq.cpp111
-rw-r--r--src/tools/map_extractor/mpq_libmpq04.h88
-rw-r--r--src/tools/map_extractor/wdt.cpp2
-rw-r--r--src/tools/map_extractor/wdt.h2
-rw-r--r--src/tools/vmap4_assembler/CMakeLists.txt5
-rw-r--r--src/tools/vmap4_extractor/CMakeLists.txt23
-rw-r--r--src/tools/vmap4_extractor/adtfile.cpp4
-rw-r--r--src/tools/vmap4_extractor/adtfile.h2
-rw-r--r--src/tools/vmap4_extractor/dbcfile.cpp117
-rw-r--r--src/tools/vmap4_extractor/dbcfile.h227
-rw-r--r--src/tools/vmap4_extractor/gameobject_extract.cpp4
-rw-r--r--src/tools/vmap4_extractor/loadlib/loadlib.h77
-rw-r--r--src/tools/vmap4_extractor/model.cpp6
-rw-r--r--src/tools/vmap4_extractor/model.h1
-rw-r--r--src/tools/vmap4_extractor/modelheaders.h7
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq.cpp111
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h88
-rw-r--r--src/tools/vmap4_extractor/mpqfile.cpp87
-rw-r--r--src/tools/vmap4_extractor/mpqfile.h81
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp309
-rw-r--r--src/tools/vmap4_extractor/wdtfile.cpp6
-rw-r--r--src/tools/vmap4_extractor/wdtfile.h2
-rw-r--r--src/tools/vmap4_extractor/wmo.cpp8
-rw-r--r--src/tools/vmap4_extractor/wmo.h2
887 files changed, 134572 insertions, 40538 deletions
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index ad5e04cb321..4778c309df9 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -39,5 +39,5 @@ if(SERVERS)
endif()
if(TOOLS)
- add_subdirectory(libmpq)
+ add_subdirectory(StormLib)
endif()
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index 4f52dfca906..6e3e8574b0f 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -16,10 +16,6 @@ jemalloc (a general-purpose scalable concurrent malloc-implementation)
http://www.canonware.com/jemalloc/
Version: 3.3.1
-libMPQ (a library for reading MPQ files)
- https://libmpq.org/
- Version: 1.0.4
-
MySQL (the world's most popular open source database software)
http://www.mysql.com/
Version: 5.5.9 (GA)
@@ -43,3 +39,7 @@ gSOAP (a portable development toolkit for C and C++ XML Web services and XML dat
recastnavigation (Recast is state of the art navigation mesh construction toolset for games)
http://code.google.com/p/recastnavigation/
Version: 1.4
+
+StormLib (a pack of modules, written in C++, which are able to read and also to write files from/to the MPQ archives)
+ http://www.zezula.net/en/mpq/stormlib.html
+ Version: 8.04
diff --git a/dep/StormLib/CMakeLists.txt b/dep/StormLib/CMakeLists.txt
new file mode 100644
index 00000000000..7096c8f8729
--- /dev/null
+++ b/dep/StormLib/CMakeLists.txt
@@ -0,0 +1,272 @@
+set(SRC_FILES
+ src/adpcm/adpcm.cpp
+ src/huffman/huff.cpp
+ src/jenkins/lookup3.c
+ src/lzma/C/LzFind.c
+ src/lzma/C/LzmaDec.c
+ src/lzma/C/LzmaEnc.c
+ src/pklib/explode.c
+ src/pklib/implode.c
+ src/sparse/sparse.cpp
+ src/FileStream.cpp
+ src/SBaseCommon.cpp
+ src/SBaseFileTable.cpp
+ src/SCompression.cpp
+ src/SFileAddFile.cpp
+ src/SFileAttributes.cpp
+ src/SFileCompactArchive.cpp
+ src/SFileCreateArchive.cpp
+ src/SFileExtractFile.cpp
+ src/SFileFindFile.cpp
+ src/SFileListFile.cpp
+ src/SFileOpenArchive.cpp
+ src/SFileOpenFileEx.cpp
+ src/SFilePatchArchives.cpp
+ src/SFileReadFile.cpp
+ src/SFileVerify.cpp
+)
+
+set(TOMCRYPT_FILES
+ src/libtomcrypt/src/hashes/hash_memory.c
+ src/libtomcrypt/src/hashes/md5.c
+ src/libtomcrypt/src/hashes/sha1.c
+ src/libtomcrypt/src/math/ltm_desc.c
+ src/libtomcrypt/src/math/multi.c
+ src/libtomcrypt/src/math/rand_prime.c
+ src/libtomcrypt/src/misc/base64_decode.c
+ src/libtomcrypt/src/misc/crypt_argchk.c
+ src/libtomcrypt/src/misc/crypt_find_hash.c
+ src/libtomcrypt/src/misc/crypt_find_prng.c
+ src/libtomcrypt/src/misc/crypt_hash_descriptor.c
+ src/libtomcrypt/src/misc/crypt_hash_is_valid.c
+ src/libtomcrypt/src/misc/crypt_libc.c
+ src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
+ src/libtomcrypt/src/misc/crypt_prng_descriptor.c
+ src/libtomcrypt/src/misc/crypt_prng_is_valid.c
+ src/libtomcrypt/src/misc/crypt_register_hash.c
+ src/libtomcrypt/src/misc/crypt_register_prng.c
+ src/libtomcrypt/src/misc/zeromem.c
+ src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
+ src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
+ src/libtomcrypt/src/pk/asn1/der_decode_choice.c
+ src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
+ src/libtomcrypt/src/pk/asn1/der_decode_integer.c
+ src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
+ src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c
+ src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c
+ src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c
+ src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c
+ src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c
+ src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c
+ src/libtomcrypt/src/pk/asn1/der_decode_utctime.c
+ src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_bit_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_boolean.c
+ src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_integer.c
+ src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c
+ src/libtomcrypt/src/pk/asn1/der_length_octet_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_printable_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_sequence.c
+ src/libtomcrypt/src/pk/asn1/der_length_utctime.c
+ src/libtomcrypt/src/pk/asn1/der_sequence_free.c
+ src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c
+ src/libtomcrypt/src/pk/asn1/der_length_short_integer.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
+ src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
+ src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
+ src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
+ src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
+ src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c
+ src/libtomcrypt/src/pk/rsa/rsa_exptmod.c
+ src/libtomcrypt/src/pk/rsa/rsa_free.c
+ src/libtomcrypt/src/pk/rsa/rsa_import.c
+ src/libtomcrypt/src/pk/rsa/rsa_make_key.c
+ src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
+ src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c
+)
+
+set(TOMMATH_FILES
+ src/libtommath/bncore.c
+ src/libtommath/bn_fast_mp_invmod.c
+ src/libtommath/bn_fast_mp_montgomery_reduce.c
+ src/libtommath/bn_fast_s_mp_mul_digs.c
+ src/libtommath/bn_fast_s_mp_mul_high_digs.c
+ src/libtommath/bn_fast_s_mp_sqr.c
+ src/libtommath/bn_mp_2expt.c
+ src/libtommath/bn_mp_abs.c
+ src/libtommath/bn_mp_add.c
+ src/libtommath/bn_mp_addmod.c
+ src/libtommath/bn_mp_add_d.c
+ src/libtommath/bn_mp_and.c
+ src/libtommath/bn_mp_clamp.c
+ src/libtommath/bn_mp_clear.c
+ src/libtommath/bn_mp_clear_multi.c
+ src/libtommath/bn_mp_cmp.c
+ src/libtommath/bn_mp_cmp_d.c
+ src/libtommath/bn_mp_cmp_mag.c
+ src/libtommath/bn_mp_cnt_lsb.c
+ src/libtommath/bn_mp_copy.c
+ src/libtommath/bn_mp_count_bits.c
+ src/libtommath/bn_mp_div.c
+ src/libtommath/bn_mp_div_2.c
+ src/libtommath/bn_mp_div_2d.c
+ src/libtommath/bn_mp_div_3.c
+ src/libtommath/bn_mp_div_d.c
+ src/libtommath/bn_mp_dr_is_modulus.c
+ src/libtommath/bn_mp_dr_reduce.c
+ src/libtommath/bn_mp_dr_setup.c
+ src/libtommath/bn_mp_exch.c
+ src/libtommath/bn_mp_exptmod.c
+ src/libtommath/bn_mp_exptmod_fast.c
+ src/libtommath/bn_mp_expt_d.c
+ src/libtommath/bn_mp_exteuclid.c
+ src/libtommath/bn_mp_fread.c
+ src/libtommath/bn_mp_fwrite.c
+ src/libtommath/bn_mp_gcd.c
+ src/libtommath/bn_mp_get_int.c
+ src/libtommath/bn_mp_grow.c
+ src/libtommath/bn_mp_init.c
+ src/libtommath/bn_mp_init_copy.c
+ src/libtommath/bn_mp_init_multi.c
+ src/libtommath/bn_mp_init_set.c
+ src/libtommath/bn_mp_init_set_int.c
+ src/libtommath/bn_mp_init_size.c
+ src/libtommath/bn_mp_invmod.c
+ src/libtommath/bn_mp_invmod_slow.c
+ src/libtommath/bn_mp_is_square.c
+ src/libtommath/bn_mp_jacobi.c
+ src/libtommath/bn_mp_karatsuba_mul.c
+ src/libtommath/bn_mp_karatsuba_sqr.c
+ src/libtommath/bn_mp_lcm.c
+ src/libtommath/bn_mp_lshd.c
+ src/libtommath/bn_mp_mod.c
+ src/libtommath/bn_mp_mod_2d.c
+ src/libtommath/bn_mp_mod_d.c
+ src/libtommath/bn_mp_montgomery_calc_normalization.c
+ src/libtommath/bn_mp_montgomery_reduce.c
+ src/libtommath/bn_mp_montgomery_setup.c
+ src/libtommath/bn_mp_mul.c
+ src/libtommath/bn_mp_mulmod.c
+ src/libtommath/bn_mp_mul_2.c
+ src/libtommath/bn_mp_mul_2d.c
+ src/libtommath/bn_mp_mul_d.c
+ src/libtommath/bn_mp_neg.c
+ src/libtommath/bn_mp_n_root.c
+ src/libtommath/bn_mp_or.c
+ src/libtommath/bn_mp_prime_fermat.c
+ src/libtommath/bn_mp_prime_is_divisible.c
+ src/libtommath/bn_mp_prime_is_prime.c
+ src/libtommath/bn_mp_prime_miller_rabin.c
+ src/libtommath/bn_mp_prime_next_prime.c
+ src/libtommath/bn_mp_prime_rabin_miller_trials.c
+ src/libtommath/bn_mp_prime_random_ex.c
+ src/libtommath/bn_mp_radix_size.c
+ src/libtommath/bn_mp_radix_smap.c
+ src/libtommath/bn_mp_rand.c
+ src/libtommath/bn_mp_read_radix.c
+ src/libtommath/bn_mp_read_signed_bin.c
+ src/libtommath/bn_mp_read_unsigned_bin.c
+ src/libtommath/bn_mp_reduce.c
+ src/libtommath/bn_mp_reduce_2k.c
+ src/libtommath/bn_mp_reduce_2k_l.c
+ src/libtommath/bn_mp_reduce_2k_setup.c
+ src/libtommath/bn_mp_reduce_2k_setup_l.c
+ src/libtommath/bn_mp_reduce_is_2k.c
+ src/libtommath/bn_mp_reduce_is_2k_l.c
+ src/libtommath/bn_mp_reduce_setup.c
+ src/libtommath/bn_mp_rshd.c
+ src/libtommath/bn_mp_set.c
+ src/libtommath/bn_mp_set_int.c
+ src/libtommath/bn_mp_shrink.c
+ src/libtommath/bn_mp_signed_bin_size.c
+ src/libtommath/bn_mp_sqr.c
+ src/libtommath/bn_mp_sqrmod.c
+ src/libtommath/bn_mp_sqrt.c
+ src/libtommath/bn_mp_sub.c
+ src/libtommath/bn_mp_submod.c
+ src/libtommath/bn_mp_sub_d.c
+ src/libtommath/bn_mp_toom_mul.c
+ src/libtommath/bn_mp_toom_sqr.c
+ src/libtommath/bn_mp_toradix.c
+ src/libtommath/bn_mp_toradix_n.c
+ src/libtommath/bn_mp_to_signed_bin.c
+ src/libtommath/bn_mp_to_signed_bin_n.c
+ src/libtommath/bn_mp_to_unsigned_bin.c
+ src/libtommath/bn_mp_to_unsigned_bin_n.c
+ src/libtommath/bn_mp_unsigned_bin_size.c
+ src/libtommath/bn_mp_xor.c
+ src/libtommath/bn_mp_zero.c
+ src/libtommath/bn_prime_tab.c
+ src/libtommath/bn_reverse.c
+ src/libtommath/bn_s_mp_add.c
+ src/libtommath/bn_s_mp_exptmod.c
+ src/libtommath/bn_s_mp_mul_digs.c
+ src/libtommath/bn_s_mp_mul_high_digs.c
+ src/libtommath/bn_s_mp_sqr.c
+ src/libtommath/bn_s_mp_sub.c
+)
+
+set(ZLIB_BZIP2_FILES
+ src/bzip2/blocksort.c
+ src/bzip2/bzlib.c
+ src/bzip2/compress.c
+ src/bzip2/crctable.c
+ src/bzip2/decompress.c
+ src/bzip2/huffman.c
+ src/bzip2/randtable.c
+ src/zlib/adler32.c
+ src/zlib/compress2.c
+ src/zlib/crc32.c
+ src/zlib/deflate.c
+ src/zlib/inffast.c
+ src/zlib/inflate.c
+ src/zlib/inftrees.c
+ src/zlib/trees.c
+ src/zlib/zutil.c
+)
+
+set(TEST_SRC_FILES
+ test/Test.cpp
+)
+
+add_definitions(-D_7ZIP_ST -DBZ_STRICT_ANSI)
+
+if(WIN32)
+ if(MSVC)
+ add_definitions(-D_7ZIP_ST -DWIN32)
+ endif()
+ set(SRC_ADDITIONAL_FILES ${ZLIB_BZIP2_FILES} ${TOMCRYPT_FILES} ${TOMMATH_FILES})
+ set(LINK_LIBS wininet)
+endif()
+
+if(APPLE)
+ set(LINK_LIBS z bz2)
+ set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES})
+endif()
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL Linux)
+ option(WITH_LIBTOMCRYPT "Use system LibTomCrypt library" OFF)
+ if(WITH_LIBTOMCRYPT)
+ set(LINK_LIBS z bz2 tomcrypt)
+ else()
+ set(LINK_LIBS z bz2)
+ set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES})
+ endif()
+endif()
+
+add_library(storm STATIC ${SRC_FILES} ${SRC_ADDITIONAL_FILES})
+target_link_libraries(storm ${LINK_LIBS})
+
+if(UNIX)
+ set_target_properties(storm PROPERTIES SOVERSION 0)
+endif()
+
+# On Win32, build StormLib.dll since we don't want to clash with Storm.dll
+if(WIN32)
+ set_target_properties(storm PROPERTIES OUTPUT_NAME StormLib)
+endif()
diff --git a/dep/StormLib/doc/History.txt b/dep/StormLib/doc/History.txt
new file mode 100644
index 00000000000..5e32894d7b1
--- /dev/null
+++ b/dep/StormLib/doc/History.txt
@@ -0,0 +1,62 @@
+
+ StormLib history
+ ================
+
+ Version 8.02
+
+ - Support for UNICODE encoding for on-disk files
+ - Optimized file deleting
+
+ Version 8.01
+
+ - SFileFindFirstFile and SFileFindNextFile no longer find files that have
+ patch file in the oldest MPQ in the patch chain
+ - Write support for MPQs version 4
+
+ Version 8.00
+
+ - Updated support for protected maps from Warcraft III
+
+ Version 7.11
+
+ - Support for MPQs v 3.0 (WOW-Cataclysm BETA)
+ - StormLib now deals properly with files that have MPQ_SECTOR_CHECKSUM missing,
+ but have sector checksum entry present in the sector offset table
+
+ Version 7.10
+
+ - Support for partial MPQs ("interface.MPQ.part")
+ - The only operation that is externally allowed to do with internal files
+ ("(listfile)", "(attributes)" and "(signature)") is reading. Attempt to modify any of the file
+ fails and GetLastError returns ERROR_INTERNAL_FILE
+ - Fixed memory leak that has occured when writing more than one sector to the file at once
+
+ Version 7.01
+
+ - Support for adding files from memory
+ - Fixed improper validation of handles to MPQ file and MPQ archive
+ - Fixed bug where StormLib didn't save CRC32 of the file when added to archive
+
+ Version 7.00
+
+ - Properly deals with MPQs protected by w3xMaster
+ - Major rewrite
+ - Fixed support for (attributes)
+ - Added file verification
+ - Added MPQ signature verification
+
+ Version 6.22
+
+ - Properly deals with MPQs protected by w3xMaster
+
+ Version 6.21
+
+ - SFileRenameFile now properly re-crypts the file if necessary.
+ - SFileFindFirstFile correctly deals with deleted files
+
+ Version 6.20
+
+ - Fixed lots of bugs when processing files with same names but different locales
+ - Fixed bugs when repeately extracts the same file with MPQ_FILE_SINGLE_UNIT flag
+ - Added SFileFlushArchive
+ - Fixed issue opening AVI files renamed to MPQ using SFileCreateArchiveEx
diff --git a/dep/StormLib/doc/Sector Offset MD5.txt b/dep/StormLib/doc/Sector Offset MD5.txt
new file mode 100644
index 00000000000..a22506ac704
--- /dev/null
+++ b/dep/StormLib/doc/Sector Offset MD5.txt
@@ -0,0 +1,25 @@
+
+ After sector offset table
+ =========================
+
+FileSize CmpSize DWORDs
+00007588 000075A4 0x01
+0000A9EA 000095EC 0x01
+0000E51D 0000E20D 0x02
+00015C00 00015C40 0x02
+0001C578 000186C4 0x02
+0002A9D4 0002A9EA 0x04
+00037BAC 00037A42 0x06
+0003C3C1 00034084 0x06
+0003D224 0003B30F 0x06
+00045105 0004195A 0x07
+00045D9C 0003D87D 0x07
+0004AAB8 0004860A 0x08
+0004D18E 00048E0C 0x07
+00056B4C 00056BDD 0x09
+0005DC08 00059426 0x09
+00061EC0 00057711 0x0A
+0006CEC4 00062561 0x0B
+000778EE 00066736 0x0C
+000AD0CB 0007F32E 0x11
+00327EAC 00303395 0x53
diff --git a/dep/StormLib/doc/The MoPaQ File Format 0.9.txt b/dep/StormLib/doc/The MoPaQ File Format 0.9.txt
new file mode 100644
index 00000000000..ce8d8f70166
--- /dev/null
+++ b/dep/StormLib/doc/The MoPaQ File Format 0.9.txt
@@ -0,0 +1,318 @@
+THE MOPAQ ARCHIVE FORMAT
+v0.9 (Thursday, June 30, 2005)
+by Justin Olbrantz(Quantam)
+
+Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting
+in other works is freely allowed, as long as the source and author of the quote is stated.
+
+TABLE OF CONTENTS
+1. Introduction to the MoPaQ Format
+2. The MoPaQ Format
+ 2.1 General Archive Layout
+ 2.2 Archive Header
+ 2.3 Block Table
+ 2.4 Hash Table
+ 2.5 File Data
+ 2.6 Listfile
+ 2.7 Extended Attributes
+ 2.8 Weak (Old) Digital Signature
+ 2.9 Strong (New) Digital Signature
+3. Algorithm Source Code
+ 3.1 Encryption/Decryption
+ 3.2 Hashing
+ 3.3 Conversion of FILETIME and time_t
+
+1. INTRODUCTION TO THE MOPAQ FORMAT
+The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard
+Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be
+a read-only game archive format, and excels at this role.
+
+The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked.
+The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
+
+2. THE MOPAQ FORMAT
+All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified),
+byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise.
+Structure members are listed in the following general form:
+offset from the beginning of the structure: data type(array size) member name : member description
+
+2.1 GENERAL ARCHIVE LAYOUT
+- Archive Header
+- File Data
+- File Data - Special Files
+- Hash Table
+- Block Table
+- Strong Digital signature
+
+This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table
+and file table after the archive header, and before the file data.
+
+2.2 ARCHIVE HEADER
+00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
+04h: int32 HeaderSize : Size of the archive header. Should be 32.
+08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present.
+This size is used, among other things, for determining the region to hash in computing the digital signature.
+0Ch: int16 Unknown : Unknown
+0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
+in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate
+that this should always be 3 (4096 byte sectors).
+10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
+14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
+18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16.
+1Ch: int32 BlockTableEntries : Number of entries in the block table.
+
+The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset
+0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not
+at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the
+archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer
+versions (due to the strong digital signature not being considered a part of the archive).
+
+2.3 BLOCK TABLE
+The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be
+overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash
+of "(block table)" as the key. Each entry is structured as follows:
+
+00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0.
+04h: int32 BlockSize : Size of the block in the archive.
+08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
+0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
+ 80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared.
+ 01000000h: File is stored as a single unit, rather than split into sectors.
+ 00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
+ 00010000h: File is encrypted.
+ 00000200h: File is compressed. Mutually exclusive to file imploded.
+ 00000100h: File is imploded. Mutually exclusive to file compressed.
+
+2.4 HASH TABLE
+Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
+
+00h: int32 FilePathHashA : The hash of the file path, using method A.
+04h: int32 FilePathHashB : The hash of the file path, using method B.
+08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
+0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
+0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
+ FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
+ FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
+
+2.5 FILE DATA
+00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below).
+immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below).
+
+Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize).
+
+If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib.
+ 40h: IMA ADPCM mono
+ 80h: IMA ADPCM stereo
+ 01h: Huffman encoded
+ 02h: Deflated (see ZLib)
+ 08h: Imploded (see PKWare Data Compression Library)
+ 10h: BZip2 compressed (see BZip2)
+
+If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which
+contains the entire file.
+
+If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable)
+is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the
+directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is
+adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset)
+XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions,
+by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the
+0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
+
+The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize.
+This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors
+is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the
+SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously.
+Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as
+a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the
+archive's sector size).
+
+2.6 LISTFILE
+The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive.
+The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)",
+and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file
+"(listfile)" may not be listed in the listfile.
+
+2.7 EXTENDED ATTRIBUTES
+The extended attributes are optional file attributes for files in the block table. These attributes were added at times after
+the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes.
+If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although
+the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the
+blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file,
+in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other
+structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some
+archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This
+file is structured as follows:
+
+00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
+04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
+ 00000001h: File CRC32s.
+ 00000002h: File timestamps.
+ 00000004h: File MD5s.
+08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the
+archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block
+in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
+immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive.
+Omitted if the archive does not have MD5s.
+
+2.8 WEAK DIGITAL SIGNATURE
+The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5
+digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this
+protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature
+is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the
+archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature
+file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during
+signing/verification. This file is structured as follows:
+
+00h: int32 Unknown : Must be 0.
+04h: int32 Unknown : must be 0.
+08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order.
+
+2.9 STRONG DIGITAL SIGNATURE
+The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and
+a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well.
+The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize
+bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
+
+00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
+04h: int2048 Signature : The digital signature, stored in little-endian format.
+
+When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows:
+
+00h: byte Padding : Must be 0Bh.
+01h: byte(235) Padding : Must be BBh.
+ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format.
+
+3. ALGORITHM SOURCE CODE
+3.1 ENCRYPTION/DECRYPTION
+I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order.
+
+unsigned long dwCryptTable[0x500];
+
+void InitializeCryptTable()
+{
+ unsigned long seed = 0x00100001;
+ unsigned long index1 = 0;
+ unsigned long index2 = 0;
+ int i;
+
+ for (index1 = 0; index1 < 0x100; index1++)
+ {
+ for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
+ {
+ unsigned long temp1, temp2;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp1 = (seed & 0xFFFF) << 0x10;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp2 = (seed & 0xFFFF);
+
+ dwCryptTable[index2] = (temp1 | temp2);
+ }
+ }
+}
+
+void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
+{
+ unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
+ unsigned long seed = 0xEEEEEEEE;
+ unsigned long ch;
+
+ assert(lpbyBuffer);
+
+ dwLength /= sizeof(unsigned long);
+
+ while(dwLength-- > 0)
+ {
+ seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
+ ch = *lpdwBuffer ^ (dwKey + seed);
+
+ dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
+ seed = *lpdwBuffer + seed + (seed << 5) + 3;
+
+ *lpdwBuffer++ = ch;
+ }
+}
+
+void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
+{
+ unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
+ unsigned long seed = 0xEEEEEEEE;
+ unsigned long ch;
+
+ assert(lpbyBuffer);
+
+ dwLength /= sizeof(unsigned long);
+
+ while(dwLength-- > 0)
+ {
+ seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
+ ch = *lpdwBuffer ^ (dwKey + seed);
+
+ dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
+ seed = ch + seed + (seed << 5) + 3;
+
+ *lpdwBuffer++ = ch;
+ }
+}
+
+3.2 HASHING
+Based on code from StormLib.
+
+// Different types of hashes to make with HashString
+#define MPQ_HASH_TABLE_OFFSET 0
+#define MPQ_HASH_NAME_A 1
+#define MPQ_HASH_NAME_B 2
+#define MPQ_HASH_FILE_KEY 3
+
+unsigned long HashString(const char *lpszString, unsigned long dwHashType)
+{
+ unsigned long seed1 = 0x7FED7FED;
+ unsigned long seed2 = 0xEEEEEEEE;
+ int ch;
+
+ while (*lpszString != 0)
+ {
+ ch = toupper(*lpszString++);
+
+ seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+ return seed1;
+}
+
+3.3 CONVERSION OF FILETIME AND time_t
+
+#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
+
+bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time)
+{
+ // The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
+ unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
+
+ if (nTime < EPOCH_OFFSET)
+ return false;
+
+ nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
+ nTime /= 10000000ULL; // Convert 100 ns to sec
+
+ time = (time_t)nTime;
+
+ // Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
+ if ((nTime - (unsigned long long)time) > 0)
+ return false;
+
+ return true;
+}
+
+void GetFileTimeFromTime(time_t &time, FILETIME &fileTime)
+{
+ unsigned long long nTime = (unsigned long long)time;
+
+ nTime *= 10000000ULL;
+ nTime += EPOCH_OFFSET;
+
+ fileTime.dwLowDateTime = (DWORD)nTime;
+ fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
+}
diff --git a/dep/StormLib/doc/The MoPaQ File Format 1.0.txt b/dep/StormLib/doc/The MoPaQ File Format 1.0.txt
new file mode 100644
index 00000000000..2f139453e0e
--- /dev/null
+++ b/dep/StormLib/doc/The MoPaQ File Format 1.0.txt
@@ -0,0 +1,433 @@
+THE MOPAQ ARCHIVE FORMAT
+v1.0 (Friday, September 1, 2006)
+by Justin Olbrantz(Quantam)
+
+Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quotation in other works is freely allowed, as long as the source and author of the quote are stated.
+
+TABLE OF CONTENTS
+1. Introduction to the MoPaQ Format
+2. The MoPaQ Format
+ 2.1 General Archive Layout
+ 2.2 Archive Header
+ 2.3 Block Table
+ 2.4 Extended Block Table
+ 2.5 Hash Table
+ 2.6 File Data
+ 2.7 Listfile
+ 2.8 Extended Attributes
+ 2.9 Weak (Old) Digital Signature
+ 2.10 Strong (New) Digital Signature
+3. Algorithm Source Code
+ 3.1 Encryption/Decryption
+ 3.2 Hashing and File Key Computation
+ 3.3 Finding Files
+ 3.4 Deleting Files
+ 3.5 Conversion of FILETIME and time_t
+ 3.6 Forming a 64-bit Large Archive Offset from 32-bit and 16-bit Components
+4. Revision History
+
+1. INTRODUCTION TO THE MOPAQ FORMAT
+The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be a read-only game archive format, and excels at this role.
+
+The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
+
+StormLib - mentioned several times in this specification - is an open-source MoPaQ reading and writing library written by Ladislav Zezula (no affiliation with Blizzard Entertainment). While it's a bit dated, and does not support all of the newer MoPaQ features, it contains source code to the more exotic compression methods used by MoPaQ, such as the PKWare implode algorithm, MoPaQ's huffman compression algorithm, and the IMA ADPCM compression used by MoPaQ.
+
+2. THE MOPAQ FORMAT
+All numbers in the MoPaQ format are in little endian byte order; signed numbers use the two's complement system. Data types are listed either as int (integer, the number of bits specified), byte (8 bits), or char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. Structure members are listed in the following general form:
+offset from the beginning of the structure: data type(array size) member name : member description
+
+2.1 GENERAL ARCHIVE LAYOUT
+- Archive Header
+- File Data
+- File Data - Special Files
+- Hash Table
+- Block Table
+- Extended Block Table
+- Strong Digital signature
+
+This is the usual archive format, but it is not mandatory. Some archives have been observed placing the hash table and file table after the archive header, and before the file data.
+
+2.2 ARCHIVE HEADER
+00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
+04h: int32 HeaderSize : Size of the archive header.
+08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. This size is used, among other things, for determining the region to hash in computing the digital signature. This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive is calculated as the size from the beginning of the archive to the end of the hash table, block table, or extended block table (whichever is largest).
+0Ch: int16 FormatVersion : MoPaQ format version. MPQAPI will not open archives where this is negative. Known versions:
+ 0000h: Original format. HeaderSize should be 20h, and large archives are not supported.
+ 0001h: Burning Crusade format. Header size should be 2Ch, and large archives are supported.
+0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors).
+10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
+14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
+18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
+1Ch: int32 BlockTableEntries : Number of entries in the block table.
+Fields only present in the Burning Crusade format and later:
+20h: int64 ExtendedBlockTableOffset : Offset to the beginning of the extended block table, relative to the beginning of the archive.
+28h: int16 HashTableOffsetHigh : High 16 bits of the hash table offset for large archives.
+2Ah: int16 BlockTableOffsetHigh : High 16 bits of the block table offset for large archives.
+
+The archive header is the first structure in the archive, at archive offset 0; however, the archive does not need to be at offset 0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer versions (due to the strong digital signature not being considered a part of the archive).
+
+2.3 BLOCK TABLE
+The block table contains entries for each region in the archive. Regions may be either files, empty space, which may be overwritten by new files (typically this space is from deleted file data), or unused block table entries. Empty space entries should have BlockOffset and BlockSize nonzero, and FileSize and Flags zero; unused block table entries should have BlockSize, FileSize, and Flags zero. The block table is encrypted, using the hash of "(block table)" as the key. Each entry is structured as follows:
+
+00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive.
+04h: int32 BlockSize : Size of the block in the archive.
+08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file; otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
+0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
+ 80000000h: Block is a file, and follows the file data format; otherwise, block is free space or unused. If the block is not a file, all other flags should be cleared, and FileSize should be 0.
+ 01000000h: File is stored as a single unit, rather than split into sectors.
+ 00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
+ 00010000h: File is encrypted.
+ 00000200h: File is compressed. File cannot be imploded.
+ 00000100h: File is imploded. File cannot be compressed.
+
+2.4 EXTENDED BLOCK TABLE
+The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes). The table contains the upper bits of the archive offsets for each block in the block table. It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block, with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size.
+
+As of the Burning Crusade Friends and Family beta, this table is not encrypted.
+
+2.5 HASH TABLE
+Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
+
+00h: int32 FilePathHashA : The hash of the file path, using method A.
+04h: int32 FilePathHashB : The hash of the file path, using method B.
+08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
+0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
+0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
+ FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
+ FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
+
+2.6 FILE DATA
+The data for each file is composed of the following structure:
+00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector, relative to the beginning of the file data. The last entry contains the file size, making it possible to easily calculate the size of any given sector. This table is not present if this information can be calculated (see details below).
+immediately following SectorOffsetTable: SECTOR Sectors(SectorsInFile) : Data of each sector in the file, packed end to end (see details below).
+
+Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may contain less than this, depending on the size of the entire file's data. If the file is compressed or imploded, the sector will be smaller or the same size as the file data it contains. Individual sectors in a compressed or imploded file may be stored uncompressed; this occurs if and only if the file data the sector contains could not be compressed by the algorithm(s) used (if the compressed sector size was greater than or equal to the size of the file data), and is indicated by the sector's size in SectorOffsetTable being equal to the size of the file data in the sector (which may be calculated from the FileSize).
+
+The format of each sector depends on the kind of sector it is. Uncompressed sectors are simply the the raw file data contained in the sector. Imploded sectors are the raw compressed data following compression with the implode algorithm (these sectors can only be in imploded files). Compressed sectors (only found in compressed - not imploded - files) are compressed with one or more compression algorithms, and have the following structure:
+00h: byte CompressionMask : Mask of the compression types applied to this sector. If multiple compression types are used, they are applied in the order listed below, and decompression is performed in the opposite order. This byte counts towards the total sector size, meaning that the sector will be stored uncompressed if the data cannot be compressed by at least two bytes; as well, this byte is encrypted with the sector data, if applicable. The following compression types are defined (for implementations of these algorithms, see StormLib):
+ 40h: IMA ADPCM mono
+ 80h: IMA ADPCM stereo
+ 01h: Huffman encoded
+ 02h: Deflated (see ZLib)
+ 08h: Imploded (see PKWare Data Compression Library)
+ 10h: BZip2 compressed (see BZip2)
+01h: byte(SectorSize - 1) SectorData : The compressed data for the sector.
+
+If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which contains the entire file data.
+
+If the file is encrypted, each sector (after compression/implosion, if applicable) is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) XOR FileSize) (StormLib incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the 0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
+
+The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. However, the SectorOffsetTable will be present if the file is compressed/imploded and the file is not stored as a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the archive's sector size).
+
+2.7 LISTFILE
+The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)" (default language and platform), and is simply a text file with file paths separated by ';', 0Dh, 0Ah, or some combination of these. The file "(listfile)" may not be listed in the listfile.
+
+2.8 EXTENDED ATTRIBUTES
+The extended attributes are optional file attributes for files in the block table. These attributes were added at times after the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file (default language and platform), in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This file is structured as follows:
+
+00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
+04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
+ 00000001h: File CRC32s.
+ 00000002h: File timestamps.
+ 00000004h: File MD5s.
+08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have CRC32s.
+immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
+immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have MD5s.
+
+2.9 WEAK DIGITAL SIGNATURE
+The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation
+of the RSASSA-PKCS1-v1_5 digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak)
+RSA key (for more information about this protocol, see the RSA Labs PKCS1 specification). The public key
+and exponent are stored in a resource in Storm, the private key is stored in a separate file, whose filename
+is passed to MPQAPI (the private key is not stored in MPQAPI). The signature is stored uncompressed,
+unencrypted in the file "(signature)" (default language and platform) in the archive. The archive
+is hashed from the beginning of the archive (ArchiveOffset in the containing file) to the end of
+the archive (the length indicated by ArchiveSize, or calculated in the Burning Crusade MoPaQ format);
+the signature file is added to the archive before signing, and the space occupied by the file is considered
+to be all binary 0s during signing/verification. This file is structured as follows:
+
+00h: int32 Unknown : Must be 0.
+04h: int32 Unknown : Must be 0.
+08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored
+in little-endian order. The structure of this, when decrypted, follows the RSASSA-PKCS1-v1_5 specification;
+this format is rather icky to work with (I wrote a program to verify this signature using nothing but an MD5
+function and huge integer functions; it wasn't pleasant), and best left to an encryption library such as Cryto++.
+
+2.10 STRONG DIGITAL SIGNATURE
+The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
+
+00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
+04h: int2048 Signature : The digital signature, stored in little-endian format.
+
+When the Signature field is decrypted with the public key and exponent, and the resulting large integer is stored in little-endian order, it is structured as follows:
+
+00h: byte Padding : Must be 0Bh.
+01h: byte(235) Padding : Must be BBh.
+ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 byte order.
+
+3. ALGORITHM SOURCE CODE
+All of the sample code here assumes little endian machine byte order, that the short type is 16 bits, that the long type is 32 bits, and that the long long type is 64 bits. Adjustments must be made if these assumptions are not correct on a given platform. All code not credited otherwise was written by myself in the writing of this specification.
+
+3.1 ENCRYPTION/DECRYPTION
+Based on code from StormLib.
+
+unsigned long dwCryptTable[0x500];
+
+// The encryption and hashing functions use a number table in their procedures. This table must be initialized before the functions are called the first time.
+void InitializeCryptTable()
+{
+ unsigned long seed = 0x00100001;
+ unsigned long index1 = 0;
+ unsigned long index2 = 0;
+ int i;
+
+ for (index1 = 0; index1 < 0x100; index1++)
+ {
+ for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
+ {
+ unsigned long temp1, temp2;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp1 = (seed & 0xFFFF) << 0x10;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp2 = (seed & 0xFFFF);
+
+ dwCryptTable[index2] = (temp1 | temp2);
+ }
+ }
+}
+
+void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
+{
+ assert(lpbyBuffer);
+
+ unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
+ unsigned long seed = 0xEEEEEEEE;
+ unsigned long ch;
+
+ dwLength /= sizeof(unsigned long);
+
+ while(dwLength-- > 0)
+ {
+ seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
+ ch = *lpdwBuffer ^ (dwKey + seed);
+
+ dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
+ seed = *lpdwBuffer + seed + (seed << 5) + 3;
+
+ *lpdwBuffer++ = ch;
+ }
+}
+
+void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
+{
+ assert(lpbyBuffer);
+
+ unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
+ unsigned long seed = 0xEEEEEEEEL;
+ unsigned long ch;
+
+ dwLength /= sizeof(unsigned long);
+
+ while(dwLength-- > 0)
+ {
+ seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
+ ch = *lpdwBuffer ^ (dwKey + seed);
+
+ dwKey = ((~dwKey << 0x15) + 0x11111111L) | (dwKey >> 0x0B);
+ seed = ch + seed + (seed << 5) + 3;
+
+ *lpdwBuffer++ = ch;
+ }
+}
+
+3.2 HASHING AND FILE KEY COMPUTATION
+These functions may have been derived from StormLib code at some point in the very distant past. It was so long ago that I don't remember for certain.
+
+// Different types of hashes to make with HashString
+#define MPQ_HASH_TABLE_OFFSET 0
+#define MPQ_HASH_NAME_A 1
+#define MPQ_HASH_NAME_B 2
+#define MPQ_HASH_FILE_KEY 3
+
+// Based on code from StormLib.
+unsigned long HashString(const char *lpszString, unsigned long dwHashType)
+{
+ assert(lpszString);
+ assert(dwHashType <= MPQ_HASH_FILE_KEY);
+
+ unsigned long seed1 = 0x7FED7FEDL;
+ unsigned long seed2 = 0xEEEEEEEEL;
+ int ch;
+
+ while (*lpszString != 0)
+ {
+ ch = toupper(*lpszString++);
+
+ seed1 = dwCryptTable[(dwHashType * 0x100) + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+ return seed1;
+}
+
+#define BLOCK_OFFSET_ADJUSTED_KEY 0x00020000L
+
+unsigned long ComputeFileKey(const char *lpszFilePath, const BlockTableEntry &blockEntry, unsigned long nArchiveOffset)
+{
+ assert(lpszFilePath);
+
+ // Find the file name part of the path
+ const char *lpszFileName = strrchr(lpszFilePath, '\\');
+ if (lpszFileName)
+ lpszFileName++; // Skip the \
+ else
+ lpszFileName = lpszFilePath;
+
+ // Hash the name to get the base key
+ unsigned long nFileKey = HashString(lpszFileName, MPQ_HASH_FILE_KEY);
+
+ // Offset-adjust the key if necessary
+ if (blockEntry.Flags & BLOCK_OFFSET_ADJUSTED_KEY)
+ nFileKey = (nFileKey + blockEntry.BlockOffset) ^ blockEntry.FileSize;
+
+ return nFileKey;
+}
+
+3.3 FINDING FILES
+
+#define MPQ_HASH_ENTRY_EMPTY 0xFFFFFFFFL
+#define MPQ_HASH_ENTRY_DELETED 0xFFFFFFFEL
+
+bool FindFileInHashTable(const HashTableEntry *lpHashTable, unsigned long nHashTableSize, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform, unsigned long &iFileHashEntry)
+{
+ assert(lpHashTable);
+ assert(nHashTableSize);
+ assert(lpszFilePath);
+
+ // Find the home entry in the hash table for the file
+ unsigned long iInitEntry = HashString(lpszFilePath, MPQ_HASH_TABLE_OFFSET) & (nHashTableSize - 1);
+
+ // Is there anything there at all?
+ if (lpHashTable[iInitEntry].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
+ return false;
+
+ // Compute the hashes to compare the hash table entry against
+ unsigned long nNameHashA = HashString(lpszFilePath, MPQ_HASH_NAME_A),
+ nNameHashB = HashString(lpszFilePath, MPQ_HASH_NAME_B),
+ iCurEntry = iInitEntry;
+
+ // Check each entry in the hash table till a termination point is reached
+ do
+ {
+ if (lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_DELETED)
+ {
+ if (lpHashTable[iCurEntry].FilePathHashA == nNameHashA
+ && lpHashTable[iCurEntry].FilePathHashB == nNameHashB
+ && lpHashTable[iCurEntry].Language == nLang
+ && lpHashTable[iCurEntry].Platform == nPlatform)
+ {
+ iFileHashEntry = iCurEntry;
+
+ return true;
+ }
+ }
+
+ iCurEntry = (iCurEntry + 1) & (nHashTableSize - 1);
+ } while (iCurEntry != iInitEntry && lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_EMPTY);
+
+ return false;
+}
+
+3.4 DELETING FILES
+
+bool DeleteFile(HashTableEntry *lpHashTable, unsigned long nHashTableSize, BlockTableEntry *lpBlockTable, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform)
+{
+ assert(lpHashTable);
+ assert(nHashTableSize);
+ assert(lpBlockTable);
+
+ // Find the file in the hash table
+ unsigned long iFileHashEntry;
+
+ if (!FindFileInHashTable(lpHashTable, nHashTableSize, lpszFilePath, nLang, nPlatform, iFileHashEntry))
+ return false;
+
+ // Get the block table index before we nuke the hash table entry
+ unsigned long iFileBlockEntry = lpHashTable[iFileHashEntry].FileBlockIndex;
+
+ // Delete the file's entry in the hash table
+ memset(&lpHashTable[iFileHashEntry], 0xFF, sizeof(HashTableEntry));
+
+ // If the next entry is empty, mark this one as empty; otherwise, mark this as deleted.
+ if (lpHashTable[(iFileHashEntry + 1) & (nHashTableSize - 1)].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
+ lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_EMPTY;
+ else
+ lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_DELETED;
+
+ // If the block occupies space, mark the block as free space; otherwise, clear the block table entry.
+ if (lpBlockTable[iFileBlockEntry].BlockSize > 0)
+ {
+ lpBlockTable[iFileBlockEntry].FileSize = 0;
+ lpBlockTable[iFileBlockEntry].Flags = 0;
+ }
+ else
+ memset(&lpBlockTable[iFileBlockEntry], 0, sizeof(BlockTableEntry);
+
+ return true;
+}
+
+3.5 CONVERSION OF FILETIME AND time_t
+This code assumes that the base ("zero") date for time_t is 01/01/1970. This is true on Windows, Unix System V systems, and Mac OS X. It is unknown whether this is true on all other platforms. You'll need to research this yourself, if you plan on porting it somewhere else.
+
+#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
+
+bool GetTimeFromFileTime(const FILETIME &fileTime, time_t &time)
+{
+ // The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
+ unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
+
+ if (nTime < EPOCH_OFFSET)
+ return false;
+
+ nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
+ nTime /= 10000000ULL; // Convert 100 ns to sec
+
+ time = (time_t)nTime;
+
+ // Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
+ if ((nTime - (unsigned long long)time) > 0)
+ return false;
+
+ return true;
+}
+
+void GetFileTimeFromTime(const time_t &time, FILETIME &fileTime)
+{
+ unsigned long long nTime = (unsigned long long)time;
+
+ nTime *= 10000000ULL;
+ nTime += EPOCH_OFFSET;
+
+ fileTime.dwLowDateTime = (DWORD)nTime;
+ fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
+}
+
+3.6 FORMING A 64-BIT LARGE ARCHIVE OFFSET FROM 32-BIT AND 16-BIT COMPONENTS
+unsigned long long MakeLargeArchiveOffset(unsigned long nOffsetLow, unsigned short nOffsetHigh)
+{
+ return ((unsigned long long)nOffsetHigh << 32) + (unsigned long long)nOffsetLow;
+}
+
+4. REVISION HISTORY
+1.0
+ - Updated to include most of the changes found in the Burning Crusade Friends and Family beta
+
+0.91.
+ - Updated several structure member descriptions
+ - Listed the full set of characters that can separate list file entries
+ - Noted that (attributes), (listfile), and (signature) use the default language and platform codes
+ - Redid part of the file data specs to clarify the format of sectors
+ - Enhanced descriptions of the different kinds of block table entries
+ - Added ComputeFileKey, FindFileInHashTable, and DeleteFile source \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-deDE.txt b/dep/StormLib/doc/d3-authenticationcode-deDE.txt
new file mode 100644
index 00000000000..cac66712af0
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-deDE.txt
@@ -0,0 +1 @@
+UCMXF6EJY352EFH4XFRXCFH2XC9MQRZK \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-enGB.txt b/dep/StormLib/doc/d3-authenticationcode-enGB.txt
new file mode 100644
index 00000000000..2bc9c83859d
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-enGB.txt
@@ -0,0 +1 @@
+MMKVHY48RP7WXP4GHYBQ7SL9J9UNPHBP \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-enSG.txt b/dep/StormLib/doc/d3-authenticationcode-enSG.txt
new file mode 100644
index 00000000000..e6f1ec29609
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-enSG.txt
@@ -0,0 +1 @@
+8MXLWHQ7VGGLTZ9MQZQSFDCLJYET3CPP \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-enUS.txt b/dep/StormLib/doc/d3-authenticationcode-enUS.txt
new file mode 100644
index 00000000000..8d73e61def9
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-enUS.txt
@@ -0,0 +1 @@
+EJ2R5TM6XFE2GUNG5QDGHKQ9UAKPWZSZ \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-esES.txt b/dep/StormLib/doc/d3-authenticationcode-esES.txt
new file mode 100644
index 00000000000..6b1b0a1b811
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-esES.txt
@@ -0,0 +1 @@
+PBGFBE42Z6LNK65UGJQ3WZVMCLP4HQQT \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-esMX.txt b/dep/StormLib/doc/d3-authenticationcode-esMX.txt
new file mode 100644
index 00000000000..504759e8d55
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-esMX.txt
@@ -0,0 +1 @@
+X7SEJJS9TSGCW5P28EBSC47AJPEY8VU2 \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-frFR.txt b/dep/StormLib/doc/d3-authenticationcode-frFR.txt
new file mode 100644
index 00000000000..bb35a2bfdc6
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-frFR.txt
@@ -0,0 +1 @@
+5KVBQA8VYE6XRY3DLGC5ZDE4XS4P7YA2 \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-itIT.txt b/dep/StormLib/doc/d3-authenticationcode-itIT.txt
new file mode 100644
index 00000000000..a62031d3883
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-itIT.txt
@@ -0,0 +1 @@
+478JD2K56EVNVVY4XX8TDWYT5B8KB254 \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-koKR.txt b/dep/StormLib/doc/d3-authenticationcode-koKR.txt
new file mode 100644
index 00000000000..296ffcc9450
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-koKR.txt
@@ -0,0 +1 @@
+8TS4VNFQRZTN6YWHE9CHVDH9NVWD474A \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-plPL.txt b/dep/StormLib/doc/d3-authenticationcode-plPL.txt
new file mode 100644
index 00000000000..a92563c1815
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-plPL.txt
@@ -0,0 +1 @@
+LJ52Z32DF4LZ4ZJJXVKK3AZQA6GABLJB \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-ptBR.txt b/dep/StormLib/doc/d3-authenticationcode-ptBR.txt
new file mode 100644
index 00000000000..e6e5c3568d9
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-ptBR.txt
@@ -0,0 +1 @@
+K6BDHY2ECUE2545YKNLBJPVYWHE7XYAG \ No newline at end of file
diff --git a/dep/StormLib/doc/d3-authenticationcode-zhTW.txt b/dep/StormLib/doc/d3-authenticationcode-zhTW.txt
new file mode 100644
index 00000000000..138a5449c7a
--- /dev/null
+++ b/dep/StormLib/doc/d3-authenticationcode-zhTW.txt
@@ -0,0 +1 @@
+6VWCQTN8V3ZZMRUCZXV8A8CGUX2TAA8H \ No newline at end of file
diff --git a/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob b/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob
new file mode 100644
index 00000000000..7972b2d7636
--- /dev/null
+++ b/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob
@@ -0,0 +1,49 @@
+{
+"config":{
+ "product": "D3",
+ "install_progress_percent": 70.0,
+ "install_progress_info": [8000000000.0, 0.0, 0.0],
+ "download_progress_info": [10000000.0, 500000000.0, 500000000.0],
+ "install_progress_speed": 5000000.0,
+ "tome_download_progress_percent": 0.0,
+ "updater_product": "d3_patch",
+ "expansion_level": 0,
+ "ptr": false,
+ "beta": false,
+ "update_method": "patch on demand",
+ "supports_multibox": false,
+ "data_dir": "Data_D3/PC/MPQs/",
+ "patch_url": "http://ruRU.patch.battle.net:1119/patch",
+ "update_regex": "(?P<prefix>d3-update-(?P<dataset>\\w+))-(?P<build>\\d+)\\.mpq$",
+ "update_identifier": "d3-update-",
+ "torrent_file_path": "Diablo III.tfil",
+ "manifest_file_path": "Diablo III.mfil",
+ "priority_file_path": "Diablo III.pfil",
+ "priority_file_layout": "Retail",
+ "binary_version_path": "Diablo III.exe",
+ "binary_launch_path": "Diablo III.exe",
+ "display_locales":["ruRU"],
+ "supported_locales" : ["enUS", "esMX", "ptBR", "enGB", "deDE", "esES", "frFR", "itIT", "plPL", "enSG", "ptPT", "ruRU", "koKR", "zhTW", "zhCN"],
+ "launch_arguments":["-launch","-uid","diablo3_ruru"],
+ "form": {
+ "eula": {
+ "eula":false
+ },
+ "game_dir": {
+ "default": "Program Files",
+ "dirname": "Diablo III",
+ "required_space": 15032385536
+ },
+ "language": {
+ "default":["ruRU"],
+ "list":["ruRU"]
+ },
+ "authentication_key": {
+ "url": [
+ "http://ruru.nydus.battle.net/D3/ruRU/setup/mediakey",
+ "http://dist.blizzard.com/mediakey/d3-authenticationcode-ruRU.txt"
+ ]
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dep/StormLib/doc/diablo3_urls.txt b/dep/StormLib/doc/diablo3_urls.txt
new file mode 100644
index 00000000000..d89f4899528
--- /dev/null
+++ b/dep/StormLib/doc/diablo3_urls.txt
@@ -0,0 +1,14 @@
+http://dist.blizzard.com/mediakey/d3-authenticationcode-deDE.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-enGB.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-enSG.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-enUS.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-esES.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-esMX.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-frFR.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-itIT.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-koKR.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-plPL.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-ptBR.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-ruRU.txt <====
+http://dist.blizzard.com/mediakey/d3-authenticationcode-zhTW.txt
+http://dist.blizzard.com/mediakey/d3-authenticationcode-zhCN.txt <====
diff --git a/dep/StormLib/src/FileStream.cpp b/dep/StormLib/src/FileStream.cpp
new file mode 100644
index 00000000000..413f2acb3a2
--- /dev/null
+++ b/dep/StormLib/src/FileStream.cpp
@@ -0,0 +1,2294 @@
+/*****************************************************************************/
+/* FileStream.cpp Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* File stream support for StormLib */
+/* */
+/* Windows support: Written by Ladislav Zezula */
+/* Mac support: Written by Sam Wilkins */
+/* Linux support: Written by Sam Wilkins and Ivan Komissarov */
+/* Big-endian: Written & debugged by Sam Wilkins */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.06.10 1.00 Lad Derived from StormPortMac.cpp and StormPortLinux.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+#include "FileStream.h"
+
+#ifdef _MSC_VER
+#pragma comment(lib, "wininet.lib")
+#endif
+
+//-----------------------------------------------------------------------------
+// Local defines
+
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE ((HANDLE)-1)
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4800) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
+#endif
+
+//-----------------------------------------------------------------------------
+// Local functions - platform-specific functions
+
+#ifndef PLATFORM_WINDOWS
+static int nLastError = ERROR_SUCCESS;
+
+int GetLastError()
+{
+ return nLastError;
+}
+
+void SetLastError(int nError)
+{
+ nLastError = nError;
+}
+#endif
+
+#ifndef PLATFORM_LITTLE_ENDIAN
+void ConvertPartHeader(void * partHeader)
+{
+ PPART_FILE_HEADER theHeader = (PPART_FILE_HEADER)partHeader;
+
+ theHeader->PartialVersion = SwapUInt32(theHeader->PartialVersion);
+ theHeader->Flags = SwapUInt32(theHeader->Flags);
+ theHeader->FileSizeLo = SwapUInt32(theHeader->FileSizeLo);
+ theHeader->FileSizeHi = SwapUInt32(theHeader->FileSizeHi);
+ theHeader->BlockSize = SwapUInt32(theHeader->BlockSize);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Preparing file bitmap for a complete file of a given size
+
+#define DEFAULT_BLOCK_SIZE 0x4000
+
+static bool Dummy_GetBitmap(
+ TFileStream * pStream,
+ TFileBitmap * pBitmap,
+ DWORD Length,
+ LPDWORD LengthNeeded)
+{
+ ULONGLONG FileSize = 0;
+ DWORD TotalLength;
+ DWORD BlockCount;
+ DWORD BitmapSize;
+ DWORD LastByte;
+ bool bResult = false;
+
+ // Get file size and calculate bitmap length
+ FileStream_GetSize(pStream, FileSize);
+ BlockCount = (DWORD)(((FileSize - 1) / DEFAULT_BLOCK_SIZE) + 1);
+ BitmapSize = (DWORD)(((BlockCount - 1) / 8) + 1);
+
+ // Calculate and give the total length
+ TotalLength = sizeof(TFileBitmap) + BitmapSize;
+ if(LengthNeeded != NULL)
+ *LengthNeeded = TotalLength;
+
+ // Has the caller given enough space for storing the structure?
+ if(Length >= sizeof(TFileBitmap))
+ {
+ memset(pBitmap, 0, sizeof(TFileBitmap));
+ pBitmap->EndOffset = FileSize;
+ pBitmap->IsComplete = 1;
+ pBitmap->BitmapSize = BitmapSize;
+ pBitmap->BlockSize = DEFAULT_BLOCK_SIZE;
+ bResult = true;
+ }
+
+ // Do we have enough space to fill the bitmap as well?
+ if(Length >= TotalLength)
+ {
+ LPBYTE pbBitmap = (LPBYTE)(pBitmap + 1);
+
+ // Fill the full blocks
+ memset(pbBitmap, 0xFF, (BlockCount / 8));
+ pbBitmap += (BlockCount / 8);
+ bResult = true;
+
+ // Supply the last block
+ if(BlockCount & 7)
+ {
+ LastByte = (1 << (BlockCount & 7)) - 1;
+ pbBitmap[0] = (BYTE)LastByte;
+ }
+ }
+
+ return bResult;
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - base file support
+
+static bool BaseFile_Read(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead) // Number of bytes to read from the file
+{
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
+ DWORD dwBytesRead = 0; // Must be set by platform-specific code
+
+#ifdef PLATFORM_WINDOWS
+ {
+ // Note: StormLib no longer supports Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
+
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if(dwBytesToRead != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
+ return false;
+ }
+/*
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if(ByteOffset != pStream->Base.File.FilePos)
+ {
+ LONG ByteOffsetHi = (LONG)(ByteOffset >> 32);
+
+ SetFilePointer(pStream->Base.File.hFile, (LONG)ByteOffset, &ByteOffsetHi, FILE_BEGIN);
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Read the data
+ if(dwBytesToRead != 0)
+ {
+ if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, NULL))
+ return false;
+ }
+*/
+ }
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ {
+ ssize_t bytes_read;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if(ByteOffset != pStream->Base.File.FilePos)
+ {
+ lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET);
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Perform the read operation
+ if(dwBytesToRead != 0)
+ {
+ bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
+ if(bytes_read == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ dwBytesRead = (DWORD)(size_t)bytes_read;
+ }
+ }
+#endif
+
+ // Increment the current file position by number of bytes read
+ // If the number of bytes read doesn't match to required amount, return false
+ pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
+ if(dwBytesRead != dwBytesToRead)
+ SetLastError(ERROR_HANDLE_EOF);
+ return (dwBytesRead == dwBytesToRead);
+}
+
+/**
+ * \a pStream Pointer to an open stream
+ * \a pByteOffset Pointer to file byte offset. If NULL, writes to current position
+ * \a pvBuffer Pointer to data to be written
+ * \a dwBytesToWrite Number of bytes to write to the file
+ */
+
+static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
+{
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
+ DWORD dwBytesWritten = 0; // Must be set by platform-specific code
+
+#ifdef PLATFORM_WINDOWS
+ {
+ // Note: StormLib no longer supports Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
+
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if(dwBytesToWrite != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
+ return false;
+ }
+/*
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if(ByteOffset != pStream->Base.File.FilePos)
+ {
+ LONG ByteOffsetHi = (LONG)(ByteOffset >> 32);
+
+ SetFilePointer(pStream->Base.File.hFile, (LONG)ByteOffset, &ByteOffsetHi, FILE_BEGIN);
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Read the data
+ if(dwBytesToWrite != 0)
+ {
+ if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, NULL))
+ return false;
+ }
+*/
+ }
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ {
+ ssize_t bytes_written;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if(ByteOffset != pStream->Base.File.FilePos)
+ {
+ lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET);
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Perform the read operation
+ bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
+ if(bytes_written == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ dwBytesWritten = (DWORD)(size_t)bytes_written;
+ }
+#endif
+
+ // Increment the current file position by number of bytes read
+ pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
+
+ // Also modify the file size, if needed
+ if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
+ pStream->Base.File.FileSize = pStream->Base.File.FilePos;
+
+ if(dwBytesWritten != dwBytesToWrite)
+ SetLastError(ERROR_DISK_FULL);
+ return (dwBytesWritten == dwBytesToWrite);
+}
+
+static bool BaseFile_GetPos(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & ByteOffset) // Pointer to file byte offset
+{
+ ByteOffset = pStream->Base.File.FilePos;
+ return true;
+}
+
+static bool BaseFile_GetSize(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & FileSize) // Pointer where to store file size
+{
+ FileSize = pStream->Base.File.FileSize;
+ return true;
+}
+
+/**
+ * \a pStream Pointer to an open stream
+ * \a NewFileSize New size of the file
+ */
+static bool BaseFile_SetSize(TFileStream * pStream, ULONGLONG NewFileSize)
+{
+#ifdef PLATFORM_WINDOWS
+ {
+ LONG FileSizeHi = (LONG)(NewFileSize >> 32);
+ LONG FileSizeLo;
+ DWORD dwNewPos;
+ bool bResult;
+
+ // Set the position at the new file size
+ dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN);
+ if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
+ return false;
+
+ // Set the current file pointer as the end of the file
+ bResult = (bool)SetEndOfFile(pStream->Base.File.hFile);
+
+ // Restore the file position
+ FileSizeHi = (LONG)(pStream->Base.File.FilePos >> 32);
+ FileSizeLo = (LONG)(pStream->Base.File.FilePos);
+ SetFilePointer(pStream->Base.File.hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN);
+ return bResult;
+ }
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ {
+ if(ftruncate((intptr_t)pStream->Base.File.hFile, (off_t)NewFileSize) == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ return true;
+ }
+#endif
+}
+
+static bool BaseFile_GetTime(TFileStream * pStream, ULONGLONG * pFileTime)
+{
+ *pFileTime = pStream->Base.File.FileTime;
+ return true;
+}
+
+// Renames the file pointed by pStream so that it contains data from pNewStream
+static bool BaseFile_Switch(TFileStream * pStream, TFileStream * pNewStream)
+{
+#ifdef PLATFORM_WINDOWS
+ // Delete the original stream file. Don't check the result value,
+ // because if the file doesn't exist, it would fail
+ DeleteFile(pStream->szFileName);
+
+ // Rename the new file to the old stream's file
+ return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ // "rename" on Linux also works if the target file exists
+ if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ return true;
+#endif
+}
+
+static void BaseFile_Close(TFileStream * pStream)
+{
+ if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
+ {
+#ifdef PLATFORM_WINDOWS
+ CloseHandle(pStream->Base.File.hFile);
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ close((intptr_t)pStream->Base.File.hFile);
+#endif
+ }
+
+ // Also invalidate the handle
+ pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
+}
+
+static bool BaseFile_Create(
+ TFileStream * pStream,
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+#ifdef PLATFORM_WINDOWS
+ {
+ DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
+
+ pStream->Base.File.hFile = CreateFile(szFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ dwWriteShare | FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ 0,
+ NULL);
+ if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
+ return false;
+ }
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ {
+ intptr_t handle;
+
+ handle = open(szFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(handle == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ pStream->Base.File.hFile = (HANDLE)handle;
+ }
+#endif
+
+ // Fill-in the entry points
+ pStream->BaseRead = BaseFile_Read;
+ pStream->BaseWrite = BaseFile_Write;
+ pStream->BaseGetPos = BaseFile_GetPos;
+ pStream->BaseGetSize = BaseFile_GetSize;
+ pStream->BaseSetSize = BaseFile_SetSize;
+ pStream->BaseSetSize = BaseFile_SetSize;
+ pStream->BaseGetTime = BaseFile_GetTime;
+ pStream->BaseClose = BaseFile_Close;
+
+ // Reset the file position
+ pStream->Base.File.FileSize = 0;
+ pStream->Base.File.FilePos = 0;
+ pStream->dwFlags = dwStreamFlags;
+ return true;
+}
+
+static bool BaseFile_Open(
+ TFileStream * pStream,
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+#ifdef PLATFORM_WINDOWS
+ {
+ ULARGE_INTEGER FileSize;
+ DWORD dwDesiredAccess = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? GENERIC_READ : GENERIC_ALL;
+ DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
+
+ // Open the file
+ pStream->Base.File.hFile = CreateFile(szFileName,
+ dwDesiredAccess,
+ dwWriteShare | FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
+ return false;
+
+ // Query the file size
+ FileSize.LowPart = GetFileSize(pStream->Base.File.hFile, &FileSize.HighPart);
+ pStream->Base.File.FileSize = FileSize.QuadPart;
+
+ // Query last write time
+ GetFileTime(pStream->Base.File.hFile, NULL, NULL, (LPFILETIME)&pStream->Base.File.FileTime);
+ }
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ {
+ struct stat fileinfo;
+ int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR;
+ intptr_t handle;
+
+ // Open the file
+ handle = open(szFileName, oflag);
+ if(handle == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ // Get the file size
+ if(fstat(handle, &fileinfo) == -1)
+ {
+ nLastError = errno;
+ return false;
+ }
+
+ // time_t is number of seconds since 1.1.1970, UTC.
+ // 1 second = 10000000 (decimal) in FILETIME
+ // Set the start to 1.1.1970 00:00:00
+ pStream->Base.File.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
+ pStream->Base.File.FileSize = (ULONGLONG)fileinfo.st_size;
+ pStream->Base.File.hFile = (HANDLE)handle;
+ }
+#endif
+
+ // Fill-in the entry points
+ pStream->BaseRead = BaseFile_Read;
+ pStream->BaseWrite = BaseFile_Write;
+ pStream->BaseGetPos = BaseFile_GetPos;
+ pStream->BaseGetSize = BaseFile_GetSize;
+ pStream->BaseSetSize = BaseFile_SetSize;
+ pStream->BaseGetTime = BaseFile_GetTime;
+ pStream->BaseClose = BaseFile_Close;
+
+ // Reset the file position
+ pStream->Base.File.FilePos = 0;
+ pStream->dwFlags = dwStreamFlags;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - base memory-mapped file support
+
+static bool BaseMap_Read(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead) // Number of bytes to read from the file
+{
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Map.FilePos;
+
+ // Do we have to read anything at all?
+ if(dwBytesToRead != 0)
+ {
+ // Don't allow reading past file size
+ if((ByteOffset + dwBytesToRead) > pStream->Base.Map.FileSize)
+ return false;
+
+ // Copy the required data
+ memcpy(pvBuffer, pStream->Base.Map.pbFile + (size_t)ByteOffset, dwBytesToRead);
+ }
+
+ // Move the current file position
+ pStream->Base.Map.FilePos += dwBytesToRead;
+ return true;
+}
+
+static bool BaseMap_GetPos(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & ByteOffset) // Pointer to file byte offset
+{
+ ByteOffset = pStream->Base.Map.FilePos;
+ return true;
+}
+
+static bool BaseMap_GetSize(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & FileSize) // Pointer where to store file size
+{
+ FileSize = pStream->Base.Map.FileSize;
+ return true;
+}
+
+static bool BaseMap_GetTime(TFileStream * pStream, ULONGLONG * pFileTime)
+{
+ *pFileTime = pStream->Base.Map.FileTime;
+ return true;
+}
+
+static void BaseMap_Close(TFileStream * pStream)
+{
+#ifdef PLATFORM_WINDOWS
+ if(pStream->Base.Map.pbFile != NULL)
+ UnmapViewOfFile(pStream->Base.Map.pbFile);
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ if(pStream->Base.Map.pbFile != NULL)
+ munmap(pStream->Base.Map.pbFile, (size_t )pStream->Base.Map.FileSize);
+#endif
+
+ pStream->Base.Map.pbFile = NULL;
+}
+
+static bool BaseMap_Open(
+ TFileStream * pStream,
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+#ifdef PLATFORM_WINDOWS
+
+ ULARGE_INTEGER FileSize;
+ HANDLE hFile;
+ HANDLE hMap;
+ bool bResult = false;
+
+ // Open the file for read access
+ hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if(hFile != NULL)
+ {
+ // Retrieve file size. Don't allow mapping file of a zero size.
+ FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
+ if(FileSize.QuadPart != 0)
+ {
+ // Retrieve file time
+ GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime);
+
+ // Now create mapping object
+ hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if(hMap != NULL)
+ {
+ // Map the entire view into memory
+ // Note that this operation will fail if the file can't fit
+ // into usermode address space
+ pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
+ if(pStream->Base.Map.pbFile != NULL)
+ {
+ pStream->Base.Map.FileSize = FileSize.QuadPart;
+ pStream->Base.Map.FilePos = 0;
+ bResult = true;
+ }
+
+ // Close the map handle
+ CloseHandle(hMap);
+ }
+ }
+
+ // Close the file handle
+ CloseHandle(hFile);
+ }
+
+ // If the file is not there and is not available for random access,
+ // report error
+ if(bResult == false)
+ return false;
+#endif
+
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ struct stat fileinfo;
+ intptr_t handle;
+ bool bResult = false;
+
+ // Open the file
+ handle = open(szFileName, O_RDONLY);
+ if(handle != -1)
+ {
+ // Get the file size
+ if(fstat(handle, &fileinfo) != -1)
+ {
+ pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0);
+ if(pStream->Base.Map.pbFile != NULL)
+ {
+ // time_t is number of seconds since 1.1.1970, UTC.
+ // 1 second = 10000000 (decimal) in FILETIME
+ // Set the start to 1.1.1970 00:00:00
+ pStream->Base.Map.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
+ pStream->Base.Map.FileSize = (ULONGLONG)fileinfo.st_size;
+ pStream->Base.Map.FilePos = 0;
+ bResult = true;
+ }
+ }
+ close(handle);
+ }
+
+ // Did the mapping fail?
+ if(bResult == false)
+ {
+ nLastError = errno;
+ return false;
+ }
+#endif
+
+ // Fill-in entry points
+ pStream->BaseRead = BaseMap_Read;
+ pStream->BaseGetPos = BaseMap_GetPos;
+ pStream->BaseGetSize = BaseMap_GetSize;
+ pStream->BaseGetTime = BaseMap_GetTime;
+ pStream->BaseClose = BaseMap_Close;
+ pStream->dwFlags = dwStreamFlags;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - base HTTP file support
+
+static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR * szServerName)
+{
+ // Check for HTTP
+ if(!_tcsnicmp(szFileName, _T("http://"), 7))
+ szFileName += 7;
+
+ // Cut off the server name
+ if(szServerName != NULL)
+ {
+ while(szFileName[0] != 0 && szFileName[0] != _T('/'))
+ *szServerName++ = *szFileName++;
+ *szServerName = 0;
+ }
+ else
+ {
+ while(szFileName[0] != 0 && szFileName[0] != _T('/'))
+ *szFileName++;
+ }
+
+ // Return the remainder
+ return szFileName;
+}
+
+static bool BaseHttp_Read(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead) // Number of bytes to read from the file
+{
+#ifdef PLATFORM_WINDOWS
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Http.FilePos;
+ DWORD dwTotalBytesRead = 0;
+
+ // Do we have to read anything at all?
+ if(dwBytesToRead != 0)
+ {
+ HINTERNET hRequest;
+ LPCTSTR szFileName;
+ LPBYTE pbBuffer = (LPBYTE)pvBuffer;
+ TCHAR szRangeRequest[0x80];
+ DWORD dwStartOffset = (DWORD)ByteOffset;
+ DWORD dwEndOffset = dwStartOffset + dwBytesToRead;
+ BYTE Buffer[0x200];
+
+ // Open HTTP request to the file
+ szFileName = BaseHttp_ExtractServerName(pStream->szFileName, NULL);
+ hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
+ if(hRequest != NULL)
+ {
+ // Add range request to the HTTP headers
+ // http://www.clevercomponents.com/articles/article015/resuming.asp
+ _stprintf(szRangeRequest, _T("Range: bytes=%d-%d"), dwStartOffset, dwEndOffset);
+ HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
+
+ // Send the request to the server
+ if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
+ {
+ while(dwTotalBytesRead < dwBytesToRead)
+ {
+ DWORD dwBlockBytesToRead = dwBytesToRead - dwTotalBytesRead;
+ DWORD dwBlockBytesRead = 0;
+
+ // Read the block from the file
+ if(dwBlockBytesToRead > sizeof(Buffer))
+ dwBlockBytesToRead = sizeof(Buffer);
+ InternetReadFile(hRequest, pbBuffer, dwBlockBytesToRead, &dwBlockBytesRead);
+
+ // Check for end
+ if(dwBlockBytesRead == 0)
+ break;
+
+ // Move buffers
+ dwTotalBytesRead += dwBlockBytesRead;
+ pbBuffer += dwBlockBytesRead;
+ }
+ }
+ InternetCloseHandle(hRequest);
+ }
+ }
+
+ // Increment the current file position by number of bytes read
+ pStream->Base.Http.FilePos = ByteOffset + dwTotalBytesRead;
+
+ // If the number of bytes read doesn't match the required amount, return false
+ if(dwTotalBytesRead != dwBytesToRead)
+ SetLastError(ERROR_HANDLE_EOF);
+ return (dwTotalBytesRead == dwBytesToRead);
+
+#else
+
+ // Not supported
+ pStream = pStream;
+ pByteOffset = pByteOffset;
+ pvBuffer = pvBuffer;
+ dwBytesToRead = dwBytesToRead;
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return false;
+
+#endif
+}
+
+static bool BaseHttp_GetPos(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & ByteOffset) // Pointer to file byte offset
+{
+ ByteOffset = pStream->Base.Http.FilePos;
+ return true;
+}
+
+static bool BaseHttp_GetSize(
+ TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & FileSize) // Pointer where to store file size
+{
+ FileSize = pStream->Base.Http.FileSize;
+ return true;
+}
+
+static bool BaseHttp_GetTime(TFileStream * pStream, ULONGLONG * pFileTime)
+{
+ *pFileTime = pStream->Base.Http.FileTime;
+ return true;
+}
+
+static void BaseHttp_Close(TFileStream * pStream)
+{
+#ifdef PLATFORM_WINDOWS
+ if(pStream->Base.Http.hConnect != NULL)
+ InternetCloseHandle(pStream->Base.Http.hConnect);
+ pStream->Base.Http.hConnect = NULL;
+
+ if(pStream->Base.Http.hInternet != NULL)
+ InternetCloseHandle(pStream->Base.Http.hInternet);
+ pStream->Base.Http.hInternet = NULL;
+#else
+ pStream = pStream;
+#endif
+}
+
+static bool BaseHttp_Open(
+ TFileStream * pStream,
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+#ifdef PLATFORM_WINDOWS
+
+ HINTERNET hRequest;
+ DWORD dwTemp = 0;
+ bool bFileAvailable = false;
+ int nError = ERROR_SUCCESS;
+
+ // Don't connect to the internet
+ if(!InternetGetConnectedState(&dwTemp, 0))
+ nError = GetLastError();
+
+ // Initiate the connection to the internet
+ if(nError == ERROR_SUCCESS)
+ {
+ pStream->Base.Http.hInternet = InternetOpen(_T("StormLib HTTP MPQ reader"),
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ 0);
+ if(pStream->Base.Http.hInternet == NULL)
+ nError = GetLastError();
+ }
+
+ // Connect to the server
+ if(nError == ERROR_SUCCESS)
+ {
+ TCHAR szServerName[MAX_PATH];
+ DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE;
+
+ // Initiate connection with the server
+ szFileName = BaseHttp_ExtractServerName(szFileName, szServerName);
+ pStream->Base.Http.hConnect = InternetConnect(pStream->Base.Http.hInternet,
+ szServerName,
+ INTERNET_DEFAULT_HTTP_PORT,
+ NULL,
+ NULL,
+ INTERNET_SERVICE_HTTP,
+ dwFlags,
+ 0);
+ if(pStream->Base.Http.hConnect == NULL)
+ nError = GetLastError();
+ }
+
+ // Now try to query the file size
+ if(nError == ERROR_SUCCESS)
+ {
+ // Open HTTP request to the file
+ hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
+ if(hRequest != NULL)
+ {
+ if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
+ {
+ ULONGLONG FileTime = 0;
+ DWORD dwFileSize = 0;
+ DWORD dwDataSize;
+ DWORD dwIndex = 0;
+
+ // Check if the MPQ has Last Modified field
+ dwDataSize = sizeof(ULONGLONG);
+ if(HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &FileTime, &dwDataSize, &dwIndex))
+ pStream->Base.Http.FileTime = FileTime;
+
+ // Verify if the server supports random access
+ dwDataSize = sizeof(DWORD);
+ if(HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFileSize, &dwDataSize, &dwIndex))
+ {
+ if(dwFileSize != 0)
+ {
+ pStream->Base.Http.FileSize = dwFileSize;
+ pStream->Base.Http.FilePos = 0;
+ bFileAvailable = true;
+ }
+ }
+ }
+ InternetCloseHandle(hRequest);
+ }
+ }
+
+ // If the file is not there and is not available for random access,
+ // report error
+ if(bFileAvailable == false)
+ {
+ BaseHttp_Close(pStream);
+ return false;
+ }
+
+ // Fill-in entry points
+ pStream->BaseRead = BaseHttp_Read;
+ pStream->BaseGetPos = BaseHttp_GetPos;
+ pStream->BaseGetSize = BaseHttp_GetSize;
+ pStream->BaseGetTime = BaseHttp_GetTime;
+ pStream->BaseClose = BaseHttp_Close;
+ pStream->dwFlags = dwStreamFlags;
+ return true;
+
+#else
+
+ // Not supported
+ pStream = pStream;
+ szFileName = szFileName;
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return false;
+
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - linear stream support
+
+static bool LinearStream_Read(
+ TLinearStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead) // Number of bytes to read from the file
+{
+ ULONGLONG ByteOffset;
+ ULONGLONG EndOffset;
+ LPBYTE pbBitmap;
+ DWORD BlockIndex;
+ DWORD ByteIndex;
+ DWORD BitMask;
+
+ // At this point, we must have a bitmap set
+ assert(pStream->pBitmap != NULL);
+
+ // If we have data map, we must check if the data block is present in the MPQ
+ if(dwBytesToRead != 0)
+ {
+ DWORD BlockSize = pStream->pBitmap->BlockSize;
+
+ // Get the offset where we read it from
+ if(pByteOffset == NULL)
+ pStream->BaseGetPos(pStream, ByteOffset);
+ else
+ ByteOffset = *pByteOffset;
+ EndOffset = ByteOffset + dwBytesToRead;
+
+ // If the start of the area is within the region
+ // protected by data map, check each block
+ if(ByteOffset < pStream->pBitmap->EndOffset)
+ {
+ // Cut the end of the stream protected by the data map
+ EndOffset = STORMLIB_MIN(EndOffset, pStream->pBitmap->EndOffset);
+
+ // Calculate the initial block index
+ BlockIndex = (DWORD)(ByteOffset / BlockSize);
+ pbBitmap = (LPBYTE)(pStream->pBitmap + 1);
+
+ // Parse each block
+ while(ByteOffset < EndOffset)
+ {
+ // Prepare byte index and bit mask
+ ByteIndex = BlockIndex / 8;
+ BitMask = 1 << (BlockIndex & 0x07);
+
+ // If that bit is not set, it means that the block is not present
+ if((pbBitmap[ByteIndex] & BitMask) == 0)
+ {
+ SetLastError(ERROR_FILE_CORRUPT);
+ return false;
+ }
+
+ // Move to tne next block
+ ByteOffset += BlockSize;
+ BlockIndex++;
+ }
+ }
+ }
+
+ // Now if all tests passed, we can call the base read function
+ return pStream->BaseRead(pStream, pByteOffset, pvBuffer, dwBytesToRead);
+}
+
+static bool LinearStream_Switch(TLinearStream * pStream, TLinearStream * pNewStream)
+{
+ // Sanity checks
+ assert((pNewStream->dwFlags & STREAM_PROVIDER_MASK) == STREAM_PROVIDER_LINEAR);
+ assert((pNewStream->dwFlags & BASE_PROVIDER_MASK) == BASE_PROVIDER_FILE);
+ assert((pStream->dwFlags & STREAM_PROVIDER_MASK) == STREAM_PROVIDER_LINEAR);
+ assert((pStream->dwFlags & BASE_PROVIDER_MASK) == BASE_PROVIDER_FILE);
+
+ // Close the new stream
+ pNewStream->BaseClose(pNewStream);
+
+ // Close the source stream
+ pStream->BaseClose(pStream);
+
+ // Rename the new data source file to the existing file
+ if(!BaseFile_Switch(pStream, pNewStream))
+ return false;
+
+ // Now we have to open the "pStream" again
+ if(!BaseFile_Open(pStream, pStream->szFileName, pNewStream->dwFlags))
+ return false;
+
+ // We need to cleanup the new data stream
+ FileStream_Close(pNewStream);
+ return true;
+}
+
+static bool LinearStream_GetBitmap(
+ TLinearStream * pStream,
+ TFileBitmap * pBitmap,
+ DWORD Length,
+ LPDWORD LengthNeeded)
+{
+ DWORD TotalLength;
+ bool bResult = false;
+
+ // Assumed that we have bitmap now
+ assert(pStream->pBitmap != NULL);
+
+ // Give the bitmap length
+ TotalLength = sizeof(TFileBitmap) + pStream->pBitmap->BitmapSize;
+ if(LengthNeeded != NULL)
+ *LengthNeeded = TotalLength;
+
+ // Do we have enough space to fill at least the bitmap structure?
+ if(Length >= sizeof(TFileBitmap))
+ {
+ // Enough space for complete bitmap?
+ if(Length >= TotalLength)
+ {
+ memcpy(pBitmap, pStream->pBitmap, TotalLength);
+ bResult = true;
+ }
+ else
+ {
+ memcpy(pBitmap, pStream->pBitmap, sizeof(TFileBitmap));
+ bResult = true;
+ }
+ }
+
+ return bResult;
+}
+
+static void LinearStream_Close(TLinearStream * pStream)
+{
+ // Free the data map, if any
+ if(pStream->pBitmap != NULL)
+ STORM_FREE(pStream->pBitmap);
+ pStream->pBitmap = NULL;
+
+ // Call the base class for closing the stream
+ return pStream->BaseClose(pStream);
+}
+
+static bool LinearStream_Open(TLinearStream * pStream)
+{
+ // No extra work here really; just set entry points
+ pStream->StreamRead = pStream->BaseRead;
+ pStream->StreamWrite = pStream->BaseWrite;
+ pStream->StreamGetPos = pStream->BaseGetPos;
+ pStream->StreamGetSize = pStream->BaseGetSize;
+ pStream->StreamSetSize = pStream->BaseSetSize;
+ pStream->StreamGetTime = pStream->BaseGetTime;
+ pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap;
+ pStream->StreamSwitch = (STREAM_SWITCH)LinearStream_Switch;
+ pStream->StreamClose = (STREAM_CLOSE)LinearStream_Close;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - partial stream support
+
+static bool IsPartHeader(PPART_FILE_HEADER pPartHdr)
+{
+ // Version number must be 2
+ if(pPartHdr->PartialVersion == 2)
+ {
+ // GameBuildNumber must be an ASCII number
+ if(isdigit(pPartHdr->GameBuildNumber[0]) && isdigit(pPartHdr->GameBuildNumber[1]) && isdigit(pPartHdr->GameBuildNumber[2]))
+ {
+ // Block size must be power of 2
+ if((pPartHdr->BlockSize & (pPartHdr->BlockSize - 1)) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool PartialStream_Read(
+ TPartialStream * pStream,
+ ULONGLONG * pByteOffset,
+ void * pvBuffer,
+ DWORD dwBytesToRead)
+{
+ ULONGLONG RawByteOffset;
+ LPBYTE pbBuffer = (LPBYTE)pvBuffer;
+ DWORD dwBytesRemaining = dwBytesToRead;
+ DWORD dwPartOffset;
+ DWORD dwPartIndex;
+ DWORD dwBytesRead = 0;
+ DWORD dwBlockSize = pStream->BlockSize;
+ bool bResult = false;
+ int nFailReason = ERROR_HANDLE_EOF; // Why it failed if not enough bytes was read
+
+ // If the byte offset is not entered, use the current position
+ if(pByteOffset == NULL)
+ pByteOffset = &pStream->VirtualPos;
+
+ // Check if the file position is not at or beyond end of the file
+ if(*pByteOffset >= pStream->VirtualSize)
+ {
+ SetLastError(ERROR_HANDLE_EOF);
+ return false;
+ }
+
+ // Get the part index where the read offset is
+ // Note that the part index should now be within the range,
+ // as read requests beyond-EOF are handled by the previous test
+ dwPartIndex = (DWORD)(*pByteOffset / pStream->BlockSize);
+ assert(dwPartIndex < pStream->BlockCount);
+
+ // If the number of bytes remaining goes past
+ // the end of the file, cut them
+ if((*pByteOffset + dwBytesRemaining) > pStream->VirtualSize)
+ dwBytesRemaining = (DWORD)(pStream->VirtualSize - *pByteOffset);
+
+ // Calculate the offset in the current part
+ dwPartOffset = (DWORD)(*pByteOffset) & (pStream->BlockSize - 1);
+
+ // Read all data, one part at a time
+ while(dwBytesRemaining != 0)
+ {
+ PPART_FILE_MAP_ENTRY PartMap = pStream->PartMap + dwPartIndex;
+ DWORD dwBytesInPart;
+
+ // If the part is not present in the file, we fail the read
+ if((PartMap->Flags & 3) == 0)
+ {
+ nFailReason = ERROR_FILE_CORRUPT;
+ bResult = false;
+ break;
+ }
+
+ // If we are in the last part, we have to cut the number of bytes in the last part
+ if(dwPartIndex == pStream->BlockCount - 1)
+ dwBlockSize = (DWORD)pStream->VirtualSize & (pStream->BlockSize - 1);
+
+ // Get the number of bytes reamining in the current part
+ dwBytesInPart = dwBlockSize - dwPartOffset;
+
+ // Compute the raw file offset of the file part
+ RawByteOffset = MAKE_OFFSET64(PartMap->BlockOffsHi, PartMap->BlockOffsLo);
+ if(RawByteOffset == 0)
+ {
+ nFailReason = ERROR_FILE_CORRUPT;
+ bResult = false;
+ break;
+ }
+
+ // If the number of bytes in part is too big, cut it
+ if(dwBytesInPart > dwBytesRemaining)
+ dwBytesInPart = dwBytesRemaining;
+
+ // Append the offset within the part
+ RawByteOffset += dwPartOffset;
+ if(!pStream->BaseRead(pStream, &RawByteOffset, pbBuffer, dwBytesInPart))
+ {
+ nFailReason = ERROR_FILE_CORRUPT;
+ bResult = false;
+ break;
+ }
+
+ // Increment the file position
+ dwBytesRemaining -= dwBytesInPart;
+ dwBytesRead += dwBytesInPart;
+ pbBuffer += dwBytesInPart;
+
+ // Move to the next file part
+ dwPartOffset = 0;
+ dwPartIndex++;
+ }
+
+ // Move the file position by the number of bytes read
+ pStream->VirtualPos = *pByteOffset + dwBytesRead;
+ if(dwBytesRead != dwBytesToRead)
+ SetLastError(nFailReason);
+ return (dwBytesRead == dwBytesToRead);
+}
+
+static bool PartialStream_GetPos(
+ TPartialStream * pStream,
+ ULONGLONG & ByteOffset)
+{
+ ByteOffset = pStream->VirtualPos;
+ return true;
+}
+
+static bool PartialStream_GetSize(
+ TPartialStream * pStream, // Pointer to an open stream
+ ULONGLONG & FileSize) // Pointer where to store file size
+{
+ FileSize = pStream->VirtualSize;
+ return true;
+}
+
+static bool PartialStream_GetBitmap(
+ TPartialStream * pStream,
+ TFileBitmap * pBitmap,
+ DWORD Length,
+ LPDWORD LengthNeeded)
+{
+ LPBYTE pbBitmap;
+ DWORD TotalLength;
+ DWORD BitmapSize = 0;
+ DWORD ByteOffset;
+ DWORD BitMask;
+ bool bResult = false;
+
+ // Do we have stream bitmap?
+ BitmapSize = ((pStream->BlockCount - 1) / 8) + 1;
+
+ // Give the bitmap length
+ TotalLength = sizeof(TFileBitmap) + BitmapSize;
+ if(LengthNeeded != NULL)
+ *LengthNeeded = TotalLength;
+
+ // Do we have enough to fill at least the header?
+ if(Length >= sizeof(TFileBitmap))
+ {
+ // Fill the bitmap header
+ pBitmap->StartOffset = 0;
+ pBitmap->EndOffset = pStream->VirtualSize;
+ pBitmap->IsComplete = 1;
+ pBitmap->BitmapSize = BitmapSize;
+ pBitmap->BlockSize = pStream->BlockSize;
+ pBitmap->Reserved = 0;
+
+ // Is there at least one incomplete block?
+ for(DWORD i = 0; i < pStream->BlockCount; i++)
+ {
+ if(pStream->PartMap[i].Flags != 3)
+ {
+ pBitmap->IsComplete = 0;
+ break;
+ }
+ }
+
+ bResult = true;
+ }
+
+ // Do we have enough space for supplying the bitmap?
+ if(Length >= TotalLength)
+ {
+ // Fill the file bitmap
+ pbBitmap = (LPBYTE)(pBitmap + 1);
+ for(DWORD i = 0; i < pStream->BlockCount; i++)
+ {
+ // Is the block there?
+ if(pStream->PartMap[i].Flags == 3)
+ {
+ ByteOffset = i / 8;
+ BitMask = 1 << (i & 7);
+ pbBitmap[ByteOffset] |= BitMask;
+ }
+ }
+ bResult = true;
+ }
+
+ return bResult;
+}
+
+static void PartialStream_Close(TPartialStream * pStream)
+{
+ // Free the part map
+ if(pStream->PartMap != NULL)
+ STORM_FREE(pStream->PartMap);
+ pStream->PartMap = NULL;
+
+ // Clear variables
+ pStream->VirtualSize = 0;
+ pStream->VirtualPos = 0;
+
+ // Close the base stream
+ assert(pStream->BaseClose != NULL);
+ pStream->BaseClose(pStream);
+}
+
+static bool PartialStream_Open(TPartialStream * pStream)
+{
+ PART_FILE_HEADER PartHdr;
+ ULONGLONG VirtualSize; // Size of the file stored in part file
+ ULONGLONG ByteOffset = {0};
+ DWORD BlockCount;
+
+ // Sanity check
+ assert(pStream->BaseRead != NULL);
+
+ // Attempt to read PART file header
+ if(pStream->BaseRead(pStream, &ByteOffset, &PartHdr, sizeof(PART_FILE_HEADER)))
+ {
+ // We need to swap PART file header on big-endian platforms
+ BSWAP_PART_HEADER(&PartHdr);
+
+ // Verify the PART file header
+ if(IsPartHeader(&PartHdr))
+ {
+ // Calculate the number of parts in the file
+ VirtualSize = MAKE_OFFSET64(PartHdr.FileSizeHi, PartHdr.FileSizeLo);
+ assert(VirtualSize != 0);
+ BlockCount = (DWORD)((VirtualSize + PartHdr.BlockSize - 1) / PartHdr.BlockSize);
+
+ // Allocate the map entry array
+ pStream->PartMap = STORM_ALLOC(PART_FILE_MAP_ENTRY, BlockCount);
+ if(pStream->PartMap != NULL)
+ {
+ // Load the block map
+ if(pStream->BaseRead(pStream, NULL, pStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY)))
+ {
+ // Swap the array of file map entries
+ BSWAP_ARRAY32_UNSIGNED(pStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY));
+
+ // Fill the members of PART file stream
+ pStream->VirtualSize = ((ULONGLONG)PartHdr.FileSizeHi) + PartHdr.FileSizeLo;
+ pStream->VirtualPos = 0;
+ pStream->BlockCount = BlockCount;
+ pStream->BlockSize = PartHdr.BlockSize;
+
+ // Set new function pointers
+ pStream->StreamRead = (STREAM_READ)PartialStream_Read;
+ pStream->StreamGetPos = (STREAM_GETPOS)PartialStream_GetPos;
+ pStream->StreamGetSize = (STREAM_GETSIZE)PartialStream_GetSize;
+ pStream->StreamGetTime = pStream->BaseGetTime;
+ pStream->StreamGetTime = pStream->BaseGetTime;
+ pStream->StreamGetBmp = (STREAM_GETBMP)PartialStream_GetBitmap;
+ pStream->StreamClose = (STREAM_CLOSE)PartialStream_Close;
+ return true;
+ }
+
+ // Free the part map
+ STORM_FREE(pStream->PartMap);
+ pStream->PartMap = NULL;
+ }
+ }
+ }
+
+ SetLastError(ERROR_BAD_FORMAT);
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Local functions - encrypted stream support
+
+// Note: Starcraft II - Installer.exe (4.1.1.4219): Suffix derived from battle.net auth. code
+// Address of decryption routine: 0053A3D0 http://us.battle.net/static/mediakey/sc2-authenticationcode-enUS.txt
+// Pointer to decryptor object: ECX Numbers mean offset of 4-char group of auth code (follows in comment)
+// Pointer to key: ECX+0x5C -0C- -1C--08- -18--04- -14--00- -10-
+static const char * MpqeKey_Starcraft2_Install_deDE = "expand 32-byte kSSXH00004XFXK4KX00008EKJD3CA0000Y64ZY45M0000YD9V"; // Y45MD3CAK4KXSSXHYD9VY64Z8EKJ4XFX
+static const char * MpqeKey_Starcraft2_Install_enGB = "expand 32-byte kANGY000029ZH6NA20000HRGF8UDG0000NY82G8MN00006A3D"; // G8MN8UDG6NA2ANGY6A3DNY82HRGF29ZH
+static const char * MpqeKey_Starcraft2_Install_enSG = "expand 32-byte kWW5B0000F7HWFDU90000FWZSHLB20000BLRSW9RR00003ECE"; // W9RRHLB2FDU9WW5B3ECEBLRSFWZSF7HW
+static const char * MpqeKey_Starcraft2_Install_enUS = "expand 32-byte kTFD80000ETR5VM5G0000K859RE5N0000WT6F3DH500005LXG"; // 3DH5RE5NVM5GTFD85LXGWT6FK859ETR5
+static const char * MpqeKey_Starcraft2_Install_esES = "expand 32-byte kQU4Y0000XKTQ94PF0000N4R4UAXE0000AZ248WLK0000249P"; // 8WLKUAXE94PFQU4Y249PAZ24N4R4XKTQ
+static const char * MpqeKey_Starcraft2_Install_esMX = "expand 32-byte kSQBR00004G54HGGX0000MF9GXX3V0000FFDXA34D0000FE5U"; // A34DXX3VHGGXSQBRFE5UFFDXMF9G4G54
+static const char * MpqeKey_Starcraft2_Install_frFR = "expand 32-byte kFWPQ00006EAJ8HJE0000PFER9K9300008MA2ZG7J0000UA76"; // ZG7J9K938HJEFWPQUA768MA2PFER6EAJ
+static const char * MpqeKey_Starcraft2_Install_itIT = "expand 32-byte kXV7E00008BL2TVAP0000GVMWUNNN0000SVBWNE7C00003G2B"; // NE7CUNNNTVAPXV7E3G2BSVBWGVMW8BL2
+static const char * MpqeKey_Starcraft2_Install_koKR = "expand 32-byte kQWK70000838FBM9Q0000WQDB2FTM0000MWAZ3V9E0000U6MA"; // 3V9E2FTMBM9QQWK7U6MAMWAZWQDB838F
+static const char * MpqeKey_Starcraft2_Install_plPL = "expand 32-byte k83U6000048L6LULJ00004MQDB8ME0000UP6K2NSF0000YHA3"; // 2NSFB8MELULJ83U6YHA3UP6K4MQD48L6
+static const char * MpqeKey_Starcraft2_Install_ptBR = "expand 32-byte kU8BM0000SW4EZ4CU00005F9CZ9EW0000CTY6QA2T0000B5WX"; // QA2TZ9EWZ4CUU8BMB5WXCTY65F9CSW4E
+static const char * MpqeKey_Starcraft2_Install_ruRU = "expand 32-byte k9SH70000YEGT4BAT0000QDK978W60000V9NLVHB30000D68V"; // VHB378W64BAT9SH7D68VV9NLQDK9YEGT
+static const char * MpqeKey_Starcraft2_Install_zhTW = "expand 32-byte k7KBN0000D9NEM6GC0000N3PLQJV400003BRDU3NF00009XQJ"; // U3NFQJV4M6GC7KBN9XQJ3BRDN3PLD9NE
+
+// Note: Diablo III: Agent.exe (1.0.0.954): Suffix derived from battle.net auth. code
+// Address of decryption routine: 00502b00 http://dist.blizzard.com/mediakey/d3-authenticationcode-enGB.txt
+// Pointer to decryptor object: ECX Numbers mean offset of 4-char group of auth code (follows in comment)
+// Pointer to key: ECX+0x5C -0C- -1C--08- -18--04- -14--00- -10-
+static const char * MpqeKey_Diablo3_Install_deDE = "expand 32-byte kEFH40000QRZKY3520000XC9MF6EJ0000CFH2UCMX0000XFRX"; // UCMXF6EJY352EFH4XFRXCFH2XC9MQRZK
+static const char * MpqeKey_Diablo3_Install_enGB = "expand 32-byte kXP4G0000PHBPRP7W0000J9UNHY4800007SL9MMKV0000HYBQ"; // MMKVHY48RP7WXP4GHYBQ7SL9J9UNPHBP
+static const char * MpqeKey_Diablo3_Install_enSG = "expand 32-byte kTZ9M00003CPPVGGL0000JYETWHQ70000FDCL8MXL0000QZQS"; // 8MXLWHQ7VGGLTZ9MQZQSFDCLJYET3CPP
+static const char * MpqeKey_Diablo3_Install_enUS = "expand 32-byte kGUNG0000WZSZXFE20000UAKP5TM60000HKQ9EJ2R00005QDG"; // EJ2R5TM6XFE2GUNG5QDGHKQ9UAKPWZSZ
+static const char * MpqeKey_Diablo3_Install_esES = "expand 32-byte kK65U0000HQQTZ6LN0000CLP4BE420000WZVMPBGF0000GJQ3"; // PBGFBE42Z6LNK65UGJQ3WZVMCLP4HQQT
+static const char * MpqeKey_Diablo3_Install_esMX = "expand 32-byte kW5P200008VU2TSGC0000JPEYJJS90000C47AX7SE00008EBS"; // X7SEJJS9TSGCW5P28EBSC47AJPEY8VU2
+static const char * MpqeKey_Diablo3_Install_frFR = "expand 32-byte kRY3D00007YA2YE6X0000XS4PQA8V0000ZDE45KVB0000LGC5"; // 5KVBQA8VYE6XRY3DLGC5ZDE4XS4P7YA2
+static const char * MpqeKey_Diablo3_Install_itIT = "expand 32-byte kVVY40000B2546EVN00005B8KD2K50000DWYT478J0000XX8T"; // 478JD2K56EVNVVY4XX8TDWYT5B8KB254
+static const char * MpqeKey_Diablo3_Install_koKR = "expand 32-byte k6YWH0000474ARZTN0000NVWDVNFQ0000VDH98TS40000E9CH"; // 8TS4VNFQRZTN6YWHE9CHVDH9NVWD474A
+static const char * MpqeKey_Diablo3_Install_plPL = "expand 32-byte k4ZJJ0000BLJBF4LZ0000A6GAZ32D00003AZQLJ520000XVKK"; // LJ52Z32DF4LZ4ZJJXVKK3AZQA6GABLJB
+static const char * MpqeKey_Diablo3_Install_ptBR = "expand 32-byte k545Y0000XYAGCUE20000WHE7HY2E0000JPVYK6BD0000KNLB"; // K6BDHY2ECUE2545YKNLBJPVYWHE7XYAG
+static const char * MpqeKey_Diablo3_Install_ruRU = "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //
+static const char * MpqeKey_Diablo3_Install_zhTW = "expand 32-byte kMRUC0000AA8HV3ZZ0000UX2TQTN80000A8CG6VWC0000ZXV8"; // 6VWCQTN8V3ZZMRUCZXV8A8CGUX2TAA8H
+static const char * MpqeKey_Diablo3_Install_zhCN = "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //
+
+static const char * MpqKeyArray[] =
+{
+ MpqeKey_Starcraft2_Install_deDE,
+ MpqeKey_Starcraft2_Install_enGB,
+ MpqeKey_Starcraft2_Install_enSG,
+ MpqeKey_Starcraft2_Install_enUS,
+ MpqeKey_Starcraft2_Install_esES,
+ MpqeKey_Starcraft2_Install_esMX,
+ MpqeKey_Starcraft2_Install_frFR,
+ MpqeKey_Starcraft2_Install_itIT,
+ MpqeKey_Starcraft2_Install_koKR,
+ MpqeKey_Starcraft2_Install_plPL,
+ MpqeKey_Starcraft2_Install_ptBR,
+ MpqeKey_Starcraft2_Install_ruRU,
+ MpqeKey_Starcraft2_Install_zhTW,
+
+ MpqeKey_Diablo3_Install_deDE,
+ MpqeKey_Diablo3_Install_enGB,
+ MpqeKey_Diablo3_Install_enSG,
+ MpqeKey_Diablo3_Install_enUS,
+ MpqeKey_Diablo3_Install_esES,
+ MpqeKey_Diablo3_Install_esMX,
+ MpqeKey_Diablo3_Install_frFR,
+ MpqeKey_Diablo3_Install_itIT,
+ MpqeKey_Diablo3_Install_koKR,
+ MpqeKey_Diablo3_Install_plPL,
+ MpqeKey_Diablo3_Install_ptBR,
+// MpqeKey_Diablo3_Install_ruRU,
+ MpqeKey_Diablo3_Install_zhTW,
+// MpqeKey_Diablo3_Install_zhCN,
+
+ NULL
+};
+
+static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
+{
+ DWORD dwShiftRight = 32 - dwRolCount;
+
+ return (dwValue << dwRolCount) | (dwValue >> dwShiftRight);
+}
+
+static void DecryptFileChunk(
+ DWORD * MpqData,
+ LPBYTE pbKey,
+ ULONGLONG ByteOffset,
+ DWORD dwLength)
+{
+ ULONGLONG ChunkOffset;
+ DWORD KeyShuffled[0x10];
+ DWORD KeyMirror[0x10];
+ DWORD RoundCount = 0x14;
+
+ // Prepare the key
+ ChunkOffset = ByteOffset / MPQE_CHUNK_SIZE;
+ memcpy(KeyMirror, pbKey, MPQE_CHUNK_SIZE);
+ BSWAP_ARRAY32_UNSIGNED(KeyMirror, MPQE_CHUNK_SIZE);
+ KeyMirror[0x05] = (DWORD)(ChunkOffset >> 32);
+ KeyMirror[0x08] = (DWORD)(ChunkOffset);
+
+ while(dwLength >= MPQE_CHUNK_SIZE)
+ {
+ // Shuffle the key - part 1
+ KeyShuffled[0x0E] = KeyMirror[0x00];
+ KeyShuffled[0x0C] = KeyMirror[0x01];
+ KeyShuffled[0x05] = KeyMirror[0x02];
+ KeyShuffled[0x0F] = KeyMirror[0x03];
+ KeyShuffled[0x0A] = KeyMirror[0x04];
+ KeyShuffled[0x07] = KeyMirror[0x05];
+ KeyShuffled[0x0B] = KeyMirror[0x06];
+ KeyShuffled[0x09] = KeyMirror[0x07];
+ KeyShuffled[0x03] = KeyMirror[0x08];
+ KeyShuffled[0x06] = KeyMirror[0x09];
+ KeyShuffled[0x08] = KeyMirror[0x0A];
+ KeyShuffled[0x0D] = KeyMirror[0x0B];
+ KeyShuffled[0x02] = KeyMirror[0x0C];
+ KeyShuffled[0x04] = KeyMirror[0x0D];
+ KeyShuffled[0x01] = KeyMirror[0x0E];
+ KeyShuffled[0x00] = KeyMirror[0x0F];
+
+ // Shuffle the key - part 2
+ for(DWORD i = 0; i < RoundCount; i += 2)
+ {
+ KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x02]), 0x07);
+ KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0E]), 0x09);
+ KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x0A]), 0x0D);
+ KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x03]), 0x12);
+
+ KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x04]), 0x07);
+ KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x0C]), 0x09);
+ KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x07]), 0x0D);
+ KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x06]), 0x12);
+
+ KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x01]), 0x07);
+ KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x05]), 0x09);
+ KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x0B]), 0x0D);
+ KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x08]), 0x12);
+
+ KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x00]), 0x07);
+ KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x0F]), 0x09);
+ KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x09]), 0x0D);
+ KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x0D]), 0x12);
+
+ KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x09]), 0x07);
+ KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x0E]), 0x09);
+ KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x04]), 0x0D);
+ KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x08]), 0x12);
+
+ KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x0A]), 0x07);
+ KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x0C]), 0x09);
+ KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x01]), 0x0D);
+ KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0D]), 0x12);
+
+ KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x07]), 0x07);
+ KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x05]), 0x09);
+ KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x00]), 0x0D);
+ KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x03]), 0x12);
+
+ KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x0B]), 0x07);
+ KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x0F]), 0x09);
+ KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x02]), 0x0D);
+ KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x06]), 0x12);
+ }
+
+ // Decrypt one data chunk
+ BSWAP_ARRAY32_UNSIGNED(MpqData, MPQE_CHUNK_SIZE);
+ MpqData[0x00] = MpqData[0x00] ^ (KeyShuffled[0x0E] + KeyMirror[0x00]);
+ MpqData[0x01] = MpqData[0x01] ^ (KeyShuffled[0x04] + KeyMirror[0x0D]);
+ MpqData[0x02] = MpqData[0x02] ^ (KeyShuffled[0x08] + KeyMirror[0x0A]);
+ MpqData[0x03] = MpqData[0x03] ^ (KeyShuffled[0x09] + KeyMirror[0x07]);
+ MpqData[0x04] = MpqData[0x04] ^ (KeyShuffled[0x0A] + KeyMirror[0x04]);
+ MpqData[0x05] = MpqData[0x05] ^ (KeyShuffled[0x0C] + KeyMirror[0x01]);
+ MpqData[0x06] = MpqData[0x06] ^ (KeyShuffled[0x01] + KeyMirror[0x0E]);
+ MpqData[0x07] = MpqData[0x07] ^ (KeyShuffled[0x0D] + KeyMirror[0x0B]);
+ MpqData[0x08] = MpqData[0x08] ^ (KeyShuffled[0x03] + KeyMirror[0x08]);
+ MpqData[0x09] = MpqData[0x09] ^ (KeyShuffled[0x07] + KeyMirror[0x05]);
+ MpqData[0x0A] = MpqData[0x0A] ^ (KeyShuffled[0x05] + KeyMirror[0x02]);
+ MpqData[0x0B] = MpqData[0x0B] ^ (KeyShuffled[0x00] + KeyMirror[0x0F]);
+ MpqData[0x0C] = MpqData[0x0C] ^ (KeyShuffled[0x02] + KeyMirror[0x0C]);
+ MpqData[0x0D] = MpqData[0x0D] ^ (KeyShuffled[0x06] + KeyMirror[0x09]);
+ MpqData[0x0E] = MpqData[0x0E] ^ (KeyShuffled[0x0B] + KeyMirror[0x06]);
+ MpqData[0x0F] = MpqData[0x0F] ^ (KeyShuffled[0x0F] + KeyMirror[0x03]);
+ BSWAP_ARRAY32_UNSIGNED(MpqData, MPQE_CHUNK_SIZE);
+
+ // Update byte offset in the key
+ KeyMirror[0x08]++;
+ if(KeyMirror[0x08] == 0)
+ KeyMirror[0x05]++;
+
+ // Move pointers and decrease number of bytes to decrypt
+ MpqData += (MPQE_CHUNK_SIZE / sizeof(DWORD));
+ dwLength -= MPQE_CHUNK_SIZE;
+ }
+}
+
+static const char * DetectFileKey(LPBYTE pbEncryptedHeader)
+{
+ ULONGLONG ByteOffset = 0;
+ BYTE FileHeader[MPQE_CHUNK_SIZE];
+ BYTE Key[MPQE_CHUNK_SIZE];
+
+ // We just try all known keys one by one
+ for(int i = 0; MpqKeyArray[i] != NULL; i++)
+ {
+ // Copy the key there
+ memcpy(Key, MpqKeyArray[i], MPQE_CHUNK_SIZE);
+ BSWAP_ARRAY32_UNSIGNED(Key, MPQE_CHUNK_SIZE);
+
+ // Try to decrypt with the given key
+ memcpy(FileHeader, pbEncryptedHeader, MPQE_CHUNK_SIZE);
+ DecryptFileChunk((LPDWORD)FileHeader, Key, ByteOffset, MPQE_CHUNK_SIZE);
+
+ // We check the decrypted data
+ // All known encrypted MPQs have header at the begin of the file,
+ // so we check for MPQ signature there.
+ if(FileHeader[0] == 'M' && FileHeader[1] == 'P' && FileHeader[2] == 'Q')
+ return MpqKeyArray[i];
+ }
+
+ // Key not found, sorry
+ return NULL;
+}
+
+static bool EncryptedStream_Read(
+ TEncryptedStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead) // Number of bytes to read from the file
+{
+ ULONGLONG StartOffset; // Offset of the first byte to be read from the file
+ ULONGLONG ByteOffset; // Offset that the caller wants
+ ULONGLONG EndOffset; // End offset that is to be read from the file
+ DWORD dwBytesToAllocate;
+ DWORD dwBytesToDecrypt;
+ DWORD dwOffsetInCache;
+ LPBYTE pbMpqData = NULL;
+ bool bResult = false;
+
+ // Get the byte offset
+ if(pByteOffset == NULL)
+ pStream->BaseGetPos(pStream, ByteOffset);
+ else
+ ByteOffset = *pByteOffset;
+
+ // Cut it down to MPQE chunk size
+ StartOffset = ByteOffset;
+ StartOffset = StartOffset & ~(MPQE_CHUNK_SIZE - 1);
+ EndOffset = ByteOffset + dwBytesToRead;
+
+ // Calculate number of bytes to decrypt
+ dwBytesToDecrypt = (DWORD)(EndOffset - StartOffset);
+ dwBytesToAllocate = (dwBytesToDecrypt + (MPQE_CHUNK_SIZE - 1)) & ~(MPQE_CHUNK_SIZE - 1);
+
+ // Allocate buffers for encrypted and decrypted data
+ pbMpqData = STORM_ALLOC(BYTE, dwBytesToAllocate);
+ if(pbMpqData)
+ {
+ // Get the offset of the desired data in the cache
+ dwOffsetInCache = (DWORD)(ByteOffset - StartOffset);
+
+ // Read the file from the stream as-is
+ if(pStream->BaseRead(pStream, &StartOffset, pbMpqData, dwBytesToDecrypt))
+ {
+ // Decrypt the data
+ DecryptFileChunk((LPDWORD)pbMpqData, pStream->Key, StartOffset, dwBytesToAllocate);
+
+ // Copy the decrypted data
+ memcpy(pvBuffer, pbMpqData + dwOffsetInCache, dwBytesToRead);
+ bResult = true;
+ }
+ else
+ {
+ assert(false);
+ }
+
+ // Free decryption buffer
+ STORM_FREE(pbMpqData);
+ }
+
+ // Free buffers and exit
+ return bResult;
+}
+
+static bool EncryptedStream_Open(TEncryptedStream * pStream)
+{
+ ULONGLONG ByteOffset = 0;
+ BYTE EncryptedHeader[MPQE_CHUNK_SIZE];
+ const char * szKey;
+
+ // Sanity check
+ assert(pStream->BaseRead != NULL);
+
+ // Load one MPQE chunk and try to detect the file key
+ if(pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, sizeof(EncryptedHeader)))
+ {
+ // Attempt to decrypt the MPQ header with all known keys
+ szKey = DetectFileKey(EncryptedHeader);
+ if(szKey != NULL)
+ {
+ // Copy the key for the file
+ memcpy(pStream->Key, szKey, MPQE_CHUNK_SIZE);
+ BSWAP_ARRAY32_UNSIGNED(pStream->Key, MPQE_CHUNK_SIZE);
+
+ // Assign functions
+ pStream->StreamRead = (STREAM_READ)EncryptedStream_Read;
+ pStream->StreamGetPos = pStream->BaseGetPos;
+ pStream->StreamGetSize = pStream->BaseGetSize;
+ pStream->StreamGetTime = pStream->BaseGetTime;
+ pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap;
+ pStream->StreamClose = pStream->BaseClose;
+
+ // We need to reset the position back to the begin of the file
+ pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, 0);
+ return true;
+ }
+
+ // An unknown key
+ SetLastError(ERROR_UNKNOWN_FILE_KEY);
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+/**
+ * This function creates a new file for read-write access
+ *
+ * - If the current platform supports file sharing,
+ * the file must be created for read sharing (i.e. another application
+ * can open the file for read, but not for write)
+ * - If the file does not exist, the function must create new one
+ * - If the file exists, the function must rewrite it and set to zero size
+ * - The parameters of the function must be validate by the caller
+ * - The function must initialize all stream function pointers in TFileStream
+ * - If the function fails from any reason, it must close all handles
+ * and free all memory that has been allocated in the process of stream creation,
+ * including the TFileStream structure itself
+ *
+ * \a szFileName Name of the file to create
+ */
+
+TFileStream * FileStream_CreateFile(
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+ TFileStream * pStream;
+
+ // We only support creation of linear, local file
+ if((dwStreamFlags & (STREAM_PROVIDER_MASK | BASE_PROVIDER_MASK)) != (STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE))
+ {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ // Allocate file stream structure for linear stream
+ pStream = STORM_ALLOC(TFileStream, 1);
+ if(pStream != NULL)
+ {
+ // Reset entire structure to zero
+ memset(pStream, 0, sizeof(TFileStream));
+ _tcscpy(pStream->szFileName, szFileName);
+
+ // Attempt to create the disk file
+ if(BaseFile_Create(pStream, szFileName, dwStreamFlags))
+ {
+ // Fill the stream provider functions
+ pStream->StreamRead = pStream->BaseRead;
+ pStream->StreamWrite = pStream->BaseWrite;
+ pStream->StreamGetPos = pStream->BaseGetPos;
+ pStream->StreamGetSize = pStream->BaseGetSize;
+ pStream->StreamSetSize = pStream->BaseSetSize;
+ pStream->StreamGetTime = pStream->BaseGetTime;
+ pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap;;
+ pStream->StreamSwitch = (STREAM_SWITCH)LinearStream_Switch;
+ pStream->StreamClose = pStream->BaseClose;
+ return pStream;
+ }
+
+ // File create failed, delete the stream
+ STORM_FREE(pStream);
+ pStream = NULL;
+ }
+
+ // Return the stream
+ return pStream;
+}
+
+/**
+ * This function opens an existing file for read or read-write access
+ * - If the current platform supports file sharing,
+ * the file must be open for read sharing (i.e. another application
+ * can open the file for read, but not for write)
+ * - If the file does not exist, the function must return NULL
+ * - If the file exists but cannot be open, then function must return NULL
+ * - The parameters of the function must be validate by the caller
+ * - The function must check if the file is a PART file,
+ * and create TPartialStream object if so.
+ * - The function must initialize all stream function pointers in TFileStream
+ * - If the function fails from any reason, it must close all handles
+ * and free all memory that has been allocated in the process of stream creation,
+ * including the TFileStream structure itself
+ *
+ * \a szFileName Name of the file to open
+ * \a dwStreamFlags specifies the provider and base storage type
+ */
+
+TFileStream * FileStream_OpenFile(
+ const TCHAR * szFileName,
+ DWORD dwStreamFlags)
+{
+ TFileStream * pStream = NULL;
+ size_t StreamSize = 0;
+ bool bStreamResult = false;
+ bool bBaseResult = false;
+
+ // Allocate file stream for each stream provider
+ switch(dwStreamFlags & STREAM_PROVIDER_MASK)
+ {
+ case STREAM_PROVIDER_LINEAR: // Allocate structure for linear stream
+ StreamSize = sizeof(TLinearStream);
+ break;
+
+ case STREAM_PROVIDER_PARTIAL:
+ dwStreamFlags |= STREAM_FLAG_READ_ONLY;
+ StreamSize = sizeof(TPartialStream);
+ break;
+
+ case STREAM_PROVIDER_ENCRYPTED:
+ dwStreamFlags |= STREAM_FLAG_READ_ONLY;
+ StreamSize = sizeof(TEncryptedStream);
+ break;
+
+ default:
+ return NULL;
+ }
+
+ // Allocate the stream for each type
+ pStream = (TFileStream *)STORM_ALLOC(BYTE, StreamSize);
+ if(pStream == NULL)
+ return NULL;
+
+ // Fill the stream structure with zeros
+ memset(pStream, 0, StreamSize);
+ _tcscpy(pStream->szFileName, szFileName);
+
+ // Now initialize the respective base provider
+ switch(dwStreamFlags & BASE_PROVIDER_MASK)
+ {
+ case BASE_PROVIDER_FILE:
+ bBaseResult = BaseFile_Open(pStream, szFileName, dwStreamFlags);
+ break;
+
+ case BASE_PROVIDER_MAP:
+ dwStreamFlags |= STREAM_FLAG_READ_ONLY;
+ bBaseResult = BaseMap_Open(pStream, szFileName, dwStreamFlags);
+ break;
+
+ case BASE_PROVIDER_HTTP:
+ dwStreamFlags |= STREAM_FLAG_READ_ONLY;
+ bBaseResult = BaseHttp_Open(pStream, szFileName, dwStreamFlags);
+ break;
+ }
+
+ // If we failed to open the base storage, fail the operation
+ if(bBaseResult == false)
+ {
+ STORM_FREE(pStream);
+ return NULL;
+ }
+
+ // Now initialize the stream provider
+ switch(dwStreamFlags & STREAM_PROVIDER_MASK)
+ {
+ case STREAM_PROVIDER_LINEAR:
+ bStreamResult = LinearStream_Open((TLinearStream *)pStream);
+ break;
+
+ case STREAM_PROVIDER_PARTIAL:
+ bStreamResult = PartialStream_Open((TPartialStream *)pStream);
+ break;
+
+ case STREAM_PROVIDER_ENCRYPTED:
+ bStreamResult = EncryptedStream_Open((TEncryptedStream *)pStream);
+ break;
+ }
+
+ // If the operation failed, free the stream and set it to NULL
+ if(bStreamResult == false)
+ {
+ // Only close the base stream
+ pStream->BaseClose(pStream);
+ STORM_FREE(pStream);
+ pStream = NULL;
+ }
+
+ return pStream;
+}
+
+/**
+ * Reads data from the stream
+ *
+ * - Returns true if the read operation succeeded and all bytes have been read
+ * - Returns false if either read failed or not all bytes have been read
+ * - If the pByteOffset is NULL, the function must read the data from the current file position
+ * - The function can be called with dwBytesToRead = 0. In that case, pvBuffer is ignored
+ * and the function just adjusts file pointer.
+ *
+ * \a pStream Pointer to an open stream
+ * \a pByteOffset Pointer to file byte offset. If NULL, it reads from the current position
+ * \a pvBuffer Pointer to data to be read
+ * \a dwBytesToRead Number of bytes to read from the file
+ *
+ * \returns
+ * - If the function reads the required amount of bytes, it returns true.
+ * - If the function reads less than required bytes, it returns false and GetLastError() returns ERROR_HANDLE_EOF
+ * - If the function fails, it reads false and GetLastError() returns an error code different from ERROR_HANDLE_EOF
+ */
+bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead)
+{
+ assert(pStream->StreamRead != NULL);
+ return pStream->StreamRead(pStream, pByteOffset, pvBuffer, dwBytesToRead);
+}
+
+/**
+ * This function writes data to the stream
+ *
+ * - Returns true if the write operation succeeded and all bytes have been written
+ * - Returns false if either write failed or not all bytes have been written
+ * - If the pByteOffset is NULL, the function must write the data to the current file position
+ *
+ * \a pStream Pointer to an open stream
+ * \a pByteOffset Pointer to file byte offset. If NULL, it reads from the current position
+ * \a pvBuffer Pointer to data to be written
+ * \a dwBytesToWrite Number of bytes to write to the file
+ */
+bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
+{
+ if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
+ return false;
+
+ assert(pStream->StreamWrite != NULL);
+ return pStream->StreamWrite(pStream, pByteOffset, pvBuffer, dwBytesToWrite);
+}
+
+/**
+ * This function returns the current file position
+ * \a pStream
+ * \a ByteOffset
+ */
+bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset)
+{
+ assert(pStream->StreamGetPos != NULL);
+ return pStream->StreamGetPos(pStream, ByteOffset);
+}
+
+/**
+ * Returns the size of a file
+ *
+ * \a pStream Pointer to an open stream
+ * \a FileSize Pointer where to store the file size
+ */
+bool FileStream_GetSize(TFileStream * pStream, ULONGLONG & FileSize)
+{
+ assert(pStream->StreamGetSize != NULL);
+ return pStream->StreamGetSize(pStream, FileSize);
+}
+
+/**
+ * Sets the size of a file
+ *
+ * \a pStream Pointer to an open stream
+ * \a NewFileSize File size to set
+ */
+bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize)
+{
+ if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
+ return false;
+
+ assert(pStream->StreamSetSize != NULL);
+ return pStream->StreamSetSize(pStream, NewFileSize);
+}
+
+/**
+ * Returns the last write time of a file
+ *
+ * \a pStream Pointer to an open stream
+ * \a pFileType Pointer where to store the file last write time
+ */
+bool FileStream_GetTime(TFileStream * pStream, ULONGLONG * pFileTime)
+{
+ assert(pStream->StreamGetTime != NULL);
+ return pStream->StreamGetTime(pStream, pFileTime);
+}
+
+/**
+ * Switches a stream with another. Used for final phase of archive compacting.
+ * Performs these steps:
+ *
+ * 1) Closes the handle to the existing MPQ
+ * 2) Renames the temporary MPQ to the original MPQ, overwrites existing one
+ * 3) Opens the MPQ stores the handle and stream position to the new stream structure
+ *
+ * \a pStream Pointer to an open stream
+ * \a pTempStream Temporary ("working") stream (created during archive compacting)
+ */
+bool FileStream_Switch(TFileStream * pStream, TFileStream * pNewStream)
+{
+ if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
+ return false;
+
+ assert(pStream->StreamSwitch != NULL);
+ return pStream->StreamSwitch(pStream, pNewStream);
+}
+
+/**
+ * Returns the file name of the stream
+ *
+ * \a pStream Pointer to an open stream
+ */
+TCHAR * FileStream_GetFileName(TFileStream * pStream)
+{
+ assert(pStream != NULL);
+ return pStream->szFileName;
+}
+
+/**
+ * Returns true if the stream is read-only
+ *
+ * \a pStream Pointer to an open stream
+ */
+bool FileStream_IsReadOnly(TFileStream * pStream)
+{
+ return (pStream->dwFlags & STREAM_FLAG_READ_ONLY) ? true : false;
+}
+
+/**
+ * This function enabled a linear stream to include data bitmap.
+ * Used by MPQs v 4.0 from WoW. Each file block is represented by
+ * a bit in the bitmap. 1 means the block is present, 0 means it's not.
+ *
+ * \a pStream Pointer to an open stream
+ * \a pBitmap Pointer to file bitmap
+ */
+
+bool FileStream_SetBitmap(TFileStream * pStream, TFileBitmap * pBitmap)
+{
+ TLinearStream * pLinearStream;
+
+ // It must be a linear stream.
+ if((pStream->dwFlags & STREAM_PROVIDER_MASK) != STREAM_PROVIDER_LINEAR)
+ return false;
+ pLinearStream = (TLinearStream *)pStream;
+
+ // Two bitmaps are not allowed
+ if(pLinearStream->pBitmap != NULL)
+ return false;
+
+ // We need to change some entry points
+ pLinearStream->StreamRead = (STREAM_READ)LinearStream_Read;
+ pLinearStream->StreamGetBmp = (STREAM_GETBMP)LinearStream_GetBitmap;
+
+ // Using data bitmap renders the stream to be read only.
+ pLinearStream->dwFlags |= STREAM_FLAG_READ_ONLY;
+ pLinearStream->pBitmap = pBitmap;
+ return true;
+}
+
+/**
+ * This function retrieves the file bitmap. A file bitmap is an array
+ * of bits, each bit representing one file block. A value of 1 means
+ * that the block is present in the file, a value of 0 means that the
+ * block is not present.
+ *
+ * \a pStream Pointer to an open stream
+ * \a pBitmap Pointer to buffer where to store the file bitmap
+ * \a Length Size of buffer pointed by pBitmap, in bytes
+ * \a LengthNeeded If non-NULL, the function supplies the necessary byte size of the buffer
+ */
+bool FileStream_GetBitmap(TFileStream * pStream, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded)
+{
+ assert(pStream->StreamGetBmp != NULL);
+ return pStream->StreamGetBmp(pStream, pBitmap, Length, LengthNeeded);
+}
+
+/**
+ * This function closes an archive file and frees any data buffers
+ * that have been allocated for stream management. The function must also
+ * support partially allocated structure, i.e. one or more buffers
+ * can be NULL, if there was an allocation failure during the process
+ *
+ * \a pStream Pointer to an open stream
+ */
+void FileStream_Close(TFileStream * pStream)
+{
+ // Check if the stream structure is allocated at all
+ if(pStream != NULL)
+ {
+ // Close the stream provider.
+ // This will also close the base stream
+ assert(pStream->StreamClose != NULL);
+ pStream->StreamClose(pStream);
+
+ // Free the stream itself
+ STORM_FREE(pStream);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// main - for testing purposes
+
+#ifdef __STORMLIB_TEST__
+int FileStream_Test(const TCHAR * szFileName, DWORD dwStreamFlags)
+{
+ TFileStream * pStream;
+ TMPQHeader MpqHeader;
+ ULONGLONG FilePos;
+ TMPQBlock * pBlock;
+ TMPQHash * pHash;
+
+ InitializeMpqCryptography();
+
+ pStream = FileStream_OpenFile(szFileName, dwStreamFlags);
+ if(pStream == NULL)
+ return GetLastError();
+
+ // Read the MPQ header
+ FileStream_Read(pStream, NULL, &MpqHeader, MPQ_HEADER_SIZE_V2);
+ if(MpqHeader.dwID != ID_MPQ)
+ return ERROR_FILE_CORRUPT;
+
+ // Read the hash table
+ pHash = STORM_ALLOC(TMPQHash, MpqHeader.dwHashTableSize);
+ if(pHash != NULL)
+ {
+ FilePos = MpqHeader.dwHashTablePos;
+ FileStream_Read(pStream, &FilePos, pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash));
+ DecryptMpqBlock(pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash), MPQ_KEY_HASH_TABLE);
+ STORM_FREE(pHash);
+ }
+
+ // Read the block table
+ pBlock = STORM_ALLOC(TMPQBlock, MpqHeader.dwBlockTableSize);
+ if(pBlock != NULL)
+ {
+ FilePos = MpqHeader.dwBlockTablePos;
+ FileStream_Read(pStream, &FilePos, pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock));
+ DecryptMpqBlock(pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock), MPQ_KEY_BLOCK_TABLE);
+ STORM_FREE(pBlock);
+ }
+
+ FileStream_Close(pStream);
+ return ERROR_SUCCESS;
+}
+#endif
+
+/*
+int FileStream_Test()
+{
+ TFileStream * pStream;
+
+ InitializeMpqCryptography();
+
+ //
+ // Test 1: Write to a stream
+ //
+
+ pStream = FileStream_CreateFile("E:\\Stream.bin", 0);
+ if(pStream != NULL)
+ {
+ char szString1[100] = "This is a single line\n\r";
+ DWORD dwLength = strlen(szString1);
+
+ for(int i = 0; i < 10; i++)
+ {
+ if(!FileStream_Write(pStream, NULL, szString1, dwLength))
+ {
+ printf("Failed to write to the stream\n");
+ return ERROR_CAN_NOT_COMPLETE;
+ }
+ }
+ FileStream_Close(pStream);
+ }
+
+ //
+ // Test2: Read from the stream
+ //
+
+ pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream != NULL)
+ {
+ char szString1[100] = "This is a single line\n\r";
+ char szString2[100];
+ DWORD dwLength = strlen(szString1);
+
+ // This call must end with an error
+ if(FileStream_Write(pStream, NULL, "aaa", 3))
+ {
+ printf("Write succeeded while it should fail\n");
+ return -1;
+ }
+
+ for(int i = 0; i < 10; i++)
+ {
+ if(!FileStream_Read(pStream, NULL, szString2, dwLength))
+ {
+ printf("Failed to read from the stream\n");
+ return -1;
+ }
+
+ szString2[dwLength] = 0;
+ if(strcmp(szString1, szString2))
+ {
+ printf("Data read from file are different from data written\n");
+ return -1;
+ }
+ }
+ FileStream_Close(pStream);
+ }
+
+ //
+ // Test3: Open the temp stream, write some data and switch it to the original stream
+ //
+
+ pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream != NULL)
+ {
+ TFileStream * pTempStream;
+ ULONGLONG FileSize;
+
+ pTempStream = FileStream_CreateFile("E:\\TempStream.bin", 0);
+ if(pTempStream == NULL)
+ {
+ printf("Failed to create temp stream\n");
+ return -1;
+ }
+
+ // Copy the original stream to the temp
+ if(!FileStream_GetSize(pStream, FileSize))
+ {
+ printf("Failed to get the file size\n");
+ return -1;
+ }
+
+ while(FileSize != 0)
+ {
+ DWORD dwBytesToRead = (DWORD)FileSize;
+ char Buffer[0x80];
+
+ if(dwBytesToRead > sizeof(Buffer))
+ dwBytesToRead = sizeof(Buffer);
+
+ if(!FileStream_Read(pStream, NULL, Buffer, dwBytesToRead))
+ {
+ printf("CopyStream: Read source file failed\n");
+ return -1;
+ }
+
+ if(!FileStream_Write(pTempStream, NULL, Buffer, dwBytesToRead))
+ {
+ printf("CopyStream: Write target file failed\n");
+ return -1;
+ }
+
+ FileSize -= dwBytesToRead;
+ }
+
+ // Switch the streams
+ // Note that the pTempStream is closed by the operation
+ FileStream_Switch(pStream, pTempStream);
+ FileStream_Close(pStream);
+ }
+
+ //
+ // Test4: Read from the stream again
+ //
+
+ pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream != NULL)
+ {
+ char szString1[100] = "This is a single line\n\r";
+ char szString2[100];
+ DWORD dwLength = strlen(szString1);
+
+ for(int i = 0; i < 10; i++)
+ {
+ if(!FileStream_Read(pStream, NULL, szString2, dwLength))
+ {
+ printf("Failed to read from the stream\n");
+ return -1;
+ }
+
+ szString2[dwLength] = 0;
+ if(strcmp(szString1, szString2))
+ {
+ printf("Data read from file are different from data written\n");
+ return -1;
+ }
+ }
+ FileStream_Close(pStream);
+ }
+
+ return 0;
+}
+*/
+
diff --git a/dep/StormLib/src/FileStream.h b/dep/StormLib/src/FileStream.h
new file mode 100644
index 00000000000..31fe757514d
--- /dev/null
+++ b/dep/StormLib/src/FileStream.h
@@ -0,0 +1,189 @@
+/*****************************************************************************/
+/* FileStream.h Copyright (c) Ladislav Zezula 2012 */
+/*---------------------------------------------------------------------------*/
+/* Description: Definitions for FileStream object */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 14.04.12 1.00 Lad The first version of FileStream.h */
+/*****************************************************************************/
+
+#ifndef __FILESTREAM_H__
+#define __FILESTREAM_H__
+
+//-----------------------------------------------------------------------------
+// Function prototypes
+
+typedef bool (*STREAM_READ)(
+ struct TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
+ void * pvBuffer, // Pointer to data to be read
+ DWORD dwBytesToRead // Number of bytes to read from the file
+ );
+
+typedef bool (*STREAM_WRITE)(
+ struct TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position
+ const void * pvBuffer, // Pointer to data to be written
+ DWORD dwBytesToWrite // Number of bytes to read from the file
+ );
+
+typedef bool (*STREAM_GETPOS)(
+ struct TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & ByteOffset // Pointer to store current file position
+ );
+
+typedef bool (*STREAM_GETSIZE)(
+ struct TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG & FileSize // Receives the file size, in bytes
+ );
+
+typedef bool (*STREAM_SETSIZE)(
+ struct TFileStream * pStream, // Pointer to an open stream
+ ULONGLONG FileSize // New size for the file, in bytes
+ );
+
+typedef bool (*STREAM_GETTIME)(
+ struct TFileStream * pStream,
+ ULONGLONG * pFT
+ );
+
+typedef bool (*STREAM_SWITCH)(
+ struct TFileStream * pStream,
+ struct TFileStream * pNewStream
+ );
+
+typedef bool (*STREAM_GETBMP)(
+ TFileStream * pStream,
+ TFileBitmap * pBitmap,
+ DWORD Length,
+ LPDWORD LengthNeeded
+ );
+
+typedef void (*STREAM_CLOSE)(
+ struct TFileStream * pStream
+ );
+
+//-----------------------------------------------------------------------------
+// Local structures - part file structure
+
+typedef struct _PART_FILE_HEADER
+{
+ DWORD PartialVersion; // Always set to 2
+ char GameBuildNumber[0x20]; // Minimum build number of the game that can use this MPQ
+ DWORD Flags; // Flags (details unknown)
+ DWORD FileSizeLo; // Low 32 bits of the contained file size
+ DWORD FileSizeHi; // High 32 bits of the contained file size
+ DWORD BlockSize; // Size of one file block, in bytes
+
+} PART_FILE_HEADER, *PPART_FILE_HEADER;
+
+// Structure describing the block-to-file map entry
+typedef struct _PART_FILE_MAP_ENTRY
+{
+ DWORD Flags; // 3 = the block is present in the file
+ DWORD BlockOffsLo; // Low 32 bits of the block position in the file
+ DWORD BlockOffsHi; // High 32 bits of the block position in the file
+ DWORD LargeValueLo; // 64-bit value, meaning is unknown
+ DWORD LargeValueHi;
+
+} PART_FILE_MAP_ENTRY, *PPART_FILE_MAP_ENTRY;
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+union TBaseData
+{
+ struct
+ {
+ ULONGLONG FileSize; // Size of the file
+ ULONGLONG FilePos; // Current file position
+ ULONGLONG FileTime; // Date/time of last modification of the file
+ HANDLE hFile; // File handle
+ } File;
+
+ struct
+ {
+ ULONGLONG FileSize; // Mapped file size
+ ULONGLONG FilePos; // Current stream position
+ ULONGLONG FileTime; // Date/time of last modification of the file
+ LPBYTE pbFile; // Pointer to mapped view
+ } Map;
+
+ struct
+ {
+ ULONGLONG FileSize; // Size of the internet file
+ ULONGLONG FilePos; // Current position in the file
+ ULONGLONG FileTime; // Date/time of last modification of the file
+ HANDLE hInternet; // Internet handle
+ HANDLE hConnect; // Connection to the internet server
+ } Http;
+};
+
+//-----------------------------------------------------------------------------
+// Structure for linear stream
+
+struct TFileStream
+{
+ // Stream provider functions
+ STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly.
+ STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly.
+ STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position
+ STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size
+ STREAM_SETSIZE StreamSetSize; // Pointer to function changing file size
+ STREAM_GETTIME StreamGetTime; // Pointer to function retrieving the file time
+ STREAM_GETBMP StreamGetBmp; // Pointer to function that retrieves the file bitmap
+ STREAM_SWITCH StreamSwitch; // Pointer to function changing the stream to another file
+ STREAM_CLOSE StreamClose; // Pointer to function closing the stream
+
+ // Stream provider data members
+ TCHAR szFileName[MAX_PATH]; // File name
+ DWORD dwFlags; // Stream flags
+
+ // Base provider functions
+ STREAM_READ BaseRead;
+ STREAM_WRITE BaseWrite;
+ STREAM_GETPOS BaseGetPos; // Pointer to function that returns current file position
+ STREAM_GETSIZE BaseGetSize; // Pointer to function returning file size
+ STREAM_SETSIZE BaseSetSize; // Pointer to function changing file size
+ STREAM_GETTIME BaseGetTime; // Pointer to function retrieving the file time
+ STREAM_CLOSE BaseClose; // Pointer to function closing the stream
+
+ // Base provider data members
+ TBaseData Base; // Base provider data
+
+ // Followed by stream provider data, with variable length
+};
+
+//-----------------------------------------------------------------------------
+// Structure for linear stream
+
+struct TLinearStream : public TFileStream
+{
+ TFileBitmap * pBitmap; // Pointer to the stream bitmap
+};
+
+//-----------------------------------------------------------------------------
+// Structure for partial stream
+
+struct TPartialStream : public TFileStream
+{
+ ULONGLONG VirtualSize; // Virtual size of the file
+ ULONGLONG VirtualPos; // Virtual position in the file
+ DWORD BlockCount; // Number of file blocks. Used by partial file stream
+ DWORD BlockSize; // Size of one block. Used by partial file stream
+
+ PPART_FILE_MAP_ENTRY PartMap; // File map, variable length
+};
+
+//-----------------------------------------------------------------------------
+// Structure for encrypted stream
+
+#define MPQE_CHUNK_SIZE 0x40 // Size of one chunk to be decrypted
+
+struct TEncryptedStream : public TFileStream
+{
+ BYTE Key[MPQE_CHUNK_SIZE]; // File key
+};
+
+#endif // __FILESTREAM_H__
diff --git a/dep/StormLib/src/SBaseCommon.cpp b/dep/StormLib/src/SBaseCommon.cpp
new file mode 100644
index 00000000000..65818784521
--- /dev/null
+++ b/dep/StormLib/src/SBaseCommon.cpp
@@ -0,0 +1,1700 @@
+/*****************************************************************************/
+/* SBaseCommon.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Common functions for StormLib, used by all SFile*** modules */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 24.03.03 1.00 Lad The first version of SFileCommon.cpp */
+/* 19.11.03 1.01 Dan Big endian handling */
+/* 12.06.04 1.01 Lad Renamed to SCommon.cpp */
+/* 06.09.10 1.01 Lad Renamed to SBaseCommon.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2012";
+
+//-----------------------------------------------------------------------------
+// The buffer for decryption engine.
+
+LCID lcFileLocale = LANG_NEUTRAL; // File locale
+USHORT wPlatform = 0; // File platform
+
+//-----------------------------------------------------------------------------
+// Storm buffer functions
+
+#define STORM_BUFFER_SIZE 0x500
+
+static DWORD StormBuffer[STORM_BUFFER_SIZE]; // Buffer for the decryption engine
+static bool bMpqCryptographyInitialized = false;
+
+DWORD HashString(const char * szFileName, DWORD dwHashType)
+{
+ LPBYTE pbKey = (BYTE *)szFileName;
+ DWORD dwSeed1 = 0x7FED7FED;
+ DWORD dwSeed2 = 0xEEEEEEEE;
+ DWORD ch;
+
+ while(*pbKey != 0)
+ {
+ ch = toupper(*pbKey++);
+
+ dwSeed1 = StormBuffer[dwHashType + ch] ^ (dwSeed1 + dwSeed2);
+ dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3;
+ }
+
+ return dwSeed1;
+}
+
+void InitializeMpqCryptography()
+{
+ DWORD dwSeed = 0x00100001;
+ DWORD index1 = 0;
+ DWORD index2 = 0;
+ int i;
+
+ // Initialize the decryption buffer.
+ // Do nothing if already done.
+ if(bMpqCryptographyInitialized == false)
+ {
+ for(index1 = 0; index1 < 0x100; index1++)
+ {
+ for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
+ {
+ DWORD temp1, temp2;
+
+ dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB;
+ temp1 = (dwSeed & 0xFFFF) << 0x10;
+
+ dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB;
+ temp2 = (dwSeed & 0xFFFF);
+
+ StormBuffer[index2] = (temp1 | temp2);
+ }
+ }
+
+ // Also register both MD5 and SHA1 hash algorithms
+ register_hash(&md5_desc);
+ register_hash(&sha1_desc);
+
+ // Use LibTomMath as support math library for LibTomCrypt
+ ltc_mp = ltm_desc;
+
+ // Don't do that again
+ bMpqCryptographyInitialized = true;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Calculates the hash table size for a given amount of files
+
+DWORD GetHashTableSizeForFileCount(DWORD dwFileCount)
+{
+ DWORD dwPowerOfTwo;
+
+ // Round the hash table size up to the nearest power of two
+ for(dwPowerOfTwo = HASH_TABLE_SIZE_MIN; dwPowerOfTwo < HASH_TABLE_SIZE_MAX; dwPowerOfTwo <<= 1)
+ {
+ if(dwPowerOfTwo >= dwFileCount)
+ {
+ return dwPowerOfTwo;
+ }
+ }
+
+ // Don't allow the hash table size go over allowed maximum
+ return HASH_TABLE_SIZE_MAX;
+}
+
+//-----------------------------------------------------------------------------
+// Calculates a Jenkin's Encrypting and decrypting MPQ file data
+
+ULONGLONG HashStringJenkins(const char * szFileName)
+{
+ char * szTemp;
+ char szLocFileName[0x108];
+ char chOneChar;
+ size_t nLength = 0;
+ unsigned int primary_hash = 1;
+ unsigned int secondary_hash = 2;
+
+ // This is required to produce defined results
+ assert(szFileName != NULL);
+
+ // Normalize the file name - convert to uppercase, and convert "/" to "\\".
+ if(szFileName != NULL)
+ {
+ szTemp = szLocFileName;
+ while(*szFileName != 0)
+ {
+ chOneChar = (char)tolower(*szFileName++);
+ if(chOneChar == '/')
+ chOneChar = '\\';
+
+ *szTemp++ = chOneChar;
+ }
+
+ nLength = szTemp - szLocFileName;
+ *szTemp = 0;
+ }
+
+ // Thanks Quantam for finding out what the algorithm is.
+ // I am really getting old for reversing large chunks of assembly
+ // that does hashing :-)
+ hashlittle2(szLocFileName, nLength, &secondary_hash, &primary_hash);
+
+ // Combine those 2 together
+ return (ULONGLONG)primary_hash * (ULONGLONG)0x100000000ULL + (ULONGLONG)secondary_hash;
+}
+
+//-----------------------------------------------------------------------------
+// This function converts the MPQ header so it always looks like version 4
+
+int ConvertMpqHeaderToFormat4(
+ TMPQArchive * ha,
+ ULONGLONG FileSize,
+ DWORD dwFlags)
+{
+ ULONGLONG ByteOffset;
+ TMPQHeader * pHeader = ha->pHeader;
+ DWORD dwExpectedArchiveSize;
+ USHORT wFormatVersion = pHeader->wFormatVersion;
+ int nError = ERROR_SUCCESS;
+
+ // If version 1.0 is forced, then the format version is forced to be 1.0
+ // Reason: Storm.dll in Warcraft III ignores format version value
+ if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
+ wFormatVersion = MPQ_FORMAT_VERSION_1;
+
+ // Format-specific fixes
+ switch(wFormatVersion)
+ {
+ case MPQ_FORMAT_VERSION_1:
+
+ // Check for malformed MPQ header version 1.0
+ if(pHeader->dwHeaderSize != MPQ_HEADER_SIZE_V1)
+ {
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
+ ha->dwFlags |= MPQ_FLAG_PROTECTED;
+ }
+
+ //
+ // The value of "dwArchiveSize" member in the MPQ header
+ // is ignored by Storm.dll and can contain garbage value
+ // ("w3xmaster" protector).
+ //
+
+ dwExpectedArchiveSize = (DWORD)(FileSize - ha->MpqPos);
+ if(pHeader->dwArchiveSize != dwExpectedArchiveSize)
+ {
+ // Note: dwExpectedArchiveSize might be incorrect at this point.
+ // MPQs version 1.0 can have strong digital signature appended at the end,
+ // or they might just have arbitrary data there.
+ // In either case, we recalculate the archive size later when
+ // block table is loaded and positions of all files is known.
+ pHeader->dwArchiveSize = dwExpectedArchiveSize;
+ ha->dwFlags |= MPQ_FLAG_NEED_FIX_SIZE;
+ }
+
+ // Zero the fields in 2.0 part of the MPQ header
+ pHeader->HiBlockTablePos64 = 0;
+ pHeader->wHashTablePosHi = 0;
+ pHeader->wBlockTablePosHi = 0;
+ // No break here !!!
+
+ case MPQ_FORMAT_VERSION_2:
+ case MPQ_FORMAT_VERSION_3:
+
+ // In MPQ format 3.0, the entire header is optional
+ // and the size of the header can actually be identical
+ // to size of header 2.0
+ if(pHeader->dwHeaderSize < MPQ_HEADER_SIZE_V3)
+ {
+ ULONGLONG ArchiveSize64 = pHeader->dwArchiveSize;
+
+ // In format 2.0, the archive size is obsolete and is calculated
+ // as the highest offset of hash table, block table or hi-block table.
+ // However, we can still rely on it, if the size of the archive is under 4 GB
+ if((FileSize - ha->MpqPos) >> 32)
+ {
+ ByteOffset = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos) + (pHeader->dwHashTableSize * sizeof(TMPQHash));
+ if(ByteOffset > ArchiveSize64)
+ ArchiveSize64 = ByteOffset;
+
+ ByteOffset = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) + (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
+ if(ByteOffset > ArchiveSize64)
+ ArchiveSize64 = ByteOffset;
+
+ // Only if we actually have a hi-block table
+ if(pHeader->HiBlockTablePos64)
+ {
+ ByteOffset = pHeader->HiBlockTablePos64 + (pHeader->dwBlockTableSize * sizeof(USHORT));
+ if(ByteOffset > ArchiveSize64)
+ ArchiveSize64 = ByteOffset;
+ }
+
+ // We need to recalculate archive size later,
+ // when block table is loaded and the position of files is known
+ ha->dwFlags |= MPQ_FLAG_NEED_FIX_SIZE;
+ }
+
+ // Initialize the rest of the 3.0 header
+ pHeader->ArchiveSize64 = ArchiveSize64;
+ pHeader->HetTablePos64 = 0;
+ pHeader->BetTablePos64 = 0;
+ }
+
+ //
+ // Calculate compressed size of each table. We assume the following order:
+ // 1) HET table
+ // 2) BET table
+ // 3) Classic hash table
+ // 4) Classic block table
+ // 5) Hi-block table
+ //
+
+ // Set all sizes to zero
+ pHeader->HetTableSize64 = 0;
+ pHeader->BetTableSize64 = 0;
+
+ // Either both HET and BET table exist or none of them does.
+ if(pHeader->HetTablePos64)
+ {
+ // Compressed size of the HET and BET tables
+ pHeader->HetTableSize64 = pHeader->BetTablePos64 - pHeader->HetTablePos64;
+ pHeader->BetTableSize64 = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos) - pHeader->HetTablePos64;
+ }
+
+ // Compressed size of hash and block table
+ if(wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ {
+ // Compressed size of the hash table
+ pHeader->HashTableSize64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) - MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
+
+ // Block and hi-block table
+ if(pHeader->HiBlockTablePos64)
+ {
+ pHeader->BlockTableSize64 = pHeader->HiBlockTablePos64 - MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ pHeader->HiBlockTableSize64 = pHeader->ArchiveSize64 - pHeader->HiBlockTablePos64;
+ }
+ else
+ {
+ pHeader->BlockTableSize64 = pHeader->ArchiveSize64 - MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ pHeader->HiBlockTableSize64 = 0;
+ }
+ }
+ else
+ {
+ // No known MPQ in format 1.0 has any of the tables compressed
+ pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash);
+ pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ pHeader->HiBlockTableSize64 = 0;
+ }
+
+ // Set the data chunk size for MD5 to zero
+ pHeader->dwRawChunkSize = 0;
+
+ // Fill the MD5's
+ memset(pHeader->MD5_BlockTable, 0, MD5_DIGEST_SIZE);
+ memset(pHeader->MD5_HashTable, 0, MD5_DIGEST_SIZE);
+ memset(pHeader->MD5_HiBlockTable, 0, MD5_DIGEST_SIZE);
+ memset(pHeader->MD5_BetTable, 0, MD5_DIGEST_SIZE);
+ memset(pHeader->MD5_HetTable, 0, MD5_DIGEST_SIZE);
+ memset(pHeader->MD5_MpqHeader, 0, MD5_DIGEST_SIZE);
+ // No break here !!!!
+
+ case MPQ_FORMAT_VERSION_4:
+
+ // Verify header MD5. Header MD5 is calculated from the MPQ header since the 'MPQ\x1A'
+ // signature until the position of header MD5 at offset 0xC0
+ if(!VerifyDataBlockHash(ha->pHeader, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE, ha->pHeader->MD5_MpqHeader))
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Default flags for (attributes) and (listfile)
+
+DWORD GetDefaultSpecialFileFlags(TMPQArchive * ha, DWORD dwFileSize)
+{
+ // Fixed for format 1.0
+ if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
+ return MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY;
+
+ // Size-dependent for formats 2.0-4.0
+ return (dwFileSize > 0x4000) ? (MPQ_FILE_COMPRESS | MPQ_FILE_SECTOR_CRC) : (MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT);
+}
+
+
+//-----------------------------------------------------------------------------
+// Encrypting and decrypting MPQ file data
+
+void EncryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwSeed1)
+{
+ LPDWORD block = (LPDWORD)pvFileBlock;
+ DWORD dwSeed2 = 0xEEEEEEEE;
+ DWORD ch;
+
+ // Round to DWORDs
+ dwLength >>= 2;
+
+ while(dwLength-- > 0)
+ {
+ dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)];
+ ch = *block;
+ *block++ = ch ^ (dwSeed1 + dwSeed2);
+
+ dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B);
+ dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3;
+ }
+}
+
+void DecryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwSeed1)
+{
+ LPDWORD block = (LPDWORD)pvFileBlock;
+ DWORD dwSeed2 = 0xEEEEEEEE;
+ DWORD ch;
+
+ // Round to DWORDs
+ dwLength >>= 2;
+
+ while(dwLength-- > 0)
+ {
+ dwSeed2 += StormBuffer[0x400 + (dwSeed1 & 0xFF)];
+ ch = *block ^ (dwSeed1 + dwSeed2);
+
+ dwSeed1 = ((~dwSeed1 << 0x15) + 0x11111111) | (dwSeed1 >> 0x0B);
+ dwSeed2 = ch + dwSeed2 + (dwSeed2 << 5) + 3;
+ *block++ = ch;
+ }
+}
+
+/*
+void EncryptMpqTable(void * pvMpqTable, DWORD dwLength, const char * szKey)
+{
+ EncryptMpqBlock(pvMpqTable, dwLength, HashString(szKey, MPQ_HASH_FILE_KEY));
+}
+
+void DecryptMpqTable(void * pvMpqTable, DWORD dwLength, const char * szKey)
+{
+ DecryptMpqBlock(pvMpqTable, dwLength, HashString(szKey, MPQ_HASH_FILE_KEY));
+}
+*/
+
+/**
+ * Functions tries to get file decryption key. The trick comes from sector
+ * positions which are stored at the begin of each compressed file. We know the
+ * file size, that means we know number of sectors that means we know the first
+ * DWORD value in sector position. And if we know encrypted and decrypted value,
+ * we can find the decryption key !!!
+ *
+ * hf - MPQ file handle
+ * SectorOffsets - DWORD array of sector positions
+ * ch - Decrypted value of the first sector pos
+ */
+
+DWORD DetectFileKeyBySectorSize(LPDWORD SectorOffsets, DWORD decrypted)
+{
+ DWORD saveKey1;
+ DWORD temp = *SectorOffsets ^ decrypted; // temp = seed1 + seed2
+ temp -= 0xEEEEEEEE; // temp = seed1 + StormBuffer[0x400 + (seed1 & 0xFF)]
+
+ for(int i = 0; i < 0x100; i++) // Try all 255 possibilities
+ {
+ DWORD seed1;
+ DWORD seed2 = 0xEEEEEEEE;
+ DWORD ch;
+
+ // Try the first DWORD (We exactly know the value)
+ seed1 = temp - StormBuffer[0x400 + i];
+ seed2 += StormBuffer[0x400 + (seed1 & 0xFF)];
+ ch = SectorOffsets[0] ^ (seed1 + seed2);
+
+ if(ch != decrypted)
+ continue;
+
+ // Add 1 because we are decrypting sector positions
+ saveKey1 = seed1 + 1;
+
+ // If OK, continue and test the second value. We don't know exactly the value,
+ // but we know that the second one has lower 16 bits set to zero
+ // (no compressed sector is larger than 0xFFFF bytes)
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+
+ seed2 += StormBuffer[0x400 + (seed1 & 0xFF)];
+ ch = SectorOffsets[1] ^ (seed1 + seed2);
+
+ if((ch & 0xFFFF0000) == 0)
+ return saveKey1;
+ }
+ return 0;
+}
+
+// Function tries to detect file encryption key. It expectes at least two uncompressed bytes
+DWORD DetectFileKeyByKnownContent(void * pvFileContent, DWORD nDwords, ...)
+{
+ LPDWORD pdwContent = (LPDWORD)pvFileContent;
+ va_list argList;
+ DWORD dwDecrypted[0x10];
+ DWORD saveKey1;
+ DWORD dwTemp;
+ DWORD i, j;
+
+ // We need at least two DWORDS to detect the file key
+ if(nDwords < 0x02 || nDwords > 0x10)
+ return 0;
+
+ va_start(argList, nDwords);
+ for(i = 0; i < nDwords; i++)
+ dwDecrypted[i] = va_arg(argList, DWORD);
+ va_end(argList);
+
+ dwTemp = (*pdwContent ^ dwDecrypted[0]) - 0xEEEEEEEE;
+ for(i = 0; i < 0x100; i++) // Try all 256 possibilities
+ {
+ DWORD seed1;
+ DWORD seed2 = 0xEEEEEEEE;
+ DWORD ch;
+
+ // Try the first DWORD
+ seed1 = dwTemp - StormBuffer[0x400 + i];
+ seed2 += StormBuffer[0x400 + (seed1 & 0xFF)];
+ ch = pdwContent[0] ^ (seed1 + seed2);
+
+ if(ch != dwDecrypted[0])
+ continue;
+
+ saveKey1 = seed1;
+
+ // If OK, continue and test all bytes.
+ for(j = 1; j < nDwords; j++)
+ {
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+
+ seed2 += StormBuffer[0x400 + (seed1 & 0xFF)];
+ ch = pdwContent[j] ^ (seed1 + seed2);
+
+ if(ch == dwDecrypted[j] && j == nDwords - 1)
+ return saveKey1;
+ }
+ }
+ return 0;
+}
+
+DWORD DetectFileKeyByContent(void * pvFileContent, DWORD dwFileSize)
+{
+ DWORD dwFileKey;
+
+ // Try to break the file encryption key as if it was a WAVE file
+ if(dwFileSize >= 0x0C)
+ {
+ dwFileKey = DetectFileKeyByKnownContent(pvFileContent, 3, 0x46464952, dwFileSize - 8, 0x45564157);
+ if(dwFileKey != 0)
+ return dwFileKey;
+ }
+
+ // Try to break the encryption key as if it was an EXE file
+ if(dwFileSize > 0x40)
+ {
+ dwFileKey = DetectFileKeyByKnownContent(pvFileContent, 2, 0x00905A4D, 0x00000003);
+ if(dwFileKey != 0)
+ return dwFileKey;
+ }
+
+ // Try to break the encryption key as if it was a XML file
+ if(dwFileSize > 0x04)
+ {
+ dwFileKey = DetectFileKeyByKnownContent(pvFileContent, 2, 0x6D783F3C, 0x6576206C);
+ if(dwFileKey != 0)
+ return dwFileKey;
+ }
+
+ // Not detected, sorry
+ return 0;
+}
+
+DWORD DecryptFileKey(
+ const char * szFileName,
+ ULONGLONG MpqPos,
+ DWORD dwFileSize,
+ DWORD dwFlags)
+{
+ DWORD dwFileKey;
+ DWORD dwMpqPos = (DWORD)MpqPos;
+
+ // File key is calculated from plain name
+ szFileName = GetPlainFileNameA(szFileName);
+ dwFileKey = HashString(szFileName, MPQ_HASH_FILE_KEY);
+
+ // Fix the key, if needed
+ if(dwFlags & MPQ_FILE_FIX_KEY)
+ dwFileKey = (dwFileKey + dwMpqPos) ^ dwFileSize;
+
+ // Return the key
+ return dwFileKey;
+}
+
+//-----------------------------------------------------------------------------
+// Handle validation functions
+
+bool IsValidMpqHandle(TMPQArchive * ha)
+{
+ if(ha == NULL)
+ return false;
+ if(ha->pHeader == NULL || ha->pHeader->dwID != ID_MPQ)
+ return false;
+
+ return (bool)(ha->pHeader->dwID == ID_MPQ);
+}
+
+bool IsValidFileHandle(TMPQFile * hf)
+{
+ if(hf == NULL)
+ return false;
+
+ if(hf->dwMagic != ID_MPQ_FILE)
+ return false;
+
+ if(hf->pStream != NULL)
+ return true;
+
+ return IsValidMpqHandle(hf->ha);
+}
+
+//-----------------------------------------------------------------------------
+// Hash table and block table manipulation
+
+// Retrieves the first hash entry for the given file.
+// Every locale version of a file has its own hash entry
+TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName)
+{
+ TMPQHash * pStartHash; // File hash entry (start)
+ TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
+ TMPQHash * pHash; // File hash entry (current)
+ DWORD dwHashTableSizeMask;
+ DWORD dwIndex = HashString(szFileName, MPQ_HASH_TABLE_INDEX);
+ DWORD dwName1 = HashString(szFileName, MPQ_HASH_NAME_A);
+ DWORD dwName2 = HashString(szFileName, MPQ_HASH_NAME_B);
+
+ // Get the first possible has entry that might be the one
+ dwHashTableSizeMask = ha->pHeader->dwHashTableSize ? (ha->pHeader->dwHashTableSize - 1) : 0;
+ pStartHash = pHash = ha->pHashTable + (dwIndex & dwHashTableSizeMask);
+
+ // There might be deleted entries in the hash table prior to our desired entry.
+ while(pHash->dwBlockIndex != HASH_ENTRY_FREE)
+ {
+ // If the entry agrees, we found it.
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->dwFileTableSize)
+ return pHash;
+
+ // Move to the next hash entry. Stop searching
+ // if we got reached the original hash entry
+ if(++pHash >= pHashEnd)
+ pHash = ha->pHashTable;
+ if(pHash == pStartHash)
+ break;
+ }
+
+ // The apropriate hash entry was not found
+ return NULL;
+}
+
+TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash)
+{
+ TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
+ TMPQHash * pHash = pPrevHash;
+ DWORD dwName1 = pPrevHash->dwName1;
+ DWORD dwName2 = pPrevHash->dwName2;
+
+ // Now go for any next entry that follows the pPrevHash,
+ // until either free hash entry was found, or the start entry was reached
+ for(;;)
+ {
+ // Move to the next hash entry. Stop searching
+ // if we got reached the original hash entry
+ if(++pHash >= pHashEnd)
+ pHash = ha->pHashTable;
+ if(pHash == pFirstHash)
+ break;
+
+ // If the entry is a free entry, stop search
+ if(pHash->dwBlockIndex == HASH_ENTRY_FREE)
+ break;
+
+ // If the entry is not free and the name agrees, we found it
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->pHeader->dwBlockTableSize)
+ return pHash;
+ }
+
+ // No next entry
+ return NULL;
+}
+
+// Allocates an entry in the hash table
+DWORD AllocateHashEntry(
+ TMPQArchive * ha,
+ TFileEntry * pFileEntry)
+{
+ TMPQHash * pStartHash; // File hash entry (start)
+ TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
+ TMPQHash * pHash; // File hash entry (current)
+ DWORD dwHashTableSizeMask;
+ DWORD dwIndex = HashString(pFileEntry->szFileName, MPQ_HASH_TABLE_INDEX);
+ DWORD dwName1 = HashString(pFileEntry->szFileName, MPQ_HASH_NAME_A);
+ DWORD dwName2 = HashString(pFileEntry->szFileName, MPQ_HASH_NAME_B);
+
+ // Get the first possible has entry that might be the one
+ dwHashTableSizeMask = ha->pHeader->dwHashTableSize ? (ha->pHeader->dwHashTableSize - 1) : 0;
+ pStartHash = pHash = ha->pHashTable + (dwIndex & dwHashTableSizeMask);
+
+ // There might be deleted entries in the hash table prior to our desired entry.
+ while(pHash->dwBlockIndex < HASH_ENTRY_DELETED)
+ {
+ // If there already is an existing entry, reuse it.
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->lcLocale == pFileEntry->lcLocale)
+ break;
+
+ // Move to the next hash entry.
+ // If we reached the starting entry, it's failure.
+ if(++pHash >= pHashEnd)
+ pHash = ha->pHashTable;
+ if(pHash == pStartHash)
+ return HASH_ENTRY_FREE;
+ }
+
+ // Fill the free hash entry
+ pHash->dwName1 = dwName1;
+ pHash->dwName2 = dwName2;
+ pHash->lcLocale = pFileEntry->lcLocale;
+ pHash->wPlatform = pFileEntry->wPlatform;
+ pHash->dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
+
+ // Fill the hash index in the file entry
+ pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable);
+ return pFileEntry->dwHashIndex;
+}
+
+// Finds a free space in the MPQ where to store next data
+// The free space begins beyond the file that is stored at the fuhrtest
+// position in the MPQ.
+void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pFileEntry = ha->pFileTable;
+ ULONGLONG FreeSpacePos = ha->pHeader->dwHeaderSize;
+ DWORD dwChunkCount;
+
+ // Parse the entire block table
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // Only take existing files
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
+ {
+ // If the end of the file is bigger than current MPQ table pos, update it
+ if((pFileEntry->ByteOffset + pFileEntry->dwCmpSize) > FreeSpacePos)
+ {
+ // Get the end of the file data
+ FreeSpacePos = pFileEntry->ByteOffset + pFileEntry->dwCmpSize;
+
+ // Add the MD5 chunks, if present
+ if(pHeader->dwRawChunkSize != 0 && pFileEntry->dwCmpSize != 0)
+ {
+ dwChunkCount = ((pFileEntry->dwCmpSize - 1) / pHeader->dwRawChunkSize) + 1;
+ FreeSpacePos += dwChunkCount * MD5_DIGEST_SIZE;
+ }
+ }
+ }
+ }
+
+ // Give the free space position to the caller
+ if(pFreeSpacePos != NULL)
+ *pFreeSpacePos = FreeSpacePos;
+}
+
+//-----------------------------------------------------------------------------
+// Common functions - MPQ File
+
+TMPQFile * CreateMpqFile(TMPQArchive * ha)
+{
+ TMPQFile * hf;
+
+ // Allocate space for TMPQFile
+ hf = STORM_ALLOC(TMPQFile, 1);
+ if(hf != NULL)
+ {
+ // Fill the file structure
+ memset(hf, 0, sizeof(TMPQFile));
+ hf->ha = ha;
+ hf->pStream = NULL;
+ hf->dwMagic = ID_MPQ_FILE;
+ }
+
+ return hf;
+}
+
+// Loads a table from MPQ.
+// Can be used for hash table, block table, sector offset table or sector checksum table
+int LoadMpqTable(
+ TMPQArchive * ha,
+ ULONGLONG ByteOffset,
+ void * pvTable,
+ DWORD dwCompressedSize,
+ DWORD dwRealSize,
+ DWORD dwKey)
+{
+ LPBYTE pbCompressed = NULL;
+ LPBYTE pbToRead = (LPBYTE)pvTable;
+ int nError = ERROR_SUCCESS;
+
+ // "interface.MPQ.part" in trial version of World of Warcraft
+ // has block table and hash table compressed.
+ if(dwCompressedSize < dwRealSize)
+ {
+ // Allocate temporary buffer for holding compressed data
+ pbCompressed = STORM_ALLOC(BYTE, dwCompressedSize);
+ if(pbCompressed == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Assign the temporary buffer as target for read operation
+ pbToRead = pbCompressed;
+ }
+
+ // Read the table
+ if(FileStream_Read(ha->pStream, &ByteOffset, pbToRead, dwCompressedSize))
+ {
+ // First of all, decrypt the table
+ if(dwKey != 0)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pbToRead, dwCompressedSize);
+ DecryptMpqBlock(pbToRead, dwCompressedSize, dwKey);
+ BSWAP_ARRAY32_UNSIGNED(pbToRead, dwCompressedSize);
+ }
+
+ // If the table is compressed, decompress it
+ if(dwCompressedSize < dwRealSize)
+ {
+ int cbOutBuffer = (int)dwRealSize;
+ int cbInBuffer = (int)dwCompressedSize;
+
+ if(!SCompDecompress2((char *)pvTable, &cbOutBuffer, (char *)pbCompressed, cbInBuffer))
+ nError = GetLastError();
+
+ // Free the temporary buffer
+ STORM_FREE(pbCompressed);
+ }
+ }
+ else
+ {
+ nError = GetLastError();
+ }
+
+ BSWAP_ARRAY32_UNSIGNED(pvTable, dwRealSize);
+ return nError;
+}
+
+void CalculateRawSectorOffset(
+ ULONGLONG & RawFilePos,
+ TMPQFile * hf,
+ DWORD dwSectorOffset)
+{
+ //
+ // Some MPQ protectors place the sector offset table after the actual file data.
+ // Sector offsets in the sector offset table are negative. When added
+ // to MPQ file offset from the block table entry, the result is a correct
+ // position of the file data in the MPQ.
+ //
+ // The position of sector table must be always within the MPQ, however.
+ // When a negative sector offset is found, we make sure that we make the addition
+ // just in 32-bits, and then add the MPQ offset.
+ //
+
+ if(dwSectorOffset & 0x80000000)
+ {
+ RawFilePos = hf->ha->MpqPos + ((DWORD)hf->pFileEntry->ByteOffset + dwSectorOffset);
+ }
+ else
+ {
+ RawFilePos = hf->RawFilePos + dwSectorOffset;
+ }
+
+ // We also have to add patch header size, if patch header is present
+ if(hf->pPatchInfo != NULL)
+ RawFilePos += hf->pPatchInfo->dwLength;
+}
+
+unsigned char * AllocateMd5Buffer(
+ DWORD dwRawDataSize,
+ DWORD dwChunkSize,
+ LPDWORD pcbMd5Size)
+{
+ unsigned char * md5_array;
+ DWORD cbMd5Size;
+
+ // Sanity check
+ assert(dwRawDataSize != 0);
+ assert(dwChunkSize != 0);
+
+ // Calculate how many MD5's we will calculate
+ cbMd5Size = (((dwRawDataSize - 1) / dwChunkSize) + 1) * MD5_DIGEST_SIZE;
+
+ // Allocate space for array or MD5s
+ md5_array = STORM_ALLOC(BYTE, cbMd5Size);
+
+ // Give the size of the MD5 array
+ if(pcbMd5Size != NULL)
+ *pcbMd5Size = cbMd5Size;
+ return md5_array;
+}
+
+// Allocates sector buffer and sector offset table
+int AllocateSectorBuffer(TMPQFile * hf)
+{
+ TMPQArchive * ha = hf->ha;
+
+ // Caller of AllocateSectorBuffer must ensure these
+ assert(hf->pbFileSector == NULL);
+ assert(hf->pFileEntry != NULL);
+ assert(hf->ha != NULL);
+
+ // Don't allocate anything if the file has zero size
+ if(hf->pFileEntry->dwFileSize == 0 || hf->dwDataSize == 0)
+ return ERROR_SUCCESS;
+
+ // Determine the file sector size and allocate buffer for it
+ hf->dwSectorSize = (hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) ? hf->dwDataSize : ha->dwSectorSize;
+ hf->pbFileSector = STORM_ALLOC(BYTE, hf->dwSectorSize);
+ hf->dwSectorOffs = SFILE_INVALID_POS;
+
+ // Return result
+ return (hf->pbFileSector != NULL) ? (int)ERROR_SUCCESS : (int)ERROR_NOT_ENOUGH_MEMORY;
+}
+
+// Allocates sector offset table
+int AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile)
+{
+ TMPQArchive * ha = hf->ha;
+ DWORD dwLength = sizeof(TPatchInfo);
+
+ // The following conditions must be true
+ assert(hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE);
+ assert(hf->pPatchInfo == NULL);
+
+__AllocateAndLoadPatchInfo:
+
+ // Allocate space for patch header. Start with default size,
+ // and if its size if bigger, then we reload them
+ hf->pPatchInfo = (TPatchInfo *)STORM_ALLOC(BYTE, dwLength);
+ if(hf->pPatchInfo == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Do we have to load the patch header from the file ?
+ if(bLoadFromFile)
+ {
+ // Load the patch header
+ if(!FileStream_Read(ha->pStream, &hf->RawFilePos, hf->pPatchInfo, dwLength))
+ {
+ // Free the patch info
+ STORM_FREE(hf->pPatchInfo);
+ hf->pPatchInfo = NULL;
+ return GetLastError();
+ }
+
+ // Perform necessary swapping
+ hf->pPatchInfo->dwLength = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwLength);
+ hf->pPatchInfo->dwFlags = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwFlags);
+ hf->pPatchInfo->dwDataSize = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwDataSize);
+
+ // Verify the size of the patch header
+ // If it's not default size, we have to reload them
+ if(hf->pPatchInfo->dwLength > dwLength)
+ {
+ // Free the patch info
+ dwLength = hf->pPatchInfo->dwLength;
+ STORM_FREE(hf->pPatchInfo);
+ hf->pPatchInfo = NULL;
+
+ // If the length is out of all possible ranges, fail the operation
+ if(dwLength > 0x400)
+ return ERROR_FILE_CORRUPT;
+ goto __AllocateAndLoadPatchInfo;
+ }
+
+ // Patch file data size according to the patch header
+ hf->dwDataSize = hf->pPatchInfo->dwDataSize;
+ }
+ else
+ {
+ memset(hf->pPatchInfo, 0, dwLength);
+ }
+
+ // Save the final length to the patch header
+ hf->pPatchInfo->dwLength = dwLength;
+ hf->pPatchInfo->dwFlags = 0x80000000;
+ return ERROR_SUCCESS;
+}
+
+// Allocates sector offset table
+int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile)
+{
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ DWORD dwSectorOffsLen;
+ bool bSectorOffsetTableCorrupt = false;
+
+ // Caller of AllocateSectorOffsets must ensure these
+ assert(hf->SectorOffsets == NULL);
+ assert(hf->pFileEntry != NULL);
+ assert(hf->dwDataSize != 0);
+ assert(hf->ha != NULL);
+
+ // If the file is stored as single unit, just set number of sectors to 1
+ if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
+ {
+ hf->dwSectorCount = 1;
+ return ERROR_SUCCESS;
+ }
+
+ // Calculate the number of data sectors
+ // Note that this doesn't work if the file size is zero
+ hf->dwSectorCount = ((hf->dwDataSize - 1) / hf->dwSectorSize) + 1;
+
+ // Calculate the number of file sectors
+ dwSectorOffsLen = (hf->dwSectorCount + 1) * sizeof(DWORD);
+
+ // If MPQ_FILE_SECTOR_CRC flag is set, there will either be extra DWORD
+ // or an array of MD5's. Either way, we read at least 4 bytes more
+ // in order to save additional read from the file.
+ if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)
+ dwSectorOffsLen += sizeof(DWORD);
+
+ // Only allocate and load the table if the file is compressed
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ {
+ __LoadSectorOffsets:
+
+ // Allocate the sector offset table
+ hf->SectorOffsets = (DWORD *)STORM_ALLOC(BYTE, dwSectorOffsLen);
+ if(hf->SectorOffsets == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Only read from the file if we are supposed to do so
+ if(bLoadFromFile)
+ {
+ ULONGLONG RawFilePos = hf->RawFilePos;
+
+ if(hf->pPatchInfo != NULL)
+ RawFilePos += hf->pPatchInfo->dwLength;
+
+ // Load the sector offsets from the file
+ if(!FileStream_Read(ha->pStream, &RawFilePos, hf->SectorOffsets, dwSectorOffsLen))
+ {
+ // Free the sector offsets
+ STORM_FREE(hf->SectorOffsets);
+ hf->SectorOffsets = NULL;
+ return GetLastError();
+ }
+
+ // Swap the sector positions
+ BSWAP_ARRAY32_UNSIGNED(hf->SectorOffsets, dwSectorOffsLen);
+
+ // Decrypt loaded sector positions if necessary
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ // If we don't know the file key, try to find it.
+ if(hf->dwFileKey == 0)
+ {
+ hf->dwFileKey = DetectFileKeyBySectorSize(hf->SectorOffsets, dwSectorOffsLen);
+ if(hf->dwFileKey == 0)
+ {
+ STORM_FREE(hf->SectorOffsets);
+ hf->SectorOffsets = NULL;
+ return ERROR_UNKNOWN_FILE_KEY;
+ }
+ }
+
+ // Decrypt sector positions
+ DecryptMpqBlock(hf->SectorOffsets, dwSectorOffsLen, hf->dwFileKey - 1);
+ }
+
+ //
+ // Validate the sector offset table
+ //
+ // Note: Some MPQ protectors put the actual file data before the sector offset table.
+ // In this case, the sector offsets are negative (> 0x80000000).
+ //
+
+ for(DWORD i = 0; i < hf->dwSectorCount; i++)
+ {
+ DWORD dwSectorOffset1 = hf->SectorOffsets[i+1];
+ DWORD dwSectorOffset0 = hf->SectorOffsets[i];
+
+ // Every following sector offset must be bigger than the previous one
+ if(dwSectorOffset1 <= dwSectorOffset0)
+ {
+ bSectorOffsetTableCorrupt = true;
+ break;
+ }
+
+ // The sector size must not be bigger than compressed file size
+ if((dwSectorOffset1 - dwSectorOffset0) > pFileEntry->dwCmpSize)
+ {
+ bSectorOffsetTableCorrupt = true;
+ break;
+ }
+ }
+
+ // If data corruption detected, free the sector offset table
+ if(bSectorOffsetTableCorrupt)
+ {
+ STORM_FREE(hf->SectorOffsets);
+ hf->SectorOffsets = NULL;
+ return ERROR_FILE_CORRUPT;
+ }
+
+ //
+ // There may be various extra DWORDs loaded after the sector offset table.
+ // They are mostly empty on WoW release MPQs, but on MPQs from PTR,
+ // they contain random non-zero data. Their meaning is unknown.
+ //
+ // These extra values are, however, include in the dwCmpSize in the file
+ // table. We cannot ignore them, because compacting archive would fail
+ //
+
+ if(hf->SectorOffsets[0] > dwSectorOffsLen)
+ {
+ dwSectorOffsLen = hf->SectorOffsets[0];
+ STORM_FREE(hf->SectorOffsets);
+ hf->SectorOffsets = NULL;
+ goto __LoadSectorOffsets;
+ }
+ }
+ else
+ {
+ memset(hf->SectorOffsets, 0, dwSectorOffsLen);
+ hf->SectorOffsets[0] = dwSectorOffsLen;
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile)
+{
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ ULONGLONG RawFilePos;
+ DWORD dwCompressedSize = 0;
+ DWORD dwExpectedSize;
+ DWORD dwCrcOffset; // Offset of the CRC table, relative to file offset in the MPQ
+ DWORD dwCrcSize;
+
+ // Caller of AllocateSectorChecksums must ensure these
+ assert(hf->SectorChksums == NULL);
+ assert(hf->SectorOffsets != NULL);
+ assert(hf->pFileEntry != NULL);
+ assert(hf->ha != NULL);
+
+ // Single unit files don't have sector checksums
+ if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
+ return ERROR_SUCCESS;
+
+ // Caller must ensure that we are only called when we have sector checksums
+ assert(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC);
+
+ //
+ // Older MPQs store an array of CRC32's after
+ // the raw file data in the MPQ.
+ //
+ // In newer MPQs, the (since Cataclysm BETA) the (attributes) file
+ // contains additional 32-bit values beyond the sector table.
+ // Their number depends on size of the (attributes), but their
+ // meaning is unknown. They are usually zeroed in retail game files,
+ // but contain some sort of checksum in BETA MPQs
+ //
+
+ // Does the size of the file table match with the CRC32-based checksums?
+ dwExpectedSize = (hf->dwSectorCount + 2) * sizeof(DWORD);
+ if(hf->SectorOffsets[0] == dwExpectedSize)
+ {
+ // Is there valid size of the sector checksums?
+ if(hf->SectorOffsets[hf->dwSectorCount + 1] >= hf->SectorOffsets[hf->dwSectorCount])
+ dwCompressedSize = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount];
+
+ // Ignore cases when the length is too small or too big.
+ if(dwCompressedSize < sizeof(DWORD) || dwCompressedSize > hf->dwSectorSize)
+ return ERROR_SUCCESS;
+
+ // Allocate the array for the sector checksums
+ hf->SectorChksums = STORM_ALLOC(DWORD, hf->dwSectorCount);
+ if(hf->SectorChksums == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // If we are not supposed to load it from the file, allocate empty buffer
+ if(bLoadFromFile == false)
+ {
+ memset(hf->SectorChksums, 0, hf->dwSectorCount * sizeof(DWORD));
+ return ERROR_SUCCESS;
+ }
+
+ // Calculate offset of the CRC table
+ dwCrcSize = hf->dwSectorCount * sizeof(DWORD);
+ dwCrcOffset = hf->SectorOffsets[hf->dwSectorCount];
+ CalculateRawSectorOffset(RawFilePos, hf, dwCrcOffset);
+
+ // Now read the table from the MPQ
+ return LoadMpqTable(ha, RawFilePos, hf->SectorChksums, dwCompressedSize, dwCrcSize, 0);
+ }
+
+ // If the size doesn't match, we ignore sector checksums
+// assert(false);
+ return ERROR_SUCCESS;
+}
+
+int WritePatchInfo(TMPQFile * hf)
+{
+ TMPQArchive * ha = hf->ha;
+ TPatchInfo * pPatchInfo = hf->pPatchInfo;
+
+ // The caller must make sure that this function is only called
+ // when the following is true.
+ assert(hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE);
+ assert(pPatchInfo != NULL);
+
+ BSWAP_ARRAY32_UNSIGNED(pPatchInfo, 3 * sizeof(DWORD));
+ if(!FileStream_Write(ha->pStream, &hf->RawFilePos, pPatchInfo, sizeof(TPatchInfo)))
+ return GetLastError();
+
+ return ERROR_SUCCESS;
+}
+
+int WriteSectorOffsets(TMPQFile * hf)
+{
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ ULONGLONG RawFilePos = hf->RawFilePos;
+ DWORD dwSectorOffsLen;
+
+ // The caller must make sure that this function is only called
+ // when the following is true.
+ assert(hf->pFileEntry->dwFlags & MPQ_FILE_COMPRESSED);
+ assert(hf->SectorOffsets != NULL);
+ dwSectorOffsLen = hf->SectorOffsets[0];
+
+ // If file is encrypted, sector positions are also encrypted
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ EncryptMpqBlock(hf->SectorOffsets, dwSectorOffsLen, hf->dwFileKey - 1);
+ BSWAP_ARRAY32_UNSIGNED(hf->SectorOffsets, dwSectorOffsLen);
+
+ // Adjust sector offset table position, if we also have patch info
+ if(hf->pPatchInfo != NULL)
+ RawFilePos += hf->pPatchInfo->dwLength;
+
+ // Write sector offsets to the archive
+ if(!FileStream_Write(ha->pStream, &RawFilePos, hf->SectorOffsets, dwSectorOffsLen))
+ return GetLastError();
+
+ // Not necessary, as the sector checksums
+ // are going to be freed when this is done.
+// BSWAP_ARRAY32_UNSIGNED(hf->SectorOffsets, dwSectorOffsLen);
+ return ERROR_SUCCESS;
+}
+
+
+int WriteSectorChecksums(TMPQFile * hf)
+{
+ TMPQArchive * ha = hf->ha;
+ ULONGLONG RawFilePos;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ LPBYTE pbCompressed;
+ DWORD dwCompressedSize = 0;
+ DWORD dwCrcSize;
+ int nOutSize;
+ int nError = ERROR_SUCCESS;
+
+ // The caller must make sure that this function is only called
+ // when the following is true.
+ assert(hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC);
+ assert(hf->SectorOffsets != NULL);
+ assert(hf->SectorChksums != NULL);
+
+ // If the MPQ has MD5 of each raw data chunk,
+ // we leave sector offsets empty
+ if(ha->pHeader->dwRawChunkSize != 0)
+ {
+ hf->SectorOffsets[hf->dwSectorCount + 1] = hf->SectorOffsets[hf->dwSectorCount];
+ return ERROR_SUCCESS;
+ }
+
+ // Calculate size of the checksum array
+ dwCrcSize = hf->dwSectorCount * sizeof(DWORD);
+
+ // Allocate buffer for compressed sector CRCs.
+ pbCompressed = STORM_ALLOC(BYTE, dwCrcSize);
+ if(pbCompressed == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Perform the compression
+ BSWAP_ARRAY32_UNSIGNED(hf->SectorChksums, dwCrcSize);
+
+ nOutSize = (int)dwCrcSize;
+ SCompCompress((char *)pbCompressed, &nOutSize, (char *)hf->SectorChksums, (int)dwCrcSize, MPQ_COMPRESSION_ZLIB, 0, 0);
+ dwCompressedSize = (DWORD)nOutSize;
+
+ // Write the sector CRCs to the archive
+ RawFilePos = hf->RawFilePos + hf->SectorOffsets[hf->dwSectorCount];
+ if(hf->pPatchInfo != NULL)
+ RawFilePos += hf->pPatchInfo->dwLength;
+ if(!FileStream_Write(ha->pStream, &RawFilePos, pbCompressed, dwCompressedSize))
+ nError = GetLastError();
+
+ // Not necessary, as the sector checksums
+ // are going to be freed when this is done.
+// BSWAP_ARRAY32_UNSIGNED(hf->SectorChksums, dwCrcSize);
+
+ // Store the sector CRCs
+ hf->SectorOffsets[hf->dwSectorCount + 1] = hf->SectorOffsets[hf->dwSectorCount] + dwCompressedSize;
+ pFileEntry->dwCmpSize += dwCompressedSize;
+ STORM_FREE(pbCompressed);
+ return nError;
+}
+
+int WriteMemDataMD5(
+ TFileStream * pStream,
+ ULONGLONG RawDataOffs,
+ void * pvRawData,
+ DWORD dwRawDataSize,
+ DWORD dwChunkSize,
+ LPDWORD pcbTotalSize)
+{
+ unsigned char * md5_array;
+ unsigned char * md5;
+ LPBYTE pbRawData = (LPBYTE)pvRawData;
+ DWORD dwBytesRemaining = dwRawDataSize;
+ DWORD dwMd5ArraySize = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate buffer for array of MD5
+ md5_array = md5 = AllocateMd5Buffer(dwRawDataSize, dwChunkSize, &dwMd5ArraySize);
+ if(md5_array == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // For every file chunk, calculate MD5
+ while(dwBytesRemaining != 0)
+ {
+ // Get the remaining number of bytes to read
+ dwChunkSize = STORMLIB_MIN(dwBytesRemaining, dwChunkSize);
+
+ // Calculate MD5
+ CalculateDataBlockHash(pbRawData, dwChunkSize, md5);
+ md5 += MD5_DIGEST_SIZE;
+
+ // Move offset and size
+ dwBytesRemaining -= dwChunkSize;
+ pbRawData += dwChunkSize;
+ }
+
+ // Write the array od MD5's to the file
+ RawDataOffs += dwRawDataSize;
+ if(!FileStream_Write(pStream, &RawDataOffs, md5_array, dwMd5ArraySize))
+ nError = GetLastError();
+
+ // Give the caller the size of the MD5 array
+ if(pcbTotalSize != NULL)
+ *pcbTotalSize = dwRawDataSize + dwMd5ArraySize;
+
+ // Free buffers and exit
+ STORM_FREE(md5_array);
+ return nError;
+}
+
+
+// Writes the MD5 for each chunk of the raw file data
+int WriteMpqDataMD5(
+ TFileStream * pStream,
+ ULONGLONG RawDataOffs,
+ DWORD dwRawDataSize,
+ DWORD dwChunkSize)
+{
+ unsigned char * md5_array;
+ unsigned char * md5;
+ LPBYTE pbFileChunk;
+ DWORD dwMd5ArraySize = 0;
+ DWORD dwToRead = dwRawDataSize;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate buffer for array of MD5
+ md5_array = md5 = AllocateMd5Buffer(dwRawDataSize, dwChunkSize, &dwMd5ArraySize);
+ if(md5_array == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Allocate space for file chunk
+ pbFileChunk = STORM_ALLOC(BYTE, dwChunkSize);
+ if(pbFileChunk == NULL)
+ {
+ STORM_FREE(md5_array);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // For every file chunk, calculate MD5
+ while(dwRawDataSize != 0)
+ {
+ // Get the remaining number of bytes to read
+ dwToRead = STORMLIB_MIN(dwRawDataSize, dwChunkSize);
+
+ // Read the chunk
+ if(!FileStream_Read(pStream, &RawDataOffs, pbFileChunk, dwToRead))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Calculate MD5
+ CalculateDataBlockHash(pbFileChunk, dwToRead, md5);
+ md5 += MD5_DIGEST_SIZE;
+
+ // Move offset and size
+ RawDataOffs += dwToRead;
+ dwRawDataSize -= dwToRead;
+ }
+
+ // Write the array od MD5's to the file
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!FileStream_Write(pStream, NULL, md5_array, dwMd5ArraySize))
+ nError = GetLastError();
+ }
+
+ // Free buffers and exit
+ STORM_FREE(pbFileChunk);
+ STORM_FREE(md5_array);
+ return nError;
+}
+
+// Frees the structure for MPQ file
+void FreeMPQFile(TMPQFile *& hf)
+{
+ if(hf != NULL)
+ {
+ // If we have patch file attached to this one, free it first
+ if(hf->hfPatchFile != NULL)
+ FreeMPQFile(hf->hfPatchFile);
+
+ // Then free all buffers allocated in the file structure
+ if(hf->pPatchHeader != NULL)
+ STORM_FREE(hf->pPatchHeader);
+ if(hf->pbFileData != NULL)
+ STORM_FREE(hf->pbFileData);
+ if(hf->pPatchInfo != NULL)
+ STORM_FREE(hf->pPatchInfo);
+ if(hf->SectorOffsets != NULL)
+ STORM_FREE(hf->SectorOffsets);
+ if(hf->SectorChksums != NULL)
+ STORM_FREE(hf->SectorChksums);
+ if(hf->pbFileSector != NULL)
+ STORM_FREE(hf->pbFileSector);
+ FileStream_Close(hf->pStream);
+ STORM_FREE(hf);
+ hf = NULL;
+ }
+}
+
+// Frees the MPQ archive
+void FreeMPQArchive(TMPQArchive *& ha)
+{
+ if(ha != NULL)
+ {
+ // First of all, free the patch archive, if any
+ if(ha->haPatch != NULL)
+ FreeMPQArchive(ha->haPatch);
+
+ // Close the file stream
+ FileStream_Close(ha->pStream);
+ ha->pStream = NULL;
+
+ // Free the file names from the file table
+ if(ha->pFileTable != NULL)
+ {
+ for(DWORD i = 0; i < ha->dwFileTableSize; i++)
+ {
+ if(ha->pFileTable[i].szFileName != NULL)
+ STORM_FREE(ha->pFileTable[i].szFileName);
+ ha->pFileTable[i].szFileName = NULL;
+ }
+
+ // Then free all buffers allocated in the archive structure
+ STORM_FREE(ha->pFileTable);
+ }
+
+ if(ha->pBitmap != NULL)
+ STORM_FREE(ha->pBitmap);
+ if(ha->pHashTable != NULL)
+ STORM_FREE(ha->pHashTable);
+ if(ha->pHetTable != NULL)
+ FreeHetTable(ha->pHetTable);
+ STORM_FREE(ha);
+ ha = NULL;
+ }
+}
+
+const char * GetPlainFileNameA(const char * szFileName)
+{
+ const char * szPlainName = szFileName;
+
+ while(*szFileName != 0)
+ {
+ if(*szFileName == '\\' || *szFileName == '/')
+ szPlainName = szFileName + 1;
+ szFileName++;
+ }
+
+ return szPlainName;
+}
+
+const TCHAR * GetPlainFileNameT(const TCHAR * szFileName)
+{
+ const TCHAR * szPlainName = szFileName;
+
+ while(*szFileName != 0)
+ {
+ if(*szFileName == '\\' || *szFileName == '/')
+ szPlainName = szFileName + 1;
+ szFileName++;
+ }
+
+ return szPlainName;
+}
+
+bool IsInternalMpqFileName(const char * szFileName)
+{
+ if(szFileName != NULL && szFileName[0] == '(')
+ {
+ if(!_stricmp(szFileName, LISTFILE_NAME) ||
+ !_stricmp(szFileName, ATTRIBUTES_NAME) ||
+ !_stricmp(szFileName, SIGNATURE_NAME))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Verifies if the file name is a pseudo-name
+bool IsPseudoFileName(const char * szFileName, DWORD * pdwFileIndex)
+{
+ DWORD dwFileIndex = 0;
+
+ if(szFileName != NULL)
+ {
+ // Must be "File########.ext"
+ if(!_strnicmp(szFileName, "File", 4))
+ {
+ // Check 8 digits
+ for(int i = 4; i < 4+8; i++)
+ {
+ if(szFileName[i] < '0' || szFileName[i] > '9')
+ return false;
+ dwFileIndex = (dwFileIndex * 10) + (szFileName[i] - '0');
+ }
+
+ // An extension must follow
+ if(szFileName[12] == '.')
+ {
+ if(pdwFileIndex != NULL)
+ *pdwFileIndex = dwFileIndex;
+ return true;
+ }
+ }
+ }
+
+ // Not a pseudo-name
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Functions calculating and verifying the MD5 signature
+
+bool IsValidMD5(LPBYTE pbMd5)
+{
+ BYTE BitSummary = 0;
+
+ // The MD5 is considered invalid of it is zeroed
+ BitSummary |= pbMd5[0x00] | pbMd5[0x01] | pbMd5[0x02] | pbMd5[0x03] | pbMd5[0x04] | pbMd5[0x05] | pbMd5[0x06] | pbMd5[0x07];
+ BitSummary |= pbMd5[0x08] | pbMd5[0x09] | pbMd5[0x0A] | pbMd5[0x0B] | pbMd5[0x0C] | pbMd5[0x0D] | pbMd5[0x0E] | pbMd5[0x0F];
+ return (BitSummary != 0);
+}
+
+bool VerifyDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5)
+{
+ hash_state md5_state;
+ BYTE md5_digest[MD5_DIGEST_SIZE];
+
+ // Don't verify the block if the MD5 is not valid.
+ if(!IsValidMD5(expected_md5))
+ return true;
+
+ // Calculate the MD5 of the data block
+ md5_init(&md5_state);
+ md5_process(&md5_state, (unsigned char *)pvDataBlock, cbDataBlock);
+ md5_done(&md5_state, md5_digest);
+
+ // Does the MD5's match?
+ return (memcmp(md5_digest, expected_md5, MD5_DIGEST_SIZE) == 0);
+}
+
+void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_hash)
+{
+ hash_state md5_state;
+
+ md5_init(&md5_state);
+ md5_process(&md5_state, (unsigned char *)pvDataBlock, cbDataBlock);
+ md5_done(&md5_state, md5_hash);
+}
+
+
+//-----------------------------------------------------------------------------
+// Swapping functions
+
+#ifndef PLATFORM_LITTLE_ENDIAN
+
+//
+// Note that those functions are implemented for Mac operating system,
+// as this is the only supported platform that uses big endian.
+//
+
+// Swaps a signed 16-bit integer
+int16_t SwapInt16(uint16_t data)
+{
+ return (int16_t)CFSwapInt16(data);
+}
+
+// Swaps an unsigned 16-bit integer
+uint16_t SwapUInt16(uint16_t data)
+{
+ return CFSwapInt16(data);
+}
+
+// Swaps signed 32-bit integer
+int32_t SwapInt32(uint32_t data)
+{
+ return (int32_t)CFSwapInt32(data);
+}
+
+// Swaps an unsigned 32-bit integer
+uint32_t SwapUInt32(uint32_t data)
+{
+ return CFSwapInt32(data);
+}
+
+// Swaps signed 64-bit integer
+int64_t SwapInt64(int64_t data)
+{
+ return (int64_t)CFSwapInt64(data);
+}
+
+// Swaps an unsigned 64-bit integer
+uint64_t SwapUInt64(uint64_t data)
+{
+ return CFSwapInt64(data);
+}
+
+// Swaps array of unsigned 16-bit integers
+void ConvertUInt16Buffer(void * ptr, size_t length)
+{
+ uint16_t * buffer = (uint16_t *)ptr;
+ uint32_t nElements = (uint32_t)(length / sizeof(uint16_t));
+
+ while(nElements-- > 0)
+ {
+ *buffer = SwapUInt16(*buffer);
+ buffer++;
+ }
+}
+
+// Swaps array of unsigned 32-bit integers
+void ConvertUInt32Buffer(void * ptr, size_t length)
+{
+ uint32_t * buffer = (uint32_t *)ptr;
+ uint32_t nElements = (uint32_t)(length / sizeof(uint32_t));
+
+ while(nElements-- > 0)
+ {
+ *buffer = SwapUInt32(*buffer);
+ buffer++;
+ }
+}
+
+// Swaps array of unsigned 64-bit integers
+void ConvertUInt64Buffer(void * ptr, size_t length)
+{
+ uint64_t * buffer = (uint64_t *)ptr;
+ uint32_t nElements = (uint32_t)(length / sizeof(uint64_t));
+
+ while(nElements-- > 0)
+ {
+ *buffer = SwapUInt64(*buffer);
+ buffer++;
+ }
+}
+
+// Swaps the TMPQUserData structure
+void ConvertTMPQUserData(void *userData)
+{
+ TMPQUserData * theData = (TMPQUserData *)userData;
+
+ theData->dwID = SwapUInt32(theData->dwID);
+ theData->cbUserDataSize = SwapUInt32(theData->cbUserDataSize);
+ theData->dwHeaderOffs = SwapUInt32(theData->dwHeaderOffs);
+ theData->cbUserDataHeader = SwapUInt32(theData->cbUserDataHeader);
+}
+
+// Swaps the TMPQHeader structure
+void ConvertTMPQHeader(void *header)
+{
+ TMPQHeader * theHeader = (TMPQHeader *)header;
+
+ theHeader->dwID = SwapUInt32(theHeader->dwID);
+ theHeader->dwHeaderSize = SwapUInt32(theHeader->dwHeaderSize);
+ theHeader->dwArchiveSize = SwapUInt32(theHeader->dwArchiveSize);
+ theHeader->wFormatVersion = SwapUInt16(theHeader->wFormatVersion);
+ theHeader->wSectorSize = SwapUInt16(theHeader->wSectorSize);
+ theHeader->dwHashTablePos = SwapUInt32(theHeader->dwHashTablePos);
+ theHeader->dwBlockTablePos = SwapUInt32(theHeader->dwBlockTablePos);
+ theHeader->dwHashTableSize = SwapUInt32(theHeader->dwHashTableSize);
+ theHeader->dwBlockTableSize = SwapUInt32(theHeader->dwBlockTableSize);
+
+ if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ {
+ // Swap the hi-block table position
+ theHeader->HiBlockTablePos64 = SwapUInt64(theHeader->HiBlockTablePos64);
+
+ theHeader->wHashTablePosHi = SwapUInt16(theHeader->wHashTablePosHi);
+ theHeader->wBlockTablePosHi = SwapUInt16(theHeader->wBlockTablePosHi);
+
+ if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_3)
+ {
+ theHeader->ArchiveSize64 = SwapUInt64(theHeader->ArchiveSize64);
+ theHeader->BetTablePos64 = SwapUInt64(theHeader->BetTablePos64);
+ theHeader->HetTablePos64 = SwapUInt64(theHeader->HetTablePos64);
+
+ if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4)
+ {
+ theHeader->HashTableSize64 = SwapUInt64(theHeader->HashTableSize64);
+ theHeader->BlockTableSize64 = SwapUInt64(theHeader->BlockTableSize64);
+ theHeader->HiBlockTableSize64 = SwapUInt64(theHeader->HiBlockTableSize64);
+ theHeader->HetTableSize64 = SwapUInt64(theHeader->HetTableSize64);
+ theHeader->BetTableSize64 = SwapUInt64(theHeader->BetTableSize64);
+ }
+ }
+ }
+}
+
+#endif // PLATFORM_LITTLE_ENDIAN
diff --git a/dep/StormLib/src/SBaseDumpData.cpp b/dep/StormLib/src/SBaseDumpData.cpp
new file mode 100644
index 00000000000..c9dcf0a3366
--- /dev/null
+++ b/dep/StormLib/src/SBaseDumpData.cpp
@@ -0,0 +1,144 @@
+/*****************************************************************************/
+/* SBaseDumpData.cpp Copyright (c) Ladislav Zezula 2011 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 26.01.11 1.00 Lad The first version of SBaseDumpData.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+#ifdef __STORMLIB_DUMP_DATA__
+
+void DumpMpqHeader(TMPQHeader * pHeader)
+{
+ printf("== MPQ Header =================================\n");
+ printf("DWORD dwID = %08X\n", pHeader->dwID);
+ printf("DWORD dwHeaderSize = %08X\n", pHeader->dwHeaderSize);
+ printf("DWORD dwArchiveSize = %08X\n", pHeader->dwArchiveSize);
+ printf("USHORT wFormatVersion = %04X\n", pHeader->wFormatVersion);
+ printf("USHORT wSectorSize = %04X\n", pHeader->wSectorSize);
+ printf("DWORD dwHashTablePos = %08X\n", pHeader->dwHashTablePos);
+ printf("DWORD dwBlockTablePos = %08X\n", pHeader->dwBlockTablePos);
+ printf("DWORD dwHashTableSize = %08X\n", pHeader->dwHashTableSize);
+ printf("DWORD dwBlockTableSize = %08X\n", pHeader->dwBlockTableSize);
+ printf("ULONGLONG HiBlockTablePos64 = %016llX\n", pHeader->HiBlockTablePos64);
+ printf("USHORT wHashTablePosHi = %04X\n", pHeader->wHashTablePosHi);
+ printf("USHORT wBlockTablePosHi = %04X\n", pHeader->wBlockTablePosHi);
+ printf("ULONGLONG ArchiveSize64 = %016llX\n", pHeader->ArchiveSize64);
+ printf("ULONGLONG BetTablePos64 = %016llX\n", pHeader->BetTablePos64);
+ printf("ULONGLONG HetTablePos64 = %016llX\n", pHeader->HetTablePos64);
+ printf("ULONGLONG HashTableSize64 = %016llX\n", pHeader->HashTableSize64);
+ printf("ULONGLONG BlockTableSize64 = %016llX\n", pHeader->BlockTableSize64);
+ printf("ULONGLONG HiBlockTableSize64 = %016llX\n", pHeader->HiBlockTableSize64);
+ printf("ULONGLONG HetTableSize64 = %016llX\n", pHeader->HetTableSize64);
+ printf("ULONGLONG BetTableSize64 = %016llX\n", pHeader->BetTableSize64);
+ printf("DWORD dwRawChunkSize = %08X\n", pHeader->dwRawChunkSize);
+ printf("-----------------------------------------------\n\n");
+}
+
+void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable)
+{
+ DWORD i;
+
+ if(pHetTable == NULL || pBetTable == NULL)
+ return;
+
+ printf("== HET Header =================================\n");
+ printf("ULONGLONG AndMask64 = %016llX\n", pHetTable->AndMask64);
+ printf("ULONGLONG OrMask64 = %016llX\n", pHetTable->OrMask64);
+ printf("DWORD dwIndexSizeTotal = %08X\n", pHetTable->dwIndexSizeTotal);
+ printf("DWORD dwIndexSizeExtra = %08X\n", pHetTable->dwIndexSizeExtra);
+ printf("DWORD dwIndexSize = %08X\n", pHetTable->dwIndexSize);
+ printf("DWORD dwMaxFileCount = %08X\n", pHetTable->dwMaxFileCount);
+ printf("DWORD dwHashTableSize = %08X\n", pHetTable->dwHashTableSize);
+ printf("DWORD dwHashBitSize = %08X\n", pHetTable->dwHashBitSize);
+ printf("-----------------------------------------------\n\n");
+
+ printf("== BET Header =================================\n");
+ printf("DWORD dwTableEntrySize = %08X\n", pBetTable->dwTableEntrySize);
+ printf("DWORD dwBitIndex_FilePos = %08X\n", pBetTable->dwBitIndex_FilePos);
+ printf("DWORD dwBitIndex_FileSize = %08X\n", pBetTable->dwBitIndex_FileSize);
+ printf("DWORD dwBitIndex_CmpSize = %08X\n", pBetTable->dwBitIndex_CmpSize);
+ printf("DWORD dwBitIndex_FlagIndex = %08X\n", pBetTable->dwBitIndex_FlagIndex);
+ printf("DWORD dwBitIndex_Unknown = %08X\n", pBetTable->dwBitIndex_Unknown);
+ printf("DWORD dwBitCount_FilePos = %08X\n", pBetTable->dwBitCount_FilePos);
+ printf("DWORD dwBitCount_FileSize = %08X\n", pBetTable->dwBitCount_FileSize);
+ printf("DWORD dwBitCount_CmpSize = %08X\n", pBetTable->dwBitCount_CmpSize);
+ printf("DWORD dwBitCount_FlagIndex = %08X\n", pBetTable->dwBitCount_FlagIndex);
+ printf("DWORD dwBitCount_Unknown = %08X\n", pBetTable->dwBitCount_Unknown);
+ printf("DWORD dwBetHashSizeTotal = %08X\n", pBetTable->dwBetHashSizeTotal);
+ printf("DWORD dwBetHashSizeExtra = %08X\n", pBetTable->dwBetHashSizeExtra);
+ printf("DWORD dwBetHashSize = %08X\n", pBetTable->dwBetHashSize);
+ printf("DWORD dwMaxFileCount = %08X\n", pBetTable->dwMaxFileCount);
+ printf("DWORD dwFlagCount = %08X\n", pBetTable->dwFlagCount);
+ printf("-----------------------------------------------\n\n");
+
+ printf("== HET & Bet Table ======================================================================\n\n");
+ printf("HetIdx HetHash BetIdx BetHash ByteOffset FileSize CmpSize FlgIdx Flags \n");
+ printf("------ ------- ------ ---------------- ---------------- -------- -------- ------ --------\n");
+ for(i = 0; i < pHetTable->dwHashTableSize; i++)
+ {
+ ULONGLONG ByteOffset = 0;
+ ULONGLONG BetHash = 0;
+ DWORD dwFileSize = 0;
+ DWORD dwCmpSize = 0;
+ DWORD dwFlagIndex = 0;
+ DWORD dwFlags = 0;
+ DWORD dwBetIndex = 0;
+
+ pHetTable->pBetIndexes->GetBits(i * pHetTable->dwIndexSizeTotal,
+ pHetTable->dwIndexSize,
+ &dwBetIndex,
+ 4);
+
+ if(dwBetIndex < pHetTable->dwMaxFileCount)
+ {
+ DWORD dwEntryIndex = pBetTable->dwTableEntrySize * dwBetIndex;
+
+ pBetTable->pBetHashes->GetBits(dwBetIndex * pBetTable->dwBetHashSizeTotal,
+ pBetTable->dwBetHashSize,
+ &BetHash,
+ 8);
+
+ pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FilePos,
+ pBetTable->dwBitCount_FilePos,
+ &ByteOffset,
+ 8);
+
+ pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FileSize,
+ pBetTable->dwBitCount_FileSize,
+ &dwFileSize,
+ 4);
+
+ pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_CmpSize,
+ pBetTable->dwBitCount_CmpSize,
+ &dwCmpSize,
+ 4);
+
+ pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FlagIndex,
+ pBetTable->dwBitCount_FlagIndex,
+ &dwFlagIndex,
+ 4);
+
+ dwFlags = pBetTable->pFileFlags[dwFlagIndex];
+ }
+
+ printf(" %04X %02lX %04X %016llX %016llX %08X %08X %04X %08X\n", i,
+ pHetTable->pHetHashes[i],
+ dwBetIndex,
+ BetHash,
+ ByteOffset,
+ dwFileSize,
+ dwCmpSize,
+ dwFlagIndex,
+ dwFlags);
+ }
+ printf("-----------------------------------------------------------------------------------------\n");
+}
+
+#endif // __STORMLIB_DUMP_DATA__
diff --git a/dep/StormLib/src/SBaseFileTable.cpp b/dep/StormLib/src/SBaseFileTable.cpp
new file mode 100644
index 00000000000..09379ca5da7
--- /dev/null
+++ b/dep/StormLib/src/SBaseFileTable.cpp
@@ -0,0 +1,2550 @@
+/*****************************************************************************/
+/* SBaseFileTable.cpp Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* Description: Common handler for classic and new hash&block tables */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 06.09.10 1.00 Lad The first version of SBaseFileTable.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local defines
+
+#define INVALID_FLAG_VALUE 0xCCCCCCCC
+#define MAX_FLAG_INDEX 512
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+// Structure for HET table header
+typedef struct _HET_TABLE_HEADER
+{
+ DWORD dwTableSize; // Size of the entire HET table, including HET_TABLE_HEADER (in bytes)
+ DWORD dwMaxFileCount; // Maximum number of files in the MPQ
+ DWORD dwHashTableSize; // Size of the hash table (in bytes)
+ DWORD dwHashEntrySize; // Effective size of the hash entry (in bits)
+ DWORD dwIndexSizeTotal; // Total size of file index (in bits)
+ DWORD dwIndexSizeExtra; // Extra bits in the file index
+ DWORD dwIndexSize; // Effective size of the file index (in bits)
+ DWORD dwIndexTableSize; // Size of the block index subtable (in bytes)
+
+} HET_TABLE_HEADER, *PHET_TABLE_HEADER;
+
+// Structure for BET table header
+typedef struct _BET_TABLE_HEADER
+{
+ DWORD dwTableSize; // Size of the entire BET table, including the header (in bytes)
+ DWORD dwFileCount; // Number of files in the BET table
+ DWORD dwUnknown08;
+ DWORD dwTableEntrySize; // Size of one table entry (in bits)
+ DWORD dwBitIndex_FilePos; // Bit index of the file position (within the entry record)
+ DWORD dwBitIndex_FileSize; // Bit index of the file size (within the entry record)
+ DWORD dwBitIndex_CmpSize; // Bit index of the compressed size (within the entry record)
+ DWORD dwBitIndex_FlagIndex; // Bit index of the flag index (within the entry record)
+ DWORD dwBitIndex_Unknown; // Bit index of the ??? (within the entry record)
+ DWORD dwBitCount_FilePos; // Bit size of file position (in the entry record)
+ DWORD dwBitCount_FileSize; // Bit size of file size (in the entry record)
+ DWORD dwBitCount_CmpSize; // Bit size of compressed file size (in the entry record)
+ DWORD dwBitCount_FlagIndex; // Bit size of flags index (in the entry record)
+ DWORD dwBitCount_Unknown; // Bit size of ??? (in the entry record)
+ DWORD dwBetHashSizeTotal; // Total size of the BET hash
+ DWORD dwBetHashSizeExtra; // Extra bits in the BET hash
+ DWORD dwBetHashSize; // Effective size of BET hash (in bits)
+ DWORD dwBetHashArraySize; // Size of BET hashes array, in bytes
+ DWORD dwFlagCount; // Number of flags in the following array
+
+} BET_TABLE_HEADER, *PBET_TABLE_HEADER;
+
+//-----------------------------------------------------------------------------
+// Support for calculating bit sizes
+
+static void InitFileFlagArray(LPDWORD FlagArray)
+{
+ for(DWORD dwFlagIndex = 0; dwFlagIndex < MAX_FLAG_INDEX; dwFlagIndex++)
+ FlagArray[dwFlagIndex] = INVALID_FLAG_VALUE;
+}
+
+static DWORD GetFileFlagIndex(LPDWORD FlagArray, DWORD dwFlags)
+{
+ // Find free or equal entry in the flag array
+ for(DWORD dwFlagIndex = 0; dwFlagIndex < MAX_FLAG_INDEX; dwFlagIndex++)
+ {
+ if(FlagArray[dwFlagIndex] == INVALID_FLAG_VALUE || FlagArray[dwFlagIndex] == dwFlags)
+ {
+ FlagArray[dwFlagIndex] = dwFlags;
+ return dwFlagIndex;
+ }
+ }
+
+ // This should never happen
+ assert(false);
+ return 0xFFFFFFFF;
+}
+
+static DWORD GetNecessaryBitCount(ULONGLONG MaxValue)
+{
+ DWORD dwBitCount = 0;
+
+ while(MaxValue > 0)
+ {
+ MaxValue >>= 1;
+ dwBitCount++;
+ }
+
+ return dwBitCount;
+}
+
+//-----------------------------------------------------------------------------
+// Support functions for BIT_ARRAY
+
+static USHORT SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
+
+static TBitArray * CreateBitArray(
+ DWORD NumberOfBits,
+ BYTE FillValue)
+{
+ TBitArray * pBitArray;
+ size_t nSize = sizeof(TBitArray) + (NumberOfBits + 7) / 8;
+
+ // Allocate the bit array
+ pBitArray = (TBitArray *)STORM_ALLOC(BYTE, nSize);
+ if(pBitArray != NULL)
+ {
+ memset(pBitArray, FillValue, nSize);
+ pBitArray->NumberOfBits = NumberOfBits;
+ }
+
+ return pBitArray;
+}
+
+void TBitArray::GetBits(
+ unsigned int nBitPosition,
+ unsigned int nBitLength,
+ void * pvBuffer,
+ int nResultByteSize)
+{
+ unsigned char * pbBuffer = (unsigned char *)pvBuffer;
+ unsigned int nBytePosition0 = (nBitPosition / 8);
+ unsigned int nBytePosition1 = nBytePosition0 + 1;
+ unsigned int nByteLength = (nBitLength / 8);
+ unsigned int nBitOffset = (nBitPosition & 0x07);
+ unsigned char BitBuffer;
+
+ // Keep compiler happy for platforms where nResultByteSize is not used
+ nResultByteSize = nResultByteSize;
+
+#ifdef _DEBUG
+ // Check if the target is properly zeroed
+ for(int i = 0; i < nResultByteSize; i++)
+ assert(pbBuffer[i] == 0);
+#endif
+
+#ifndef PLATFORM_LITTLE_ENDIAN
+ // Adjust the buffer pointer for big endian platforms
+ pbBuffer += (nResultByteSize - 1);
+#endif
+
+ // Copy whole bytes, if any
+ while(nByteLength > 0)
+ {
+ // Is the current position in the Elements byte-aligned?
+ if(nBitOffset != 0)
+ {
+ BitBuffer = (unsigned char)((Elements[nBytePosition0] >> nBitOffset) | (Elements[nBytePosition1] << (0x08 - nBitOffset)));
+ }
+ else
+ {
+ BitBuffer = Elements[nBytePosition0];
+ }
+
+#ifdef PLATFORM_LITTLE_ENDIAN
+ *pbBuffer++ = BitBuffer;
+#else
+ *pbBuffer-- = BitBuffer;
+#endif
+
+ // Move byte positions and lengths
+ nBytePosition1++;
+ nBytePosition0++;
+ nByteLength--;
+ }
+
+ // Get the rest of the bits
+ nBitLength = (nBitLength & 0x07);
+ if(nBitLength != 0)
+ {
+ *pbBuffer = (unsigned char)(Elements[nBytePosition0] >> nBitOffset);
+
+ if(nBitLength > (8 - nBitOffset))
+ *pbBuffer = (unsigned char)((Elements[nBytePosition1] << (8 - nBitOffset)) | (Elements[nBytePosition0] >> nBitOffset));
+
+ *pbBuffer &= (0x01 << nBitLength) - 1;
+ }
+}
+
+void TBitArray::SetBits(
+ unsigned int nBitPosition,
+ unsigned int nBitLength,
+ void * pvBuffer,
+ int nResultByteSize)
+{
+ unsigned char * pbBuffer = (unsigned char *)pvBuffer;
+ unsigned int nBytePosition = (nBitPosition / 8);
+ unsigned int nBitOffset = (nBitPosition & 0x07);
+ unsigned short BitBuffer = 0;
+ unsigned short AndMask = 0;
+ unsigned short OneByte = 0;
+
+ // Keep compiler happy for platforms where nResultByteSize is not used
+ nResultByteSize = nResultByteSize;
+
+#ifndef PLATFORM_LITTLE_ENDIAN
+ // Adjust the buffer pointer for big endian platforms
+ pbBuffer += (nResultByteSize - 1);
+#endif
+
+ // Copy whole bytes, if any
+ while(nBitLength > 8)
+ {
+ // Reload the bit buffer
+#ifdef PLATFORM_LITTLE_ENDIAN
+ OneByte = *pbBuffer++;
+#else
+ OneByte = *pbBuffer--;
+#endif
+ // Update the BitBuffer and AndMask for the bit array
+ BitBuffer = (BitBuffer >> 0x08) | (OneByte << nBitOffset);
+ AndMask = (AndMask >> 0x08) | (0x00FF << nBitOffset);
+
+ // Update the byte in the array
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
+
+ // Move byte positions and lengths
+ nBytePosition++;
+ nBitLength -= 0x08;
+ }
+
+ if(nBitLength != 0)
+ {
+ // Reload the bit buffer
+ OneByte = *pbBuffer;
+
+ // Update the AND mask for the last bit
+ BitBuffer = (BitBuffer >> 0x08) | (OneByte << nBitOffset);
+ AndMask = (AndMask >> 0x08) | (SetBitsMask[nBitLength] << nBitOffset);
+
+ // Update the byte in the array
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
+
+ // Update the next byte, if needed
+ if(AndMask & 0xFF00)
+ {
+ nBytePosition++;
+ BitBuffer >>= 0x08;
+ AndMask >>= 0x08;
+
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Support for hash table
+
+// Returns a hash table entry in the following order:
+// 1) A hash table entry with the neutral locale
+// 2) A hash table entry with any other locale
+// 3) NULL
+static TMPQHash * GetHashEntryAny(TMPQArchive * ha, const char * szFileName)
+{
+ TMPQHash * pHashNeutral = NULL;
+ TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
+ TMPQHash * pHashAny = NULL;
+ TMPQHash * pHash = pFirstHash;
+
+ // Parse the found hashes
+ while(pHash != NULL)
+ {
+ // If we found neutral hash, remember it
+ if(pHash->lcLocale == 0)
+ pHashNeutral = pHash;
+ if(pHashAny == NULL)
+ pHashAny = pHash;
+
+ // Get the next hash entry for that file
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+
+ // At the end, return neutral hash (if found), otherwise NULL
+ return (pHashNeutral != NULL) ? pHashNeutral : pHashAny;
+}
+
+// Returns a hash table entry in the following order:
+// 1) A hash table entry with the preferred locale
+// 2) A hash table entry with the neutral locale
+// 3) NULL
+static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
+{
+ TMPQHash * pHashNeutral = NULL;
+ TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
+ TMPQHash * pHash = pFirstHash;
+
+ // Parse the found hashes
+ while(pHash != NULL)
+ {
+ // If the locales match, return it
+ if(pHash->lcLocale == lcLocale)
+ return pHash;
+
+ // If we found neutral hash, remember it
+ if(pHash->lcLocale == 0)
+ pHashNeutral = pHash;
+
+ // Get the next hash entry for that file
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+
+ // At the end, return neutral hash (if found), otherwise NULL
+ return pHashNeutral;
+}
+
+// Returns a hash table entry in the following order:
+// 1) A hash table entry with the preferred locale
+// 2) NULL
+static TMPQHash * GetHashEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
+{
+ TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
+ TMPQHash * pHash = pFirstHash;
+
+ // Parse the found hashes
+ while(pHash != NULL)
+ {
+ // If the locales match, return it
+ if(pHash->lcLocale == lcLocale)
+ return pHash;
+
+ // Get the next hash entry for that file
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+
+ // Not found
+ return NULL;
+}
+
+static TMPQHash * TranslateHashTable(
+ TMPQArchive * ha,
+ ULONGLONG * pcbTableSize)
+{
+ TMPQHash * pHashTable;
+ size_t HashTableSize;
+
+ // Allocate copy of the hash table
+ pHashTable = STORM_ALLOC(TMPQHash, ha->pHeader->dwHashTableSize);
+ if(pHashTable != NULL)
+ {
+ // Copy the hash table
+ HashTableSize = sizeof(TMPQHash) * ha->pHeader->dwHashTableSize;
+ memcpy(pHashTable, ha->pHashTable, HashTableSize);
+
+ // Give the size to the caller
+ if(pcbTableSize != NULL)
+ {
+ *pcbTableSize = (ULONGLONG)HashTableSize;
+ }
+ }
+
+ return pHashTable;
+}
+
+static TMPQBlock * TranslateBlockTable(
+ TMPQArchive * ha,
+ ULONGLONG * pcbTableSize,
+ bool * pbNeedHiBlockTable)
+{
+ TFileEntry * pFileEntry = ha->pFileTable;
+ TMPQBlock * pBlockTable;
+ TMPQBlock * pBlock;
+ size_t BlockTableSize;
+ bool bNeedHiBlockTable = false;
+
+ // Allocate copy of the hash table
+ pBlockTable = pBlock = STORM_ALLOC(TMPQBlock, ha->dwFileTableSize);
+ if(pBlockTable != NULL)
+ {
+ // Copy the block table
+ BlockTableSize = sizeof(TMPQBlock) * ha->dwFileTableSize;
+ for(DWORD i = 0; i < ha->dwFileTableSize; i++)
+ {
+ bNeedHiBlockTable = (pFileEntry->ByteOffset >> 32) ? true : false;
+ pBlock->dwFilePos = (DWORD)pFileEntry->ByteOffset;
+ pBlock->dwFSize = pFileEntry->dwFileSize;
+ pBlock->dwCSize = pFileEntry->dwCmpSize;
+ pBlock->dwFlags = pFileEntry->dwFlags;
+
+ pFileEntry++;
+ pBlock++;
+ }
+
+ // Give the size to the caller
+ if(pcbTableSize != NULL)
+ *pcbTableSize = (ULONGLONG)BlockTableSize;
+
+ if(pbNeedHiBlockTable != NULL)
+ *pbNeedHiBlockTable = bNeedHiBlockTable;
+ }
+
+ return pBlockTable;
+}
+
+static USHORT * TranslateHiBlockTable(
+ TMPQArchive * ha,
+ ULONGLONG * pcbTableSize)
+{
+ TFileEntry * pFileEntry = ha->pFileTable;
+ USHORT * pHiBlockTable;
+ USHORT * pHiBlock;
+ size_t HiBlockTableSize;
+
+ // Allocate copy of the hash table
+ pHiBlockTable = pHiBlock = STORM_ALLOC(USHORT, ha->dwFileTableSize);
+ if(pHiBlockTable != NULL)
+ {
+ // Copy the block table
+ HiBlockTableSize = sizeof(USHORT) * ha->dwFileTableSize;
+ for(DWORD i = 0; i < ha->dwFileTableSize; i++)
+ pHiBlock[i] = (USHORT)(pFileEntry[i].ByteOffset >> 0x20);
+
+ // Give the size to the caller
+ if(pcbTableSize != NULL)
+ *pcbTableSize = (ULONGLONG)HiBlockTableSize;
+ }
+
+ return pHiBlockTable;
+}
+
+//-----------------------------------------------------------------------------
+// General EXT table functions
+
+TMPQExtTable * LoadExtTable(
+ TMPQArchive * ha,
+ ULONGLONG ByteOffset,
+ size_t Size,
+ DWORD dwSignature,
+ DWORD dwKey)
+{
+ TMPQExtTable * pCompressed = NULL; // Compressed table
+ TMPQExtTable * pExtTable = NULL; // Uncompressed table
+
+ // Do nothing if the size is zero
+ if(ByteOffset != 0 && Size != 0)
+ {
+ // Allocate size for the compressed table
+ pExtTable = (TMPQExtTable *)STORM_ALLOC(BYTE, Size);
+ if(pExtTable != NULL)
+ {
+ // Load the table from the MPQ
+ ByteOffset += ha->MpqPos;
+ if(!FileStream_Read(ha->pStream, &ByteOffset, pExtTable, (DWORD)Size))
+ {
+ STORM_FREE(pExtTable);
+ return NULL;
+ }
+
+ // Swap the ext table header
+ BSWAP_ARRAY32_UNSIGNED(pExtTable, sizeof(TMPQExtTable));
+ if(pExtTable->dwSignature != dwSignature)
+ {
+ STORM_FREE(pExtTable);
+ return NULL;
+ }
+
+ // Decrypt the block
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
+ DecryptMpqBlock(pExtTable + 1, (DWORD)(Size - sizeof(TMPQExtTable)), dwKey);
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
+
+ // If the table is compressed, decompress it
+ if((pExtTable->dwDataSize + sizeof(TMPQExtTable)) > Size)
+ {
+ pCompressed = pExtTable;
+ pExtTable = (TMPQExtTable *)STORM_ALLOC(BYTE, sizeof(TMPQExtTable) + pCompressed->dwDataSize);
+ if(pExtTable != NULL)
+ {
+ int cbOutBuffer = (int)pCompressed->dwDataSize;
+ int cbInBuffer = (int)Size;
+
+ // Decompress the extended table
+ pExtTable->dwSignature = pCompressed->dwSignature;
+ pExtTable->dwVersion = pCompressed->dwVersion;
+ pExtTable->dwDataSize = pCompressed->dwDataSize;
+ if(!SCompDecompress2((char *)(pExtTable + 1), &cbOutBuffer, (char *)(pCompressed + 1), cbInBuffer))
+ {
+ STORM_FREE(pExtTable);
+ pExtTable = NULL;
+ }
+ }
+
+ // Free the compressed block
+ STORM_FREE(pCompressed);
+ }
+ }
+ }
+
+ // Return the decompressed table to the caller
+ return pExtTable;
+}
+
+// Used in MPQ Editor
+void FreeMpqBuffer(void * pvBuffer)
+{
+ STORM_FREE(pvBuffer);
+}
+
+static int SaveMpqTable(
+ TMPQArchive * ha,
+ void * pMpqTable,
+ ULONGLONG ByteOffset,
+ size_t Size,
+ unsigned char * md5,
+ DWORD dwKey,
+ bool bCompress)
+{
+ ULONGLONG FileOffset;
+ void * pCompressed = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Do we have to compress the table?
+ if(bCompress)
+ {
+ int cbOutBuffer = (int)Size;
+ int cbInBuffer = (int)Size;
+
+ // Allocate extra space for compressed table
+ pCompressed = STORM_ALLOC(BYTE, Size);
+ if(pCompressed == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Compress the table
+ SCompCompress((char *)pCompressed, &cbOutBuffer, (char *)pMpqTable, cbInBuffer, MPQ_COMPRESSION_ZLIB, 0, 0);
+
+ // If the compression failed, revert it. Otherwise, swap the tables
+ if(cbOutBuffer >= cbInBuffer)
+ {
+ STORM_FREE(pCompressed);
+ pCompressed = NULL;
+ }
+ else
+ {
+ pMpqTable = pCompressed;
+ }
+ }
+
+ // Encrypt the table
+ if(dwKey != 0)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
+ EncryptMpqBlock(pMpqTable, (DWORD)Size, dwKey);
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
+ }
+
+ // Calculate the MD5
+ if(md5 != NULL)
+ {
+ CalculateDataBlockHash(pMpqTable, (DWORD)Size, md5);
+ }
+
+ // Save the table to the MPQ
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
+ FileOffset = ha->MpqPos + ByteOffset;
+ if(!FileStream_Write(ha->pStream, &FileOffset, pMpqTable, (DWORD)Size))
+ nError = GetLastError();
+
+ // Free the compressed table, if any
+ if(pCompressed != NULL)
+ STORM_FREE(pCompressed);
+ return nError;
+}
+
+static int SaveExtTable(
+ TMPQArchive * ha,
+ TMPQExtTable * pExtTable,
+ ULONGLONG ByteOffset,
+ DWORD dwTableSize,
+ unsigned char * md5,
+ DWORD dwKey,
+ bool bCompress,
+ LPDWORD pcbTotalSize)
+{
+ ULONGLONG FileOffset;
+ TMPQExtTable * pCompressed = NULL;
+ DWORD cbTotalSize = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Do we have to compress the table?
+ if(bCompress)
+ {
+ int cbOutBuffer = (int)dwTableSize;
+ int cbInBuffer = (int)dwTableSize;
+
+ // Allocate extra space for compressed table
+ pCompressed = (TMPQExtTable *)STORM_ALLOC(BYTE, dwTableSize);
+ if(pCompressed == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Compress the table
+ pCompressed->dwSignature = pExtTable->dwSignature;
+ pCompressed->dwVersion = pExtTable->dwVersion;
+ pCompressed->dwDataSize = pExtTable->dwDataSize;
+ SCompCompress((char *)(pCompressed + 1), &cbOutBuffer, (char *)(pExtTable + 1), cbInBuffer, MPQ_COMPRESSION_ZLIB, 0, 0);
+
+ // If the compression failed, revert it. Otherwise, swap the tables
+ if(cbOutBuffer >= cbInBuffer)
+ {
+ STORM_FREE(pCompressed);
+ pCompressed = NULL;
+ }
+ else
+ {
+ pExtTable = pCompressed;
+ }
+ }
+
+ // Encrypt the table
+ if(dwKey != 0)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
+ EncryptMpqBlock(pExtTable + 1, (DWORD)(dwTableSize - sizeof(TMPQExtTable)), dwKey);
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
+ }
+
+ // Calculate the MD5 of the table after
+ if(md5 != NULL)
+ {
+ CalculateDataBlockHash(pExtTable, dwTableSize, md5);
+ }
+
+ // Save the table to the MPQ
+ FileOffset = ha->MpqPos + ByteOffset;
+ if(FileStream_Write(ha->pStream, &FileOffset, pExtTable, dwTableSize))
+ cbTotalSize += dwTableSize;
+ else
+ nError = GetLastError();
+
+ // We have to write raw data MD5
+ if(nError == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
+ {
+ nError = WriteMemDataMD5(ha->pStream,
+ FileOffset,
+ pExtTable,
+ dwTableSize,
+ ha->pHeader->dwRawChunkSize,
+ &cbTotalSize);
+ }
+
+ // Give the total written size, if needed
+ if(pcbTotalSize != NULL)
+ *pcbTotalSize = cbTotalSize;
+
+ // Free the compressed table, if any
+ if(pCompressed != NULL)
+ STORM_FREE(pCompressed);
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Support for HET table
+
+static void CreateHetHeader(
+ TMPQHetTable * pHetTable,
+ PHET_TABLE_HEADER pHetHeader)
+{
+ // Fill the BET header
+ pHetHeader->dwMaxFileCount = pHetTable->dwMaxFileCount;
+ pHetHeader->dwHashTableSize = pHetTable->dwHashTableSize;
+ pHetHeader->dwHashEntrySize = pHetTable->dwHashBitSize;
+ pHetHeader->dwIndexSizeTotal = GetNecessaryBitCount(pHetTable->dwMaxFileCount);
+ pHetHeader->dwIndexSizeExtra = 0;
+ pHetHeader->dwIndexSize = pHetHeader->dwIndexSizeTotal;
+ pHetHeader->dwIndexTableSize = ((pHetHeader->dwIndexSizeTotal * pHetTable->dwHashTableSize) + 7) / 8;
+
+ // Calculate the total size needed for holding HET table
+ pHetHeader->dwTableSize = sizeof(HET_TABLE_HEADER) +
+ pHetHeader->dwHashTableSize +
+ pHetHeader->dwIndexTableSize;
+}
+
+TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bCreateEmpty)
+{
+ TMPQHetTable * pHetTable;
+
+ pHetTable = STORM_ALLOC(TMPQHetTable, 1);
+ if(pHetTable != NULL)
+ {
+ pHetTable->dwIndexSizeTotal = 0;
+ pHetTable->dwIndexSizeExtra = 0;
+ pHetTable->dwIndexSize = pHetTable->dwIndexSizeTotal;
+ pHetTable->dwMaxFileCount = dwMaxFileCount;
+ pHetTable->dwHashTableSize = (dwMaxFileCount * 4 / 3);
+ pHetTable->dwHashBitSize = dwHashBitSize;
+
+ // Size of one index is calculated from max file count
+ pHetTable->dwIndexSizeTotal = GetNecessaryBitCount(dwMaxFileCount);
+ pHetTable->dwIndexSizeExtra = 0;
+ pHetTable->dwIndexSize = pHetTable->dwIndexSizeTotal;
+
+ // Allocate hash table
+ pHetTable->pHetHashes = STORM_ALLOC(BYTE, pHetTable->dwHashTableSize);
+ memset(pHetTable->pHetHashes, 0, pHetTable->dwHashTableSize);
+
+ // If we shall create empty HET table, we have to allocate empty block index table as well
+ if(bCreateEmpty)
+ pHetTable->pBetIndexes = CreateBitArray(pHetTable->dwHashTableSize * pHetTable->dwIndexSizeTotal, 0xFF);
+
+ // Calculate masks
+ pHetTable->AndMask64 = 0;
+ if(dwHashBitSize != 0x40)
+ pHetTable->AndMask64 = (ULONGLONG)1 << dwHashBitSize;
+ pHetTable->AndMask64--;
+
+ pHetTable->OrMask64 = (ULONGLONG)1 << (dwHashBitSize - 1);
+ }
+
+ return pHetTable;
+}
+
+static TMPQHetTable * TranslateHetTable(TMPQExtTable * pExtTable)
+{
+ HET_TABLE_HEADER HetHeader;
+ TMPQHetTable * pHetTable = NULL;
+ LPBYTE pbSrcData = (LPBYTE)(pExtTable + 1);
+
+ // Sanity check
+ assert(pExtTable->dwSignature == HET_TABLE_SIGNATURE);
+ assert(pExtTable->dwVersion == 1);
+
+ // Verify size of the HET table
+ if(pExtTable != NULL && pExtTable->dwDataSize >= sizeof(HET_TABLE_HEADER))
+ {
+ // Copy the table header in order to have it aligned and swapped
+ memcpy(&HetHeader, pbSrcData, sizeof(HET_TABLE_HEADER));
+ BSWAP_ARRAY32_UNSIGNED(&HetHeader, sizeof(HET_TABLE_HEADER));
+ pbSrcData += sizeof(HET_TABLE_HEADER);
+
+ // Verify the size of the table in the header
+ if(HetHeader.dwTableSize == pExtTable->dwDataSize)
+ {
+ // Create translated table
+ pHetTable = CreateHetTable(HetHeader.dwMaxFileCount, HetHeader.dwHashEntrySize, false);
+ if(pHetTable != NULL)
+ {
+ // Copy the hash table size, index size and extra bits from the HET header
+ pHetTable->dwHashTableSize = HetHeader.dwHashTableSize;
+ pHetTable->dwIndexSizeTotal = HetHeader.dwIndexSizeTotal;
+ pHetTable->dwIndexSizeExtra = HetHeader.dwIndexSizeExtra;
+
+ // Fill the hash table
+ if(pHetTable->pHetHashes != NULL)
+ memcpy(pHetTable->pHetHashes, pbSrcData, pHetTable->dwHashTableSize);
+ pbSrcData += pHetTable->dwHashTableSize;
+
+ // Copy the block index table
+ pHetTable->pBetIndexes = CreateBitArray(HetHeader.dwIndexTableSize * 8, 0xFF);
+ if(pHetTable->pBetIndexes != NULL)
+ memcpy(pHetTable->pBetIndexes->Elements, pbSrcData, HetHeader.dwIndexTableSize);
+ pbSrcData += HetHeader.dwIndexTableSize;
+ }
+ }
+ }
+
+ return pHetTable;
+}
+
+static TMPQExtTable * TranslateHetTable(TMPQHetTable * pHetTable, ULONGLONG * pcbHetTable)
+{
+ TMPQExtTable * pExtTable = NULL;
+ HET_TABLE_HEADER HetHeader;
+ LPBYTE pbLinearTable = NULL;
+ LPBYTE pbTrgData;
+ size_t HetTableSize;
+
+ // Prepare header of the HET table
+ CreateHetHeader(pHetTable, &HetHeader);
+
+ // Calculate the total size needed for holding the encrypted HET table
+ HetTableSize = HetHeader.dwTableSize;
+
+ // Allocate space for the linear table
+ pbLinearTable = STORM_ALLOC(BYTE, sizeof(TMPQExtTable) + HetTableSize);
+ if(pbLinearTable != NULL)
+ {
+ // Create the common ext table header
+ pExtTable = (TMPQExtTable *)pbLinearTable;
+ pExtTable->dwSignature = HET_TABLE_SIGNATURE;
+ pExtTable->dwVersion = 1;
+ pExtTable->dwDataSize = (DWORD)HetTableSize;
+ pbTrgData = (LPBYTE)(pExtTable + 1);
+
+ // Copy the HET table header
+ memcpy(pbTrgData, &HetHeader, sizeof(HET_TABLE_HEADER));
+ BSWAP_ARRAY32_UNSIGNED(pbTrgData, sizeof(HET_TABLE_HEADER));
+ pbTrgData += sizeof(HET_TABLE_HEADER);
+
+ // Copy the array of HET hashes
+ memcpy(pbTrgData, pHetTable->pHetHashes, pHetTable->dwHashTableSize);
+ pbTrgData += pHetTable->dwHashTableSize;
+
+ // Copy the bit array of BET indexes
+ memcpy(pbTrgData, pHetTable->pBetIndexes->Elements, HetHeader.dwIndexTableSize);
+
+ // Calculate the total size of the table, including the TMPQExtTable
+ if(pcbHetTable != NULL)
+ {
+ *pcbHetTable = (ULONGLONG)(sizeof(TMPQExtTable) + HetTableSize);
+ }
+ }
+
+ return pExtTable;
+}
+
+DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName)
+{
+ TMPQHetTable * pHetTable = ha->pHetTable;
+ ULONGLONG FileNameHash;
+ ULONGLONG AndMask64;
+ ULONGLONG OrMask64;
+ ULONGLONG BetHash;
+ DWORD StartIndex;
+ DWORD Index;
+ BYTE HetHash; // Upper 8 bits of the masked file name hash
+
+ // Do nothing if the MPQ has no HET table
+ assert(ha->pHetTable != NULL);
+
+ // Calculate 64-bit hash of the file name
+ AndMask64 = pHetTable->AndMask64;
+ OrMask64 = pHetTable->OrMask64;
+ FileNameHash = (HashStringJenkins(szFileName) & AndMask64) | OrMask64;
+
+ // Split the file name hash into two parts:
+ // Part 1: The highest 8 bits of the name hash
+ // Part 2: The rest of the name hash (without the highest 8 bits)
+ HetHash = (BYTE)(FileNameHash >> (pHetTable->dwHashBitSize - 8));
+ BetHash = FileNameHash & (AndMask64 >> 0x08);
+
+ // Calculate the starting index to the hash table
+ StartIndex = Index = (DWORD)(FileNameHash % pHetTable->dwHashTableSize);
+
+ // Go through HET table until we find a terminator
+ while(pHetTable->pHetHashes[Index] != HET_ENTRY_FREE)
+ {
+ // Did we find match ?
+ if(pHetTable->pHetHashes[Index] == HetHash)
+ {
+ DWORD dwFileIndex = 0;
+
+ // Get the index of the BetHash
+ pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * Index,
+ pHetTable->dwIndexSize,
+ &dwFileIndex,
+ 4);
+
+ //
+ // TODO: This condition only happens when we are opening a MPQ
+ // where some files were deleted by StormLib. Perhaps
+ // we should not allow shrinking of the file table in MPQs v 4.0?
+ // assert(dwFileIndex <= ha->dwFileTableSize);
+ //
+
+ // Verify the BetHash against the entry in the table of BET hashes
+ if(dwFileIndex <= ha->dwFileTableSize && ha->pFileTable[dwFileIndex].BetHash == BetHash)
+ return dwFileIndex;
+ }
+
+ // Move to the next entry in the primary search table
+ // If we came to the start index again, we are done
+ Index = (Index + 1) % pHetTable->dwHashTableSize;
+ if(Index == StartIndex)
+ break;
+ }
+
+ // File not found
+ return HASH_ENTRY_FREE;
+}
+
+DWORD AllocateHetEntry(
+ TMPQArchive * ha,
+ TFileEntry * pFileEntry)
+{
+ TMPQHetTable * pHetTable = ha->pHetTable;
+ ULONGLONG FileNameHash;
+ ULONGLONG AndMask64;
+ ULONGLONG OrMask64;
+ ULONGLONG BetHash;
+ DWORD FreeHetIndex = HASH_ENTRY_FREE;
+ DWORD dwFileIndex;
+ DWORD StartIndex;
+ DWORD Index;
+ BYTE HetHash; // Upper 8 bits of the masked file name hash
+
+ // Do nothing if the MPQ has no HET table
+ assert(ha->pHetTable != NULL);
+
+ // Calculate 64-bit hash of the file name
+ AndMask64 = pHetTable->AndMask64;
+ OrMask64 = pHetTable->OrMask64;
+ FileNameHash = (HashStringJenkins(pFileEntry->szFileName) & AndMask64) | OrMask64;
+
+ // Calculate the starting index to the hash table
+ StartIndex = Index = (DWORD)(FileNameHash % pHetTable->dwHashTableSize);
+
+ // Split the file name hash into two parts:
+ // Part 1: The highest 8 bits of the name hash
+ // Part 2: The rest of the name hash (without the highest 8 bits)
+ HetHash = (BYTE)(FileNameHash >> (pHetTable->dwHashBitSize - 8));
+ BetHash = FileNameHash & (AndMask64 >> 0x08);
+
+ // Go through HET table until we find a terminator
+ for(;;)
+ {
+ // Check for entries that might have been deleted
+ if(pHetTable->pHetHashes[Index] == HET_ENTRY_DELETED)
+ {
+ DWORD dwInvalidBetIndex = (1 << pHetTable->dwIndexSizeTotal) - 1;
+ DWORD dwBetIndex = 0;
+
+ // Verify the BET index. If it's really free, we can use it
+ dwFileIndex = (DWORD)(pFileEntry - ha->pFileTable);
+ pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * Index,
+ pHetTable->dwIndexSize,
+ &dwBetIndex,
+ 4);
+
+ if(dwBetIndex == dwInvalidBetIndex)
+ {
+ FreeHetIndex = Index;
+ break;
+ }
+ }
+
+ // Is that entry free ?
+ if(pHetTable->pHetHashes[Index] == HET_ENTRY_FREE)
+ {
+ FreeHetIndex = Index;
+ break;
+ }
+
+ // Move to the next entry in the primary search table
+ // If we came to the start index again, we are done
+ Index = (Index + 1) % pHetTable->dwHashTableSize;
+ if(Index == StartIndex)
+ return HASH_ENTRY_FREE;
+ }
+
+ // Fill the HET table entry
+ dwFileIndex = (DWORD)(pFileEntry - ha->pFileTable);
+ pHetTable->pHetHashes[FreeHetIndex] = HetHash;
+ pHetTable->pBetIndexes->SetBits(pHetTable->dwIndexSizeTotal * FreeHetIndex,
+ pHetTable->dwIndexSize,
+ &dwFileIndex,
+ 4);
+ // Fill the file entry
+ pFileEntry->BetHash = BetHash;
+ pFileEntry->dwHetIndex = FreeHetIndex;
+ return FreeHetIndex;
+}
+
+void FreeHetTable(TMPQHetTable * pHetTable)
+{
+ if(pHetTable != NULL)
+ {
+ if(pHetTable->pHetHashes != NULL)
+ STORM_FREE(pHetTable->pHetHashes);
+ if(pHetTable->pBetIndexes != NULL)
+ STORM_FREE(pHetTable->pBetIndexes);
+
+ STORM_FREE(pHetTable);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Support for BET table
+
+static void CreateBetHeader(
+ TMPQArchive * ha,
+ PBET_TABLE_HEADER pBetHeader)
+{
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pFileEntry;
+ ULONGLONG MaxByteOffset = 0;
+ DWORD FlagArray[MAX_FLAG_INDEX];
+ DWORD dwMaxFlagIndex = 0;
+ DWORD dwMaxFileSize = 0;
+ DWORD dwMaxCmpSize = 0;
+ DWORD dwFlagIndex;
+
+ // Initialize array of flag combinations
+ InitFileFlagArray(FlagArray);
+
+ // Get the maximum values for the BET table
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // Highest file position in the MPQ
+ if(pFileEntry->ByteOffset > MaxByteOffset)
+ MaxByteOffset = pFileEntry->ByteOffset;
+
+ // Biggest file size
+ if(pFileEntry->dwFileSize > dwMaxFileSize)
+ dwMaxFileSize = pFileEntry->dwFileSize;
+
+ // Biggest compressed size
+ if(pFileEntry->dwCmpSize > dwMaxCmpSize)
+ dwMaxCmpSize = pFileEntry->dwCmpSize;
+
+ // Check if this flag was there before
+ dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags);
+ if(dwFlagIndex > dwMaxFlagIndex)
+ dwMaxFlagIndex = dwFlagIndex;
+ }
+
+ // Now save bit count for every piece of file information
+ pBetHeader->dwBitIndex_FilePos = 0;
+ pBetHeader->dwBitCount_FilePos = GetNecessaryBitCount(MaxByteOffset);
+
+ pBetHeader->dwBitIndex_FileSize = pBetHeader->dwBitIndex_FilePos + pBetHeader->dwBitCount_FilePos;
+ pBetHeader->dwBitCount_FileSize = GetNecessaryBitCount(dwMaxFileSize);
+
+ pBetHeader->dwBitIndex_CmpSize = pBetHeader->dwBitIndex_FileSize + pBetHeader->dwBitCount_FileSize;
+ pBetHeader->dwBitCount_CmpSize = GetNecessaryBitCount(dwMaxCmpSize);
+
+ pBetHeader->dwBitIndex_FlagIndex = pBetHeader->dwBitIndex_CmpSize + pBetHeader->dwBitCount_CmpSize;
+ pBetHeader->dwBitCount_FlagIndex = GetNecessaryBitCount(dwMaxFlagIndex + 1);
+
+ pBetHeader->dwBitIndex_Unknown = pBetHeader->dwBitIndex_FlagIndex + pBetHeader->dwBitCount_FlagIndex;
+ pBetHeader->dwBitCount_Unknown = 0;
+
+ // Calculate the total size of one entry
+ pBetHeader->dwTableEntrySize = pBetHeader->dwBitCount_FilePos +
+ pBetHeader->dwBitCount_FileSize +
+ pBetHeader->dwBitCount_CmpSize +
+ pBetHeader->dwBitCount_FlagIndex +
+ pBetHeader->dwBitCount_Unknown;
+
+ // Save the file count and flag count
+ pBetHeader->dwFileCount = ha->dwFileTableSize;
+ pBetHeader->dwFlagCount = dwMaxFlagIndex + 1;
+ pBetHeader->dwUnknown08 = 0x10;
+
+ // Save the total size of the BET hash
+ pBetHeader->dwBetHashSizeTotal = ha->pHetTable->dwHashBitSize - 0x08;
+ pBetHeader->dwBetHashSizeExtra = 0;
+ pBetHeader->dwBetHashSize = pBetHeader->dwBetHashSizeTotal;
+ pBetHeader->dwBetHashArraySize = ((pBetHeader->dwBetHashSizeTotal * pBetHeader->dwFileCount) + 7) / 8;
+
+ // Save the total table size
+ pBetHeader->dwTableSize = sizeof(BET_TABLE_HEADER) +
+ pBetHeader->dwFlagCount * sizeof(DWORD) +
+ ((pBetHeader->dwTableEntrySize * pBetHeader->dwFileCount) + 7) / 8 +
+ pBetHeader->dwBetHashArraySize;
+}
+
+TMPQBetTable * CreateBetTable(DWORD dwFileCount)
+{
+ TMPQBetTable * pBetTable;
+
+ // Allocate BET table
+ pBetTable = STORM_ALLOC(TMPQBetTable, 1);
+ if(pBetTable != NULL)
+ {
+ memset(pBetTable, 0, sizeof(TMPQBetTable));
+ pBetTable->dwFileCount = dwFileCount;
+ }
+
+ return pBetTable;
+}
+
+static TMPQBetTable * TranslateBetTable(
+ TMPQArchive * ha,
+ TMPQExtTable * pExtTable)
+{
+ BET_TABLE_HEADER BetHeader;
+ TMPQBetTable * pBetTable = NULL;
+ LPBYTE pbSrcData = (LPBYTE)(pExtTable + 1);
+ DWORD LengthInBytes;
+
+ // Sanity check
+ assert(pExtTable->dwSignature == BET_TABLE_SIGNATURE);
+ assert(pExtTable->dwVersion == 1);
+ assert(ha->pHetTable != NULL);
+ ha = ha;
+
+ // Verify size of the HET table
+ if(pExtTable != NULL && pExtTable->dwDataSize >= sizeof(BET_TABLE_HEADER))
+ {
+ // Copy the table header in order to have it aligned and swapped
+ memcpy(&BetHeader, pbSrcData, sizeof(BET_TABLE_HEADER));
+ BSWAP_ARRAY32_UNSIGNED(&BetHeader, sizeof(BET_TABLE_HEADER));
+ pbSrcData += sizeof(BET_TABLE_HEADER);
+
+ // Some MPQs affected by a bug in StormLib have pBetTable->dwFileCount
+ // greater than ha->dwMaxFileCount
+ if(BetHeader.dwFileCount > ha->dwMaxFileCount)
+ return NULL;
+
+ // Verify the size of the table in the header
+ if(BetHeader.dwTableSize == pExtTable->dwDataSize)
+ {
+ // Create translated table
+ pBetTable = CreateBetTable(BetHeader.dwFileCount);
+ if(pBetTable != NULL)
+ {
+ // Copy the variables from the header to the BetTable
+ pBetTable->dwTableEntrySize = BetHeader.dwTableEntrySize;
+ pBetTable->dwBitIndex_FilePos = BetHeader.dwBitIndex_FilePos;
+ pBetTable->dwBitIndex_FileSize = BetHeader.dwBitIndex_FileSize;
+ pBetTable->dwBitIndex_CmpSize = BetHeader.dwBitIndex_CmpSize;
+ pBetTable->dwBitIndex_FlagIndex = BetHeader.dwBitIndex_FlagIndex;
+ pBetTable->dwBitIndex_Unknown = BetHeader.dwBitIndex_Unknown;
+ pBetTable->dwBitCount_FilePos = BetHeader.dwBitCount_FilePos;
+ pBetTable->dwBitCount_FileSize = BetHeader.dwBitCount_FileSize;
+ pBetTable->dwBitCount_CmpSize = BetHeader.dwBitCount_CmpSize;
+ pBetTable->dwBitCount_FlagIndex = BetHeader.dwBitCount_FlagIndex;
+ pBetTable->dwBitCount_Unknown = BetHeader.dwBitCount_Unknown;
+
+ // Since we don't know what the "unknown" is, we'll assert when it's nonzero
+ assert(pBetTable->dwBitCount_Unknown == 0);
+
+ // Allocate array for flags
+ if(BetHeader.dwFlagCount != 0)
+ {
+ // Allocate array for file flags and load it
+ pBetTable->pFileFlags = STORM_ALLOC(DWORD, BetHeader.dwFlagCount);
+ if(pBetTable->pFileFlags != NULL)
+ {
+ LengthInBytes = BetHeader.dwFlagCount * sizeof(DWORD);
+ memcpy(pBetTable->pFileFlags, pbSrcData, LengthInBytes);
+ BSWAP_ARRAY32_UNSIGNED(pBetTable->pFileFlags, LengthInBytes);
+ pbSrcData += LengthInBytes;
+ }
+
+ // Save the number of flags
+ pBetTable->dwFlagCount = BetHeader.dwFlagCount;
+ }
+
+ // Load the bit-based file table
+ pBetTable->pFileTable = CreateBitArray(pBetTable->dwTableEntrySize * BetHeader.dwFileCount, 0);
+ LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
+ if(pBetTable->pFileTable != NULL)
+ memcpy(pBetTable->pFileTable->Elements, pbSrcData, LengthInBytes);
+ pbSrcData += LengthInBytes;
+
+ // Fill the sizes of BET hash
+ pBetTable->dwBetHashSizeTotal = BetHeader.dwBetHashSizeTotal;
+ pBetTable->dwBetHashSizeExtra = BetHeader.dwBetHashSizeExtra;
+ pBetTable->dwBetHashSize = BetHeader.dwBetHashSize;
+
+ // Create and load the array of BET hashes
+ pBetTable->pBetHashes = CreateBitArray(pBetTable->dwBetHashSizeTotal * BetHeader.dwFileCount, 0);
+ LengthInBytes = (pBetTable->pBetHashes->NumberOfBits + 7) / 8;
+ if(pBetTable->pBetHashes != NULL)
+ memcpy(pBetTable->pBetHashes->Elements, pbSrcData, LengthInBytes);
+ pbSrcData += BetHeader.dwBetHashArraySize;
+
+ // Dump both tables
+// DumpHetAndBetTable(ha->pHetTable, pBetTable);
+ }
+ }
+ }
+
+ return pBetTable;
+}
+
+TMPQExtTable * TranslateBetTable(
+ TMPQArchive * ha,
+ ULONGLONG * pcbBetTable)
+{
+ TMPQExtTable * pExtTable = NULL;
+ BET_TABLE_HEADER BetHeader;
+ TBitArray * pBitArray = NULL;
+ LPBYTE pbLinearTable = NULL;
+ LPBYTE pbTrgData;
+ size_t BetTableSize;
+ DWORD LengthInBytes;
+ DWORD FlagArray[MAX_FLAG_INDEX];
+ DWORD i;
+
+ // Calculate the bit sizes of various entries
+ InitFileFlagArray(FlagArray);
+ CreateBetHeader(ha, &BetHeader);
+
+ // Calculate the size of the BET table
+ BetTableSize = sizeof(BET_TABLE_HEADER) +
+ BetHeader.dwFlagCount * sizeof(DWORD) +
+ ((BetHeader.dwTableEntrySize * BetHeader.dwFileCount) + 7) / 8 +
+ BetHeader.dwBetHashArraySize;
+
+ // Allocate space
+ pbLinearTable = STORM_ALLOC(BYTE, sizeof(TMPQExtTable) + BetTableSize);
+ if(pbLinearTable != NULL)
+ {
+ // Create the common ext table header
+ pExtTable = (TMPQExtTable *)pbLinearTable;
+ pExtTable->dwSignature = BET_TABLE_SIGNATURE;
+ pExtTable->dwVersion = 1;
+ pExtTable->dwDataSize = (DWORD)BetTableSize;
+ pbTrgData = (LPBYTE)(pExtTable + 1);
+
+ // Copy the BET table header
+ memcpy(pbTrgData, &BetHeader, sizeof(BET_TABLE_HEADER));
+ BSWAP_ARRAY32_UNSIGNED(pbTrgData, sizeof(BET_TABLE_HEADER));
+ pbTrgData += sizeof(BET_TABLE_HEADER);
+
+ // Save the bit-based block table
+ pBitArray = CreateBitArray(BetHeader.dwFileCount * BetHeader.dwTableEntrySize, 0);
+ if(pBitArray != NULL)
+ {
+ TFileEntry * pFileEntry = ha->pFileTable;
+ DWORD dwFlagIndex = 0;
+ DWORD nBitOffset = 0;
+
+ // Construct the array of flag values and bit-based file table
+ for(i = 0; i < BetHeader.dwFileCount; i++, pFileEntry++)
+ {
+ //
+ // Note: Blizzard MPQs contain valid values even for non-existant files
+ // (FilePos, FileSize, CmpSize and FlagIndex)
+ // Note: If flags is zero, it must be in the flag table too !!!
+ //
+
+ // Save the byte offset
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FilePos,
+ BetHeader.dwBitCount_FilePos,
+ &pFileEntry->ByteOffset,
+ 8);
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FileSize,
+ BetHeader.dwBitCount_FileSize,
+ &pFileEntry->dwFileSize,
+ 4);
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_CmpSize,
+ BetHeader.dwBitCount_CmpSize,
+ &pFileEntry->dwCmpSize,
+ 4);
+
+ // Save the flag index
+ dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags);
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FlagIndex,
+ BetHeader.dwBitCount_FlagIndex,
+ &dwFlagIndex,
+ 4);
+
+ // Move the bit offset
+ nBitOffset += BetHeader.dwTableEntrySize;
+ }
+
+ // Write the array of flags
+ LengthInBytes = BetHeader.dwFlagCount * sizeof(DWORD);
+ memcpy(pbTrgData, FlagArray, LengthInBytes);
+ BSWAP_ARRAY32_UNSIGNED(pbTrgData, LengthInBytes);
+ pbTrgData += LengthInBytes;
+
+ // Write the bit-based block table
+ LengthInBytes = (pBitArray->NumberOfBits + 7) / 8;
+ memcpy(pbTrgData, pBitArray->Elements, LengthInBytes);
+ pbTrgData += LengthInBytes;
+
+ // Free the bit array
+ STORM_FREE(pBitArray);
+ }
+
+ // Create bit array for BET hashes
+ pBitArray = CreateBitArray(BetHeader.dwBetHashSizeTotal * BetHeader.dwFileCount, 0);
+ if(pBitArray != NULL)
+ {
+ TFileEntry * pFileEntry = ha->pFileTable;
+ ULONGLONG AndMask64 = ha->pHetTable->AndMask64;
+ ULONGLONG OrMask64 = ha->pHetTable->OrMask64;
+
+ for(i = 0; i < BetHeader.dwFileCount; i++)
+ {
+ ULONGLONG FileNameHash = 0;
+
+ // Calculate 64-bit hash of the file name
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->szFileName != NULL)
+ {
+ FileNameHash = (HashStringJenkins(pFileEntry->szFileName) & AndMask64) | OrMask64;
+ FileNameHash = FileNameHash & (AndMask64 >> 0x08);
+ }
+
+ // Insert the name hash to the bit array
+ pBitArray->SetBits(BetHeader.dwBetHashSizeTotal * i,
+ BetHeader.dwBetHashSize,
+ &FileNameHash,
+ 8);
+
+ // Move to the next file entry
+ pFileEntry++;
+ }
+
+ // Write the array of BET hashes
+ LengthInBytes = (pBitArray->NumberOfBits + 7) / 8;
+ memcpy(pbTrgData, pBitArray->Elements, LengthInBytes);
+ pbTrgData += LengthInBytes;
+
+ // Free the bit array
+ STORM_FREE(pBitArray);
+ }
+
+ // Write the size of the BET table in the MPQ
+ if(pcbBetTable != NULL)
+ {
+ *pcbBetTable = (ULONGLONG)(sizeof(TMPQExtTable) + BetTableSize);
+ }
+ }
+
+ return pExtTable;
+}
+
+void FreeBetTable(TMPQBetTable * pBetTable)
+{
+ if(pBetTable != NULL)
+ {
+ if(pBetTable->pFileTable != NULL)
+ STORM_FREE(pBetTable->pFileTable);
+ if(pBetTable->pFileFlags != NULL)
+ STORM_FREE(pBetTable->pFileFlags);
+ if(pBetTable->pBetHashes != NULL)
+ STORM_FREE(pBetTable->pBetHashes);
+
+ STORM_FREE(pBetTable);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Support for file table
+
+TFileEntry * GetFileEntryAny(TMPQArchive * ha, const char * szFileName)
+{
+ TMPQHash * pHash;
+ DWORD dwFileIndex;
+
+ // If we have HET table in the MPQ, try to find the file in HET table
+ if(ha->pHetTable != NULL)
+ {
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
+ if(dwFileIndex != HASH_ENTRY_FREE)
+ return ha->pFileTable + dwFileIndex;
+ }
+
+ // Otherwise, perform the file search in the classic hash table
+ if(ha->pHashTable != NULL)
+ {
+ pHash = GetHashEntryAny(ha, szFileName);
+ if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
+ return ha->pFileTable + pHash->dwBlockIndex;
+ }
+
+ // Not found
+ return NULL;
+}
+
+TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
+{
+ TMPQHash * pHash;
+ DWORD dwFileIndex;
+
+ // If we have HET table in the MPQ, try to find the file in HET table
+ if(ha->pHetTable != NULL)
+ {
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
+ if(dwFileIndex != HASH_ENTRY_FREE)
+ return ha->pFileTable + dwFileIndex;
+ }
+
+ // Otherwise, perform the file search in the classic hash table
+ if(ha->pHashTable != NULL)
+ {
+ pHash = GetHashEntryLocale(ha, szFileName, lcLocale);
+ if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
+ return ha->pFileTable + pHash->dwBlockIndex;
+ }
+
+ // Not found
+ return NULL;
+}
+
+TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
+{
+ TMPQHash * pHash;
+ DWORD dwFileIndex;
+
+ // If we have HET table in the MPQ, try to find the file in HET table
+ if(ha->pHetTable != NULL)
+ {
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
+ if(dwFileIndex != HASH_ENTRY_FREE)
+ return ha->pFileTable + dwFileIndex;
+ }
+
+ // Otherwise, perform the file search in the classic hash table
+ if(ha->pHashTable != NULL)
+ {
+ pHash = GetHashEntryExact(ha, szFileName, lcLocale);
+ if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
+ return ha->pFileTable + pHash->dwBlockIndex;
+ }
+
+ // Not found
+ return NULL;
+}
+
+TFileEntry * GetFileEntryByIndex(TMPQArchive * ha, DWORD dwIndex)
+{
+ // For MPQs with classic hash table
+ if(dwIndex < ha->dwFileTableSize)
+ return ha->pFileTable + dwIndex;
+ return NULL;
+}
+
+void AllocateFileName(TFileEntry * pFileEntry, const char * szFileName)
+{
+ // Sanity check
+ assert(pFileEntry != NULL);
+
+ // If the file name is pseudo file name, free it at this point
+ if(IsPseudoFileName(pFileEntry->szFileName, NULL))
+ {
+ if(pFileEntry->szFileName != NULL)
+ STORM_FREE(pFileEntry->szFileName);
+ pFileEntry->szFileName = NULL;
+ }
+
+ // Only allocate new file name if it's not there yet
+ if(pFileEntry->szFileName == NULL)
+ {
+ pFileEntry->szFileName = STORM_ALLOC(char, strlen(szFileName) + 1);
+ if(pFileEntry->szFileName != NULL)
+ strcpy(pFileEntry->szFileName, szFileName);
+ }
+}
+
+
+// Finds a free file entry. Does NOT increment table size.
+TFileEntry * FindFreeFileEntry(TMPQArchive * ha)
+{
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pFreeEntry = NULL;
+ TFileEntry * pFileEntry;
+
+ // Try to find a free entry
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // If that entry is free, we reuse it
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
+ {
+ pFreeEntry = pFileEntry;
+ break;
+ }
+
+ //
+ // Note: Files with "delete marker" are not deleted.
+ // Don't consider them free entries
+ //
+ }
+
+ // Do we have a deleted entry?
+ if(pFreeEntry != NULL)
+ {
+ ClearFileEntry(ha, pFreeEntry);
+ return pFreeEntry;
+ }
+
+ // If no file entry within the existing file table is free,
+ // we try the reserve space after current file table
+ if(ha->dwFileTableSize < ha->dwMaxFileCount)
+ return ha->pFileTable + ha->dwFileTableSize;
+
+ // If we reached maximum file count, we cannot add more files to the MPQ
+ assert(ha->dwFileTableSize == ha->dwMaxFileCount);
+ return NULL;
+}
+
+
+TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
+{
+ TFileEntry * pFileEntry = NULL;
+ TMPQHash * pHash;
+ DWORD dwHashIndex;
+ DWORD dwFileIndex;
+ bool bHashEntryExists = false;
+ bool bHetEntryExists = false;
+
+ // If the archive has classic hash table, we try to
+ // find the file in the hash table
+ if(ha->pHashTable != NULL)
+ {
+ // If the hash entry is already there, we reuse the file entry
+ pHash = GetHashEntryExact(ha, szFileName, lcLocale);
+ if(pHash != NULL)
+ {
+ pFileEntry = ha->pFileTable + pHash->dwBlockIndex;
+ bHashEntryExists = true;
+ }
+ }
+
+ // If the archive has HET table, try to use it for
+ // finding the file
+ if(ha->pHetTable != NULL)
+ {
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
+ if(dwFileIndex != HASH_ENTRY_FREE)
+ {
+ pFileEntry = ha->pFileTable + dwFileIndex;
+ bHetEntryExists = true;
+ }
+ }
+
+ // If still haven't found the file entry, we allocate new one
+ if(pFileEntry == NULL)
+ {
+ pFileEntry = FindFreeFileEntry(ha);
+ if(pFileEntry == NULL)
+ return NULL;
+ }
+
+ // Fill the rest of the file entry
+ pFileEntry->ByteOffset = 0;
+ pFileEntry->FileTime = 0;
+ pFileEntry->dwFileSize = 0;
+ pFileEntry->dwCmpSize = 0;
+ pFileEntry->dwFlags = 0;
+ pFileEntry->lcLocale = 0;
+ pFileEntry->wPlatform = 0;
+ pFileEntry->dwCrc32 = 0;
+ memset(pFileEntry->md5, 0, MD5_DIGEST_SIZE);
+
+ // Allocate space for file name, if it's not there yet
+ AllocateFileName(pFileEntry, szFileName);
+
+ // If the free file entry is at the end of the file table,
+ // we have to increment file table size
+ if(pFileEntry == ha->pFileTable + ha->dwFileTableSize)
+ {
+ assert(ha->dwFileTableSize < ha->dwMaxFileCount);
+ ha->pHeader->dwBlockTableSize++;
+ ha->dwFileTableSize++;
+ }
+
+ // If the MPQ has hash table, we have to insert the new entry into the hash table
+ if(ha->pHashTable != NULL && bHashEntryExists == false)
+ {
+ dwHashIndex = AllocateHashEntry(ha, pFileEntry);
+ assert(dwHashIndex != HASH_ENTRY_FREE);
+ }
+
+ // If the MPQ has HET table, we have to insert it to the HET table as well
+ if(ha->pHetTable != NULL && bHetEntryExists == false)
+ {
+ // TODO: Does HET table even support locales?
+ // Most probably, Blizzard gave up that silly idea long ago.
+ dwHashIndex = AllocateHetEntry(ha, pFileEntry);
+ assert(dwHashIndex != HASH_ENTRY_FREE);
+ }
+
+ // Return the file entry
+ return pFileEntry;
+}
+
+int RenameFileEntry(
+ TMPQArchive * ha,
+ TFileEntry * pFileEntry,
+ const char * szNewFileName)
+{
+ TMPQHash * pHash;
+ DWORD dwFileIndex;
+ int nError = ERROR_SUCCESS;
+
+ // If the MPQ has classic hash table, clear the entry there
+ if(ha->pHashTable != NULL)
+ {
+ assert(pFileEntry->dwHashIndex < ha->pHeader->dwHashTableSize);
+
+ pHash = ha->pHashTable + pFileEntry->dwHashIndex;
+ memset(pHash, 0xFF, sizeof(TMPQHash));
+ pHash->dwBlockIndex = HASH_ENTRY_DELETED;
+ }
+
+ // If the MPQ has HET table, clear the entry there as well
+ if(ha->pHetTable != NULL)
+ {
+ TMPQHetTable * pHetTable = ha->pHetTable;
+ DWORD dwInvalidFileIndex = (1 << pHetTable->dwIndexSizeTotal) - 1;
+
+ assert(pFileEntry->dwHetIndex < pHetTable->dwHashTableSize);
+
+ // Clear the entry in the HET hash array
+ pHetTable->pHetHashes[pFileEntry->dwHetIndex] = HET_ENTRY_DELETED;
+
+ // Set the BET index to invalid index
+ pHetTable->pBetIndexes->SetBits(pHetTable->dwIndexSizeTotal * pFileEntry->dwHetIndex,
+ pHetTable->dwIndexSize,
+ &dwInvalidFileIndex,
+ 4);
+ }
+
+ // Free the old file name
+ if(pFileEntry->szFileName != NULL)
+ STORM_FREE(pFileEntry->szFileName);
+ pFileEntry->szFileName = NULL;
+
+ // Allocate new file name
+ AllocateFileName(pFileEntry, szNewFileName);
+
+ // Now find a hash entry for the new file name
+ if(ha->pHashTable != NULL)
+ {
+ // Try to find the hash table entry for the new file name
+ // Note: If this fails, we leave the MPQ in a corrupt state
+ dwFileIndex = AllocateHashEntry(ha, pFileEntry);
+ if(dwFileIndex == HASH_ENTRY_FREE)
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // If the archive has HET table, we have to allocate HET table for the file as well
+ // finding the file
+ if(ha->pHetTable != NULL)
+ {
+ dwFileIndex = AllocateHetEntry(ha, pFileEntry);
+ if(dwFileIndex == HASH_ENTRY_FREE)
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Invalidate the entries for (listfile) and (attributes)
+ // After we are done with MPQ changes, we need to re-create them
+ InvalidateInternalFiles(ha);
+ return nError;
+}
+
+void ClearFileEntry(
+ TMPQArchive * ha,
+ TFileEntry * pFileEntry)
+{
+ TMPQHash * pHash = NULL;
+
+ // If the MPQ has classic hash table, clear the entry there
+ if(ha->pHashTable != NULL)
+ {
+ assert(pFileEntry->dwHashIndex < ha->pHeader->dwHashTableSize);
+
+ pHash = ha->pHashTable + pFileEntry->dwHashIndex;
+ memset(pHash, 0xFF, sizeof(TMPQHash));
+ pHash->dwBlockIndex = HASH_ENTRY_DELETED;
+ }
+
+ // If the MPQ has HET table, clear the entry there as well
+ if(ha->pHetTable != NULL)
+ {
+ TMPQHetTable * pHetTable = ha->pHetTable;
+ DWORD dwInvalidFileIndex = (1 << pHetTable->dwIndexSizeTotal) - 1;
+
+ assert(pFileEntry->dwHetIndex < pHetTable->dwHashTableSize);
+
+ // Clear the entry in the HET hash array
+ pHetTable->pHetHashes[pFileEntry->dwHetIndex] = HET_ENTRY_DELETED;
+
+ // Set the BET index to invalid index
+ pHetTable->pBetIndexes->SetBits(pHetTable->dwIndexSizeTotal * pFileEntry->dwHetIndex,
+ pHetTable->dwIndexSize,
+ &dwInvalidFileIndex,
+ 4);
+ }
+
+ // Free the file name, and set the file entry as deleted
+ if(pFileEntry->szFileName != NULL)
+ STORM_FREE(pFileEntry->szFileName);
+
+ // Invalidate the file entry
+ memset(pFileEntry, 0, sizeof(TFileEntry));
+}
+
+int FreeFileEntry(
+ TMPQArchive * ha,
+ TFileEntry * pFileEntry)
+{
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pTempEntry;
+ int nError = ERROR_SUCCESS;
+
+ //
+ // If we have HET table, we cannot just get rid of the file
+ // Doing so would lead to empty gaps in the HET table
+ // We have to keep BET hash, hash index, HET index, locale, platform and file name
+ //
+
+ if(ha->pHetTable == NULL)
+ {
+ TFileEntry * pLastFileEntry = ha->pFileTable + ha->dwFileTableSize - 1;
+ TFileEntry * pLastUsedEntry = pLastFileEntry;
+
+ // Zero the file entry
+ ClearFileEntry(ha, pFileEntry);
+
+ // Now there is a chance that we created a chunk of free
+ // file entries at the end of the file table. We check this
+ // and eventually free all deleted file entries at the end
+ for(pTempEntry = ha->pFileTable; pTempEntry < pFileTableEnd; pTempEntry++)
+ {
+ // Is that an occupied file entry?
+ if(pTempEntry->dwFlags & MPQ_FILE_EXISTS)
+ pLastUsedEntry = pTempEntry;
+ }
+
+ // Can we free some entries at the end?
+ if(pLastUsedEntry < pLastFileEntry)
+ {
+ // Fix the size of the file table entry
+ ha->dwFileTableSize = (DWORD)(pLastUsedEntry - ha->pFileTable) + 1;
+ ha->pHeader->dwBlockTableSize = ha->dwFileTableSize;
+ }
+ }
+ else
+ {
+ // Note: Deleted entries in Blizzard MPQs version 4.0
+ // normally contain valid byte offset and length
+ pFileEntry->dwFlags &= ~MPQ_FILE_EXISTS;
+ nError = ERROR_SUCCESS;
+ }
+
+ return nError;
+}
+
+void InvalidateInternalFiles(TMPQArchive * ha)
+{
+ TFileEntry * pFileEntry;
+
+ // Invalidate the (listfile), if not done yet
+ if(!(ha->dwFlags & MPQ_FLAG_INV_LISTFILE))
+ {
+ pFileEntry = GetFileEntryExact(ha, LISTFILE_NAME, LANG_NEUTRAL);
+ if(pFileEntry != NULL)
+ FreeFileEntry(ha, pFileEntry);
+ ha->dwFlags |= MPQ_FLAG_INV_LISTFILE;
+ }
+
+ // Invalidate the (attributes), if not done yet
+ if(!(ha->dwFlags & MPQ_FLAG_INV_ATTRIBUTES))
+ {
+ pFileEntry = GetFileEntryExact(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
+ if(pFileEntry != NULL)
+ FreeFileEntry(ha, pFileEntry);
+ ha->dwFlags |= MPQ_FLAG_INV_ATTRIBUTES;
+ }
+
+ // Remember that the MPQ has been changed and it will be necessary
+ // to update the tables
+ ha->dwFlags |= MPQ_FLAG_CHANGED;
+}
+
+//-----------------------------------------------------------------------------
+// Functions that loads and verify MPQ data bitmap
+
+int LoadMpqDataBitmap(TMPQArchive * ha, ULONGLONG FileSize, bool * pbFileIsComplete)
+{
+ TMPQBitmap * pBitmap = NULL;
+ TMPQBitmap DataBitmap;
+ ULONGLONG BitmapOffset;
+ ULONGLONG EndOfMpq;
+ DWORD DataBlockCount = 0;
+ DWORD BitmapByteSize;
+ DWORD WholeByteCount;
+ DWORD ExtraBitsCount;
+
+ // Is there enough space for a MPQ bitmap?
+ EndOfMpq = ha->MpqPos + ha->pHeader->ArchiveSize64;
+ FileSize = FileSize - sizeof(TMPQBitmap);
+ if(FileSize > EndOfMpq)
+ {
+ // Try to load the data bitmap from the end of the file
+ if(FileStream_Read(ha->pStream, &FileSize, &DataBitmap, sizeof(TMPQBitmap)))
+ {
+ // Is it a valid data bitmap?
+ BSWAP_ARRAY32_UNSIGNED((LPDWORD)(&DataBitmap), sizeof(TMPQBitmap));
+ if(DataBitmap.dwSignature == MPQ_DATA_BITMAP_SIGNATURE)
+ {
+ // We assume that MPQs with data bitmap begin at position 0
+ assert(ha->MpqPos == 0);
+
+ // Calculate the number of extra bytes for data bitmap
+ DataBlockCount = (DWORD)(((ha->pHeader->ArchiveSize64 - 1) / DataBitmap.dwBlockSize) + 1);
+ BitmapByteSize = ((DataBlockCount - 1) / 8) + 1;
+
+ // Verify the data block size
+ BitmapOffset = ((ULONGLONG)DataBitmap.dwMapOffsetHi << 32) | DataBitmap.dwMapOffsetLo;
+ assert((DWORD)(FileSize - BitmapOffset) == BitmapByteSize);
+
+ // Allocate space for the data bitmap
+ pBitmap = (TMPQBitmap *)STORM_ALLOC(BYTE, sizeof(TMPQBitmap) + BitmapByteSize);
+ if(pBitmap != NULL)
+ {
+ // Copy the bitmap header
+ memcpy(pBitmap, &DataBitmap, sizeof(TMPQBitmap));
+
+ // Read the remaining part
+ if(!FileStream_Read(ha->pStream, &BitmapOffset, (pBitmap + 1), BitmapByteSize))
+ {
+ STORM_FREE(pBitmap);
+ pBitmap = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ // If the caller asks for file completeness, check it
+ if(pBitmap != NULL && pbFileIsComplete != NULL)
+ {
+ LPBYTE pbBitmap = (LPBYTE)(pBitmap + 1);
+ DWORD i;
+ bool bFileIsComplete = true;
+
+ // Calculate the number of whole bytes and extra bits of the bitmap
+ WholeByteCount = (DataBlockCount / 8);
+ ExtraBitsCount = (DataBlockCount & 7);
+
+ // Verify the whole bytes - their value must be 0xFF
+ for(i = 0; i < WholeByteCount; i++)
+ {
+ if(pbBitmap[i] != 0xFF)
+ bFileIsComplete = false;
+ }
+
+ // If there are extra bits, calculate the mask
+ if(ExtraBitsCount != 0)
+ {
+ BYTE ExpectedValue = (BYTE)((1 << ExtraBitsCount) - 1);
+
+ if(pbBitmap[i] != ExpectedValue)
+ bFileIsComplete = false;
+ }
+
+ // Give the result to the caller
+ *pbFileIsComplete = bFileIsComplete;
+ }
+
+ ha->pBitmap = pBitmap;
+ return ERROR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// Support for file tables - hash table, block table, hi-block table
+
+int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize)
+{
+ TMPQHash * pHashTable;
+
+ // Sanity checks
+ assert((dwHashTableSize & (dwHashTableSize - 1)) == 0);
+ assert(ha->pHashTable == NULL);
+
+ // Create the hash table
+ pHashTable = STORM_ALLOC(TMPQHash, dwHashTableSize);
+ if(pHashTable == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Fill it
+ memset(pHashTable, 0xFF, dwHashTableSize * sizeof(TMPQHash));
+ ha->pHashTable = pHashTable;
+
+ // Set the max file count, if needed
+ if(ha->pHetTable == NULL)
+ ha->dwMaxFileCount = dwHashTableSize;
+ return ERROR_SUCCESS;
+}
+
+TMPQHash * LoadHashTable(TMPQArchive * ha)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ ULONGLONG ByteOffset;
+ TMPQHash * pHashTable;
+ DWORD dwTableSize;
+ DWORD dwCmpSize;
+ int nError;
+
+ // If the MPQ has no hash table, do nothing
+ if(pHeader->dwHashTablePos == 0 && pHeader->wHashTablePosHi == 0)
+ return NULL;
+
+ // If the hash table size is zero, do nothing
+ if(pHeader->dwHashTableSize == 0)
+ return NULL;
+
+ // Allocate buffer for the hash table
+ dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash);
+ pHashTable = STORM_ALLOC(TMPQHash, pHeader->dwHashTableSize);
+ if(pHashTable == NULL)
+ return NULL;
+
+ // Compressed size of the hash table
+ dwCmpSize = (DWORD)pHeader->HashTableSize64;
+
+ //
+ // Load the table from the MPQ, with decompression
+ //
+ // Note: We will NOT check if the hash table is properly decrypted.
+ // Some MPQ protectors corrupt the hash table by rewriting part of it.
+ // Hash table, the way how it works, allows arbitrary values for unused entries.
+ //
+
+ ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
+ nError = LoadMpqTable(ha, ByteOffset, pHashTable, dwCmpSize, dwTableSize, MPQ_KEY_HASH_TABLE);
+ if(nError != ERROR_SUCCESS)
+ {
+ STORM_FREE(pHashTable);
+ pHashTable = NULL;
+ }
+
+ // Return the hash table
+ return pHashTable;
+}
+
+static void FixBlockTableSize(
+ TMPQArchive * ha,
+ TMPQBlock * pBlockTable,
+ DWORD dwClaimedSize)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ ULONGLONG BlockTableStart;
+ ULONGLONG BlockTableEnd;
+ ULONGLONG FileDataStart;
+
+ // Only perform this check on MPQs version 1.0
+ if(pHeader->dwHeaderSize == MPQ_HEADER_SIZE_V1)
+ {
+ // Calculate claimed block table begin and end
+ BlockTableStart = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ BlockTableEnd = BlockTableStart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
+
+ for(DWORD i = 0; i < dwClaimedSize; i++)
+ {
+ // If the block table end goes into that file, fix the block table end
+ FileDataStart = ha->MpqPos + pBlockTable[i].dwFilePos;
+ if(BlockTableStart < FileDataStart && BlockTableEnd > FileDataStart)
+ {
+ dwClaimedSize = (DWORD)((FileDataStart - BlockTableStart) / sizeof(TMPQBlock));
+ BlockTableEnd = FileDataStart;
+ }
+ }
+ }
+
+ // Fix the block table size
+ pHeader->BlockTableSize64 = dwClaimedSize * sizeof(TMPQBlock);
+ pHeader->dwBlockTableSize = dwClaimedSize;
+}
+
+TMPQBlock * LoadBlockTable(TMPQArchive * ha, ULONGLONG FileSize)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ TMPQBlock * pBlockTable;
+ ULONGLONG ByteOffset;
+ DWORD dwTableSize;
+ DWORD dwCmpSize;
+ int nError;
+
+ // Do nothing if the block table position is zero
+ if(pHeader->dwBlockTablePos == 0 && pHeader->wBlockTablePosHi == 0)
+ return NULL;
+
+ // Do nothing if the block table size is zero
+ if(pHeader->dwBlockTableSize == 0)
+ return NULL;
+
+ // Sanity check, enforced by LoadAnyHashTable
+ assert(ha->dwMaxFileCount >= pHeader->dwBlockTableSize);
+
+ // Calculate sizes of both tables
+ ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ dwCmpSize = (DWORD)pHeader->BlockTableSize64;
+
+ // Allocate space for the block table
+ // Note: pHeader->dwBlockTableSize can be zero !!!
+ pBlockTable = STORM_ALLOC(TMPQBlock, ha->dwMaxFileCount);
+ if(pBlockTable == NULL)
+ return NULL;
+
+ // Fill the block table with zeros
+ memset(pBlockTable, 0, dwTableSize);
+
+ // I found a MPQ which claimed 0x200 entries in the block table,
+ // but the file was cut and there was only 0x1A0 entries.
+ // We will handle this case properly.
+ if(dwTableSize == dwCmpSize && (ByteOffset + dwTableSize) > FileSize)
+ {
+ pHeader->dwBlockTableSize = (DWORD)((FileSize - ByteOffset) / sizeof(TMPQBlock));
+ pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ dwTableSize = dwCmpSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ }
+
+ //
+ // One of the first cracked versions of Diablo I had block table unencrypted
+ // StormLib does NOT support such MPQs anymore, as they are incompatible
+ // with compressed block table feature
+ //
+
+ // Load the block table
+ nError = LoadMpqTable(ha, ByteOffset, pBlockTable, dwCmpSize, dwTableSize, MPQ_KEY_BLOCK_TABLE);
+ if(nError != ERROR_SUCCESS)
+ {
+ // Failed, sorry
+ STORM_FREE(pBlockTable);
+ return NULL;
+ }
+
+ // Defense against MPQs that claim block table to be bigger than it really is
+ FixBlockTableSize(ha, pBlockTable, pHeader->dwBlockTableSize);
+ return pBlockTable;
+}
+
+int LoadHetTable(TMPQArchive * ha)
+{
+ TMPQExtTable * pExtTable;
+ TMPQHeader * pHeader = ha->pHeader;
+ int nError = ERROR_SUCCESS;
+
+ // If the HET table position is not NULL, we expect
+ // both HET and BET tables to be present.
+ if(pHeader->HetTablePos64 != 0)
+ {
+ // Attempt to load the HET table (Hash Extended Table)
+ pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
+ if(pExtTable != NULL)
+ {
+ // If succeeded, we have to limit the maximum file count
+ // to the values saved in the HET table
+ // If loading HET table fails, we ignore the result.
+ ha->pHetTable = TranslateHetTable(pExtTable);
+ if(ha->pHetTable != NULL)
+ ha->dwMaxFileCount = ha->pHetTable->dwMaxFileCount;
+
+ STORM_FREE(pExtTable);
+ }
+
+ // If the HET hable failed to load, it's corrupt.
+ if(ha->pHetTable == NULL)
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ return nError;
+}
+
+TMPQBetTable * LoadBetTable(TMPQArchive * ha)
+{
+ TMPQExtTable * pExtTable;
+ TMPQBetTable * pBetTable = NULL;
+ TMPQHeader * pHeader = ha->pHeader;
+
+ // If the HET table position is not NULL, we expect
+ // both HET and BET tables to be present.
+ if(pHeader->BetTablePos64 != 0)
+ {
+ // Attempt to load the HET table (Hash Extended Table)
+ pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
+ if(pExtTable != NULL)
+ {
+ // If succeeded, we translate the BET table
+ // to more readable form
+ pBetTable = TranslateBetTable(ha, pExtTable);
+ STORM_FREE(pExtTable);
+ }
+ }
+
+ return pBetTable;
+}
+
+int LoadAnyHashTable(TMPQArchive * ha)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+
+ // If the MPQ archive is empty, don't bother trying to load anything
+ if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0)
+ return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT);
+
+ // Try to load HET and/or classic hash table
+ LoadHetTable(ha);
+
+ // Load the HASH table
+ ha->pHashTable = LoadHashTable(ha);
+
+ // Set the maximum file count to the size of the hash table
+ // In case there is HET table, we have to keep the file limit
+ if(ha->pHetTable == NULL)
+ ha->dwMaxFileCount = pHeader->dwHashTableSize;
+
+ // Did at least one succeed?
+ if(ha->pHetTable == NULL && ha->pHashTable == NULL)
+ return ERROR_FILE_CORRUPT;
+
+ // In theory, a MPQ could have bigger block table than hash table
+ if(ha->pHeader->dwBlockTableSize > ha->dwMaxFileCount)
+ {
+ ha->dwMaxFileCount = ha->pHeader->dwBlockTableSize;
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+int BuildFileTable_Classic(
+ TMPQArchive * ha,
+ TFileEntry * pFileTable,
+ ULONGLONG FileSize)
+{
+ TFileEntry * pFileEntry;
+ TMPQHeader * pHeader = ha->pHeader;
+ TMPQBlock * pBlockTable;
+ TMPQBlock * pBlock;
+ int nError = ERROR_SUCCESS;
+
+ // Sanity checks
+ assert(ha->pHashTable != NULL);
+
+ // Load the block table
+ pBlockTable = LoadBlockTable(ha, FileSize);
+ if(pBlockTable != NULL)
+ {
+ TMPQHash * pHashEnd = ha->pHashTable + pHeader->dwHashTableSize;
+ TMPQHash * pHash;
+
+ // If we don't have HET table, we build the file entries from the hash&block tables
+ if(ha->pHetTable == NULL)
+ {
+ for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
+ {
+ if(pHash->dwBlockIndex < pHeader->dwBlockTableSize)
+ {
+ pFileEntry = pFileTable + pHash->dwBlockIndex;
+ pBlock = pBlockTable + pHash->dwBlockIndex;
+
+ //
+ // Yet another silly map protector: For each valid file,
+ // there are 4 items in the hash table, that appears to be valid:
+ //
+ // a6d79af0 e61a0932 001e0000 0000770b <== Fake valid
+ // a6d79af0 e61a0932 0000d761 0000dacb <== Fake valid
+ // a6d79af0 e61a0932 00000000 0000002f <== Real file entry
+ // a6d79af0 e61a0932 00005a4f 000093bc <== Fake valid
+ //
+
+ if(!(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS) && (pBlock->dwFlags & MPQ_FILE_EXISTS))
+ {
+ // Fill the entry
+ pFileEntry->ByteOffset = pBlock->dwFilePos;
+ pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable);
+ pFileEntry->dwFileSize = pBlock->dwFSize;
+ pFileEntry->dwCmpSize = pBlock->dwCSize;
+ pFileEntry->dwFlags = pBlock->dwFlags;
+ pFileEntry->lcLocale = pHash->lcLocale;
+ pFileEntry->wPlatform = pHash->wPlatform;
+ }
+ else
+ {
+ // If the hash table entry doesn't point to the valid file item,
+ // we invalidate the entire hash table entry
+ pHash->dwName1 = 0xFFFFFFFF;
+ pHash->dwName2 = 0xFFFFFFFF;
+ pHash->lcLocale = 0xFFFF;
+ pHash->wPlatform = 0xFFFF;
+ pHash->dwBlockIndex = HASH_ENTRY_DELETED;
+ }
+ }
+ }
+ }
+ else
+ {
+ for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
+ {
+ if(pHash->dwBlockIndex < ha->dwFileTableSize)
+ {
+ pFileEntry = pFileTable + pHash->dwBlockIndex;
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
+ {
+ pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable);
+ pFileEntry->lcLocale = pHash->lcLocale;
+ pFileEntry->wPlatform = pHash->wPlatform;
+ }
+ }
+ }
+ }
+
+ // Free the block table
+ STORM_FREE(pBlockTable);
+ }
+ else
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Load the hi-block table
+ if(nError == ERROR_SUCCESS && pHeader->HiBlockTablePos64 != 0)
+ {
+ ULONGLONG ByteOffset;
+ USHORT * pHiBlockTable = NULL;
+ DWORD dwTableSize = pHeader->dwBlockTableSize * sizeof(USHORT);
+
+ // Allocate space for the hi-block table
+ // Note: pHeader->dwBlockTableSize can be zero !!!
+ pHiBlockTable = STORM_ALLOC(USHORT, pHeader->dwBlockTableSize + 1);
+ if(pHiBlockTable != NULL)
+ {
+ // Load the hi-block table. It is not encrypted, nor compressed
+ ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
+ if(!FileStream_Read(ha->pStream, &ByteOffset, pHiBlockTable, dwTableSize))
+ nError = GetLastError();
+
+ // Now merge the hi-block table to the file table
+ if(nError == ERROR_SUCCESS)
+ {
+ pFileEntry = pFileTable;
+
+ // Add the high file offset to the base file offset.
+ // We also need to swap it during the process.
+ for(DWORD i = 0; i < pHeader->dwBlockTableSize; i++)
+ {
+ pFileEntry->ByteOffset |= ((ULONGLONG)BSWAP_INT16_UNSIGNED(pHiBlockTable[i]) << 32);
+ pFileEntry++;
+ }
+ }
+
+ // Free the hi-block table
+ STORM_FREE(pHiBlockTable);
+ }
+ else
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ // Set the current size of the file table
+ ha->dwFileTableSize = pHeader->dwBlockTableSize;
+ return nError;
+}
+
+int BuildFileTable_HetBet(
+ TMPQArchive * ha,
+ TFileEntry * pFileTable)
+{
+ TMPQHetTable * pHetTable = ha->pHetTable;
+ TMPQBetTable * pBetTable;
+ TFileEntry * pFileEntry = pFileTable;
+ TBitArray * pBitArray;
+ DWORD dwBitPosition = 0;
+ DWORD i;
+ int nError = ERROR_FILE_CORRUPT;
+
+ // Load the BET table from the MPQ
+ pBetTable = LoadBetTable(ha);
+ if(pBetTable != NULL)
+ {
+ // Step one: Fill the indexes to the HET table
+ for(i = 0; i < pHetTable->dwHashTableSize; i++)
+ {
+ DWORD dwFileIndex = 0;
+
+ // Is the entry in the HET table occupied?
+ if(pHetTable->pHetHashes[i] != 0)
+ {
+ // Load the index to the BET table
+ pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * i,
+ pHetTable->dwIndexSize,
+ &dwFileIndex,
+ 4);
+ // Overflow test
+ if(dwFileIndex < pBetTable->dwFileCount)
+ {
+ // Get the file entry and save HET index
+ pFileEntry = pFileTable + dwFileIndex;
+ pFileEntry->dwHetIndex = i;
+
+ // Load the BET hash
+ pBetTable->pBetHashes->GetBits(pBetTable->dwBetHashSizeTotal * dwFileIndex,
+ pBetTable->dwBetHashSize,
+ &pFileEntry->BetHash,
+ 8);
+ }
+ }
+ }
+
+ // Go through the entire BET table and convert it to the file table.
+ pFileEntry = pFileTable;
+ pBitArray = pBetTable->pFileTable;
+ for(i = 0; i < pBetTable->dwFileCount; i++)
+ {
+ DWORD dwFlagIndex = 0;
+
+ // Read the file position
+ pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FilePos,
+ pBetTable->dwBitCount_FilePos,
+ &pFileEntry->ByteOffset,
+ 8);
+
+ // Read the file size
+ pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FileSize,
+ pBetTable->dwBitCount_FileSize,
+ &pFileEntry->dwFileSize,
+ 4);
+
+ // Read the compressed size
+ pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_CmpSize,
+ pBetTable->dwBitCount_CmpSize,
+ &pFileEntry->dwCmpSize,
+ 4);
+
+
+ // Read the flag index
+ if(pBetTable->dwFlagCount != 0)
+ {
+ pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FlagIndex,
+ pBetTable->dwBitCount_FlagIndex,
+ &dwFlagIndex,
+ 4);
+
+ pFileEntry->dwFlags = pBetTable->pFileFlags[dwFlagIndex];
+ }
+
+ //
+ // TODO: Locale (?)
+ //
+
+ // Move the current bit position
+ dwBitPosition += pBetTable->dwTableEntrySize;
+ pFileEntry++;
+ }
+
+ // Set the current size of the file table
+ ha->dwFileTableSize = pBetTable->dwFileCount;
+ FreeBetTable(pBetTable);
+ nError = ERROR_SUCCESS;
+ }
+ else
+ {
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ return nError;
+}
+
+int BuildFileTable(TMPQArchive * ha, ULONGLONG FileSize)
+{
+ TFileEntry * pFileTable;
+ bool bFileTableCreated = false;
+
+ // Sanity checks
+ assert(ha->dwFileTableSize == 0);
+ assert(ha->dwMaxFileCount != 0);
+
+ // Allocate the file table with size determined before
+ pFileTable = STORM_ALLOC(TFileEntry, ha->dwMaxFileCount);
+ if(pFileTable == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Fill the table with zeros
+ memset(pFileTable, 0, ha->dwMaxFileCount * sizeof(TFileEntry));
+
+ // If we have HET table, we load file table from the BET table
+ // Note: If BET table is corrupt or missing, we set the archive as read only
+ if(ha->pHetTable != NULL)
+ {
+ if(BuildFileTable_HetBet(ha, pFileTable) != ERROR_SUCCESS)
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+ else
+ bFileTableCreated = true;
+ }
+
+ // If we have hash table, we load the file table from the block table
+ // Note: If block table is corrupt or missing, we set the archive as read only
+ if(ha->pHashTable != NULL)
+ {
+ if(BuildFileTable_Classic(ha, pFileTable, FileSize) != ERROR_SUCCESS)
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+ else
+ bFileTableCreated = true;
+ }
+
+ // If something failed, we free the file table entry
+ if(bFileTableCreated == false)
+ {
+ STORM_FREE(pFileTable);
+ return ERROR_FILE_CORRUPT;
+ }
+
+ // Assign it to the archive structure
+ ha->pFileTable = pFileTable;
+ return ERROR_SUCCESS;
+}
+
+// Saves MPQ header, hash table, block table and hi-block table.
+int SaveMPQTables(TMPQArchive * ha)
+{
+ TMPQExtTable * pHetTable = NULL;
+ TMPQExtTable * pBetTable = NULL;
+ TMPQHeader * pHeader = ha->pHeader;
+ TMPQBlock * pBlockTable = NULL;
+ TMPQHash * pHashTable = NULL;
+ ULONGLONG HetTableSize64 = 0;
+ ULONGLONG BetTableSize64 = 0;
+ ULONGLONG HashTableSize64 = 0;
+ ULONGLONG BlockTableSize64 = 0;
+ ULONGLONG HiBlockTableSize64 = 0;
+ ULONGLONG TablePos = 0; // A table position, relative to the begin of the MPQ
+ USHORT * pHiBlockTable = NULL;
+ DWORD cbTotalSize;
+ bool bNeedHiBlockTable = false;
+ int nError = ERROR_SUCCESS;
+
+ // We expect this function to be called only when tables have been changed
+ assert(ha->dwFlags & MPQ_FLAG_CHANGED);
+
+ // Find the space where the MPQ tables will be saved
+ FindFreeMpqSpace(ha, &TablePos);
+
+ // If the MPQ has HET table, we prepare a ready-to-save version
+ if(nError == ERROR_SUCCESS && ha->pHetTable != NULL)
+ {
+ pHetTable = TranslateHetTable(ha->pHetTable, &HetTableSize64);
+ if(pHetTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // If the MPQ has HET table, we also must create BET table to be saved
+ if(nError == ERROR_SUCCESS && ha->pHetTable != NULL)
+ {
+ pBetTable = TranslateBetTable(ha, &BetTableSize64);
+ if(pBetTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Now create hash table
+ if(nError == ERROR_SUCCESS && ha->pHashTable != NULL)
+ {
+ pHashTable = TranslateHashTable(ha, &HashTableSize64);
+ if(pHashTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Create block table
+ if(nError == ERROR_SUCCESS && ha->pHashTable != NULL)
+ {
+ pBlockTable = TranslateBlockTable(ha, &BlockTableSize64, &bNeedHiBlockTable);
+ if(pBlockTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Create hi-block table, if needed
+ if(nError == ERROR_SUCCESS && bNeedHiBlockTable)
+ {
+ pHiBlockTable = TranslateHiBlockTable(ha, &HiBlockTableSize64);
+ if(pHiBlockTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Write the HET table, if any
+ if(nError == ERROR_SUCCESS && pHetTable != NULL)
+ {
+ pHeader->HetTableSize64 = HetTableSize64;
+ pHeader->HetTablePos64 = TablePos;
+ nError = SaveExtTable(ha, pHetTable, TablePos, (DWORD)HetTableSize64, pHeader->MD5_HetTable, MPQ_KEY_HASH_TABLE, false, &cbTotalSize);
+ TablePos += cbTotalSize;
+ }
+
+ // Write the BET table, if any
+ if(nError == ERROR_SUCCESS && pBetTable != NULL)
+ {
+ pHeader->BetTableSize64 = BetTableSize64;
+ pHeader->BetTablePos64 = TablePos;
+ nError = SaveExtTable(ha, pBetTable, TablePos, (DWORD)BetTableSize64, pHeader->MD5_BetTable, MPQ_KEY_BLOCK_TABLE, false, &cbTotalSize);
+ TablePos += cbTotalSize;
+ }
+
+ // Write the hash table, if we have any
+ if(nError == ERROR_SUCCESS && pHashTable != NULL)
+ {
+ pHeader->HashTableSize64 = HashTableSize64;
+ pHeader->wHashTablePosHi = (USHORT)(TablePos >> 32);
+ pHeader->dwHashTableSize = (DWORD)(HashTableSize64 / sizeof(TMPQHash));
+ pHeader->dwHashTablePos = (DWORD)TablePos;
+ nError = SaveMpqTable(ha, pHashTable, TablePos, (size_t)HashTableSize64, pHeader->MD5_HashTable, MPQ_KEY_HASH_TABLE, false);
+ TablePos += HashTableSize64;
+ }
+
+ // Write the block table, if we have any
+ if(nError == ERROR_SUCCESS && pBlockTable != NULL)
+ {
+ pHeader->BlockTableSize64 = BlockTableSize64;
+ pHeader->wBlockTablePosHi = (USHORT)(TablePos >> 32);
+ pHeader->dwBlockTableSize = (DWORD)(BlockTableSize64 / sizeof(TMPQBlock));
+ pHeader->dwBlockTablePos = (DWORD)TablePos;
+ nError = SaveMpqTable(ha, pBlockTable, TablePos, (size_t)BlockTableSize64, pHeader->MD5_BlockTable, MPQ_KEY_BLOCK_TABLE, false);
+ TablePos += BlockTableSize64;
+ }
+
+ // Write the hi-block table, if we have any
+ if(nError == ERROR_SUCCESS && pHiBlockTable != NULL)
+ {
+ ULONGLONG ByteOffset = ha->MpqPos + TablePos;
+
+ pHeader->HiBlockTableSize64 = HiBlockTableSize64;
+ pHeader->HiBlockTablePos64 = TablePos;
+ BSWAP_ARRAY16_UNSIGNED(pHiBlockTable, HiBlockTableSize64);
+
+ if(!FileStream_Write(ha->pStream, &ByteOffset, pHiBlockTable, (DWORD)HiBlockTableSize64))
+ nError = GetLastError();
+ TablePos += HiBlockTableSize64;
+ }
+
+ // Cut the MPQ
+ if(nError == ERROR_SUCCESS)
+ {
+ ULONGLONG FileSize = ha->MpqPos + TablePos;
+
+ if(!FileStream_SetSize(ha->pStream, FileSize))
+ nError = GetLastError();
+ }
+
+ // Write the MPQ header
+ if(nError == ERROR_SUCCESS)
+ {
+ // Update the size of the archive
+ pHeader->ArchiveSize64 = TablePos;
+ pHeader->dwArchiveSize = (DWORD)TablePos;
+
+ // Update the MD5 of the archive header
+ CalculateDataBlockHash(pHeader, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE, pHeader->MD5_MpqHeader);
+
+ // Write the MPQ header to the file
+ BSWAP_TMPQHEADER(pHeader);
+ if(!FileStream_Write(ha->pStream, &ha->MpqPos, pHeader, pHeader->dwHeaderSize))
+ nError = GetLastError();
+ BSWAP_TMPQHEADER(pHeader);
+ }
+
+ // Clear the changed flag
+ if(nError == ERROR_SUCCESS)
+ ha->dwFlags &= ~MPQ_FLAG_CHANGED;
+
+ // Cleanup and exit
+ if(pHetTable != NULL)
+ STORM_FREE(pHetTable);
+ if(pBetTable != NULL)
+ STORM_FREE(pBetTable);
+ if(pHashTable != NULL)
+ STORM_FREE(pHashTable);
+ if(pBlockTable != NULL)
+ STORM_FREE(pBlockTable);
+ if(pHiBlockTable != NULL)
+ STORM_FREE(pHiBlockTable);
+ return nError;
+}
diff --git a/dep/StormLib/src/SCompression.cpp b/dep/StormLib/src/SCompression.cpp
new file mode 100644
index 00000000000..5c7432248dc
--- /dev/null
+++ b/dep/StormLib/src/SCompression.cpp
@@ -0,0 +1,1135 @@
+/*****************************************************************************/
+/* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* This module serves as a bridge between StormLib code and (de)compression */
+/* functions. All (de)compression calls go (and should only go) through this */
+/* module. No system headers should be included in this module to prevent */
+/* compile-time problems. */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 01.04.03 1.00 Lad The first version of SCompression.cpp */
+/* 19.11.03 1.01 Dan Big endian handling */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+// Information about the input and output buffers for pklib
+typedef struct
+{
+ char * pbInBuff; // Pointer to input data buffer
+ char * pbInBuffEnd; // End of the input buffer
+ char * pbOutBuff; // Pointer to output data buffer
+ char * pbOutBuffEnd; // Pointer to output data buffer
+} TDataInfo;
+
+// Prototype of the compression function
+// Function doesn't return an error. A success means that the size of compressed buffer
+// is lower than size of uncompressed buffer.
+typedef void (*COMPRESS)(
+ char * pbOutBuffer, // [out] Pointer to the buffer where the compressed data will be stored
+ int * pcbOutBuffer, // [in] Pointer to length of the buffer pointed by pbOutBuffer
+ // [out] Contains length of the compressed data
+ char * pbInBuffer, // [in] Pointer to the buffer with data to compress
+ int cbInBuffer, // [in] Length of the buffer pointer by pbInBuffer
+ int * pCmpType, // [in] Compression-method specific value. ADPCM Setups this for the following Huffman compression
+ int nCmpLevel); // [in] Compression specific value. ADPCM uses this. Should be set to zero.
+
+// Prototype of the decompression function
+// Returns 1 if success, 0 if failure
+typedef int (*DECOMPRESS)(
+ char * pbOutBuffer, // [out] Pointer to the buffer where to store decompressed data
+ int * pcbOutBuffer, // [in] Pointer to total size of the buffer pointed by pbOutBuffer
+ // [out] Contains length of the decompressed data
+ char * pbInBuffer, // [in] Pointer to data to be decompressed
+ int cbInBuffer); // [in] Length of the data to be decompressed
+
+// Table of compression functions
+typedef struct
+{
+ unsigned long uMask; // Compression mask
+ COMPRESS Compress; // Compression function
+} TCompressTable;
+
+// Table of decompression functions
+typedef struct
+{
+ unsigned long uMask; // Decompression bit
+ DECOMPRESS Decompress; // Decompression function
+} TDecompressTable;
+
+
+/*****************************************************************************/
+/* */
+/* Support for Huffman compression (0x01) */
+/* */
+/*****************************************************************************/
+
+// 1500F4C0
+void Compress_huff(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * pCmpType,
+ int /* nCmpLevel */)
+{
+ THuffmannTree ht; // Huffmann tree for compression
+ TOutputStream os; // Output stream
+
+ // Initialize output stream
+ os.pbOutBuffer = (unsigned char *)pbOutBuffer;
+ os.cbOutSize = *pcbOutBuffer;
+ os.pbOutPos = (unsigned char *)pbOutBuffer;
+ os.dwBitBuff = 0;
+ os.nBits = 0;
+
+ // Initialize the Huffmann tree for compression
+ ht.InitTree(true);
+
+ *pcbOutBuffer = ht.DoCompression(&os, (unsigned char *)pbInBuffer, cbInBuffer, *pCmpType);
+
+ // The following code is not necessary to run, because it has no
+ // effect on the output data. It only clears the huffmann tree, but when
+ // the tree is on the stack, who cares ?
+// ht.UninitTree();
+}
+
+// 1500F5F0
+int Decompress_huff(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ THuffmannTree ht;
+ TInputStream is;
+
+ // Initialize input stream
+ is.pbInBufferEnd = (unsigned char *)pbInBuffer + cbInBuffer;
+ is.pbInBuffer = (unsigned char *)pbInBuffer;
+ is.BitBuffer = 0;
+ is.BitCount = 0;
+
+ // Initialize the Huffmann tree for compression
+ ht.InitTree(false);
+ *pcbOutBuffer = ht.DoDecompression((unsigned char *)pbOutBuffer, *pcbOutBuffer, &is);
+ if(*pcbOutBuffer == 0)
+ return 0;
+
+ // The following code is not necessary to run, because it has no
+ // effect on the output data. It only clears the huffmann tree, but when
+ // the tree is on the stack, who cares ?
+// ht.UninitTree();
+ return 1;
+}
+
+/******************************************************************************/
+/* */
+/* Support for ZLIB compression (0x02) */
+/* */
+/******************************************************************************/
+
+void Compress_ZLIB(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * /* pCmpType */,
+ int /* nCmpLevel */)
+{
+ z_stream z; // Stream information for zlib
+ int windowBits;
+ int nResult;
+
+ // Fill the stream structure for zlib
+ z.next_in = (Bytef *)pbInBuffer;
+ z.avail_in = (uInt)cbInBuffer;
+ z.total_in = cbInBuffer;
+ z.next_out = (Bytef *)pbOutBuffer;
+ z.avail_out = *pcbOutBuffer;
+ z.total_out = 0;
+ z.zalloc = NULL;
+ z.zfree = NULL;
+
+ // Determine the proper window bits (WoW.exe build 12694)
+ if(cbInBuffer <= 0x100)
+ windowBits = 8;
+ else if(cbInBuffer <= 0x200)
+ windowBits = 9;
+ else if(cbInBuffer <= 0x400)
+ windowBits = 10;
+ else if(cbInBuffer <= 0x800)
+ windowBits = 11;
+ else if(cbInBuffer <= 0x1000)
+ windowBits = 12;
+ else if(cbInBuffer <= 0x2000)
+ windowBits = 13;
+ else if(cbInBuffer <= 0x4000)
+ windowBits = 14;
+ else
+ windowBits = 15;
+
+ // Initialize the compression.
+ // Storm.dll uses zlib version 1.1.3
+ // Wow.exe uses zlib version 1.2.3
+ nResult = deflateInit2(&z,
+ 6, // Compression level used by WoW MPQs
+ Z_DEFLATED,
+ windowBits,
+ 8,
+ Z_DEFAULT_STRATEGY);
+ if(nResult == Z_OK)
+ {
+ // Call zlib to compress the data
+ nResult = deflate(&z, Z_FINISH);
+
+ if(nResult == Z_OK || nResult == Z_STREAM_END)
+ *pcbOutBuffer = z.total_out;
+
+ deflateEnd(&z);
+ }
+}
+
+int Decompress_ZLIB(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ z_stream z; // Stream information for zlib
+ int nResult;
+
+ // Fill the stream structure for zlib
+ z.next_in = (Bytef *)pbInBuffer;
+ z.avail_in = (uInt)cbInBuffer;
+ z.total_in = cbInBuffer;
+ z.next_out = (Bytef *)pbOutBuffer;
+ z.avail_out = *pcbOutBuffer;
+ z.total_out = 0;
+ z.zalloc = NULL;
+ z.zfree = NULL;
+
+ // Initialize the decompression structure. Storm.dll uses zlib version 1.1.3
+ if((nResult = inflateInit(&z)) == 0)
+ {
+ // Call zlib to decompress the data
+ nResult = inflate(&z, Z_FINISH);
+ *pcbOutBuffer = z.total_out;
+ inflateEnd(&z);
+ }
+ return nResult;
+}
+
+/******************************************************************************/
+/* */
+/* Support functions for PKWARE Data Compression Library compression (0x08) */
+/* */
+/******************************************************************************/
+
+// Function loads data from the input buffer. Used by Pklib's "implode"
+// and "explode" function as user-defined callback
+// Returns number of bytes loaded
+//
+// char * buf - Pointer to a buffer where to store loaded data
+// unsigned int * size - Max. number of bytes to read
+// void * param - Custom pointer, parameter of implode/explode
+
+static unsigned int ReadInputData(char * buf, unsigned int * size, void * param)
+{
+ TDataInfo * pInfo = (TDataInfo *)param;
+ unsigned int nMaxAvail = (unsigned int)(pInfo->pbInBuffEnd - pInfo->pbInBuff);
+ unsigned int nToRead = *size;
+
+ // Check the case when not enough data available
+ if(nToRead > nMaxAvail)
+ nToRead = nMaxAvail;
+
+ // Load data and increment offsets
+ memcpy(buf, pInfo->pbInBuff, nToRead);
+ pInfo->pbInBuff += nToRead;
+ assert(pInfo->pbInBuff <= pInfo->pbInBuffEnd);
+ return nToRead;
+}
+
+// Function for store output data. Used by Pklib's "implode" and "explode"
+// as user-defined callback
+//
+// char * buf - Pointer to data to be written
+// unsigned int * size - Number of bytes to write
+// void * param - Custom pointer, parameter of implode/explode
+
+static void WriteOutputData(char * buf, unsigned int * size, void * param)
+{
+ TDataInfo * pInfo = (TDataInfo *)param;
+ unsigned int nMaxWrite = (unsigned int)(pInfo->pbOutBuffEnd - pInfo->pbOutBuff);
+ unsigned int nToWrite = *size;
+
+ // Check the case when not enough space in the output buffer
+ if(nToWrite > nMaxWrite)
+ nToWrite = nMaxWrite;
+
+ // Write output data and increments offsets
+ memcpy(pInfo->pbOutBuff, buf, nToWrite);
+ pInfo->pbOutBuff += nToWrite;
+ assert(pInfo->pbOutBuff <= pInfo->pbOutBuffEnd);
+}
+
+static void Compress_PKLIB(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * /* pCmpType */,
+ int /* nCmpLevel */)
+{
+ TDataInfo Info; // Data information
+ char * work_buf = STORM_ALLOC(char, CMP_BUFFER_SIZE);// Pklib's work buffer
+ unsigned int dict_size; // Dictionary size
+ unsigned int ctype = CMP_BINARY; // Compression type
+
+ // Fill data information structure
+ memset(work_buf, 0, CMP_BUFFER_SIZE);
+ Info.pbInBuff = pbInBuffer;
+ Info.pbInBuffEnd = pbInBuffer + cbInBuffer;
+ Info.pbOutBuff = pbOutBuffer;
+ Info.pbOutBuffEnd = pbOutBuffer + *pcbOutBuffer;
+
+ //
+ // Set the dictionary size
+ //
+ // Diablo I ues fixed dictionary size of CMP_IMPLODE_DICT_SIZE3
+ // Starcraft uses the variable dictionary size based on algorithm below
+ //
+
+ if (cbInBuffer < 0x600)
+ dict_size = CMP_IMPLODE_DICT_SIZE1;
+ else if(0x600 <= cbInBuffer && cbInBuffer < 0xC00)
+ dict_size = CMP_IMPLODE_DICT_SIZE2;
+ else
+ dict_size = CMP_IMPLODE_DICT_SIZE3;
+
+ // Do the compression
+ if(implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size) == CMP_NO_ERROR)
+ *pcbOutBuffer = (int)(Info.pbOutBuff - pbOutBuffer);
+
+ STORM_FREE(work_buf);
+}
+
+static int Decompress_PKLIB(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ TDataInfo Info; // Data information
+ char * work_buf = STORM_ALLOC(char, EXP_BUFFER_SIZE);// Pklib's work buffer
+
+ // Fill data information structure
+ memset(work_buf, 0, EXP_BUFFER_SIZE);
+ Info.pbInBuff = pbInBuffer;
+ Info.pbInBuffEnd = pbInBuffer + cbInBuffer;
+ Info.pbOutBuff = pbOutBuffer;
+ Info.pbOutBuffEnd = pbOutBuffer + *pcbOutBuffer;
+
+ // Do the decompression
+ explode(ReadInputData, WriteOutputData, work_buf, &Info);
+
+ // If PKLIB is unable to decompress the data, return 0;
+ if(Info.pbOutBuff == pbOutBuffer)
+ return 0;
+
+ // Give away the number of decompressed bytes
+ *pcbOutBuffer = (int)(Info.pbOutBuff - pbOutBuffer);
+ STORM_FREE(work_buf);
+ return 1;
+}
+
+/******************************************************************************/
+/* */
+/* Support for Bzip2 compression (0x10) */
+/* */
+/******************************************************************************/
+
+static void Compress_BZIP2(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * /* pCmpType */,
+ int /* nCmpLevel */)
+{
+ bz_stream strm;
+ int blockSize100k = 9;
+ int workFactor = 30;
+ int bzError;
+
+ // Initialize the BZIP2 compression
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+
+ // Blizzard uses 9 as blockSize100k, (0x30 as workFactor)
+ // Last checked on Starcraft II
+ if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == BZ_OK)
+ {
+ strm.next_in = pbInBuffer;
+ strm.avail_in = cbInBuffer;
+ strm.next_out = pbOutBuffer;
+ strm.avail_out = *pcbOutBuffer;
+
+ // Perform the compression
+ for(;;)
+ {
+ bzError = BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH);
+ if(bzError == BZ_STREAM_END || bzError < 0)
+ break;
+ }
+
+ // Put the stream into idle state
+ BZ2_bzCompressEnd(&strm);
+
+ if(bzError > 0)
+ *pcbOutBuffer = strm.total_out_lo32;
+ }
+}
+
+static int Decompress_BZIP2(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ bz_stream strm;
+ int nResult = BZ_OK;
+
+ // Initialize the BZIP2 decompression
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+ if(BZ2_bzDecompressInit(&strm, 0, 0) == BZ_OK)
+ {
+ strm.next_in = pbInBuffer;
+ strm.avail_in = cbInBuffer;
+ strm.next_out = pbOutBuffer;
+ strm.avail_out = *pcbOutBuffer;
+
+ // Perform the decompression
+ while(nResult != BZ_STREAM_END)
+ {
+ nResult = BZ2_bzDecompress(&strm);
+
+ // If any error there, break the loop
+ if(nResult < BZ_OK)
+ break;
+ }
+
+ // Put the stream into idle state
+ BZ2_bzDecompressEnd(&strm);
+
+ // If all succeeded, set the number of output bytes
+ if(nResult >= BZ_OK)
+ {
+ *pcbOutBuffer = strm.total_out_lo32;
+ return 1;
+ }
+ }
+
+ // Something failed, so set number of output bytes to zero
+ *pcbOutBuffer = 0;
+ return 1;
+}
+
+/******************************************************************************/
+/* */
+/* Support functions for LZMA compression (0x12) */
+/* */
+/******************************************************************************/
+
+#define LZMA_HEADER_SIZE (1 + LZMA_PROPS_SIZE + 8)
+
+static SRes LZMA_Callback_Progress(void * /* p */, UInt64 /* inSize */, UInt64 /* outSize */)
+{
+ return SZ_OK;
+}
+
+static void * LZMA_Callback_Alloc(void *p, size_t size)
+{
+ p = p;
+ return STORM_ALLOC(BYTE, size);
+}
+
+/* address can be 0 */
+static void LZMA_Callback_Free(void *p, void *address)
+{
+ p = p;
+ if(address != NULL)
+ STORM_FREE(address);
+}
+
+//
+// Note: So far, I haven't seen any files compressed by LZMA.
+// This code haven't been verified against code ripped from Starcraft II Beta,
+// but we know that Starcraft LZMA decompression code is able to decompress
+// the data compressed by StormLib.
+//
+
+/*static */ void Compress_LZMA(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * /* pCmpType */,
+ int /* nCmpLevel */)
+{
+ ICompressProgress Progress;
+ CLzmaEncProps props;
+ ISzAlloc SzAlloc;
+ Byte * destBuffer;
+ SizeT destLen = *pcbOutBuffer;
+ SizeT srcLen = cbInBuffer;
+ Byte encodedProps[LZMA_PROPS_SIZE];
+ size_t encodedPropsSize = LZMA_PROPS_SIZE;
+ SRes nResult;
+
+ // Fill the callbacks in structures
+ Progress.Progress = LZMA_Callback_Progress;
+ SzAlloc.Alloc = LZMA_Callback_Alloc;
+ SzAlloc.Free = LZMA_Callback_Free;
+
+ // Initialize properties
+ LzmaEncProps_Init(&props);
+
+ // Perform compression
+ destBuffer = (Byte *)pbOutBuffer + LZMA_HEADER_SIZE;
+ destLen = *pcbOutBuffer - LZMA_HEADER_SIZE;
+ nResult = LzmaEncode(destBuffer,
+ &destLen,
+ (Byte *)pbInBuffer,
+ srcLen,
+ &props,
+ encodedProps,
+ &encodedPropsSize,
+ 0,
+ &Progress,
+ &SzAlloc,
+ &SzAlloc);
+ if(nResult != SZ_OK)
+ return;
+
+ // If we failed to compress the data
+ if(destLen >= (SizeT)(*pcbOutBuffer - LZMA_HEADER_SIZE))
+ return;
+
+ // Write "useFilter" variable. Blizzard MPQ must not use filter.
+ *pbOutBuffer++ = 0;
+
+ // Copy the encoded properties to the output buffer
+ memcpy(pbOutBuffer, encodedProps, encodedPropsSize);
+ pbOutBuffer += encodedPropsSize;
+
+ // Copy the size of the data
+ *pbOutBuffer++ = (unsigned char)(srcLen >> 0x00);
+ *pbOutBuffer++ = (unsigned char)(srcLen >> 0x08);
+ *pbOutBuffer++ = (unsigned char)(srcLen >> 0x10);
+ *pbOutBuffer++ = (unsigned char)(srcLen >> 0x18);
+ *pbOutBuffer++ = 0;
+ *pbOutBuffer++ = 0;
+ *pbOutBuffer++ = 0;
+ *pbOutBuffer++ = 0;
+
+ // Give the size of the data to the caller
+ *pcbOutBuffer = (unsigned int)(destLen + LZMA_HEADER_SIZE);
+}
+
+static int Decompress_LZMA(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ ELzmaStatus LzmaStatus;
+ ISzAlloc SzAlloc;
+ Byte * destBuffer = (Byte *)pbOutBuffer;
+ Byte * srcBuffer = (Byte *)pbInBuffer;
+ SizeT destLen = *pcbOutBuffer;
+ SizeT srcLen = cbInBuffer;
+ SRes nResult;
+
+ // There must be at least 0x0E bytes in the buffer
+ if(srcLen <= LZMA_HEADER_SIZE)
+ return 0;
+
+ // We only accept blocks that have no filter used
+ if(*srcBuffer != 0)
+ return 0;
+
+ // Fill the callbacks in structures
+ SzAlloc.Alloc = LZMA_Callback_Alloc;
+ SzAlloc.Free = LZMA_Callback_Free;
+
+ // Perform compression
+ srcLen = cbInBuffer - LZMA_HEADER_SIZE;
+ nResult = LzmaDecode(destBuffer,
+ &destLen,
+ srcBuffer + LZMA_HEADER_SIZE,
+ &srcLen,
+ srcBuffer + 1,
+ LZMA_PROPS_SIZE,
+ LZMA_FINISH_END,
+ &LzmaStatus,
+ &SzAlloc);
+ if(nResult != SZ_OK)
+ return 0;
+
+ *pcbOutBuffer = (unsigned int)destLen;
+ return 1;
+}
+
+/******************************************************************************/
+/* */
+/* Support functions for SPARSE compression (0x20) */
+/* */
+/******************************************************************************/
+
+void Compress_SPARSE(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * /* pCmpType */,
+ int /* nCmpLevel */)
+{
+ CompressSparse((unsigned char *)pbOutBuffer, pcbOutBuffer, (unsigned char *)pbInBuffer, cbInBuffer);
+}
+
+int Decompress_SPARSE(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ return DecompressSparse((unsigned char *)pbOutBuffer, pcbOutBuffer, (unsigned char *)pbInBuffer, cbInBuffer);
+}
+
+/******************************************************************************/
+/* */
+/* Support for ADPCM mono compression (0x40) */
+/* */
+/******************************************************************************/
+
+static void Compress_ADPCM_mono(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * pCmpType,
+ int nCmpLevel)
+{
+ // Prepare the compression level for Huffmann compression,
+ // which will be called as next step
+ if(0 < nCmpLevel && nCmpLevel <= 2)
+ {
+ nCmpLevel = 4;
+ *pCmpType = 6;
+ }
+ else if(nCmpLevel == 3)
+ {
+ nCmpLevel = 6;
+ *pCmpType = 8;
+ }
+ else
+ {
+ nCmpLevel = 5;
+ *pCmpType = 7;
+ }
+ *pcbOutBuffer = CompressADPCM((unsigned char *)pbOutBuffer, *pcbOutBuffer, (short *)pbInBuffer, cbInBuffer, 1, nCmpLevel);
+}
+
+static int Decompress_ADPCM_mono(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ *pcbOutBuffer = DecompressADPCM((unsigned char *)pbOutBuffer, *pcbOutBuffer, (unsigned char *)pbInBuffer, cbInBuffer, 1);
+ return 1;
+}
+
+/******************************************************************************/
+/* */
+/* Support for ADPCM stereo compression (0x80) */
+/* */
+/******************************************************************************/
+
+static void Compress_ADPCM_stereo(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ int * pCmpType,
+ int nCmpLevel)
+{
+ // Prepare the compression level for Huffmann compression,
+ // which will be called as next step
+ if(0 < nCmpLevel && nCmpLevel <= 2)
+ {
+ nCmpLevel = 4;
+ *pCmpType = 6;
+ }
+ else if(nCmpLevel == 3)
+ {
+ nCmpLevel = 6;
+ *pCmpType = 8;
+ }
+ else
+ {
+ nCmpLevel = 5;
+ *pCmpType = 7;
+ }
+ *pcbOutBuffer = CompressADPCM((unsigned char *)pbOutBuffer, *pcbOutBuffer, (short *)pbInBuffer, cbInBuffer, 2, nCmpLevel);
+}
+
+static int Decompress_ADPCM_stereo(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ *pcbOutBuffer = DecompressADPCM((unsigned char *)pbOutBuffer, *pcbOutBuffer, (unsigned char *)pbInBuffer, cbInBuffer, 2);
+ return 1;
+}
+
+/*****************************************************************************/
+/* */
+/* SCompImplode */
+/* */
+/*****************************************************************************/
+
+int WINAPI SCompImplode(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ int cbOutBuffer = *pcbOutBuffer;
+
+ // Check for valid parameters
+ if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pbOutBuffer || !pbInBuffer)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ // Perform the compression
+ Compress_PKLIB(pbOutBuffer, &cbOutBuffer, pbInBuffer, cbInBuffer, NULL, 0);
+
+ // If the compression was unsuccessful, copy the data as-is
+ if(cbOutBuffer >= *pcbOutBuffer)
+ {
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ cbOutBuffer = *pcbOutBuffer;
+ }
+
+ *pcbOutBuffer = cbOutBuffer;
+ return 1;
+}
+
+/*****************************************************************************/
+/* */
+/* SCompExplode */
+/* */
+/*****************************************************************************/
+
+int WINAPI SCompExplode(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ int cbOutBuffer = *pcbOutBuffer;
+
+ // Check for valid parameters
+ if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pbOutBuffer || !pbInBuffer)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ // If the input length is the same as output length, do nothing.
+ if(cbInBuffer == cbOutBuffer)
+ {
+ // If the buffers are equal, don't copy anything.
+ if(pbInBuffer == pbOutBuffer)
+ return 1;
+
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ return 1;
+ }
+
+ // Perform decompression
+ if(!Decompress_PKLIB(pbOutBuffer, &cbOutBuffer, pbInBuffer, cbInBuffer))
+ {
+ SetLastError(ERROR_FILE_CORRUPT);
+ return false;
+ }
+
+ *pcbOutBuffer = cbOutBuffer;
+ return 1;
+}
+
+/*****************************************************************************/
+/* */
+/* SCompCompress */
+/* */
+/*****************************************************************************/
+
+// This table contains compress functions which can be applied to
+// uncompressed data. Each bit means the corresponding
+// compression method/function must be applied.
+//
+// WAVes compression Data compression
+// ------------------ -------------------
+// 1st sector - 0x08 0x08 (D, HF, W2, SC, D2)
+// Next sectors - 0x81 0x02 (W3)
+
+static TCompressTable cmp_table[] =
+{
+ {MPQ_COMPRESSION_SPARSE, Compress_SPARSE}, // Sparse compression
+ {MPQ_COMPRESSION_ADPCM_MONO, Compress_ADPCM_mono}, // IMA ADPCM mono compression
+ {MPQ_COMPRESSION_ADPCM_STEREO, Compress_ADPCM_stereo}, // IMA ADPCM stereo compression
+ {MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression
+ {MPQ_COMPRESSION_ZLIB, Compress_ZLIB}, // Compression with the "zlib" library
+ {MPQ_COMPRESSION_PKWARE, Compress_PKLIB}, // Compression with Pkware DCL
+ {MPQ_COMPRESSION_BZIP2, Compress_BZIP2} // Compression Bzip2 library
+};
+
+int WINAPI SCompCompress(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer,
+ unsigned uCompressionMask,
+ int nCmpType,
+ int nCmpLevel)
+{
+ COMPRESS CompressFuncArray[0x10]; // Array of compression functions, applied sequentially
+ unsigned char CompressByte[0x10]; // CompressByte for each method in the CompressFuncArray array
+ char * pbWorkBuffer = NULL; // Temporary storage for decompressed data
+ char * pbOutput = pbOutBuffer; // Current output buffer
+ char * pbInput = pbInBuffer; // Current input buffer
+ int nCompressCount = 0;
+ int nCompressIndex = 0;
+ int nAtLeastOneCompressionDone = 0;
+ int cbOutBuffer = 0;
+ int cbInLength = cbInBuffer;
+ int nResult = 1;
+
+ // Check for valid parameters
+ if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pbOutBuffer || !pbInBuffer)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ // Zero input length brings zero output length
+ if(cbInBuffer == 0)
+ {
+ *pcbOutBuffer = 0;
+ return true;
+ }
+
+ // Setup the compression function array
+ if(uCompressionMask == MPQ_COMPRESSION_LZMA)
+ {
+ CompressFuncArray[0] = Compress_LZMA;
+ CompressByte[0] = (char)uCompressionMask;
+ nCompressCount = 1;
+ }
+ else
+ {
+ // Fill the compressions array
+ for(size_t i = 0; i < (sizeof(cmp_table) / sizeof(TCompressTable)); i++)
+ {
+ // If the mask agrees, insert the compression function to the array
+ if(uCompressionMask & cmp_table[i].uMask)
+ {
+ CompressFuncArray[nCompressCount] = cmp_table[i].Compress;
+ CompressByte[nCompressCount] = (unsigned char)cmp_table[i].uMask;
+ uCompressionMask &= ~cmp_table[i].uMask;
+ nCompressCount++;
+ }
+ }
+
+ // If at least one of the compressions remaing unknown, return an error
+ if(uCompressionMask != 0)
+ {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return 0;
+ }
+ }
+
+ // If there is at least one compression, do it
+ if(nCompressCount > 0)
+ {
+ // If we need to do more than 1 compression, allocate intermediate buffer
+ if(nCompressCount > 1)
+ {
+ pbWorkBuffer = STORM_ALLOC(char, *pcbOutBuffer);
+ if(pbWorkBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+
+ // Get the current compression index
+ nCompressIndex = nCompressCount - 1;
+
+ // Perform all compressions in the array
+ for(int i = 0; i < nCompressCount; i++)
+ {
+ // Choose the proper output buffer
+ pbOutput = (nCompressIndex & 1) ? pbWorkBuffer : pbOutBuffer;
+ nCompressIndex--;
+
+ // Perform the (next) compression
+ // Note that if the compression method is unable to compress the input data block
+ // by at least 2 bytes, we consider it as failure and will use source data instead
+ cbOutBuffer = *pcbOutBuffer - 1;
+ CompressFuncArray[i](pbOutput + 1, &cbOutBuffer, pbInput, cbInLength, &nCmpType, nCmpLevel);
+
+ // If the compression failed, we copy the input buffer as-is.
+ // Note that there is one extra byte at the end of the intermediate buffer, so it should be OK
+ if(cbOutBuffer > (cbInLength - 2))
+ {
+ memcpy(pbOutput + nAtLeastOneCompressionDone, pbInput, cbInLength);
+ cbOutBuffer = cbInLength;
+ }
+ else
+ {
+ // Remember that we have done at least one compression
+ nAtLeastOneCompressionDone = 1;
+ uCompressionMask |= CompressByte[i];
+ }
+
+ // Now point input buffer to the output buffer
+ pbInput = pbOutput + nAtLeastOneCompressionDone;
+ cbInLength = cbOutBuffer;
+ }
+
+ // If at least one compression succeeded, put the compression
+ // mask to the begin of the output buffer
+ if(nAtLeastOneCompressionDone)
+ *pbOutBuffer = (char)uCompressionMask;
+ *pcbOutBuffer = cbOutBuffer + nAtLeastOneCompressionDone;
+ }
+ else
+ {
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ *pcbOutBuffer = cbInBuffer;
+ }
+
+ // Cleanup and return
+ if(pbWorkBuffer != NULL)
+ STORM_FREE(pbWorkBuffer);
+ return nResult;
+}
+
+/*****************************************************************************/
+/* */
+/* SCompDecompress */
+/* */
+/*****************************************************************************/
+
+// This table contains decompress functions which can be applied to
+// uncompressed data. The compression mask is stored in the first byte
+// of compressed data
+static TDecompressTable dcmp_table[] =
+{
+ {MPQ_COMPRESSION_BZIP2, Decompress_BZIP2}, // Decompression with Bzip2 library
+ {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library
+ {MPQ_COMPRESSION_ZLIB, Decompress_ZLIB}, // Decompression with the "zlib" library
+ {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression
+ {MPQ_COMPRESSION_ADPCM_STEREO, Decompress_ADPCM_stereo}, // IMA ADPCM stereo decompression
+ {MPQ_COMPRESSION_ADPCM_MONO, Decompress_ADPCM_mono}, // IMA ADPCM mono decompression
+ {MPQ_COMPRESSION_SPARSE, Decompress_SPARSE} // Sparse decompression
+};
+
+int WINAPI SCompDecompress(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer)
+{
+ char * pbWorkBuffer = NULL; // Temporary storage for decompressed data
+ char * pbOutput = pbOutBuffer; // Where to store decompressed data
+ char * pbInput; // Where to store decompressed data
+ unsigned uCompressionMask; // Decompressions applied to the data
+ unsigned uCompressionCopy; // Decompressions applied to the data
+ int cbOutBuffer = *pcbOutBuffer; // Current size of the output buffer
+ int cbInLength; // Current size of the input buffer
+ int nCompressCount = 0; // Number of compressions to be applied
+ int nCompressIndex = 0;
+ int nResult = 1;
+
+ // Verify buffer sizes
+ if(cbOutBuffer < cbInBuffer || cbInBuffer < 1)
+ return 0;
+
+ // If the input length is the same as output length, do nothing.
+ if(cbOutBuffer == cbInBuffer)
+ {
+ // If the buffers are equal, don't copy anything.
+ if(pbInBuffer != pbOutBuffer)
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ return 1;
+ }
+
+ // Get applied compression types and decrement data length
+ uCompressionMask = uCompressionCopy = (unsigned char)*pbInBuffer++;
+ cbInBuffer--;
+
+ // Get current compressed data and length of it
+ pbInput = pbInBuffer;
+ cbInLength = cbInBuffer;
+
+ // This compression function doesn't support LZMA
+ assert(uCompressionMask != MPQ_COMPRESSION_LZMA);
+
+ // Parse the compression mask
+ for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++)
+ {
+ // If the mask agrees, insert the compression function to the array
+ if(uCompressionMask & dcmp_table[i].uMask)
+ {
+ uCompressionCopy &= ~dcmp_table[i].uMask;
+ nCompressCount++;
+ }
+ }
+
+ // If at least one of the compressions remaing unknown, return an error
+ if(nCompressCount == 0 || uCompressionCopy != 0)
+ {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return 0;
+ }
+
+ // If there is more than one compression, we have to allocate extra buffer
+ if(nCompressCount > 1)
+ {
+ pbWorkBuffer = STORM_ALLOC(char, cbOutBuffer);
+ if(pbWorkBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+
+ // Get the current compression index
+ nCompressIndex = nCompressCount - 1;
+
+ // Apply all decompressions
+ for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++)
+ {
+ // Perform the (next) decompression
+ if(uCompressionMask & dcmp_table[i].uMask)
+ {
+ // Get the correct output buffer
+ pbOutput = (nCompressIndex & 1) ? pbWorkBuffer : pbOutBuffer;
+ nCompressIndex--;
+
+ // Perform the decompression
+ cbOutBuffer = *pcbOutBuffer;
+ nResult = dcmp_table[i].Decompress(pbOutput, &cbOutBuffer, pbInput, cbInLength);
+ if(nResult == 0 || cbOutBuffer == 0)
+ {
+ SetLastError(ERROR_FILE_CORRUPT);
+ nResult = 0;
+ break;
+ }
+
+ // Switch buffers
+ cbInLength = cbOutBuffer;
+ pbInput = pbOutput;
+ }
+ }
+
+ // Put the length of the decompressed data to the output buffer
+ *pcbOutBuffer = cbOutBuffer;
+
+ // Cleanup and return
+ if(pbWorkBuffer != NULL)
+ STORM_FREE(pbWorkBuffer);
+ return nResult;
+}
+
+int WINAPI SCompDecompress2(
+ char * pbOutBuffer,
+ int * pcbOutBuffer,
+ char * pbInBuffer,
+ int cbInBuffer)
+{
+ DECOMPRESS pfnDecompress1 = NULL;
+ DECOMPRESS pfnDecompress2 = NULL;
+ char * pbWorkBuffer = pbOutBuffer;
+ int cbWorkBuffer = *pcbOutBuffer;
+ int nResult;
+ char CompressionMethod;
+
+ // Verify buffer sizes
+ if(*pcbOutBuffer < cbInBuffer || cbInBuffer < 1)
+ return 0;
+
+ // If the outputbuffer is as big as input buffer, just copy the block
+ if(*pcbOutBuffer == cbInBuffer)
+ {
+ if(pbOutBuffer != pbInBuffer)
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ return 1;
+ }
+
+ // Get the compression methods
+ CompressionMethod = *pbInBuffer++;
+ cbInBuffer--;
+
+ // We only recognize a fixed set of compression methods
+ switch((unsigned char)CompressionMethod)
+ {
+ case MPQ_COMPRESSION_ZLIB:
+ pfnDecompress1 = Decompress_ZLIB;
+ break;
+
+ case MPQ_COMPRESSION_PKWARE:
+ pfnDecompress1 = Decompress_PKLIB;
+ break;
+
+ case MPQ_COMPRESSION_BZIP2:
+ pfnDecompress1 = Decompress_BZIP2;
+ break;
+
+ case MPQ_COMPRESSION_LZMA:
+ pfnDecompress1 = Decompress_LZMA;
+ break;
+
+ case MPQ_COMPRESSION_SPARSE:
+ pfnDecompress1 = Decompress_SPARSE;
+ break;
+
+ case (MPQ_COMPRESSION_SPARSE | MPQ_COMPRESSION_ZLIB):
+ pfnDecompress1 = Decompress_ZLIB;
+ pfnDecompress2 = Decompress_SPARSE;
+ break;
+
+ case (MPQ_COMPRESSION_SPARSE | MPQ_COMPRESSION_BZIP2):
+ pfnDecompress1 = Decompress_BZIP2;
+ pfnDecompress2 = Decompress_SPARSE;
+ break;
+
+ //
+ // Note: Any combination including MPQ_COMPRESSION_ADPCM_MONO,
+ // MPQ_COMPRESSION_ADPCM_STEREO or MPQ_COMPRESSION_HUFFMANN
+ // is not supported by newer MPQs.
+ //
+
+ default:
+ SetLastError(ERROR_FILE_CORRUPT);
+ return 0;
+ }
+
+ // If we have to use two decompressions, allocate temporary buffer
+ if(pfnDecompress2 != NULL)
+ {
+ pbWorkBuffer = STORM_ALLOC(char, *pcbOutBuffer);
+ if(pbWorkBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+
+ // Apply the first decompression method
+ nResult = pfnDecompress1(pbWorkBuffer, &cbWorkBuffer, pbInBuffer, cbInBuffer);
+
+ // Apply the second decompression method, if any
+ if(pfnDecompress2 != NULL && nResult != 0)
+ {
+ cbInBuffer = cbWorkBuffer;
+ cbWorkBuffer = *pcbOutBuffer;
+ nResult = pfnDecompress2(pbOutBuffer, &cbWorkBuffer, pbWorkBuffer, cbInBuffer);
+ }
+
+ // Supply the output buffer size
+ *pcbOutBuffer = cbWorkBuffer;
+
+ // Free temporary buffer
+ if(pbWorkBuffer != pbOutBuffer)
+ STORM_FREE(pbWorkBuffer);
+
+ if(nResult == 0)
+ SetLastError(ERROR_FILE_CORRUPT);
+ return nResult;
+}
diff --git a/dep/StormLib/src/SFileAddFile.cpp b/dep/StormLib/src/SFileAddFile.cpp
new file mode 100644
index 00000000000..dda47370bd1
--- /dev/null
+++ b/dep/StormLib/src/SFileAddFile.cpp
@@ -0,0 +1,1286 @@
+/*****************************************************************************/
+/* SFileAddFile.cpp Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* MPQ Editing functions */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 27.03.10 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+#define FILE_SIGNATURE_RIFF 0x46464952
+#define FILE_SIGNATURE_WAVE 0x45564157
+#define FILE_SIGNATURE_FMT 0x20746D66
+#define AUDIO_FORMAT_PCM 1
+
+typedef struct _WAVE_FILE_HEADER
+{
+ DWORD dwChunkId; // 0x52494646 ("RIFF")
+ DWORD dwChunkSize; // Size of that chunk, in bytes
+ DWORD dwFormat; // Must be 0x57415645 ("WAVE")
+
+ // Format sub-chunk
+ DWORD dwSubChunk1Id; // 0x666d7420 ("fmt ")
+ DWORD dwSubChunk1Size; // 0x16 for PCM
+ USHORT wAudioFormat; // 1 = PCM. Other value means some sort of compression
+ USHORT wChannels; // Number of channels
+ DWORD dwSampleRate; // 8000, 44100, etc.
+ DWORD dwBytesRate; // SampleRate * NumChannels * BitsPerSample/8
+ USHORT wBlockAlign; // NumChannels * BitsPerSample/8
+ USHORT wBitsPerSample; // 8 bits = 8, 16 bits = 16, etc.
+
+ // Followed by "data" sub-chunk (we don't care)
+} WAVE_FILE_HEADER, *PWAVE_FILE_HEADER;
+
+//-----------------------------------------------------------------------------
+// Local variables
+
+// Data compression for SFileAddFile
+// Kept here for compatibility with code that was created with StormLib version < 6.50
+static DWORD DefaultDataCompression = MPQ_COMPRESSION_PKWARE;
+
+static SFILE_ADDFILE_CALLBACK AddFileCB = NULL;
+static void * pvUserData = NULL;
+
+//-----------------------------------------------------------------------------
+// MPQ write data functions
+
+#define LOSSY_COMPRESSION_MASK (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN)
+
+static int IsWaveFile(
+ LPBYTE pbFileData,
+ DWORD cbFileData,
+ LPDWORD pdwChannels)
+{
+ PWAVE_FILE_HEADER pWaveHdr = (PWAVE_FILE_HEADER)pbFileData;
+
+ if(cbFileData > sizeof(WAVE_FILE_HEADER))
+ {
+ if(pWaveHdr->dwChunkId == FILE_SIGNATURE_RIFF && pWaveHdr->dwFormat == FILE_SIGNATURE_WAVE)
+ {
+ if(pWaveHdr->dwSubChunk1Id == FILE_SIGNATURE_FMT && pWaveHdr->wAudioFormat == AUDIO_FORMAT_PCM)
+ {
+ *pdwChannels = pWaveHdr->wChannels;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static int WriteDataToMpqFile(
+ TMPQArchive * ha,
+ TMPQFile * hf,
+ LPBYTE pbFileData,
+ DWORD dwDataSize,
+ DWORD dwCompression)
+{
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ ULONGLONG ByteOffset;
+ LPBYTE pbCompressed = NULL; // Compressed (target) data
+ LPBYTE pbToWrite = NULL; // Data to write to the file
+ int nCompressionLevel = -1; // ADPCM compression level (only used for wave files)
+ int nError = ERROR_SUCCESS;
+
+ // If the caller wants ADPCM compression, we will set wave compression level to 4,
+ // which corresponds to medium quality
+ if(dwCompression & LOSSY_COMPRESSION_MASK)
+ nCompressionLevel = 4;
+
+ // Make sure that the caller won't overrun the previously initiated file size
+ assert(hf->dwFilePos + dwDataSize <= pFileEntry->dwFileSize);
+ assert(hf->dwSectorCount != 0);
+ assert(hf->pbFileSector != NULL);
+ if((hf->dwFilePos + dwDataSize) > pFileEntry->dwFileSize)
+ return ERROR_DISK_FULL;
+ pbToWrite = hf->pbFileSector;
+
+ // Now write all data to the file sector buffer
+ if(nError == ERROR_SUCCESS)
+ {
+ DWORD dwBytesInSector = hf->dwFilePos % hf->dwSectorSize;
+ DWORD dwSectorIndex = hf->dwFilePos / hf->dwSectorSize;
+ DWORD dwBytesToCopy;
+
+ // Process all data.
+ while(dwDataSize != 0)
+ {
+ dwBytesToCopy = dwDataSize;
+
+ // Check for sector overflow
+ if(dwBytesToCopy > (hf->dwSectorSize - dwBytesInSector))
+ dwBytesToCopy = (hf->dwSectorSize - dwBytesInSector);
+
+ // Copy the data to the file sector
+ memcpy(hf->pbFileSector + dwBytesInSector, pbFileData, dwBytesToCopy);
+ dwBytesInSector += dwBytesToCopy;
+ pbFileData += dwBytesToCopy;
+ dwDataSize -= dwBytesToCopy;
+
+ // Update the file position
+ hf->dwFilePos += dwBytesToCopy;
+
+ // If the current sector is full, or if the file is already full,
+ // then write the data to the MPQ
+ if(dwBytesInSector >= hf->dwSectorSize || hf->dwFilePos >= pFileEntry->dwFileSize)
+ {
+ // Set the position in the file
+ ByteOffset = hf->RawFilePos + pFileEntry->dwCmpSize;
+
+ // Update CRC32 and MD5 of the file
+ md5_process((hash_state *)hf->hctx, hf->pbFileSector, dwBytesInSector);
+ hf->dwCrc32 = crc32(hf->dwCrc32, hf->pbFileSector, dwBytesInSector);
+
+ // Compress the file sector, if needed
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ {
+ int nOutBuffer = (int)dwBytesInSector;
+ int nInBuffer = (int)dwBytesInSector;
+
+ // If the file is compressed, allocate buffer for the compressed data.
+ // Note that we allocate buffer that is a bit longer than sector size,
+ // for case if the compression method performs a buffer overrun
+ if(pbCompressed == NULL)
+ {
+ pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100);
+ if(pbCompressed == NULL)
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ }
+
+ //
+ // Note that both SCompImplode and SCompCompress give original buffer,
+ // if they are unable to comperss the data.
+ //
+
+ if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
+ {
+ SCompImplode((char *)pbCompressed,
+ &nOutBuffer,
+ (char *)hf->pbFileSector,
+ nInBuffer);
+ }
+
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
+ {
+ SCompCompress((char *)pbCompressed,
+ &nOutBuffer,
+ (char *)hf->pbFileSector,
+ nInBuffer,
+ (unsigned)dwCompression,
+ 0,
+ nCompressionLevel);
+ }
+
+ // Update sector positions
+ dwBytesInSector = nOutBuffer;
+ if(hf->SectorOffsets != NULL)
+ hf->SectorOffsets[dwSectorIndex+1] = hf->SectorOffsets[dwSectorIndex] + dwBytesInSector;
+
+ // We have to calculate sector CRC, if enabled
+ if(hf->SectorChksums != NULL)
+ hf->SectorChksums[dwSectorIndex] = adler32(0, pbCompressed, nOutBuffer);
+ }
+
+ // Encrypt the sector, if necessary
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector);
+ EncryptMpqBlock(pbToWrite, dwBytesInSector, hf->dwFileKey + dwSectorIndex);
+ BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector);
+ }
+
+ // Write the file sector
+ if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Call the compact callback, if any
+ if(AddFileCB != NULL)
+ AddFileCB(pvUserData, hf->dwFilePos, hf->dwDataSize, false);
+
+ // Update the compressed file size
+ pFileEntry->dwCmpSize += dwBytesInSector;
+ dwBytesInSector = 0;
+ dwSectorIndex++;
+ }
+ }
+ }
+
+ // Cleanup
+ if(pbCompressed != NULL)
+ STORM_FREE(pbCompressed);
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Recrypts file data for file renaming
+
+static int RecryptFileData(
+ TMPQArchive * ha,
+ TMPQFile * hf,
+ const char * szFileName,
+ const char * szNewFileName)
+{
+ ULONGLONG RawFilePos;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ DWORD dwBytesToRecrypt = pFileEntry->dwCmpSize;
+ DWORD dwOldKey;
+ DWORD dwNewKey;
+ int nError = ERROR_SUCCESS;
+
+ // The file must be encrypted
+ assert(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED);
+
+ // File decryption key is calculated from the plain name
+ szNewFileName = GetPlainFileNameA(szNewFileName);
+ szFileName = GetPlainFileNameA(szFileName);
+
+ // Calculate both file keys
+ dwOldKey = DecryptFileKey(szFileName, pFileEntry->ByteOffset, pFileEntry->dwFileSize, pFileEntry->dwFlags);
+ dwNewKey = DecryptFileKey(szNewFileName, pFileEntry->ByteOffset, pFileEntry->dwFileSize, pFileEntry->dwFlags);
+
+ // Incase the keys are equal, don't recrypt the file
+ if(dwNewKey == dwOldKey)
+ return ERROR_SUCCESS;
+ hf->dwFileKey = dwOldKey;
+
+ // Calculate the raw position of the file in the archive
+ hf->MpqFilePos = pFileEntry->ByteOffset;
+ hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
+
+ // Allocate buffer for file transfer
+ nError = AllocateSectorBuffer(hf);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ // Also allocate buffer for sector offsets
+ // Note: Don't load sector checksums, we don't need to recrypt them
+ nError = AllocateSectorOffsets(hf, true);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ // If we have sector offsets, recrypt these as well
+ if(hf->SectorOffsets != NULL)
+ {
+ // Allocate secondary buffer for sectors copy
+ DWORD * SectorOffsetsCopy = (DWORD *)STORM_ALLOC(BYTE, hf->SectorOffsets[0]);
+ DWORD dwSectorOffsLen = hf->SectorOffsets[0];
+
+ if(SectorOffsetsCopy == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Recrypt the array of sector offsets
+ memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorOffsLen);
+ EncryptMpqBlock(SectorOffsetsCopy, dwSectorOffsLen, dwNewKey - 1);
+ BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen);
+
+ // Write the recrypted array back
+ if(!FileStream_Write(ha->pStream, &hf->RawFilePos, SectorOffsetsCopy, dwSectorOffsLen))
+ nError = GetLastError();
+ STORM_FREE(SectorOffsetsCopy);
+ }
+
+ // Now we have to recrypt all file sectors. We do it without
+ // recompression, because recompression is not necessary in this case
+ if(nError == ERROR_SUCCESS)
+ {
+ for(DWORD dwSector = 0; dwSector < hf->dwSectorCount; dwSector++)
+ {
+ DWORD dwRawDataInSector = hf->dwSectorSize;
+ DWORD dwRawByteOffset = dwSector * hf->dwSectorSize;
+
+ // Last sector: If there is not enough bytes remaining in the file, cut the raw size
+ if(dwRawDataInSector > dwBytesToRecrypt)
+ dwRawDataInSector = dwBytesToRecrypt;
+
+ // Fix the raw data length if the file is compressed
+ if(hf->SectorOffsets != NULL)
+ {
+ dwRawDataInSector = hf->SectorOffsets[dwSector+1] - hf->SectorOffsets[dwSector];
+ dwRawByteOffset = hf->SectorOffsets[dwSector];
+ }
+
+ // Calculate the raw file offset of the file sector
+ CalculateRawSectorOffset(RawFilePos, hf, dwRawByteOffset);
+
+ // Read the file sector
+ if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // If necessary, re-encrypt the sector
+ // Note: Recompression is not necessary here. Unlike encryption,
+ // the compression does not depend on the position of the file in MPQ.
+ BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
+ DecryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwOldKey + dwSector);
+ EncryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwNewKey + dwSector);
+ BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
+
+ // Write the sector back
+ if(!FileStream_Write(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Decrement number of bytes remaining
+ dwBytesToRecrypt -= hf->dwSectorSize;
+ }
+ }
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Support functions for adding files to the MPQ
+
+int SFileAddFile_Init(
+ TMPQArchive * ha,
+ const char * szFileName,
+ ULONGLONG FileTime,
+ DWORD dwFileSize,
+ LCID lcLocale,
+ DWORD dwFlags,
+ TMPQFile ** phf)
+{
+ TFileEntry * pFileEntry = NULL;
+ ULONGLONG TempPos; // For various file offset calculations
+ TMPQFile * hf = NULL; // File structure for newly added file
+ int nError = ERROR_SUCCESS;
+
+ //
+ // Note: This is an internal function so no validity checks are done.
+ // It is the caller's responsibility to make sure that no invalid
+ // flags get to this point
+ //
+
+ // Sestor CRC is not allowed with single unit files
+ if(dwFlags & MPQ_FILE_SINGLE_UNIT)
+ dwFlags &= ~MPQ_FILE_SECTOR_CRC;
+
+ // Sector CRC is not allowed if the file is not compressed
+ if(!(dwFlags & MPQ_FILE_COMPRESSED))
+ dwFlags &= ~MPQ_FILE_SECTOR_CRC;
+
+ // Fix Key is not allowed if the file is not enrypted
+ if(!(dwFlags & MPQ_FILE_ENCRYPTED))
+ dwFlags &= ~MPQ_FILE_FIX_KEY;
+
+ // If the MPQ is of version 3.0 or higher, we ignore file locale.
+ // This is because HET and BET tables have no known support for it
+ if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_3)
+ lcLocale = 0;
+
+ // Allocate the TMPQFile entry for newly added file
+ hf = CreateMpqFile(ha);
+ if(hf == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ // Find a free space in the MPQ, as well as free block table entry
+ if(nError == ERROR_SUCCESS)
+ {
+ // Find the position where the file will be stored
+ FindFreeMpqSpace(ha, &hf->MpqFilePos);
+ hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
+ hf->bIsWriteHandle = true;
+
+ // Sanity check: The MPQ must be marked as changed at this point
+ assert((ha->dwFlags & MPQ_FLAG_CHANGED) != 0);
+
+ // When format V1, the size of the archive cannot exceed 4 GB
+ if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
+ {
+ TempPos = hf->MpqFilePos + dwFileSize;
+ TempPos += ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
+ TempPos += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ TempPos += ha->pHeader->dwBlockTableSize * sizeof(USHORT);
+ if((TempPos >> 32) != 0)
+ nError = ERROR_DISK_FULL;
+ }
+ }
+
+ // Allocate file entry in the MPQ
+ if(nError == ERROR_SUCCESS)
+ {
+ // Check if the file already exists in the archive
+ pFileEntry = GetFileEntryExact(ha, szFileName, lcLocale);
+ if(pFileEntry == NULL)
+ {
+ pFileEntry = AllocateFileEntry(ha, szFileName, lcLocale);
+ if(pFileEntry == NULL)
+ nError = ERROR_DISK_FULL;
+ }
+ else
+ {
+ // If the file exists and "replace existing" is not set, fail it
+ if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0)
+ nError = ERROR_ALREADY_EXISTS;
+
+ // If the file entry already contains a file
+ // and it is a pseudo-name, replace it
+ if(nError == ERROR_SUCCESS)
+ {
+ AllocateFileName(pFileEntry, szFileName);
+ }
+ }
+ }
+
+ //
+ // At this point, the file name in file entry must be non-NULL
+ //
+
+ // Create key for file encryption
+ if(nError == ERROR_SUCCESS && (dwFlags & MPQ_FILE_ENCRYPTED))
+ {
+ hf->dwFileKey = DecryptFileKey(szFileName, hf->MpqFilePos, dwFileSize, dwFlags);
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ // Initialize the hash entry for the file
+ hf->pFileEntry = pFileEntry;
+ hf->dwDataSize = dwFileSize;
+
+ // Initialize the block table entry for the file
+ pFileEntry->ByteOffset = hf->MpqFilePos;
+ pFileEntry->dwFileSize = dwFileSize;
+ pFileEntry->dwCmpSize = 0;
+ pFileEntry->dwFlags = dwFlags | MPQ_FILE_EXISTS;
+ pFileEntry->lcLocale = (USHORT)lcLocale;
+
+ // Initialize the file time, CRC32 and MD5
+ assert(sizeof(hf->hctx) >= sizeof(hash_state));
+ memset(pFileEntry->md5, 0, MD5_DIGEST_SIZE);
+ md5_init((hash_state *)hf->hctx);
+ pFileEntry->dwCrc32 = crc32(0, Z_NULL, 0);
+
+ // If the caller gave us a file time, use it.
+ pFileEntry->FileTime = FileTime;
+
+ // Call the callback, if needed
+ if(AddFileCB != NULL)
+ AddFileCB(pvUserData, 0, hf->dwDataSize, false);
+ }
+
+ // If an error occured, remember it
+ if(nError != ERROR_SUCCESS)
+ hf->bErrorOccured = true;
+ *phf = hf;
+ return nError;
+}
+
+int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD dwCompression)
+{
+ TMPQArchive * ha;
+ TFileEntry * pFileEntry;
+ int nError = ERROR_SUCCESS;
+
+ // Don't bother if the caller gave us zero size
+ if(pvData == NULL || dwSize == 0)
+ return ERROR_SUCCESS;
+
+ // Get pointer to the MPQ archive
+ pFileEntry = hf->pFileEntry;
+ ha = hf->ha;
+
+ // Allocate file buffers
+ if(hf->pbFileSector == NULL)
+ {
+ ULONGLONG RawFilePos = hf->RawFilePos;
+
+ // Allocate buffer for file sector
+ nError = AllocateSectorBuffer(hf);
+ if(nError != ERROR_SUCCESS)
+ {
+ hf->bErrorOccured = true;
+ return nError;
+ }
+
+ // Allocate patch info, if the data is patch
+ if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize))
+ {
+ // Set the MPQ_FILE_PATCH_FILE flag
+ hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE;
+
+ // Allocate the patch info
+ nError = AllocatePatchInfo(hf, false);
+ if(nError != ERROR_SUCCESS)
+ {
+ hf->bErrorOccured = true;
+ return nError;
+ }
+ }
+
+ // Allocate sector offsets
+ if(hf->SectorOffsets == NULL)
+ {
+ nError = AllocateSectorOffsets(hf, false);
+ if(nError != ERROR_SUCCESS)
+ {
+ hf->bErrorOccured = true;
+ return nError;
+ }
+ }
+
+ // Create array of sector checksums
+ if(hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC))
+ {
+ nError = AllocateSectorChecksums(hf, false);
+ if(nError != ERROR_SUCCESS)
+ {
+ hf->bErrorOccured = true;
+ return nError;
+ }
+ }
+
+ // Pre-save the patch info, if any
+ if(hf->pPatchInfo != NULL)
+ {
+ if(!FileStream_Write(ha->pStream, &RawFilePos, hf->pPatchInfo, hf->pPatchInfo->dwLength))
+ nError = GetLastError();
+
+ pFileEntry->dwCmpSize += hf->pPatchInfo->dwLength;
+ RawFilePos += hf->pPatchInfo->dwLength;
+ }
+
+ // Pre-save the sector offset table, just to reserve space in the file.
+ // Note that we dont need to swap the sector positions, nor encrypt the table
+ // at the moment, as it will be written again after writing all file sectors.
+ if(hf->SectorOffsets != NULL)
+ {
+ if(!FileStream_Write(ha->pStream, &RawFilePos, hf->SectorOffsets, hf->SectorOffsets[0]))
+ nError = GetLastError();
+
+ pFileEntry->dwCmpSize += hf->SectorOffsets[0];
+ RawFilePos += hf->SectorOffsets[0];
+ }
+ }
+
+ // Write the MPQ data to the file
+ if(nError == ERROR_SUCCESS)
+ nError = WriteDataToMpqFile(ha, hf, (LPBYTE)pvData, dwSize, dwCompression);
+
+ // If it succeeded and we wrote all the file data,
+ // we need to re-save sector offset table
+ if(nError == ERROR_SUCCESS)
+ {
+ if(hf->dwFilePos >= pFileEntry->dwFileSize)
+ {
+ // Finish calculating CRC32
+ hf->pFileEntry->dwCrc32 = hf->dwCrc32;
+
+ // Finish calculating MD5
+ md5_done((hash_state *)hf->hctx, hf->pFileEntry->md5);
+
+ // If we also have sector checksums, write them to the file
+ if(hf->SectorChksums != NULL)
+ {
+ nError = WriteSectorChecksums(hf);
+ if(nError != ERROR_SUCCESS)
+ hf->bErrorOccured = true;
+ }
+
+ // Now write patch info
+ if(hf->pPatchInfo != NULL)
+ {
+ memcpy(hf->pPatchInfo->md5, hf->pFileEntry->md5, MD5_DIGEST_SIZE);
+ hf->pPatchInfo->dwDataSize = hf->pFileEntry->dwFileSize;
+ hf->pFileEntry->dwFileSize = hf->dwPatchedFileSize;
+ nError = WritePatchInfo(hf);
+ if(nError != ERROR_SUCCESS)
+ hf->bErrorOccured = true;
+ }
+
+ // Now write sector offsets to the file
+ if(hf->SectorOffsets != NULL)
+ {
+ nError = WriteSectorOffsets(hf);
+ if(nError != ERROR_SUCCESS)
+ hf->bErrorOccured = true;
+ }
+
+ // Write the MD5 hashes of each file chunk, if required
+ if(ha->pHeader->dwRawChunkSize != 0)
+ {
+ nError = WriteMpqDataMD5(ha->pStream,
+ ha->MpqPos + hf->pFileEntry->ByteOffset,
+ hf->pFileEntry->dwCmpSize,
+ ha->pHeader->dwRawChunkSize);
+ if(nError != ERROR_SUCCESS)
+ hf->bErrorOccured = true;
+ }
+ }
+ }
+ else
+ {
+ hf->bErrorOccured = true;
+ }
+
+ return nError;
+}
+
+int SFileAddFile_Finish(TMPQFile * hf)
+{
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ int nError = ERROR_SUCCESS;
+
+ // If all previous operations succeeded, we can update the MPQ
+ if(!hf->bErrorOccured)
+ {
+ // Verify if the caller wrote the file properly
+ if(hf->pPatchInfo == NULL)
+ {
+ assert(pFileEntry != NULL);
+ if(hf->dwFilePos != pFileEntry->dwFileSize)
+ {
+ nError = ERROR_CAN_NOT_COMPLETE;
+ hf->bErrorOccured = true;
+ }
+ }
+ else
+ {
+ if(hf->dwFilePos != hf->pPatchInfo->dwDataSize)
+ {
+ nError = ERROR_CAN_NOT_COMPLETE;
+ hf->bErrorOccured = true;
+ }
+ }
+ }
+
+ if(!hf->bErrorOccured)
+ {
+ // Call the user callback, if any
+ if(AddFileCB != NULL)
+ AddFileCB(pvUserData, hf->dwDataSize, hf->dwDataSize, true);
+
+ // Update the size of the block table
+ ha->pHeader->dwBlockTableSize = ha->dwFileTableSize;
+ }
+ else
+ {
+ // Free the file entry in MPQ tables
+ if(pFileEntry != NULL)
+ FreeFileEntry(ha, pFileEntry);
+ }
+
+ // Clear the add file callback
+ FreeMPQFile(hf);
+ pvUserData = NULL;
+ AddFileCB = NULL;
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Adds data as file to the archive
+
+bool WINAPI SFileCreateFile(
+ HANDLE hMpq,
+ const char * szArchivedName,
+ ULONGLONG FileTime,
+ DWORD dwFileSize,
+ LCID lcLocale,
+ DWORD dwFlags,
+ HANDLE * phFile)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ int nError = ERROR_SUCCESS;
+
+ // Check valid parameters
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szArchivedName == NULL || *szArchivedName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+ if(phFile == NULL)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Don't allow to add file if the MPQ is open for read only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ nError = ERROR_ACCESS_DENIED;
+
+ // Don't allow to add a file under pseudo-file name
+ if(IsPseudoFileName(szArchivedName, NULL))
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Don't allow to add any of the internal files
+ if(IsInternalMpqFileName(szArchivedName))
+ nError = ERROR_INTERNAL_FILE;
+
+ // Perform validity check of the MPQ flags
+ if(nError == ERROR_SUCCESS)
+ {
+ // Mask all unsupported flags out
+ dwFlags &= MPQ_FILE_VALID_FLAGS;
+
+ // Check for valid flag combinations
+ if((dwFlags & (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) == (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS))
+ nError = ERROR_INVALID_PARAMETER;
+ }
+
+ // Create the file in MPQ
+ if(nError == ERROR_SUCCESS)
+ {
+ // Invalidate the entries for (listfile) and (attributes)
+ // After we are done with MPQ changes, we need to re-create them anyway
+ InvalidateInternalFiles(ha);
+
+ // Initiate the add file operation
+ nError = SFileAddFile_Init(ha, szArchivedName, FileTime, dwFileSize, lcLocale, dwFlags, (TMPQFile **)phFile);
+ }
+
+ // Deal with the errors
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+bool WINAPI SFileWriteFile(
+ HANDLE hFile,
+ const void * pvData,
+ DWORD dwSize,
+ DWORD dwCompression)
+{
+ TMPQFile * hf = (TMPQFile *)hFile;
+ int nError = ERROR_SUCCESS;
+
+ // Check the proper parameters
+ if(!IsValidFileHandle(hf))
+ nError = ERROR_INVALID_HANDLE;
+ if(hf->bIsWriteHandle == false)
+ nError = ERROR_INVALID_HANDLE;
+
+ // Special checks for single unit files
+ if(nError == ERROR_SUCCESS && (hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT))
+ {
+ //
+ // Note: Blizzard doesn't support single unit files
+ // that are stored as encrypted or imploded. We will allow them here,
+ // the calling application must ensure that such flag combination doesn't get here
+ //
+
+// if(dwFlags & MPQ_FILE_IMPLODE)
+// nError = ERROR_INVALID_PARAMETER;
+//
+// if(dwFlags & MPQ_FILE_ENCRYPTED)
+// nError = ERROR_INVALID_PARAMETER;
+
+ // Lossy compression is not allowed on single unit files
+ if(dwCompression & LOSSY_COMPRESSION_MASK)
+ nError = ERROR_INVALID_PARAMETER;
+ }
+
+
+ // Write the data to the file
+ if(nError == ERROR_SUCCESS)
+ nError = SFileAddFile_Write(hf, pvData, dwSize, dwCompression);
+
+ // Deal with errors
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+bool WINAPI SFileFinishFile(HANDLE hFile)
+{
+ TMPQFile * hf = (TMPQFile *)hFile;
+ int nError = ERROR_SUCCESS;
+
+ // Check the proper parameters
+ if(!IsValidFileHandle(hf))
+ nError = ERROR_INVALID_HANDLE;
+ if(hf->bIsWriteHandle == false)
+ nError = ERROR_INVALID_HANDLE;
+
+ // Finish the file
+ if(nError == ERROR_SUCCESS)
+ nError = SFileAddFile_Finish(hf);
+
+ // Deal with errors
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// Adds a file to the archive
+
+bool WINAPI SFileAddFileEx(
+ HANDLE hMpq,
+ const TCHAR * szFileName,
+ const char * szArchivedName,
+ DWORD dwFlags,
+ DWORD dwCompression, // Compression of the first sector
+ DWORD dwCompressionNext) // Compression of next sectors
+{
+ ULONGLONG FileSize = 0;
+ ULONGLONG FileTime = 0;
+ TFileStream * pStream = NULL;
+ HANDLE hMpqFile = NULL;
+ LPBYTE pbFileData = NULL;
+ DWORD dwBytesRemaining = 0;
+ DWORD dwBytesToRead;
+ DWORD dwSectorSize = 0x1000;
+ DWORD dwChannels = 0;
+ bool bIsAdpcmCompression = false;
+ bool bIsFirstSector = true;
+ int nError = ERROR_SUCCESS;
+
+ // Check parameters
+ if(szFileName == NULL || *szFileName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Open added file
+ if(nError == ERROR_SUCCESS)
+ {
+ pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream == NULL)
+ nError = GetLastError();
+ }
+
+ // Get the file size and file time
+ if(nError == ERROR_SUCCESS)
+ {
+ FileStream_GetTime(pStream, &FileTime);
+ FileStream_GetSize(pStream, FileSize);
+
+ // Files bigger than 4GB cannot be added to MPQ
+ if(FileSize >> 32)
+ nError = ERROR_DISK_FULL;
+ }
+
+ // Allocate data buffer for reading from the source file
+ if(nError == ERROR_SUCCESS)
+ {
+ dwBytesRemaining = (DWORD)FileSize;
+ pbFileData = STORM_ALLOC(BYTE, dwSectorSize);
+ if(pbFileData == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Deal with various combination of compressions
+ if(nError == ERROR_SUCCESS)
+ {
+ // When the compression for next blocks is set to default,
+ // we will copy the compression for the first sector
+ if(dwCompressionNext == MPQ_COMPRESSION_NEXT_SAME)
+ dwCompressionNext = dwCompression;
+
+ // If the caller wants ADPCM compression, we make sure
+ // that the first sector is not compressed with lossy compression
+ if(dwCompressionNext & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO))
+ {
+ // The first compression must not be WAVE
+ if(dwCompression & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO))
+ dwCompression = MPQ_COMPRESSION_PKWARE;
+
+ dwCompressionNext &= ~(MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO);
+ bIsAdpcmCompression = true;
+ }
+
+ // Initiate adding file to the MPQ
+ if(!SFileCreateFile(hMpq, szArchivedName, FileTime, (DWORD)FileSize, lcFileLocale, dwFlags, &hMpqFile))
+ nError = GetLastError();
+ }
+
+ // Write the file data to the MPQ
+ while(nError == ERROR_SUCCESS && dwBytesRemaining != 0)
+ {
+ // Get the number of bytes remaining in the source file
+ dwBytesToRead = dwBytesRemaining;
+ if(dwBytesToRead > dwSectorSize)
+ dwBytesToRead = dwSectorSize;
+
+ // Read data from the local file
+ if(!FileStream_Read(pStream, NULL, pbFileData, dwBytesToRead))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // If the file being added is a WAVE file, we check number of channels
+ if(bIsFirstSector && bIsAdpcmCompression)
+ {
+ // The file must really be a wave file, otherwise it's data corruption
+ if(!IsWaveFile(pbFileData, dwBytesToRead, &dwChannels))
+ {
+ nError = ERROR_BAD_FORMAT;
+ break;
+ }
+
+ // Setup the compression according to number of channels
+ dwCompressionNext |= (dwChannels == 1) ? MPQ_COMPRESSION_ADPCM_MONO : MPQ_COMPRESSION_ADPCM_STEREO;
+ bIsFirstSector = false;
+ }
+
+ // Add the file sectors to the MPQ
+ if(!SFileWriteFile(hMpqFile, pbFileData, dwBytesToRead, dwCompression))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Set the next data compression
+ dwBytesRemaining -= dwBytesToRead;
+ dwCompression = dwCompressionNext;
+ }
+
+ // Finish the file writing
+ if(hMpqFile != NULL)
+ {
+ if(!SFileFinishFile(hMpqFile))
+ nError = GetLastError();
+ }
+
+ // Cleanup and exit
+ if(pbFileData != NULL)
+ STORM_FREE(pbFileData);
+ if(pStream != NULL)
+ FileStream_Close(pStream);
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+// Adds a data file into the archive
+bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags)
+{
+ return SFileAddFileEx(hMpq,
+ szFileName,
+ szArchivedName,
+ dwFlags,
+ DefaultDataCompression,
+ DefaultDataCompression);
+}
+
+// Adds a WAVE file into the archive
+bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality)
+{
+ DWORD dwCompression = 0;
+
+ //
+ // Note to wave compression level:
+ // The following conversion table applied:
+ // High quality: WaveCompressionLevel = -1
+ // Medium quality: WaveCompressionLevel = 4
+ // Low quality: WaveCompressionLevel = 2
+ //
+ // Starcraft files are packed as Mono (0x41) on medium quality.
+ // Because this compression is not used anymore, our compression functions
+ // will default to WaveCompressionLevel = 4 when using ADPCM compression
+ //
+
+ // Convert quality to data compression
+ switch(dwQuality)
+ {
+ case MPQ_WAVE_QUALITY_HIGH:
+// WaveCompressionLevel = -1;
+ dwCompression = MPQ_COMPRESSION_PKWARE;
+ break;
+
+ case MPQ_WAVE_QUALITY_MEDIUM:
+// WaveCompressionLevel = 4;
+ dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN;
+ break;
+
+ case MPQ_WAVE_QUALITY_LOW:
+// WaveCompressionLevel = 2;
+ dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN;
+ break;
+ }
+
+ return SFileAddFileEx(hMpq,
+ szFileName,
+ szArchivedName,
+ dwFlags,
+ MPQ_COMPRESSION_PKWARE, // First sector should be compressed as data
+ dwCompression); // Next sectors should be compressed as WAVE
+}
+
+//-----------------------------------------------------------------------------
+// bool SFileRemoveFile(HANDLE hMpq, char * szFileName)
+//
+// This function removes a file from the archive. The file content
+// remains there, only the entries in the hash table and in the block
+// table are updated.
+
+bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry = NULL; // File entry of the file to be deleted
+ DWORD dwFileIndex = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Keep compiler happy
+ dwSearchScope = dwSearchScope;
+
+ // Check the parameters
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szFileName == NULL || *szFileName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+ if(IsInternalMpqFileName(szFileName))
+ nError = ERROR_INTERNAL_FILE;
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ // Do not allow to remove files from MPQ open for read only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ nError = ERROR_ACCESS_DENIED;
+ }
+
+ // Get hash entry belonging to this file
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!IsPseudoFileName(szFileName, &dwFileIndex))
+ {
+ if((pFileEntry = GetFileEntryExact(ha, (char *)szFileName, lcFileLocale)) == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+ else
+ {
+ if((pFileEntry = GetFileEntryByIndex(ha, dwFileIndex)) == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+ }
+
+ // Test if the file is not already deleted
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!(pFileEntry->dwFlags & MPQ_FILE_EXISTS))
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ // Invalidate the entries for (listfile) and (attributes)
+ // After we are done with MPQ changes, we need to re-create them anyway
+ InvalidateInternalFiles(ha);
+
+ // Mark the file entry as free
+ nError = FreeFileEntry(ha, pFileEntry);
+ }
+
+ // Resolve error and exit
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+// Renames the file within the archive.
+bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * szNewFileName)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry = NULL;
+ ULONGLONG RawDataOffs;
+ TMPQFile * hf;
+ int nError = ERROR_SUCCESS;
+
+ // Test the valid parameters
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szFileName == NULL || *szFileName == 0 || szNewFileName == NULL || *szNewFileName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ // Do not allow to rename files in MPQ open for read only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ nError = ERROR_ACCESS_DENIED;
+
+ // Do not allow renaming anything to a pseudo-file name
+ if(IsPseudoFileName(szFileName, NULL) || IsPseudoFileName(szNewFileName, NULL))
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Do not allow to rename any of the internal files
+ // Also do not allow to rename any of files to an internal file
+ if(IsInternalMpqFileName(szFileName) || IsInternalMpqFileName(szNewFileName))
+ nError = ERROR_INTERNAL_FILE;
+ }
+
+ // Find the current file entry.
+ if(nError == ERROR_SUCCESS)
+ {
+ // Get the file entry
+ pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
+ if(pFileEntry == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+
+ // Also try to find file entry for the new file.
+ // This verifies if we are not overwriting an existing file
+ // (whose name we perhaps don't know)
+ if(nError == ERROR_SUCCESS)
+ {
+ if(GetFileEntryLocale(ha, szNewFileName, pFileEntry->lcLocale) != NULL)
+ nError = ERROR_ALREADY_EXISTS;
+ }
+
+ // Now we rename the existing file entry.
+ if(nError == ERROR_SUCCESS)
+ {
+ // Rename the file entry
+ nError = RenameFileEntry(ha, pFileEntry, szNewFileName);
+ }
+
+ // Now we copy the existing file entry to the new one
+ if(nError == ERROR_SUCCESS)
+ {
+ // If the file is encrypted, we have to re-crypt the file content
+ // with the new decryption key
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ hf = CreateMpqFile(ha);
+ if(hf != NULL)
+ {
+ // Recrypt the file data in the MPQ
+ hf->pFileEntry = pFileEntry;
+ hf->dwDataSize = pFileEntry->dwFileSize;
+ nError = RecryptFileData(ha, hf, szFileName, szNewFileName);
+
+ // Update the MD5
+ if(ha->pHeader->dwRawChunkSize != 0)
+ {
+ RawDataOffs = ha->MpqPos + pFileEntry->ByteOffset;
+ WriteMpqDataMD5(ha->pStream,
+ RawDataOffs,
+ pFileEntry->dwCmpSize,
+ ha->pHeader->dwRawChunkSize);
+ }
+
+ FreeMPQFile(hf);
+ }
+ else
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+ }
+
+ //
+ // Note: MPQ_FLAG_CHANGED is set by RenameFileEntry
+ //
+
+ // Resolve error and return
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// Sets default data compression for SFileAddFile
+
+bool WINAPI SFileSetDataCompression(DWORD DataCompression)
+{
+ unsigned int uValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2 | MPQ_COMPRESSION_SPARSE);
+
+ if((DataCompression & uValidMask) != DataCompression)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ DefaultDataCompression = DataCompression;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Changes locale ID of a file
+
+bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale)
+{
+ TMPQArchive * ha;
+ TFileEntry * pFileEntry;
+ TMPQFile * hf = (TMPQFile *)hFile;
+
+ // Invalid handle => do nothing
+ if(!IsValidFileHandle(hf))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // Do not allow unnamed access
+ if(hf->pFileEntry->szFileName == NULL)
+ {
+ SetLastError(ERROR_CAN_NOT_COMPLETE);
+ return false;
+ }
+
+ // Do not allow to change locale of any internal file
+ if(IsInternalMpqFileName(hf->pFileEntry->szFileName))
+ {
+ SetLastError(ERROR_INTERNAL_FILE);
+ return false;
+ }
+
+ // Do not allow changing file locales in MPQs version 3 or higher
+ ha = hf->ha;
+ if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_3)
+ {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return false;
+ }
+
+ // Do not allow to rename files in MPQ open for read only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return false;
+ }
+
+ // If the file already has that locale, return OK
+ if(hf->pFileEntry->lcLocale == lcNewLocale)
+ return true;
+
+ // We have to check if the file+locale is not already there
+ pFileEntry = GetFileEntryExact(ha, hf->pFileEntry->szFileName, lcNewLocale);
+ if(pFileEntry != NULL)
+ {
+ SetLastError(ERROR_ALREADY_EXISTS);
+ return false;
+ }
+
+ // Set the locale and return success
+ pFileEntry = hf->pFileEntry;
+ pFileEntry->lcLocale = (USHORT)lcNewLocale;
+
+ // Save the new locale to the hash table, if any
+ if(ha->pHashTable != NULL)
+ ha->pHashTable[pFileEntry->dwHashIndex].lcLocale = (USHORT)lcNewLocale;
+
+ // Remember that the MPQ tables have been changed
+ ha->dwFlags |= MPQ_FLAG_CHANGED;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sets add file callback
+
+bool WINAPI SFileSetAddFileCallback(HANDLE /* hMpq */, SFILE_ADDFILE_CALLBACK aAddFileCB, void * pvData)
+{
+ pvUserData = pvData;
+ AddFileCB = aAddFileCB;
+ return true;
+}
diff --git a/dep/StormLib/src/SFileAttributes.cpp b/dep/StormLib/src/SFileAttributes.cpp
new file mode 100644
index 00000000000..0f056088fa3
--- /dev/null
+++ b/dep/StormLib/src/SFileAttributes.cpp
@@ -0,0 +1,477 @@
+/*****************************************************************************/
+/* SAttrFile.cpp Copyright (c) Ladislav Zezula 2007 */
+/*---------------------------------------------------------------------------*/
+/* Description: */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 12.06.04 1.00 Lad The first version of SAttrFile.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+typedef struct _MPQ_ATTRIBUTES_HEADER
+{
+ DWORD dwVersion; // Version of the (attributes) file. Must be 100 (0x64)
+ DWORD dwFlags; // See MPQ_ATTRIBUTE_XXXX
+
+ // Followed by an array of CRC32
+ // Followed by an array of file times
+ // Followed by an array of MD5
+ // Followed by an array of patch bits
+} MPQ_ATTRIBUTES_HEADER, *PMPQ_ATTRIBUTES_HEADER;
+
+//-----------------------------------------------------------------------------
+// Public functions (internal use by StormLib)
+
+int SAttrLoadAttributes(TMPQArchive * ha)
+{
+ MPQ_ATTRIBUTES_HEADER AttrHeader;
+ TMPQFile * hf;
+ HANDLE hFile = NULL;
+ DWORD dwBlockTableSize = ha->pHeader->dwBlockTableSize;
+ DWORD dwArraySize;
+ DWORD dwBytesRead;
+ DWORD i;
+ int nError = ERROR_SUCCESS;
+
+ // File table must be initialized
+ assert(ha->pFileTable != NULL);
+
+ // Attempt to open the "(attributes)" file.
+ // If it's not there, then the archive doesn't support attributes
+ if(SFileOpenFileEx((HANDLE)ha, ATTRIBUTES_NAME, SFILE_OPEN_ANY_LOCALE, &hFile))
+ {
+ // Remember the flags for (attributes)
+ hf = (TMPQFile *)hFile;
+ ha->dwFileFlags2 = hf->pFileEntry->dwFlags;
+
+ // Load the content of the attributes file
+ SFileReadFile(hFile, &AttrHeader, sizeof(MPQ_ATTRIBUTES_HEADER), &dwBytesRead, NULL);
+ if(dwBytesRead != sizeof(MPQ_ATTRIBUTES_HEADER))
+ nError = ERROR_FILE_CORRUPT;
+
+ // Verify the header of the (attributes) file
+ if(nError == ERROR_SUCCESS)
+ {
+ AttrHeader.dwVersion = BSWAP_INT32_UNSIGNED(AttrHeader.dwVersion);
+ AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED(AttrHeader.dwFlags);
+ ha->dwAttrFlags = AttrHeader.dwFlags;
+ if(dwBytesRead != sizeof(MPQ_ATTRIBUTES_HEADER))
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Verify format of the attributes
+ if(nError == ERROR_SUCCESS)
+ {
+ if(AttrHeader.dwVersion > MPQ_ATTRIBUTES_V1)
+ nError = ERROR_BAD_FORMAT;
+ }
+
+ // Load the CRC32 (if any)
+ if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_CRC32))
+ {
+ LPDWORD pArrayCRC32 = STORM_ALLOC(DWORD, dwBlockTableSize);
+
+ if(pArrayCRC32 != NULL)
+ {
+ dwArraySize = dwBlockTableSize * sizeof(DWORD);
+ SFileReadFile(hFile, pArrayCRC32, dwArraySize, &dwBytesRead, NULL);
+ if(dwBytesRead == dwArraySize)
+ {
+ for(i = 0; i < dwBlockTableSize; i++)
+ ha->pFileTable[i].dwCrc32 = BSWAP_INT32_UNSIGNED(pArrayCRC32[i]);
+ }
+ else
+ nError = ERROR_FILE_CORRUPT;
+
+ STORM_FREE(pArrayCRC32);
+ }
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Read the array of file times
+ if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_FILETIME))
+ {
+ ULONGLONG * pArrayFileTime = STORM_ALLOC(ULONGLONG, dwBlockTableSize);
+
+ if(pArrayFileTime != NULL)
+ {
+ dwArraySize = dwBlockTableSize * sizeof(ULONGLONG);
+ SFileReadFile(hFile, pArrayFileTime, dwArraySize, &dwBytesRead, NULL);
+ if(dwBytesRead == dwArraySize)
+ {
+ for(i = 0; i < dwBlockTableSize; i++)
+ ha->pFileTable[i].FileTime = BSWAP_INT64_UNSIGNED(pArrayFileTime[i]);
+ }
+ else
+ nError = ERROR_FILE_CORRUPT;
+
+ STORM_FREE(pArrayFileTime);
+ }
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Read the MD5 (if any)
+ // Note: MD5 array can be incomplete, if it's the last array in the (attributes)
+ if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_MD5))
+ {
+ unsigned char * pArrayMD5 = STORM_ALLOC(unsigned char, (dwBlockTableSize * MD5_DIGEST_SIZE));
+ unsigned char * md5;
+
+ if(pArrayMD5 != NULL)
+ {
+ dwArraySize = dwBlockTableSize * MD5_DIGEST_SIZE;
+ SFileReadFile(hFile, pArrayMD5, dwArraySize, &dwBytesRead, NULL);
+ if(dwBytesRead == dwArraySize)
+ {
+ md5 = pArrayMD5;
+ for(i = 0; i < dwBlockTableSize; i++)
+ {
+ memcpy(ha->pFileTable[i].md5, md5, MD5_DIGEST_SIZE);
+ md5 += MD5_DIGEST_SIZE;
+ }
+ }
+ else
+ nError = ERROR_FILE_CORRUPT;
+
+ STORM_FREE(pArrayMD5);
+ }
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Read the patch bit for each file
+ if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_PATCH_BIT))
+ {
+ LPBYTE pbBitArray;
+ DWORD dwByteSize = ((dwBlockTableSize - 1) / 8) + 1;
+
+ pbBitArray = STORM_ALLOC(BYTE, dwByteSize);
+ if(pbBitArray != NULL)
+ {
+ SFileReadFile(hFile, pbBitArray, dwByteSize, &dwBytesRead, NULL);
+ if(dwBytesRead == dwByteSize)
+ {
+ for(i = 0; i < dwBlockTableSize; i++)
+ {
+ DWORD dwByteIndex = i / 8;
+ DWORD dwBitMask = 0x80 >> (i & 7);
+
+ // Is the appropriate bit set?
+ if(pbBitArray[dwByteIndex] & dwBitMask)
+ {
+ // At the moment, we assume that the patch bit is present
+ // in both file table and (attributes)
+ assert((ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE) != 0);
+ ha->pFileTable[i].dwFlags |= MPQ_FILE_PATCH_FILE;
+ }
+ }
+ }
+ else
+ nError = ERROR_FILE_CORRUPT;
+
+ STORM_FREE(pbBitArray);
+ }
+ }
+
+ //
+ // Note: Version 7.00 of StormLib saved the (attributes) incorrectly.
+ // Sometimes, number of entries in the (attributes) was 1 item less
+ // than block table size.
+ // If we encounter such table, we will zero all three arrays
+ //
+
+ if(nError != ERROR_SUCCESS)
+ ha->dwAttrFlags = 0;
+
+ // Cleanup & exit
+ SFileCloseFile(hFile);
+ }
+ return nError;
+}
+
+int SAttrFileSaveToMpq(TMPQArchive * ha)
+{
+ MPQ_ATTRIBUTES_HEADER AttrHeader;
+ TFileEntry * pFileEntry;
+ TMPQFile * hf = NULL;
+ DWORD dwFinalBlockTableSize = ha->dwFileTableSize;
+ DWORD dwFileSize = 0;
+ DWORD dwToWrite;
+ DWORD i;
+ int nError = ERROR_SUCCESS;
+
+ // Now we have to check if we need patch bits in the (attributes)
+ if(nError == ERROR_SUCCESS)
+ {
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ {
+ if(ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE)
+ {
+ ha->dwAttrFlags |= MPQ_ATTRIBUTE_PATCH_BIT;
+ break;
+ }
+ }
+ }
+
+ // If the (attributes) is not in the file table yet,
+ // we have to increase the final block table size
+ pFileEntry = GetFileEntryExact(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
+ if(pFileEntry != NULL)
+ {
+ // If "(attributes)" file exists, and it's set to 0, then remove it
+ if(ha->dwAttrFlags == 0)
+ {
+ FreeFileEntry(ha, pFileEntry);
+ return ERROR_SUCCESS;
+ }
+ }
+ else
+ {
+ // If we don't want to create file atributes, do nothing
+ if(ha->dwAttrFlags == 0)
+ return ERROR_SUCCESS;
+
+ // Check where the file entry is going to be allocated.
+ // If at the end of the file table, we have to increment
+ // the expected size of the (attributes) file.
+ pFileEntry = FindFreeFileEntry(ha);
+ if(pFileEntry == ha->pFileTable + ha->dwFileTableSize)
+ dwFinalBlockTableSize++;
+ }
+
+ // Calculate the size of the attributes file
+ if(nError == ERROR_SUCCESS)
+ {
+ dwFileSize = sizeof(MPQ_ATTRIBUTES_HEADER); // Header
+ if(ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
+ dwFileSize += dwFinalBlockTableSize * sizeof(DWORD);
+ if(ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
+ dwFileSize += dwFinalBlockTableSize * sizeof(ULONGLONG);
+ if(ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5)
+ dwFileSize += dwFinalBlockTableSize * MD5_DIGEST_SIZE;
+ if(ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
+ dwFileSize += ((dwFinalBlockTableSize - 1)) / 8 + 1;
+ }
+
+ // Determine the flags for (attributes)
+ if(ha->dwFileFlags2 == 0)
+ ha->dwFileFlags2 = GetDefaultSpecialFileFlags(ha, dwFileSize);
+
+ // Create the attributes file in the MPQ
+ nError = SFileAddFile_Init(ha, ATTRIBUTES_NAME,
+ 0,
+ dwFileSize,
+ LANG_NEUTRAL,
+ ha->dwFileFlags2 | MPQ_FILE_REPLACEEXISTING,
+ &hf);
+
+ // Write all parts of the (attributes) file
+ if(nError == ERROR_SUCCESS)
+ {
+ assert(ha->dwFileTableSize == dwFinalBlockTableSize);
+
+ // Note that we don't know what the new bit (0x08) means.
+ AttrHeader.dwVersion = BSWAP_INT32_UNSIGNED(100);
+ AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED((ha->dwAttrFlags & MPQ_ATTRIBUTE_ALL));
+ dwToWrite = sizeof(MPQ_ATTRIBUTES_HEADER);
+ nError = SFileAddFile_Write(hf, &AttrHeader, dwToWrite, MPQ_COMPRESSION_ZLIB);
+ }
+
+ // Write the array of CRC32
+ if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32))
+ {
+ LPDWORD pArrayCRC32 = STORM_ALLOC(DWORD, dwFinalBlockTableSize);
+
+ if(pArrayCRC32 != NULL)
+ {
+ // Copy from file table
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ pArrayCRC32[i] = BSWAP_INT32_UNSIGNED(ha->pFileTable[i].dwCrc32);
+
+ dwToWrite = ha->dwFileTableSize * sizeof(DWORD);
+ nError = SFileAddFile_Write(hf, pArrayCRC32, dwToWrite, MPQ_COMPRESSION_ZLIB);
+ STORM_FREE(pArrayCRC32);
+ }
+ }
+
+ // Write the array of file time
+ if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME))
+ {
+ ULONGLONG * pArrayFileTime = STORM_ALLOC(ULONGLONG, ha->dwFileTableSize);
+
+ if(pArrayFileTime != NULL)
+ {
+ // Copy from file table
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ pArrayFileTime[i] = BSWAP_INT64_UNSIGNED(ha->pFileTable[i].FileTime);
+
+ dwToWrite = ha->dwFileTableSize * sizeof(ULONGLONG);
+ nError = SFileAddFile_Write(hf, pArrayFileTime, dwToWrite, MPQ_COMPRESSION_ZLIB);
+ STORM_FREE(pArrayFileTime);
+ }
+ }
+
+ // Write the array of MD5s
+ if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5))
+ {
+ char * pArrayMD5 = STORM_ALLOC(char, ha->dwFileTableSize * MD5_DIGEST_SIZE);
+
+ if(pArrayMD5 != NULL)
+ {
+ // Copy from file table
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ memcpy(&pArrayMD5[i * MD5_DIGEST_SIZE], ha->pFileTable[i].md5, MD5_DIGEST_SIZE);
+
+ dwToWrite = ha->dwFileTableSize * MD5_DIGEST_SIZE;
+ nError = SFileAddFile_Write(hf, pArrayMD5, dwToWrite, MPQ_COMPRESSION_ZLIB);
+ STORM_FREE(pArrayMD5);
+ }
+ }
+
+ // Write the array of patch bits
+ if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT))
+ {
+ LPBYTE pbBitArray;
+ DWORD dwByteSize = ((ha->dwFileTableSize - 1) / 8) + 1;
+
+ pbBitArray = STORM_ALLOC(BYTE, dwByteSize);
+ if(pbBitArray != NULL)
+ {
+ memset(pbBitArray, 0, dwByteSize);
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ {
+ DWORD dwByteIndex = i / 8;
+ DWORD dwBitMask = 0x80 >> (i & 7);
+
+ if(ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE)
+ pbBitArray[dwByteIndex] |= dwBitMask;
+ }
+
+ nError = SFileAddFile_Write(hf, pbBitArray, dwByteSize, MPQ_COMPRESSION_ZLIB);
+ STORM_FREE(pbBitArray);
+ }
+ }
+
+ // Finalize the file in the archive
+ if(hf != NULL)
+ {
+ SFileAddFile_Finish(hf);
+ }
+
+ if(nError == ERROR_SUCCESS)
+ ha->dwFlags &= ~MPQ_FLAG_INV_ATTRIBUTES;
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+DWORD WINAPI SFileGetAttributes(HANDLE hMpq)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ // Verify the parameters
+ if(!IsValidMpqHandle(ha))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return SFILE_INVALID_ATTRIBUTES;
+ }
+
+ return ha->dwAttrFlags;
+}
+
+bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ // Verify the parameters
+ if(!IsValidMpqHandle(ha))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // Not allowed when the archive is read-only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return false;
+ }
+
+ // Set the attributes
+ InvalidateInternalFiles(ha);
+ ha->dwAttrFlags = (dwFlags & MPQ_ATTRIBUTE_ALL);
+ return true;
+}
+
+bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName)
+{
+ hash_state md5_state;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TMPQFile * hf;
+ BYTE Buffer[0x1000];
+ HANDLE hFile = NULL;
+ DWORD dwTotalBytes = 0;
+ DWORD dwBytesRead;
+ DWORD dwCrc32;
+
+ // Verify the parameters
+ if(!IsValidMpqHandle(ha))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // Not allowed when the archive is read-only
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return false;
+ }
+
+ // Attempt to open the file
+ if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_FROM_MPQ, &hFile))
+ return false;
+
+ // Get the file size
+ hf = (TMPQFile *)hFile;
+ SFileGetFileInfo(hFile, SFILE_INFO_FILE_SIZE, &dwTotalBytes, sizeof(DWORD));
+
+ // Initialize the CRC32 and MD5 contexts
+ md5_init(&md5_state);
+ dwCrc32 = crc32(0, Z_NULL, 0);
+
+ // Go through entire file and calculate both CRC32 and MD5
+ while(dwTotalBytes != 0)
+ {
+ // Read data from file
+ SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
+ if(dwBytesRead == 0)
+ break;
+
+ // Update CRC32 and MD5
+ dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
+ md5_process(&md5_state, Buffer, dwBytesRead);
+
+ // Decrement the total size
+ dwTotalBytes -= dwBytesRead;
+ }
+
+ // Update both CRC32 and MD5
+ hf->pFileEntry->dwCrc32 = dwCrc32;
+ md5_done(&md5_state, hf->pFileEntry->md5);
+
+ // Remember that we need to save the MPQ tables
+ InvalidateInternalFiles(ha);
+ SFileCloseFile(hFile);
+ return true;
+}
diff --git a/dep/StormLib/src/SFileCompactArchive.cpp b/dep/StormLib/src/SFileCompactArchive.cpp
new file mode 100644
index 00000000000..319108b08f4
--- /dev/null
+++ b/dep/StormLib/src/SFileCompactArchive.cpp
@@ -0,0 +1,765 @@
+/*****************************************************************************/
+/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Archive compacting function */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
+/* 19.11.03 1.01 Dan Big endian handling */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+/*****************************************************************************/
+/* Local variables */
+/*****************************************************************************/
+
+static SFILE_COMPACT_CALLBACK CompactCB = NULL;
+static ULONGLONG CompactBytesProcessed = 0;
+static ULONGLONG CompactTotalBytes = 0;
+static void * pvUserData = NULL;
+
+/*****************************************************************************/
+/* Local functions */
+/*****************************************************************************/
+
+static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, LPDWORD pFileKeys)
+{
+ TFileEntry * pFileTableEnd;
+ TFileEntry * pFileEntry;
+ DWORD dwBlockIndex = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Add the listfile to the MPQ
+ if(nError == ERROR_SUCCESS && szListFile != NULL)
+ {
+ // Notify the user
+ if(CompactCB != NULL)
+ CompactCB(pvUserData, CCB_CHECKING_FILES, CompactBytesProcessed, CompactTotalBytes);
+
+ nError = SFileAddListFile((HANDLE)ha, szListFile);
+ }
+
+ // Verify the file table
+ if(nError == ERROR_SUCCESS)
+ {
+ pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++, dwBlockIndex++)
+ {
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
+ {
+ if(pFileEntry->szFileName != NULL && !IsPseudoFileName(pFileEntry->szFileName, NULL))
+ {
+ DWORD dwFileKey = 0;
+
+ // Resolve the file key. Use plain file name for it
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ dwFileKey = DecryptFileKey(pFileEntry->szFileName,
+ pFileEntry->ByteOffset,
+ pFileEntry->dwFileSize,
+ pFileEntry->dwFlags);
+ }
+
+ // Give the key to the caller
+ if(pFileKeys != NULL)
+ pFileKeys[dwBlockIndex] = dwFileKey;
+ }
+ else
+ {
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+ }
+ }
+ }
+
+ return nError;
+}
+
+static int CopyNonMpqData(
+ TFileStream * pSrcStream,
+ TFileStream * pTrgStream,
+ ULONGLONG & ByteOffset,
+ ULONGLONG & ByteCount)
+{
+ ULONGLONG DataSize = ByteCount;
+ DWORD dwToRead;
+ char DataBuffer[0x1000];
+ int nError = ERROR_SUCCESS;
+
+ // Copy the data
+ while(DataSize > 0)
+ {
+ // Get the proper size of data
+ dwToRead = sizeof(DataBuffer);
+ if(DataSize < dwToRead)
+ dwToRead = (DWORD)DataSize;
+
+ // Read from the source stream
+ if(!FileStream_Read(pSrcStream, &ByteOffset, DataBuffer, dwToRead))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Write to the target stream
+ if(!FileStream_Write(pTrgStream, NULL, DataBuffer, dwToRead))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Update the progress
+ if(CompactCB != NULL)
+ {
+ CompactBytesProcessed += dwToRead;
+ CompactCB(pvUserData, CCB_COPYING_NON_MPQ_DATA, CompactBytesProcessed, CompactTotalBytes);
+ }
+
+ // Decrement the number of data to be copied
+ ByteOffset += dwToRead;
+ DataSize -= dwToRead;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+// Copies all file sectors into another archive.
+static int CopyMpqFileSectors(
+ TMPQArchive * ha,
+ TMPQFile * hf,
+ TFileStream * pNewStream)
+{
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ ULONGLONG RawFilePos; // Used for calculating sector offset in the old MPQ archive
+ ULONGLONG MpqFilePos; // MPQ file position in the new archive
+ DWORD dwBytesToCopy = pFileEntry->dwCmpSize;
+ DWORD dwPatchSize = 0; // Size of patch header
+ DWORD dwFileKey1 = 0; // File key used for decryption
+ DWORD dwFileKey2 = 0; // File key used for encryption
+ DWORD dwCmpSize = 0; // Compressed file size, including patch header
+ int nError = ERROR_SUCCESS;
+
+ // Remember the position in the destination file
+ FileStream_GetPos(pNewStream, MpqFilePos);
+ MpqFilePos -= ha->MpqPos;
+
+ // Resolve decryption keys. Note that the file key given
+ // in the TMPQFile structure also includes the key adjustment
+ if(nError == ERROR_SUCCESS && (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED))
+ {
+ dwFileKey2 = dwFileKey1 = hf->dwFileKey;
+ if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
+ {
+ dwFileKey2 = (dwFileKey1 ^ pFileEntry->dwFileSize) - (DWORD)pFileEntry->ByteOffset;
+ dwFileKey2 = (dwFileKey2 + (DWORD)MpqFilePos) ^ pFileEntry->dwFileSize;
+ }
+ }
+
+ // If we have to save patch header, do it
+ if(nError == ERROR_SUCCESS && hf->pPatchInfo != NULL)
+ {
+ BSWAP_ARRAY32_UNSIGNED(hf->pPatchInfo, sizeof(DWORD) * 3);
+ if(!FileStream_Write(pNewStream, NULL, hf->pPatchInfo, hf->pPatchInfo->dwLength))
+ nError = GetLastError();
+
+ // Save the size of the patch info
+ dwPatchSize = hf->pPatchInfo->dwLength;
+ }
+
+ // If we have to save sector offset table, do it.
+ if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL)
+ {
+ DWORD * SectorOffsetsCopy = (DWORD *)STORM_ALLOC(BYTE, hf->SectorOffsets[0]);
+ DWORD dwSectorOffsLen = hf->SectorOffsets[0];
+
+ assert((pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) == 0);
+ assert(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED);
+
+ if(SectorOffsetsCopy == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ // Encrypt the secondary sector offset table and write it to the target file
+ if(nError == ERROR_SUCCESS)
+ {
+ memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorOffsLen);
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ EncryptMpqBlock(SectorOffsetsCopy, dwSectorOffsLen, dwFileKey2 - 1);
+
+ BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen);
+ if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorOffsLen))
+ nError = GetLastError();
+
+ dwBytesToCopy -= dwSectorOffsLen;
+ dwCmpSize += dwSectorOffsLen;
+ }
+
+ // Update compact progress
+ if(CompactCB != NULL)
+ {
+ CompactBytesProcessed += dwSectorOffsLen;
+ CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
+ }
+
+ STORM_FREE(SectorOffsetsCopy);
+ }
+
+ // Now we have to copy all file sectors. We do it without
+ // recompression, because recompression is not necessary in this case
+ if(nError == ERROR_SUCCESS)
+ {
+ for(DWORD dwSector = 0; dwSector < hf->dwSectorCount; dwSector++)
+ {
+ DWORD dwRawDataInSector = hf->dwSectorSize;
+ DWORD dwRawByteOffset = dwSector * hf->dwSectorSize;
+
+ // Fix the raw data length if the file is compressed
+ if(hf->SectorOffsets != NULL)
+ {
+ dwRawDataInSector = hf->SectorOffsets[dwSector+1] - hf->SectorOffsets[dwSector];
+ dwRawByteOffset = hf->SectorOffsets[dwSector];
+ }
+
+ // Last sector: If there is not enough bytes remaining in the file, cut the raw size
+ if(dwRawDataInSector > dwBytesToCopy)
+ dwRawDataInSector = dwBytesToCopy;
+
+ // Calculate the raw file offset of the file sector
+ CalculateRawSectorOffset(RawFilePos, hf, dwRawByteOffset);
+
+ // Read the file sector
+ if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // If necessary, re-encrypt the sector
+ // Note: Recompression is not necessary here. Unlike encryption,
+ // the compression does not depend on the position of the file in MPQ.
+ if((pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey1 != dwFileKey2)
+ {
+ BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
+ DecryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey1 + dwSector);
+ EncryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey2 + dwSector);
+ BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
+ }
+
+ // Now write the sector back to the file
+ if(!FileStream_Write(pNewStream, NULL, hf->pbFileSector, dwRawDataInSector))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Update compact progress
+ if(CompactCB != NULL)
+ {
+ CompactBytesProcessed += dwRawDataInSector;
+ CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
+ }
+
+ // Adjust byte counts
+ dwBytesToCopy -= dwRawDataInSector;
+ dwCmpSize += dwRawDataInSector;
+ }
+ }
+
+ // Copy the sector CRCs, if any
+ // Sector CRCs are always compressed (not imploded) and unencrypted
+ if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL && hf->SectorChksums != NULL)
+ {
+ DWORD dwCrcLength;
+
+ dwCrcLength = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount];
+ if(dwCrcLength != 0)
+ {
+ if(!FileStream_Read(ha->pStream, NULL, hf->SectorChksums, dwCrcLength))
+ nError = GetLastError();
+
+ if(!FileStream_Write(pNewStream, NULL, hf->SectorChksums, dwCrcLength))
+ nError = GetLastError();
+
+ // Update compact progress
+ if(CompactCB != NULL)
+ {
+ CompactBytesProcessed += dwCrcLength;
+ CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
+ }
+
+ // Size of the CRC block is also included in the compressed file size
+ dwBytesToCopy -= dwCrcLength;
+ dwCmpSize += dwCrcLength;
+ }
+ }
+
+ // There might be extra data beyond sector checksum table
+ // Sometimes, these data are even part of sector offset table
+ // Examples:
+ // 2012 - WoW\15354\locale-enGB.MPQ:DBFilesClient\SpellLevels.dbc
+ // 2012 - WoW\15354\locale-enGB.MPQ:Interface\AddOns\Blizzard_AuctionUI\Blizzard_AuctionUI.xml
+ if(nError == ERROR_SUCCESS && dwBytesToCopy != 0)
+ {
+ LPBYTE pbExtraData;
+
+ // Allocate space for the extra data
+ pbExtraData = STORM_ALLOC(BYTE, dwBytesToCopy);
+ if(pbExtraData != NULL)
+ {
+ if(!FileStream_Read(ha->pStream, NULL, pbExtraData, dwBytesToCopy))
+ nError = GetLastError();
+
+ if(!FileStream_Write(pNewStream, NULL, pbExtraData, dwBytesToCopy))
+ nError = GetLastError();
+
+ // Include these extra data in the compressed size
+ dwCmpSize += dwBytesToCopy;
+ dwBytesToCopy = 0;
+ STORM_FREE(pbExtraData);
+ }
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Write the MD5's of the raw file data, if needed
+ if(nError == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
+ {
+ nError = WriteMpqDataMD5(pNewStream,
+ ha->MpqPos + MpqFilePos,
+ pFileEntry->dwCmpSize,
+ ha->pHeader->dwRawChunkSize);
+ }
+
+ // Update file position in the block table
+ if(nError == ERROR_SUCCESS)
+ {
+ // At this point, number of bytes written should be exactly
+ // the same like the compressed file size. If it isn't,
+ // there's something wrong (an unknown archive version, MPQ protection, ...)
+ //
+ // Note: Diablo savegames have very weird layout, and the file "hero"
+ // seems to have improper compressed size. Instead of real compressed size,
+ // the "dwCmpSize" member of the block table entry contains
+ // uncompressed size of file data + size of the sector table.
+ // If we compact the archive, Diablo will refuse to load the game
+ // Seems like some sort of protection to me.
+ //
+ // Note: Some patch files in WOW patches don't count the patch header
+ // into compressed size
+ //
+
+ if(dwCmpSize <= pFileEntry->dwCmpSize && pFileEntry->dwCmpSize <= dwCmpSize + dwPatchSize)
+ {
+ // Note: DO NOT update the compressed size in the file entry, no matter how bad it is.
+ pFileEntry->ByteOffset = MpqFilePos;
+ }
+ else
+ {
+ nError = ERROR_FILE_CORRUPT;
+ assert(false);
+ }
+ }
+
+ return nError;
+}
+
+static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream)
+{
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pFileEntry;
+ TMPQFile * hf = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Walk through all files and write them to the destination MPQ archive
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // Copy all the file sectors
+ // Only do that when the file has nonzero size
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->dwFileSize != 0)
+ {
+ // Allocate structure for the MPQ file
+ hf = CreateMpqFile(ha);
+ if(hf == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Store file entry
+ hf->pFileEntry = pFileEntry;
+
+ // Set the raw file position
+ hf->MpqFilePos = pFileEntry->ByteOffset;
+ hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
+
+ // Set the file decryption key
+ hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable];
+ hf->dwDataSize = pFileEntry->dwFileSize;
+
+ // If the file is a patch file, load the patch header
+ if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
+ {
+ nError = AllocatePatchInfo(hf, true);
+ if(nError != ERROR_SUCCESS)
+ break;
+ }
+
+ // Allocate buffers for file sector and sector offset table
+ nError = AllocateSectorBuffer(hf);
+ if(nError != ERROR_SUCCESS)
+ break;
+
+ // Also allocate sector offset table and sector checksum table
+ nError = AllocateSectorOffsets(hf, true);
+ if(nError != ERROR_SUCCESS)
+ break;
+
+ // Also load sector checksums, if any
+ if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)
+ {
+ nError = AllocateSectorChecksums(hf, false);
+ if(nError != ERROR_SUCCESS)
+ break;
+ }
+
+ // Copy all file sectors
+ nError = CopyMpqFileSectors(ha, hf, pNewStream);
+ if(nError != ERROR_SUCCESS)
+ break;
+
+ // Free buffers. This also sets "hf" to NULL.
+ FreeMPQFile(hf);
+ }
+ }
+
+ // Cleanup and exit
+ if(hf != NULL)
+ FreeMPQFile(hf);
+ return nError;
+}
+
+
+/*****************************************************************************/
+/* Public functions */
+/*****************************************************************************/
+
+bool WINAPI SFileSetCompactCallback(HANDLE /* hMpq */, SFILE_COMPACT_CALLBACK aCompactCB, void * pvData)
+{
+ CompactCB = aCompactCB;
+ pvUserData = pvData;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Archive compacting
+
+bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bReserved */)
+{
+ TFileStream * pTempStream = NULL;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ ULONGLONG ByteOffset;
+ ULONGLONG ByteCount;
+ LPDWORD pFileKeys = NULL;
+ TCHAR szTempFile[MAX_PATH] = _T("");
+ TCHAR * szTemp = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Test the valid parameters
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ nError = ERROR_ACCESS_DENIED;
+
+ // If the MPQ is changed at this moment, we have to flush the archive
+ if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_CHANGED))
+ {
+ SFileFlushArchive(hMpq);
+ }
+
+ // Create the table with file keys
+ if(nError == ERROR_SUCCESS)
+ {
+ if((pFileKeys = STORM_ALLOC(DWORD, ha->dwFileTableSize)) != NULL)
+ memset(pFileKeys, 0, sizeof(DWORD) * ha->dwFileTableSize);
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // First of all, we have to check of we are able to decrypt all files.
+ // If not, sorry, but the archive cannot be compacted.
+ if(nError == ERROR_SUCCESS)
+ {
+ // Initialize the progress variables for compact callback
+ FileStream_GetSize(ha->pStream, CompactTotalBytes);
+ CompactBytesProcessed = 0;
+ nError = CheckIfAllFilesKnown(ha, szListFile, pFileKeys);
+ }
+
+ // Get the temporary file name and create it
+ if(nError == ERROR_SUCCESS)
+ {
+ _tcscpy(szTempFile, FileStream_GetFileName(ha->pStream));
+ if((szTemp = _tcsrchr(szTempFile, '.')) != NULL)
+ _tcscpy(szTemp + 1, _T("mp_"));
+ else
+ _tcscat(szTempFile, _T("_"));
+
+ pTempStream = FileStream_CreateFile(szTempFile, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pTempStream == NULL)
+ nError = GetLastError();
+ }
+
+ // Write the data before MPQ user data (if any)
+ if(nError == ERROR_SUCCESS && ha->UserDataPos != 0)
+ {
+ // Inform the application about the progress
+ if(CompactCB != NULL)
+ CompactCB(pvUserData, CCB_COPYING_NON_MPQ_DATA, CompactBytesProcessed, CompactTotalBytes);
+
+ ByteOffset = 0;
+ ByteCount = ha->UserDataPos;
+ nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount);
+ }
+
+ // Write the MPQ user data (if any)
+ if(nError == ERROR_SUCCESS && ha->MpqPos > ha->UserDataPos)
+ {
+ // At this point, we assume that the user data size is equal
+ // to pUserData->dwHeaderOffs.
+ // If this assumption doesn't work, then we have an unknown version of MPQ
+ ByteOffset = ha->UserDataPos;
+ ByteCount = ha->MpqPos - ha->UserDataPos;
+
+ assert(ha->pUserData != NULL);
+ assert(ha->pUserData->dwHeaderOffs == ByteCount);
+ nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount);
+ }
+
+ // Write the MPQ header
+ if(nError == ERROR_SUCCESS)
+ {
+ // Remember the header size before swapping
+ DWORD dwBytesToWrite = ha->pHeader->dwHeaderSize;
+
+ BSWAP_TMPQHEADER(ha->pHeader);
+ if(!FileStream_Write(pTempStream, NULL, ha->pHeader, dwBytesToWrite))
+ nError = GetLastError();
+ BSWAP_TMPQHEADER(ha->pHeader);
+
+ // Update the progress
+ CompactBytesProcessed += ha->pHeader->dwHeaderSize;
+ }
+
+ // Now copy all files
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = CopyMpqFiles(ha, pFileKeys, pTempStream);
+ ha->dwFlags |= MPQ_FLAG_CHANGED;
+ }
+
+ // If succeeded, switch the streams
+ if(nError == ERROR_SUCCESS)
+ {
+ if(FileStream_Switch(ha->pStream, pTempStream))
+ pTempStream = NULL;
+ else
+ nError = ERROR_CAN_NOT_COMPLETE;
+ }
+
+ // If all succeeded, save the MPQ tables
+ if(nError == ERROR_SUCCESS)
+ {
+ //
+ // Note: We don't recalculate position of the MPQ tables at this point.
+ // SaveMPQTables does it automatically.
+ //
+
+ nError = SaveMPQTables(ha);
+ if(nError == ERROR_SUCCESS && CompactCB != NULL)
+ {
+ CompactBytesProcessed += (ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
+ CompactBytesProcessed += (ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock));
+ CompactCB(pvUserData, CCB_CLOSING_ARCHIVE, CompactBytesProcessed, CompactTotalBytes);
+ }
+ }
+
+ // Invalidate the compact callback
+ pvUserData = NULL;
+ CompactCB = NULL;
+
+ // Cleanup and return
+ if(pTempStream != NULL)
+ FileStream_Close(pTempStream);
+ if(pFileKeys != NULL)
+ STORM_FREE(pFileKeys);
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// Changing hash table size
+
+DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ return ha->dwMaxFileCount;
+}
+
+bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount)
+{
+ TMPQHetTable * pOldHetTable = NULL;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pOldFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pOldFileTable = NULL;
+ TFileEntry * pOldFileEntry;
+ TFileEntry * pFileEntry;
+ TMPQHash * pOldHashTable = NULL;
+ DWORD dwOldHashTableSize = 0;
+ DWORD dwOldFileTableSize = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Test the valid parameters
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
+ nError = ERROR_ACCESS_DENIED;
+
+ // The new limit must not be lower than the index of the last file entry in the table
+ if(nError == ERROR_SUCCESS && ha->dwFileTableSize > dwMaxFileCount)
+ nError = ERROR_DISK_FULL;
+
+ // ALL file names must be known in order to be able
+ // to rebuild hash table size
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = CheckIfAllFilesKnown(ha, NULL, NULL);
+ }
+
+ // If the MPQ has a hash table, then we relocate the hash table
+ if(nError == ERROR_SUCCESS && ha->pHashTable != NULL)
+ {
+ // Save parameters for the current hash table
+ dwOldHashTableSize = ha->pHeader->dwHashTableSize;
+ pOldHashTable = ha->pHashTable;
+
+ // Allocate new hash table
+ ha->pHeader->dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);
+ ha->pHashTable = STORM_ALLOC(TMPQHash, ha->pHeader->dwHashTableSize);
+ if(ha->pHashTable != NULL)
+ memset(ha->pHashTable, 0xFF, ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // If the MPQ has HET table, allocate new one as well
+ if(nError == ERROR_SUCCESS && ha->pHetTable != NULL)
+ {
+ // Save the original HET table
+ pOldHetTable = ha->pHetTable;
+
+ // Create new one
+ ha->pHetTable = CreateHetTable(dwMaxFileCount, 0x40, true);
+ if(ha->pHetTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Now reallocate the file table
+ if(nError == ERROR_SUCCESS)
+ {
+ // Save the current file table
+ dwOldFileTableSize = ha->dwFileTableSize;
+ pOldFileTable = ha->pFileTable;
+
+ // Create new one
+ ha->pFileTable = STORM_ALLOC(TFileEntry, dwMaxFileCount);
+ if(ha->pFileTable != NULL)
+ memset(ha->pFileTable, 0, dwMaxFileCount * sizeof(TFileEntry));
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Now we have to build both classic hash table and HET table.
+ if(nError == ERROR_SUCCESS)
+ {
+ DWORD dwFileIndex = 0;
+ DWORD dwHashIndex = 0;
+
+ // Create new hash and HET entry for each file
+ pFileEntry = ha->pFileTable;
+ for(pOldFileEntry = pOldFileTable; pOldFileEntry < pOldFileTableEnd; pOldFileEntry++)
+ {
+ if(pOldFileEntry->dwFlags & MPQ_FILE_EXISTS)
+ {
+ // Copy the old file entry to the new one
+ memcpy(pFileEntry, pOldFileEntry, sizeof(TFileEntry));
+ assert(pFileEntry->szFileName != NULL);
+
+ // Create new entry in the hash table
+ if(ha->pHashTable != NULL)
+ {
+ dwHashIndex = AllocateHashEntry(ha, pFileEntry);
+ if(dwHashIndex == HASH_ENTRY_FREE)
+ {
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+ }
+
+ // Create new entry in the HET table, if needed
+ if(ha->pHetTable != NULL)
+ {
+ dwHashIndex = AllocateHetEntry(ha, pFileEntry);
+ if(dwHashIndex == HASH_ENTRY_FREE)
+ {
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+ }
+
+ // Move to the next file entry in the new table
+ pFileEntry++;
+ dwFileIndex++;
+ }
+ }
+ }
+
+ // Mark the archive as changed
+ // Note: We always have to rebuild the (attributes) file due to file table change
+ if(nError == ERROR_SUCCESS)
+ {
+ ha->dwMaxFileCount = dwMaxFileCount;
+ InvalidateInternalFiles(ha);
+ }
+ else
+ {
+ // Revert the hash table
+ if(ha->pHashTable != NULL && pOldHashTable != NULL)
+ {
+ STORM_FREE(ha->pHashTable);
+ ha->pHeader->dwHashTableSize = dwOldHashTableSize;
+ ha->pHashTable = pOldHashTable;
+ }
+
+ // Revert the HET table
+ if(ha->pHetTable != NULL && pOldHetTable != NULL)
+ {
+ FreeHetTable(ha->pHetTable);
+ ha->pHetTable = pOldHetTable;
+ }
+
+ // Revert the file table
+ if(pOldFileTable != NULL)
+ {
+ STORM_FREE(ha->pFileTable);
+ ha->pFileTable = pOldFileTable;
+ }
+
+ SetLastError(nError);
+ }
+
+ // Return the result
+ return (nError == ERROR_SUCCESS);
+}
diff --git a/dep/StormLib/src/SFileCreateArchive.cpp b/dep/StormLib/src/SFileCreateArchive.cpp
new file mode 100644
index 00000000000..59f3d3fa9e8
--- /dev/null
+++ b/dep/StormLib/src/SFileCreateArchive.cpp
@@ -0,0 +1,255 @@
+/*****************************************************************************/
+/* SFileCreateArchive.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* MPQ Editing functions */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */
+/* 08.06.10 1.00 Lad Renamed to SFileCreateArchive.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local variables
+
+static const DWORD MpqHeaderSizes[] =
+{
+ MPQ_HEADER_SIZE_V1,
+ MPQ_HEADER_SIZE_V2,
+ MPQ_HEADER_SIZE_V3,
+ MPQ_HEADER_SIZE_V4
+};
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static USHORT GetSectorSizeShift(DWORD dwSectorSize)
+{
+ USHORT wSectorSizeShift = 0;
+
+ while(dwSectorSize > 0x200)
+ {
+ dwSectorSize >>= 1;
+ wSectorSizeShift++;
+ }
+
+ return wSectorSizeShift;
+}
+
+static int WriteNakedMPQHeader(TMPQArchive * ha)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ TMPQHeader Header;
+ DWORD dwBytesToWrite = pHeader->dwHeaderSize;
+ int nError = ERROR_SUCCESS;
+
+ // Prepare the naked MPQ header
+ memset(&Header, 0, sizeof(TMPQHeader));
+ Header.dwID = pHeader->dwID;
+ Header.dwHeaderSize = pHeader->dwHeaderSize;
+ Header.dwArchiveSize = pHeader->dwHeaderSize;
+ Header.wFormatVersion = pHeader->wFormatVersion;
+ Header.wSectorSize = pHeader->wSectorSize;
+
+ // Write it to the file
+ BSWAP_TMPQHEADER(&Header);
+ if(!FileStream_Write(ha->pStream, &ha->MpqPos, &Header, dwBytesToWrite))
+ nError = GetLastError();
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Creates a new MPQ archive.
+
+bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
+{
+ SFILE_CREATE_MPQ CreateInfo;
+
+ // Fill the create structure
+ memset(&CreateInfo, 0, sizeof(SFILE_CREATE_MPQ));
+ CreateInfo.cbSize = sizeof(SFILE_CREATE_MPQ);
+ CreateInfo.dwMpqVersion = (dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> FLAGS_TO_FORMAT_SHIFT;
+ CreateInfo.dwStreamFlags = STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE;
+ CreateInfo.dwAttrFlags = (dwFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_ATTRIBUTE_ALL : 0;
+ CreateInfo.dwSectorSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000;
+ CreateInfo.dwRawChunkSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_4) ? 0x4000 : 0;
+ CreateInfo.dwMaxFileCount = dwMaxFileCount;
+ return SFileCreateArchive2(szMpqName, &CreateInfo, phMpq);
+}
+
+bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq)
+{
+ TFileStream * pStream = NULL; // File stream
+ TMPQArchive * ha = NULL; // MPQ archive handle
+ ULONGLONG MpqPos = 0; // Position of MPQ header in the file
+ HANDLE hMpq = NULL;
+ DWORD dwBlockTableSize = 0; // Initial block table size
+ DWORD dwHashTableSize = 0;
+ DWORD dwMaxFileCount;
+ int nError = ERROR_SUCCESS;
+
+ // Check the parameters, if they are valid
+ if(szMpqName == NULL || *szMpqName == 0 || pCreateInfo == NULL || phMpq == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // Verify if all variables in SFILE_CREATE_MPQ are correct
+ if((pCreateInfo->cbSize == 0 || pCreateInfo->cbSize > sizeof(SFILE_CREATE_MPQ)) ||
+ (pCreateInfo->dwMpqVersion > MPQ_FORMAT_VERSION_4) ||
+ (pCreateInfo->pvUserData != NULL || pCreateInfo->cbUserData != 0) ||
+ (pCreateInfo->dwAttrFlags & ~MPQ_ATTRIBUTE_ALL) ||
+ (pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1)) ||
+ (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1)) ||
+ (pCreateInfo->dwMaxFileCount < 4))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // One time initialization of MPQ cryptography
+ InitializeMpqCryptography();
+
+ // We verify if the file already exists and if it's a MPQ archive.
+ // If yes, we won't allow to overwrite it.
+ if(SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE | MPQ_OPEN_NO_ATTRIBUTES | MPQ_OPEN_NO_LISTFILE, &hMpq))
+ {
+ SFileCloseArchive(hMpq);
+ SetLastError(ERROR_ALREADY_EXISTS);
+ return false;
+ }
+
+ //
+ // At this point, we have to create the archive.
+ // - If the file exists, convert it to MPQ archive.
+ // - If the file doesn't exist, create new empty file
+ //
+
+ pStream = FileStream_OpenFile(szMpqName, pCreateInfo->dwStreamFlags);
+ if(pStream == NULL)
+ {
+ pStream = FileStream_CreateFile(szMpqName, pCreateInfo->dwStreamFlags);
+ if(pStream == NULL)
+ return false;
+ }
+
+ // Increment the maximum amount of files to have space
+ // for listfile and attributes file
+ dwMaxFileCount = pCreateInfo->dwMaxFileCount;
+ if(pCreateInfo->dwAttrFlags != 0)
+ dwMaxFileCount++;
+ dwMaxFileCount++;
+
+ // If file count is not zero, initialize the hash table size
+ dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);
+
+ // Retrieve the file size and round it up to 0x200 bytes
+ FileStream_GetSize(pStream, MpqPos);
+ MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL;
+ if(!FileStream_SetSize(pStream, MpqPos))
+ nError = GetLastError();
+
+#ifdef _DEBUG
+ // Debug code, used for testing StormLib
+// dwBlockTableSize = dwHashTableSize * 2;
+#endif
+
+ // Create the archive handle
+ if(nError == ERROR_SUCCESS)
+ {
+ if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Fill the MPQ archive handle structure
+ if(nError == ERROR_SUCCESS)
+ {
+ memset(ha, 0, sizeof(TMPQArchive));
+ ha->pStream = pStream;
+ ha->dwSectorSize = pCreateInfo->dwSectorSize;
+ ha->UserDataPos = MpqPos;
+ ha->MpqPos = MpqPos;
+ ha->pHeader = (TMPQHeader *)ha->HeaderData;
+ ha->dwMaxFileCount = dwMaxFileCount;
+ ha->dwFileTableSize = 0;
+ ha->dwFileFlags1 = pCreateInfo->dwFileFlags1;
+ ha->dwFileFlags2 = pCreateInfo->dwFileFlags2;
+ ha->dwFlags = 0;
+
+ // Setup the attributes
+ ha->dwAttrFlags = pCreateInfo->dwAttrFlags;
+ pStream = NULL;
+ }
+
+ // Fill the MPQ header
+ if(nError == ERROR_SUCCESS)
+ {
+ TMPQHeader * pHeader = ha->pHeader;
+
+ // Fill the MPQ header
+ memset(pHeader, 0, sizeof(ha->HeaderData));
+ pHeader->dwID = ID_MPQ;
+ pHeader->dwHeaderSize = MpqHeaderSizes[pCreateInfo->dwMpqVersion];
+ pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
+ pHeader->wFormatVersion = (USHORT)pCreateInfo->dwMpqVersion;
+ pHeader->wSectorSize = GetSectorSizeShift(ha->dwSectorSize);
+ pHeader->dwHashTablePos = pHeader->dwHeaderSize;
+ pHeader->dwHashTableSize = dwHashTableSize;
+ pHeader->dwBlockTablePos = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash);
+ pHeader->dwBlockTableSize = dwBlockTableSize;
+
+ // For MPQs version 4 and higher, we set the size of raw data block
+ // for calculating MD5
+ if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4)
+ pHeader->dwRawChunkSize = pCreateInfo->dwRawChunkSize;
+
+ // Write the naked MPQ header
+ nError = WriteNakedMPQHeader(ha);
+
+ // Remember that the (listfile) and (attributes) need to be saved
+ ha->dwFlags |= MPQ_FLAG_CHANGED | MPQ_FLAG_INV_LISTFILE | MPQ_FLAG_INV_ATTRIBUTES;
+ }
+
+ // Create initial HET table, if the caller required an MPQ format 3.0 or newer
+ if(nError == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3)
+ {
+ ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true);
+ if(ha->pHetTable == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Create initial hash table
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = CreateHashTable(ha, dwHashTableSize);
+ }
+
+ // Create initial file table
+ if(nError == ERROR_SUCCESS)
+ {
+ ha->pFileTable = STORM_ALLOC(TFileEntry, ha->dwMaxFileCount);
+ if(ha->pFileTable != NULL)
+ memset(ha->pFileTable, 0x00, sizeof(TFileEntry) * ha->dwMaxFileCount);
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Cleanup : If an error, delete all buffers and return
+ if(nError != ERROR_SUCCESS)
+ {
+ FileStream_Close(pStream);
+ FreeMPQArchive(ha);
+ SetLastError(nError);
+ ha = NULL;
+ }
+
+ // Return the values
+ *phMpq = (HANDLE)ha;
+ return (nError == ERROR_SUCCESS);
+}
diff --git a/dep/StormLib/src/SFileExtractFile.cpp b/dep/StormLib/src/SFileExtractFile.cpp
new file mode 100644
index 00000000000..c8053ed4e62
--- /dev/null
+++ b/dep/StormLib/src/SFileExtractFile.cpp
@@ -0,0 +1,67 @@
+/*****************************************************************************/
+/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Simple extracting utility */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
+{
+ TFileStream * pLocalFile = NULL;
+ HANDLE hMpqFile = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Open the MPQ file
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile))
+ nError = GetLastError();
+ }
+
+ // Create the local file
+ if(nError == ERROR_SUCCESS)
+ {
+ pLocalFile = FileStream_CreateFile(szExtracted, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pLocalFile == NULL)
+ nError = GetLastError();
+ }
+
+ // Copy the file's content
+ if(nError == ERROR_SUCCESS)
+ {
+ char szBuffer[0x1000];
+ DWORD dwTransferred;
+
+ for(;;)
+ {
+ // dwTransferred is only set to nonzero if something has been read.
+ // nError can be ERROR_SUCCESS or ERROR_HANDLE_EOF
+ if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL))
+ nError = GetLastError();
+ if(nError == ERROR_HANDLE_EOF)
+ nError = ERROR_SUCCESS;
+ if(dwTransferred == 0)
+ break;
+
+ // If something has been actually read, write it
+ if(!FileStream_Write(pLocalFile, NULL, szBuffer, dwTransferred))
+ nError = GetLastError();
+ }
+ }
+
+ // Close the files
+ if(hMpqFile != NULL)
+ SFileCloseFile(hMpqFile);
+ if(pLocalFile != NULL)
+ FileStream_Close(pLocalFile);
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
diff --git a/dep/StormLib/src/SFileFindFile.cpp b/dep/StormLib/src/SFileFindFile.cpp
new file mode 100644
index 00000000000..337be7d2c54
--- /dev/null
+++ b/dep/StormLib/src/SFileFindFile.cpp
@@ -0,0 +1,446 @@
+/*****************************************************************************/
+/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* A module for file searching within MPQs */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define LISTFILE_CACHE_SIZE 0x1000
+
+//-----------------------------------------------------------------------------
+// Private structure used for file search (search handle)
+
+struct TMPQSearch;
+typedef int (*MPQSEARCH)(TMPQSearch *, SFILE_FIND_DATA *);
+
+// Used by searching in MPQ archives
+struct TMPQSearch
+{
+ TMPQArchive * ha; // Handle to MPQ, where the search runs
+ TFileEntry ** pSearchTable; // Table for files that have been already found
+ DWORD dwSearchTableItems; // Number of items in the search table
+ DWORD dwNextIndex; // Next file index to be checked
+ DWORD dwFlagMask; // For checking flag mask
+ char szSearchMask[1]; // Search mask (variable length)
+};
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static bool IsValidSearchHandle(TMPQSearch * hs)
+{
+ if(hs == NULL)
+ return false;
+
+ return IsValidMpqHandle(hs->ha);
+}
+
+bool CheckWildCard(const char * szString, const char * szWildCard)
+{
+ const char * szSubString;
+ int nSubStringLength;
+ int nMatchCount = 0;
+
+ // When the mask is empty, it never matches
+ if(szWildCard == NULL || *szWildCard == 0)
+ return false;
+
+ // If the wildcard contains just "*", then it always matches
+ if(szWildCard[0] == '*' && szWildCard[1] == 0)
+ return true;
+
+ // Do normal test
+ for(;;)
+ {
+ // If there is '?' in the wildcard, we skip one char
+ while(*szWildCard == '?')
+ {
+ szWildCard++;
+ szString++;
+ }
+
+ // If there is '*', means zero or more chars. We have to
+ // find the sequence after '*'
+ if(*szWildCard == '*')
+ {
+ // More stars is equal to one star
+ while(*szWildCard == '*' || *szWildCard == '?')
+ szWildCard++;
+
+ // If we found end of the wildcard, it's a match
+ if(*szWildCard == 0)
+ return true;
+
+ // Determine the length of the substring in szWildCard
+ szSubString = szWildCard;
+ while(*szSubString != 0 && *szSubString != '?' && *szSubString != '*')
+ szSubString++;
+ nSubStringLength = (int)(szSubString - szWildCard);
+ nMatchCount = 0;
+
+ // Now we have to find a substring in szString,
+ // that matches the substring in szWildCard
+ while(*szString != 0)
+ {
+ // Calculate match count
+ while(nMatchCount < nSubStringLength)
+ {
+ if(toupper(szString[nMatchCount]) != toupper(szWildCard[nMatchCount]))
+ break;
+ if(szString[nMatchCount] == 0)
+ break;
+ nMatchCount++;
+ }
+
+ // If the match count has reached substring length, we found a match
+ if(nMatchCount == nSubStringLength)
+ {
+ szWildCard += nMatchCount;
+ szString += nMatchCount;
+ break;
+ }
+
+ // No match, move to the next char in szString
+ nMatchCount = 0;
+ szString++;
+ }
+ }
+ else
+ {
+ // If we came to the end of the string, compare it to the wildcard
+ if(toupper(*szString) != toupper(*szWildCard))
+ return false;
+
+ // If we arrived to the end of the string, it's a match
+ if(*szString == 0)
+ return true;
+
+ // Otherwise, continue in comparing
+ szWildCard++;
+ szString++;
+ }
+ }
+}
+
+static DWORD GetSearchTableItems(TMPQArchive * ha)
+{
+ DWORD dwMergeItems = 0;
+
+ // Loop over all patches
+ while(ha != NULL)
+ {
+ // Append the number of files
+ dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwMaxFileCount
+ : ha->pHeader->dwBlockTableSize;
+ // Move to the patched archive
+ ha = ha->haPatch;
+ }
+
+ // Return the double size of number of items
+ return (dwMergeItems | 1);
+}
+
+static bool FileWasFoundBefore(
+ TMPQArchive * ha,
+ TMPQSearch * hs,
+ TFileEntry * pFileEntry)
+{
+ TFileEntry * pEntry;
+ char * szRealFileName = pFileEntry->szFileName;
+ DWORD dwStartIndex;
+ DWORD dwNameHash;
+ DWORD dwIndex;
+
+ if(hs->pSearchTable != NULL && szRealFileName != NULL)
+ {
+ // If we are in patch MPQ, we check if patch prefix matches
+ // and then trim the patch prefix
+ if(ha->cchPatchPrefix != 0)
+ {
+ // If the patch prefix doesn't fit, we pretend that the file
+ // was there before and it will be skipped
+ if(_strnicmp(szRealFileName, ha->szPatchPrefix, ha->cchPatchPrefix))
+ return true;
+
+ szRealFileName += ha->cchPatchPrefix;
+ }
+
+ // Calculate the hash to the table
+ dwNameHash = HashString(szRealFileName, MPQ_HASH_NAME_A);
+ dwStartIndex = dwIndex = (dwNameHash % hs->dwSearchTableItems);
+
+ // The file might have been found before
+ // only if this is not the first MPQ being searched
+ if(ha->haBase != NULL)
+ {
+ // Enumerate all entries in the search table
+ for(;;)
+ {
+ // Get the file entry at that position
+ pEntry = hs->pSearchTable[dwIndex];
+ if(pEntry == NULL)
+ break;
+
+ if(pEntry->szFileName != NULL)
+ {
+ // Does the name match?
+ if(!_stricmp(pEntry->szFileName, szRealFileName))
+ return true;
+ }
+
+ // Move to the next entry
+ dwIndex = (dwIndex + 1) % hs->dwSearchTableItems;
+ if(dwIndex == dwStartIndex)
+ break;
+ }
+ }
+
+ // Put the entry to the table for later use
+ hs->pSearchTable[dwIndex] = pFileEntry;
+ }
+ return false;
+}
+
+static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
+{
+ TFileEntry * pPatchEntry = NULL;
+ TFileEntry * pTempEntry;
+ char szFileName[MAX_PATH];
+ LCID lcLocale = pFileEntry->lcLocale;
+
+ // Go while there are patches
+ while(ha->haPatch != NULL)
+ {
+ // Move to the patch archive
+ ha = ha->haPatch;
+
+ // Prepare the prefix for the file name
+ strcpy(szFileName, ha->szPatchPrefix);
+ strcat(szFileName, pFileEntry->szFileName);
+
+ // Try to find the file there
+ pTempEntry = GetFileEntryExact(ha, szFileName, lcLocale);
+ if(pTempEntry != NULL)
+ pPatchEntry = pTempEntry;
+ }
+
+ // Return the found patch entry
+ return pPatchEntry;
+}
+
+// Performs one MPQ search
+static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
+{
+ TMPQArchive * ha = hs->ha;
+ TFileEntry * pFileTableEnd;
+ TFileEntry * pPatchEntry;
+ TFileEntry * pFileEntry;
+ const char * szFileName;
+ HANDLE hFile;
+ char szPseudoName[20];
+ DWORD dwBlockIndex;
+ size_t nPrefixLength;
+
+ // Start searching with base MPQ
+ while(ha != NULL)
+ {
+ // Now parse the file entry table in order to get all files.
+ pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ pFileEntry = ha->pFileTable + hs->dwNextIndex;
+
+ // Get the length of the patch prefix (0 if none)
+ nPrefixLength = strlen(ha->szPatchPrefix);
+
+ // Parse the file table
+ while(pFileEntry < pFileTableEnd)
+ {
+ // Increment the next index for subsequent search
+ hs->dwNextIndex++;
+
+ // Is it a file and not a patch file?
+ if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
+ {
+ // Now we have to check if this file was not enumerated before
+ if(!FileWasFoundBefore(ha, hs, pFileEntry))
+ {
+ // Find a patch to this file
+ pPatchEntry = FindPatchEntry(ha, pFileEntry);
+ if(pPatchEntry == NULL)
+ pPatchEntry = pFileEntry;
+
+ // Prepare the block index
+ dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
+
+ // Get the file name. If it's not known, we will create pseudo-name
+ szFileName = pFileEntry->szFileName;
+ if(szFileName == NULL)
+ {
+ // Open the file by its pseudo-name.
+ // This also generates the file name with a proper extension
+ sprintf(szPseudoName, "File%08u.xxx", dwBlockIndex);
+ if(SFileOpenFileEx((HANDLE)hs->ha, szPseudoName, SFILE_OPEN_FROM_MPQ, &hFile))
+ {
+ szFileName = (pFileEntry->szFileName != NULL) ? pFileEntry->szFileName : szPseudoName;
+ SFileCloseFile(hFile);
+ }
+ }
+
+ // Check the file name against the wildcard
+ if(CheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
+ {
+ // Fill the found entry
+ lpFindFileData->dwHashIndex = pPatchEntry->dwHashIndex;
+ lpFindFileData->dwBlockIndex = dwBlockIndex;
+ lpFindFileData->dwFileSize = pPatchEntry->dwFileSize;
+ lpFindFileData->dwFileFlags = pPatchEntry->dwFlags;
+ lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize;
+ lpFindFileData->lcLocale = pPatchEntry->lcLocale;
+
+ // Fill the filetime
+ lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32);
+ lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime);
+
+ // Fill the file name and plain file name
+ strcpy(lpFindFileData->cFileName, szFileName + nPrefixLength);
+ lpFindFileData->szPlainName = (char *)GetPlainFileNameA(lpFindFileData->cFileName);
+ return ERROR_SUCCESS;
+ }
+
+ }
+ }
+
+ pFileEntry++;
+ }
+
+ // Move to the next patch in the patch chain
+ hs->ha = ha = ha->haPatch;
+ hs->dwNextIndex = 0;
+ }
+
+ // No more files found, return error
+ return ERROR_NO_MORE_FILES;
+}
+
+static void FreeMPQSearch(TMPQSearch *& hs)
+{
+ if(hs != NULL)
+ {
+ if(hs->pSearchTable != NULL)
+ STORM_FREE(hs->pSearchTable);
+ STORM_FREE(hs);
+ hs = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TMPQSearch * hs = NULL;
+ size_t nSize = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Check for the valid parameters
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szMask == NULL || lpFindFileData == NULL)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Include the listfile into the MPQ's internal listfile
+ // Note that if the listfile name is NULL, do nothing because the
+ // internal listfile is always included.
+ if(nError == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
+ nError = SFileAddListFile((HANDLE)ha, szListFile);
+
+ // Allocate the structure for MPQ search
+ if(nError == ERROR_SUCCESS)
+ {
+ nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
+ if((hs = (TMPQSearch *)STORM_ALLOC(char, nSize)) == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Perform the first search
+ if(nError == ERROR_SUCCESS)
+ {
+ memset(hs, 0, sizeof(TMPQSearch));
+ strcpy(&hs->szSearchMask[0], szMask);
+ hs->dwFlagMask = MPQ_FILE_EXISTS;
+ hs->ha = ha;
+
+ // If the archive is patched archive, we have to create a merge table
+ // to prevent files being repeated
+ if(ha->haPatch != NULL)
+ {
+ hs->dwSearchTableItems = GetSearchTableItems(ha);
+ hs->pSearchTable = STORM_ALLOC(TFileEntry *, hs->dwSearchTableItems);
+ hs->dwFlagMask = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE;
+ if(hs->pSearchTable != NULL)
+ memset(hs->pSearchTable, 0, hs->dwSearchTableItems * sizeof(TFileEntry *));
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ // Perform first item searching
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = DoMPQSearch(hs, lpFindFileData);
+ }
+
+ // Cleanup
+ if(nError != ERROR_SUCCESS)
+ {
+ FreeMPQSearch(hs);
+ SetLastError(nError);
+ }
+
+ // Return the result value
+ return (HANDLE)hs;
+}
+
+bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
+{
+ TMPQSearch * hs = (TMPQSearch *)hFind;
+ int nError = ERROR_SUCCESS;
+
+ // Check the parameters
+ if(!IsValidSearchHandle(hs))
+ nError = ERROR_INVALID_HANDLE;
+ if(lpFindFileData == NULL)
+ nError = ERROR_INVALID_PARAMETER;
+
+ if(nError == ERROR_SUCCESS)
+ nError = DoMPQSearch(hs, lpFindFileData);
+
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+bool WINAPI SFileFindClose(HANDLE hFind)
+{
+ TMPQSearch * hs = (TMPQSearch *)hFind;
+
+ // Check the parameters
+ if(!IsValidSearchHandle(hs))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ FreeMPQSearch(hs);
+ return true;
+}
diff --git a/dep/StormLib/src/SFileListFile.cpp b/dep/StormLib/src/SFileListFile.cpp
new file mode 100644
index 00000000000..4604206ed0a
--- /dev/null
+++ b/dep/StormLib/src/SFileListFile.cpp
@@ -0,0 +1,557 @@
+/*****************************************************************************/
+/* SListFile.cpp Copyright (c) Ladislav Zezula 2004 */
+/*---------------------------------------------------------------------------*/
+/* Description: */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 12.06.04 1.00 Lad The first version of SListFile.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+#include <assert.h>
+
+//-----------------------------------------------------------------------------
+// Listfile entry structure
+
+#define CACHE_BUFFER_SIZE 0x1000 // Size of the cache buffer
+
+struct TListFileCache
+{
+ HANDLE hFile; // Stormlib file handle
+ char * szMask; // File mask
+ DWORD dwFileSize; // Total size of the cached file
+ DWORD dwFilePos; // Position of the cache in the file
+ BYTE * pBegin; // The begin of the listfile cache
+ BYTE * pPos;
+ BYTE * pEnd; // The last character in the file cache
+
+ BYTE Buffer[CACHE_BUFFER_SIZE]; // Listfile cache itself
+};
+
+//-----------------------------------------------------------------------------
+// Local functions (cache)
+
+static TListFileCache * CreateListFileCache(HANDLE hMpq, const char * szListFile)
+{
+ TListFileCache * pCache = NULL;
+ HANDLE hListFile = NULL;
+ DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE;
+ DWORD dwBytesRead = 0;
+ int nError = ERROR_SUCCESS;
+
+ // If the szListFile is NULL, it means we have to open internal listfile
+ if(szListFile == NULL)
+ {
+ // Use SFILE_OPEN_ANY_LOCALE for listfile. This will allow us to load
+ // the listfile even if there is only non-neutral version of the listfile in the MPQ
+ dwSearchScope = SFILE_OPEN_ANY_LOCALE;
+ szListFile = LISTFILE_NAME;
+ }
+
+ // Open the local/internal listfile
+ if(SFileOpenFileEx(hMpq, szListFile, dwSearchScope, &hListFile))
+ {
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TMPQFile * hf = (TMPQFile *)hListFile;
+
+ // Remember flags for (listfile)
+ if(hf->pFileEntry != NULL)
+ ha->dwFileFlags1 = hf->pFileEntry->dwFlags;
+ }
+ else
+ nError = GetLastError();
+
+ // Allocate cache for one file block
+ if(nError == ERROR_SUCCESS)
+ {
+ pCache = (TListFileCache *)STORM_ALLOC(TListFileCache, 1);
+ if(pCache == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ // Initialize the file cache
+ memset(pCache, 0, sizeof(TListFileCache));
+ pCache->dwFileSize = SFileGetFileSize(hListFile, NULL);
+ pCache->hFile = hListFile;
+
+ // Fill the cache
+ SFileReadFile(hListFile, pCache->Buffer, CACHE_BUFFER_SIZE, &dwBytesRead, NULL);
+ if(dwBytesRead == 0)
+ nError = GetLastError();
+ }
+
+ // Initialize the pointers
+ if(nError == ERROR_SUCCESS)
+ {
+ pCache->pBegin =
+ pCache->pPos = &pCache->Buffer[0];
+ pCache->pEnd = pCache->pBegin + dwBytesRead;
+ }
+ else
+ {
+ SListFileFindClose((HANDLE)pCache);
+ SetLastError(nError);
+ pCache = NULL;
+ }
+
+ // Return the cache
+ return pCache;
+}
+
+// Reloads the cache. Returns number of characters
+// that has been loaded into the cache.
+static DWORD ReloadListFileCache(TListFileCache * pCache)
+{
+ DWORD dwBytesToRead;
+ DWORD dwBytesRead = 0;
+
+ // Only do something if the cache is empty
+ if(pCache->pPos >= pCache->pEnd)
+ {
+// __TryReadBlock:
+
+ // Move the file position forward
+ pCache->dwFilePos += CACHE_BUFFER_SIZE;
+ if(pCache->dwFilePos >= pCache->dwFileSize)
+ return 0;
+
+ // Get the number of bytes remaining
+ dwBytesToRead = pCache->dwFileSize - pCache->dwFilePos;
+ if(dwBytesToRead > CACHE_BUFFER_SIZE)
+ dwBytesToRead = CACHE_BUFFER_SIZE;
+
+ // Load the next data chunk to the cache
+ SFileSetFilePointer(pCache->hFile, pCache->dwFilePos, NULL, FILE_BEGIN);
+ SFileReadFile(pCache->hFile, pCache->Buffer, CACHE_BUFFER_SIZE, &dwBytesRead, NULL);
+
+ // If we didn't read anything, it might mean that the block
+ // of the file is not available (in case of partial MPQs).
+ // We stop reading the file at this point, because the rest
+ // of the listfile is unreliable
+ if(dwBytesRead == 0)
+ return 0;
+
+ // Set the buffer pointers
+ pCache->pBegin =
+ pCache->pPos = &pCache->Buffer[0];
+ pCache->pEnd = pCache->pBegin + dwBytesRead;
+ }
+
+ return dwBytesRead;
+}
+
+static size_t ReadListFileLine(TListFileCache * pCache, char * szLine, int nMaxChars)
+{
+ char * szLineBegin = szLine;
+ char * szLineEnd = szLine + nMaxChars - 1;
+ char * szExtraString = NULL;
+
+ // Skip newlines, spaces, tabs and another non-printable stuff
+ for(;;)
+ {
+ // If we need to reload the cache, do it
+ if(pCache->pPos == pCache->pEnd)
+ {
+ if(ReloadListFileCache(pCache) == 0)
+ break;
+ }
+
+ // If we found a non-whitespace character, stop
+ if(*pCache->pPos > 0x20)
+ break;
+
+ // Skip the character
+ pCache->pPos++;
+ }
+
+ // Copy the remaining characters
+ while(szLine < szLineEnd)
+ {
+ // If we need to reload the cache, do it now and resume copying
+ if(pCache->pPos == pCache->pEnd)
+ {
+ if(ReloadListFileCache(pCache) == 0)
+ break;
+ }
+
+ // If we have found a newline, stop loading
+ if(*pCache->pPos == 0x0D || *pCache->pPos == 0x0A)
+ break;
+
+ // Blizzard listfiles can also contain information about patch:
+ // Pass1\Files\MacOS\unconditional\user\Background Downloader.app\Contents\Info.plist~Patch(Data#frFR#base-frFR,1326)
+ if(*pCache->pPos == '~')
+ szExtraString = szLine;
+
+ // Copy the character
+ *szLine++ = *pCache->pPos++;
+ }
+
+ // Terminate line with zero
+ *szLine = 0;
+
+ // If there was extra string after the file name, clear it
+ if(szExtraString != NULL)
+ {
+ if(szExtraString[0] == '~' && szExtraString[1] == 'P')
+ {
+ szLine = szExtraString;
+ *szExtraString = 0;
+ }
+ }
+
+ // Return the length of the line
+ return (szLine - szLineBegin);
+}
+
+static int CompareFileNodes(const void * p1, const void * p2)
+{
+ char * szFileName1 = *(char **)p1;
+ char * szFileName2 = *(char **)p2;
+
+ return _stricmp(szFileName1, szFileName2);
+}
+
+static int WriteListFileLine(
+ TMPQFile * hf,
+ const char * szLine)
+{
+ char szNewLine[2] = {0x0D, 0x0A};
+ size_t nLength = strlen(szLine);
+ int nError;
+
+ nError = SFileAddFile_Write(hf, szLine, (DWORD)nLength, MPQ_COMPRESSION_ZLIB);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ return SFileAddFile_Write(hf, szNewLine, sizeof(szNewLine), MPQ_COMPRESSION_ZLIB);
+}
+
+//-----------------------------------------------------------------------------
+// Local functions (listfile nodes)
+
+// Adds a name into the list of all names. For each locale in the MPQ,
+// one entry will be created
+// If the file name is already there, does nothing.
+int SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFileName)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ TFileEntry * pFileEntry;
+ TMPQHash * pFirstHash;
+ TMPQHash * pHash;
+ bool bNameEntryCreated = false;
+
+ // If we have HET table, use that one
+ if(ha->pHetTable != NULL)
+ {
+ pFileEntry = GetFileEntryAny(ha, szFileName);
+ if(pFileEntry != NULL)
+ {
+ // Allocate file name for the file entry
+ AllocateFileName(pFileEntry, szFileName);
+ bNameEntryCreated = true;
+ }
+
+ return ERROR_SUCCESS;
+ }
+
+ // If we have hash table, we use it
+ if(bNameEntryCreated == false && ha->pHashTable != NULL)
+ {
+ // Look for the first hash table entry for the file
+ pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
+
+ // Go while we found something
+ while(pHash != NULL)
+ {
+ // Is it a valid file table index ?
+ if(pHash->dwBlockIndex < pHeader->dwBlockTableSize)
+ {
+ // Allocate file name for the file entry
+ AllocateFileName(ha->pFileTable + pHash->dwBlockIndex, szFileName);
+ bNameEntryCreated = true;
+ }
+
+ // Now find the next language version of the file
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+ }
+
+ return ERROR_CAN_NOT_COMPLETE;
+}
+
+// Saves the whole listfile into the MPQ.
+int SListFileSaveToMpq(TMPQArchive * ha)
+{
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ TFileEntry * pFileEntry;
+ TMPQFile * hf = NULL;
+ char * szPrevItem;
+ char ** SortTable = NULL;
+ DWORD dwFileSize = 0;
+ size_t nFileNodes = 0;
+ size_t i;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate the table for sorting listfile
+ SortTable = STORM_ALLOC(char*, ha->dwFileTableSize);
+ if(SortTable == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Construct the sort table
+ // Note: in MPQs with multiple locale versions of the same file,
+ // this code causes adding multiple listfile entries.
+ // Since those MPQs were last time used in Starcraft,
+ // we leave it as it is.
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // Only take existing items
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->szFileName != NULL)
+ {
+ // Ignore pseudo-names
+ if(!IsPseudoFileName(pFileEntry->szFileName, NULL) && !IsInternalMpqFileName(pFileEntry->szFileName))
+ {
+ SortTable[nFileNodes++] = pFileEntry->szFileName;
+ }
+ }
+ }
+
+ // Sort the table
+ qsort(SortTable, nFileNodes, sizeof(char *), CompareFileNodes);
+
+ // Now parse the table of file names again - remove duplicates
+ // and count file size.
+ if(nFileNodes != 0)
+ {
+ // Count the 0-th item
+ dwFileSize += (DWORD)strlen(SortTable[0]) + 2;
+ szPrevItem = SortTable[0];
+
+ // Count all next items
+ for(i = 1; i < nFileNodes; i++)
+ {
+ // If the item is the same like the last one, skip it
+ if(_stricmp(SortTable[i], szPrevItem))
+ {
+ dwFileSize += (DWORD)strlen(SortTable[i]) + 2;
+ szPrevItem = SortTable[i];
+ }
+ }
+
+ // Determine the flags for (listfile)
+ if(ha->dwFileFlags1 == 0)
+ ha->dwFileFlags1 = GetDefaultSpecialFileFlags(ha, dwFileSize);
+
+ // Create the listfile in the MPQ
+ nError = SFileAddFile_Init(ha, LISTFILE_NAME,
+ 0,
+ dwFileSize,
+ LANG_NEUTRAL,
+ ha->dwFileFlags1 | MPQ_FILE_REPLACEEXISTING,
+ &hf);
+ // Add all file names
+ if(nError == ERROR_SUCCESS)
+ {
+ // Each name is followed by newline ("\x0D\x0A")
+ szPrevItem = SortTable[0];
+ nError = WriteListFileLine(hf, SortTable[0]);
+
+ // Count all next items
+ for(i = 1; i < nFileNodes; i++)
+ {
+ // If the item is the same like the last one, skip it
+ if(_stricmp(SortTable[i], szPrevItem))
+ {
+ WriteListFileLine(hf, SortTable[i]);
+ szPrevItem = SortTable[i];
+ }
+ }
+ }
+ }
+ else
+ {
+ // Create the listfile in the MPQ
+ dwFileSize = (DWORD)strlen(LISTFILE_NAME) + 2;
+ nError = SFileAddFile_Init(ha, LISTFILE_NAME,
+ 0,
+ dwFileSize,
+ LANG_NEUTRAL,
+ MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING,
+ &hf);
+
+ // Just add "(listfile)" there
+ if(nError == ERROR_SUCCESS)
+ {
+ WriteListFileLine(hf, LISTFILE_NAME);
+ }
+ }
+
+ // Finalize the file in the MPQ
+ if(hf != NULL)
+ {
+ SFileAddFile_Finish(hf);
+ }
+
+ // Free buffers
+ if(nError == ERROR_SUCCESS)
+ ha->dwFlags &= ~MPQ_FLAG_INV_LISTFILE;
+ if(SortTable != NULL)
+ STORM_FREE(SortTable);
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// File functions
+
+// Adds a listfile into the MPQ archive.
+// Note that the function does not remove the
+int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile)
+{
+ TListFileCache * pCache = NULL;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ char szFileName[MAX_PATH];
+ size_t nLength = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Add the listfile for each MPQ in the patch chain
+ while(ha != NULL)
+ {
+ // Load the listfile to cache
+ pCache = CreateListFileCache(hMpq, szListFile);
+ if(pCache == NULL)
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // Load the node list. Add the node for every locale in the archive
+ while((nLength = ReadListFileLine(pCache, szFileName, sizeof(szFileName))) > 0)
+ SListFileCreateNodeForAllLocales(ha, szFileName);
+
+ // Also, add three special files to the listfile:
+ // (listfile) itself, (attributes) and (signature)
+ SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME);
+ SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME);
+ SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME);
+
+ // Delete the cache
+ SListFileFindClose((HANDLE)pCache);
+
+ // Move to the next archive in the chain
+ ha = ha->haPatch;
+ }
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Passing through the listfile
+
+HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData)
+{
+ TListFileCache * pCache = NULL;
+ size_t nLength = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Initialize the structure with zeros
+ memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
+
+ // Load the listfile to cache
+ pCache = CreateListFileCache(hMpq, szListFile);
+ if(pCache == NULL)
+ nError = GetLastError();
+
+ // Allocate file mask
+ if(nError == ERROR_SUCCESS && szMask != NULL)
+ {
+ pCache->szMask = STORM_ALLOC(char, strlen(szMask) + 1);
+ if(pCache->szMask != NULL)
+ strcpy(pCache->szMask, szMask);
+ else
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Perform file search
+ if(nError == ERROR_SUCCESS)
+ {
+ for(;;)
+ {
+ // Read the (next) line
+ nLength = ReadListFileLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
+ if(nLength == 0)
+ {
+ nError = ERROR_NO_MORE_FILES;
+ break;
+ }
+
+ // If some mask entered, check it
+ if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
+ break;
+ }
+ }
+
+ // Cleanup & exit
+ if(nError != ERROR_SUCCESS)
+ {
+ memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
+ SListFileFindClose((HANDLE)pCache);
+ pCache = NULL;
+
+ SetLastError(nError);
+ }
+ return (HANDLE)pCache;
+}
+
+bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
+{
+ TListFileCache * pCache = (TListFileCache *)hFind;
+ size_t nLength;
+ bool bResult = false;
+ int nError = ERROR_SUCCESS;
+
+ for(;;)
+ {
+ // Read the (next) line
+ nLength = ReadListFileLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
+ if(nLength == 0)
+ {
+ nError = ERROR_NO_MORE_FILES;
+ break;
+ }
+
+ // If some mask entered, check it
+ if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
+ {
+ bResult = true;
+ break;
+ }
+ }
+
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return bResult;
+}
+
+bool WINAPI SListFileFindClose(HANDLE hFind)
+{
+ TListFileCache * pCache = (TListFileCache *)hFind;
+
+ if(pCache != NULL)
+ {
+ if(pCache->hFile != NULL)
+ SFileCloseFile(pCache->hFile);
+ if(pCache->szMask != NULL)
+ STORM_FREE(pCache->szMask);
+
+ STORM_FREE(pCache);
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/dep/StormLib/src/SFileOpenArchive.cpp b/dep/StormLib/src/SFileOpenArchive.cpp
new file mode 100644
index 00000000000..b36b7d35ea7
--- /dev/null
+++ b/dep/StormLib/src/SFileOpenArchive.cpp
@@ -0,0 +1,470 @@
+/*****************************************************************************/
+/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
+/* */
+/* Author : Ladislav Zezula */
+/* E-mail : ladik@zezula.net */
+/* WWW : www.zezula.net */
+/*---------------------------------------------------------------------------*/
+/* Archive functions of Storm.dll */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
+/* 19.11.03 1.01 Dan Big endian handling */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+/*****************************************************************************/
+/* Local functions */
+/*****************************************************************************/
+
+static bool IsAviFile(void * pvFileBegin)
+{
+ LPDWORD AviHeader = (DWORD *)pvFileBegin;
+ DWORD DwordValue0 = BSWAP_INT32_UNSIGNED(AviHeader[0]);
+ DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(AviHeader[2]);
+ DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(AviHeader[3]);
+
+ // Test for 'RIFF', 'AVI ' or 'LIST'
+ return (DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C);
+}
+
+static TFileBitmap * CreateFileBitmap(TMPQArchive * ha, TMPQBitmap * pMpqBitmap, bool bFileIsComplete)
+{
+ TFileBitmap * pBitmap;
+ size_t nLength;
+
+ // Calculate the length of the bitmap in blocks and in bytes
+ nLength = (size_t)(((ha->pHeader->ArchiveSize64 - 1) / pMpqBitmap->dwBlockSize) + 1);
+ nLength = (size_t)(((nLength - 1) / 8) + 1);
+
+ // Allocate the file bitmap
+ pBitmap = (TFileBitmap *)STORM_ALLOC(BYTE, sizeof(TFileBitmap) + nLength);
+ if(pBitmap != NULL)
+ {
+ // Fill the structure
+ pBitmap->StartOffset = ha->MpqPos;
+ pBitmap->EndOffset = ha->MpqPos + ha->pHeader->ArchiveSize64;
+ pBitmap->IsComplete = bFileIsComplete ? 1 : 0;
+ pBitmap->BitmapSize = (DWORD)nLength;
+ pBitmap->BlockSize = pMpqBitmap->dwBlockSize;
+ pBitmap->Reserved = 0;
+
+ // Copy the file bitmap
+ memcpy((pBitmap + 1), (pMpqBitmap + 1), nLength);
+ }
+
+ return pBitmap;
+}
+
+// This function gets the right positions of the hash table and the block table.
+static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize)
+{
+ TMPQHeader * pHeader = ha->pHeader;
+ ULONGLONG ByteOffset;
+
+ // Check the begin of HET table
+ if(pHeader->HetTablePos64)
+ {
+ ByteOffset = ha->MpqPos + pHeader->HetTablePos64;
+ if(ByteOffset > FileSize)
+ return ERROR_BAD_FORMAT;
+ }
+
+ // Check the begin of BET table
+ if(pHeader->BetTablePos64)
+ {
+ ByteOffset = ha->MpqPos + pHeader->BetTablePos64;
+ if(ByteOffset > FileSize)
+ return ERROR_BAD_FORMAT;
+ }
+
+ // Check the begin of hash table
+ if(pHeader->wHashTablePosHi || pHeader->dwHashTablePos)
+ {
+ ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
+ if(ByteOffset > FileSize)
+ return ERROR_BAD_FORMAT;
+ }
+
+ // Check the begin of block table
+ if(pHeader->wBlockTablePosHi || pHeader->dwBlockTablePos)
+ {
+ ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ if(ByteOffset > FileSize)
+ return ERROR_BAD_FORMAT;
+ }
+
+ // Check the begin of hi-block table
+ if(pHeader->HiBlockTablePos64 != 0)
+ {
+ ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
+ if(ByteOffset > FileSize)
+ return ERROR_BAD_FORMAT;
+ }
+
+ // All OK.
+ return ERROR_SUCCESS;
+}
+
+
+/*****************************************************************************/
+/* Public functions */
+/*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+// SFileGetLocale and SFileSetLocale
+// Set the locale for all newly opened files
+
+LCID WINAPI SFileGetLocale()
+{
+ return lcFileLocale;
+}
+
+LCID WINAPI SFileSetLocale(LCID lcNewLocale)
+{
+ lcFileLocale = lcNewLocale;
+ return lcFileLocale;
+}
+
+//-----------------------------------------------------------------------------
+// SFileOpenArchive
+//
+// szFileName - MPQ archive file name to open
+// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
+// dwFlags - See MPQ_OPEN_XXX in StormLib.h
+// phMpq - Pointer to store open archive handle
+
+bool WINAPI SFileOpenArchive(
+ const TCHAR * szMpqName,
+ DWORD dwPriority,
+ DWORD dwFlags,
+ HANDLE * phMpq)
+{
+ TFileStream * pStream = NULL; // Open file stream
+ TMPQArchive * ha = NULL; // Archive handle
+ ULONGLONG FileSize = 0; // Size of the file
+ int nError = ERROR_SUCCESS;
+
+ // Verify the parameters
+ if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // One time initialization of MPQ cryptography
+ InitializeMpqCryptography();
+ dwPriority = dwPriority;
+
+ // Open the MPQ archive file
+ if(nError == ERROR_SUCCESS)
+ {
+ // Initialize the stream
+ pStream = FileStream_OpenFile(szMpqName, (dwFlags & STREAM_OPTIONS_MASK));
+ if(pStream == NULL)
+ nError = GetLastError();
+ }
+
+ // Allocate the MPQhandle
+ if(nError == ERROR_SUCCESS)
+ {
+ FileStream_GetSize(pStream, FileSize);
+ if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Initialize handle structure and allocate structure for MPQ header
+ if(nError == ERROR_SUCCESS)
+ {
+ memset(ha, 0, sizeof(TMPQArchive));
+ ha->pStream = pStream;
+ pStream = NULL;
+
+ // Remember if the archive is open for write
+ if(FileStream_IsReadOnly(ha->pStream))
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+
+ // Also remember if we shall check sector CRCs when reading file
+ if(dwFlags & MPQ_OPEN_CHECK_SECTOR_CRC)
+ ha->dwFlags |= MPQ_FLAG_CHECK_SECTOR_CRC;
+ }
+
+ // Find the offset of MPQ header within the file
+ if(nError == ERROR_SUCCESS)
+ {
+ ULONGLONG SearchPos = 0;
+ DWORD dwHeaderID;
+
+ while(SearchPos < FileSize)
+ {
+ DWORD dwBytesAvailable = MPQ_HEADER_SIZE_V4;
+
+ // Cut the bytes available, if needed
+ if((FileSize - SearchPos) < MPQ_HEADER_SIZE_V4)
+ dwBytesAvailable = (DWORD)(FileSize - SearchPos);
+
+ // Read the eventual MPQ header
+ if(!FileStream_Read(ha->pStream, &SearchPos, ha->HeaderData, dwBytesAvailable))
+ {
+ nError = GetLastError();
+ break;
+ }
+
+ // There are AVI files from Warcraft III with 'MPQ' extension.
+ if(SearchPos == 0 && IsAviFile(ha->HeaderData))
+ {
+ nError = ERROR_AVI_FILE;
+ break;
+ }
+
+ // If there is the MPQ user data signature, process it
+ dwHeaderID = BSWAP_INT32_UNSIGNED(*(LPDWORD)ha->HeaderData);
+ if(dwHeaderID == ID_MPQ_USERDATA && ha->pUserData == NULL)
+ {
+ // Ignore the MPQ user data completely if the caller wants to open the MPQ as V1.0
+ if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
+ {
+ // Fill the user data header
+ ha->pUserData = &ha->UserData;
+ memcpy(ha->pUserData, ha->HeaderData, sizeof(TMPQUserData));
+ BSWAP_TMPQUSERDATA(ha->pUserData);
+
+ // Remember the position of the user data and continue search
+ ha->UserDataPos = SearchPos;
+ SearchPos += ha->pUserData->dwHeaderOffs;
+ continue;
+ }
+ }
+
+ // There must be MPQ header signature
+ if(dwHeaderID == ID_MPQ)
+ {
+ // Save the position where the MPQ header has been found
+ if(ha->pUserData == NULL)
+ ha->UserDataPos = SearchPos;
+ ha->pHeader = (TMPQHeader *)ha->HeaderData;
+ ha->MpqPos = SearchPos;
+
+ // Now convert the header to version 4
+ BSWAP_TMPQHEADER(ha->pHeader);
+ nError = ConvertMpqHeaderToFormat4(ha, FileSize, dwFlags);
+ break;
+ }
+
+ // Move to the next possible offset
+ SearchPos += 0x200;
+ }
+
+ // If we haven't found MPQ header in the file, it's an error
+ if(ha->pHeader == NULL)
+ nError = ERROR_BAD_FORMAT;
+ }
+
+ // Fix table positions according to format
+ if(nError == ERROR_SUCCESS)
+ {
+ // Dump the header
+// DumpMpqHeader(ha->pHeader);
+
+ // W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data,
+ // and probably ignores the MPQ format version as well. The trick is to
+ // fake MPQ format 2, with an improper hi-word position of hash table and block table
+ // We can overcome such protectors by forcing opening the archive as MPQ v 1.0
+ if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
+ {
+ ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
+ ha->pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+ ha->pUserData = NULL;
+ }
+
+ // Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
+ if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+
+ // Set the size of file sector
+ ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);
+
+ // Verify if any of the tables doesn't start beyond the end of the file
+ nError = VerifyMpqTablePositions(ha, FileSize);
+ }
+
+ // Check if the MPQ has data bitmap. If yes, we can verify if the MPQ is complete
+ if(nError == ERROR_SUCCESS && ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4)
+ {
+ TFileBitmap * pBitmap;
+ bool bFileIsComplete = true;
+
+ LoadMpqDataBitmap(ha, FileSize, &bFileIsComplete);
+ if(ha->pBitmap != NULL && bFileIsComplete == false)
+ {
+ // Convert the MPQ bitmap to the file bitmap
+ pBitmap = CreateFileBitmap(ha, ha->pBitmap, bFileIsComplete);
+
+ // Set the data bitmap into the file stream for additional checks
+ FileStream_SetBitmap(ha->pStream, pBitmap);
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
+ }
+ }
+
+ // Read the hash table. Ignore the result, as hash table is no longer required
+ // Read HET table. Ignore the result, as HET table is no longer required
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = LoadAnyHashTable(ha);
+ }
+
+ // Now, build the file table. It will be built by combining
+ // the block table, BET table, hi-block table, (attributes) and (listfile).
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = BuildFileTable(ha, FileSize);
+ }
+
+ // Verify the file table, if no kind of protection was detected
+ if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
+ {
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
+ TFileEntry * pFileEntry = ha->pFileTable;
+// ULONGLONG ArchiveSize = 0;
+ ULONGLONG RawFilePos;
+
+ // Parse all file entries
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // If that file entry is valid, check the file position
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
+ {
+ // Get the 64-bit file position,
+ // relative to the begin of the file
+ RawFilePos = ha->MpqPos + pFileEntry->ByteOffset;
+
+ // Begin of the file must be within range
+ if(RawFilePos > FileSize)
+ {
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+
+ // End of the file must be within range
+ RawFilePos += pFileEntry->dwCmpSize;
+ if(RawFilePos > FileSize)
+ {
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+
+ // Also, we remember end of the file
+// if(RawFilePos > ArchiveSize)
+// ArchiveSize = RawFilePos;
+ }
+ }
+ }
+
+ // Load the internal listfile and include it to the file table
+ if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
+ {
+ // Ignore result of the operation. (listfile) is optional.
+ SFileAddListFile((HANDLE)ha, NULL);
+ }
+
+ // Load the "(attributes)" file and merge it to the file table
+ if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0)
+ {
+ // Ignore result of the operation. (attributes) is optional.
+ SAttrLoadAttributes(ha);
+ }
+
+ // Cleanup and exit
+ if(nError != ERROR_SUCCESS)
+ {
+ FileStream_Close(pStream);
+ FreeMPQArchive(ha);
+ SetLastError(nError);
+ ha = NULL;
+ }
+
+ *phMpq = ha;
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// SFileGetArchiveBitmap
+
+bool WINAPI SFileGetArchiveBitmap(HANDLE hMpq, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ return FileStream_GetBitmap(ha->pStream, pBitmap, Length, LengthNeeded);
+}
+
+//-----------------------------------------------------------------------------
+// bool SFileFlushArchive(HANDLE hMpq)
+//
+// Saves all dirty data into MPQ archive.
+// Has similar effect like SFileCloseArchive, but the archive is not closed.
+// Use on clients who keep MPQ archive open even for write operations,
+// and terminating without calling SFileCloseArchive might corrupt the archive.
+//
+
+bool WINAPI SFileFlushArchive(HANDLE hMpq)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ int nResultError = ERROR_SUCCESS;
+ int nError;
+
+ // Do nothing if 'hMpq' is bad parameter
+ if(!IsValidMpqHandle(ha))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // If the (listfile) has been invalidated, save it
+ if(ha->dwFlags & MPQ_FLAG_INV_LISTFILE)
+ {
+ nError = SListFileSaveToMpq(ha);
+ if(nError != ERROR_SUCCESS)
+ nResultError = nError;
+ }
+
+ // If the (attributes) has been invalidated, save it
+ if(ha->dwFlags & MPQ_FLAG_INV_ATTRIBUTES)
+ {
+ nError = SAttrFileSaveToMpq(ha);
+ if(nError != ERROR_SUCCESS)
+ nResultError = nError;
+ }
+
+ // Save HET table, BET table, hash table, block table, hi-block table
+ if(ha->dwFlags & MPQ_FLAG_CHANGED)
+ {
+ nError = SaveMPQTables(ha);
+ if(nError != ERROR_SUCCESS)
+ nResultError = nError;
+ }
+
+ // Return the error
+ if(nResultError != ERROR_SUCCESS)
+ SetLastError(nResultError);
+ return (nResultError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// bool SFileCloseArchive(HANDLE hMpq);
+//
+
+bool WINAPI SFileCloseArchive(HANDLE hMpq)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ bool bResult;
+
+ // Flush all unsaved data to the storage
+ bResult = SFileFlushArchive(hMpq);
+
+ // Free all memory used by MPQ archive
+ FreeMPQArchive(ha);
+ return bResult;
+}
+
diff --git a/dep/StormLib/src/SFileOpenFileEx.cpp b/dep/StormLib/src/SFileOpenFileEx.cpp
new file mode 100644
index 00000000000..e03a8b17998
--- /dev/null
+++ b/dep/StormLib/src/SFileOpenFileEx.cpp
@@ -0,0 +1,469 @@
+/*****************************************************************************/
+/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+/*****************************************************************************/
+/* Local functions */
+/*****************************************************************************/
+
+static bool OpenLocalFile(const char * szFileName, HANDLE * phFile)
+{
+ TFileStream * pStream;
+ TMPQFile * hf = NULL;
+
+ // We have to convert the local file name to UNICODE, if needed
+#ifdef _UNICODE
+ TCHAR szFileNameT[MAX_PATH];
+ int i;
+
+ for(i = 0; szFileName[i] != 0; i++)
+ szFileNameT[i] = szFileName[i];
+ szFileNameT[i] = 0;
+ pStream = FileStream_OpenFile(szFileNameT, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+
+#else
+ pStream = FileStream_OpenFile(szFileName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+#endif
+
+ if(pStream != NULL)
+ {
+ // Allocate and initialize file handle
+ hf = CreateMpqFile(NULL);
+ if(hf != NULL)
+ {
+ hf->pStream = pStream;
+ *phFile = hf;
+ return true;
+ }
+ else
+ {
+ FileStream_Close(pStream);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ }
+ *phFile = NULL;
+ return false;
+}
+
+bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HANDLE * phFile)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TMPQFile * hfPatch; // Pointer to patch file
+ TMPQFile * hfBase = NULL; // Pointer to base open file
+ TMPQFile * hfLast = NULL; // The highest file in the chain that is not patch file
+ TMPQFile * hf = NULL;
+ HANDLE hPatchFile;
+ char szPatchFileName[MAX_PATH];
+
+ // Keep this flag here for future updates
+ dwReserved = dwReserved;
+
+ // First of all, try to open the original version of the file in any of the patch chain
+ while(ha != NULL)
+ {
+ // Construct the name of the patch file
+ strcpy(szPatchFileName, ha->szPatchPrefix);
+ strcpy(&szPatchFileName[ha->cchPatchPrefix], szFileName);
+ if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, (HANDLE *)&hfBase))
+ {
+ // The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
+ if((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ {
+ hf = hfLast = hfBase;
+ break;
+ }
+
+ SFileCloseFile((HANDLE)hfBase);
+ }
+
+ // Move to the next file in the patch chain
+ ha = ha->haPatch;
+ }
+
+ // If we couldn't find the file in any of the patches, it doesn't exist
+ if(hf == NULL)
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return false;
+ }
+
+ // Now keep going in the patch chain and open every patch file that is there
+ for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
+ {
+ // Construct patch file name
+ strcpy(szPatchFileName, ha->szPatchPrefix);
+ strcpy(&szPatchFileName[ha->cchPatchPrefix], szFileName);
+ if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, &hPatchFile))
+ {
+ // Remember the new version
+ hfPatch = (TMPQFile *)hPatchFile;
+
+ // If we encountered a full replacement of the file,
+ // we have to remember the highest full file
+ if((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ hfLast = hfPatch;
+
+ // Set current patch to base file and move on
+ hf->hfPatchFile = hfPatch;
+ hf = hfPatch;
+ }
+ }
+
+ // Now we need to free all files that are below the highest unpatched version
+ while(hfBase != hfLast)
+ {
+ TMPQFile * hfNext = hfBase->hfPatchFile;
+
+ // Free the file below
+ hfBase->hfPatchFile = NULL;
+ FreeMPQFile(hfBase);
+
+ // Move the base to the next file
+ hfBase = hfNext;
+ }
+
+ // Give the updated base MPQ
+ if(phFile != NULL)
+ *phFile = (HANDLE)hfBase;
+ return true;
+}
+
+/*****************************************************************************/
+/* Public functions */
+/*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+// SFileEnumLocales enums all locale versions within MPQ.
+// Functions fills all available language identifiers on a file into the buffer
+// pointed by plcLocales. There must be enough entries to copy the localed,
+// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
+
+int WINAPI SFileEnumLocales(
+ HANDLE hMpq,
+ const char * szFileName,
+ LCID * plcLocales,
+ LPDWORD pdwMaxLocales,
+ DWORD dwSearchScope)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry;
+ TMPQHash * pFirstHash;
+ TMPQHash * pHash;
+ DWORD dwFileIndex = 0;
+ DWORD dwLocales = 0;
+
+ // Test the parameters
+ if(!IsValidMpqHandle(ha))
+ return ERROR_INVALID_HANDLE;
+ if(szFileName == NULL || *szFileName == 0)
+ return ERROR_INVALID_PARAMETER;
+ if(pdwMaxLocales == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ // Keep compiler happy
+ dwSearchScope = dwSearchScope;
+
+ // Parse hash table entries for all locales
+ if(!IsPseudoFileName(szFileName, &dwFileIndex))
+ {
+ // Calculate the number of locales
+ pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
+ while(pHash != NULL)
+ {
+ dwLocales++;
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+
+ // Test if there is enough space to copy the locales
+ if(*pdwMaxLocales < dwLocales)
+ {
+ *pdwMaxLocales = dwLocales;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Enum the locales
+ pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
+ while(pHash != NULL)
+ {
+ *plcLocales++ = pHash->lcLocale;
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
+ }
+ }
+ else
+ {
+ // There must be space for 1 locale
+ if(*pdwMaxLocales < 1)
+ {
+ *pdwMaxLocales = 1;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // For nameless access, always return 1 locale
+ pFileEntry = GetFileEntryByIndex(ha, dwFileIndex);
+ pHash = ha->pHashTable + pFileEntry->dwHashIndex;
+ *plcLocales = pHash->lcLocale;
+ dwLocales = 1;
+ }
+
+ // Give the caller the total number of found locales
+ *pdwMaxLocales = dwLocales;
+ return ERROR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// SFileHasFile
+//
+// hMpq - Handle of opened MPQ archive
+// szFileName - Name of file to look for
+
+bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry;
+ DWORD dwFlagsToCheck = MPQ_FILE_EXISTS;
+ DWORD dwFileIndex = 0;
+ char szPatchFileName[MAX_PATH];
+ bool bIsPseudoName;
+ int nError = ERROR_SUCCESS;
+
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szFileName == NULL || *szFileName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Prepare the file opening
+ if(nError == ERROR_SUCCESS)
+ {
+ // Different processing for pseudo-names
+ bIsPseudoName = IsPseudoFileName(szFileName, &dwFileIndex);
+
+ // Walk through the MPQ and all patches
+ while(ha != NULL)
+ {
+ // Verify presence of the file
+ pFileEntry = (bIsPseudoName == false) ? GetFileEntryLocale(ha, szFileName, lcFileLocale)
+ : GetFileEntryByIndex(ha, dwFileIndex);
+ // Verify the file flags
+ if(pFileEntry != NULL && (pFileEntry->dwFlags & dwFlagsToCheck) == MPQ_FILE_EXISTS)
+ return true;
+
+ // If this is patched archive, go to the patch
+ dwFlagsToCheck = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE;
+ ha = ha->haPatch;
+
+ // Prepare the patched file name
+ if(ha != NULL)
+ {
+ strcpy(szPatchFileName, ha->szPatchPrefix);
+ strcat(szPatchFileName, szFileName);
+ szFileName = szPatchFileName;
+ }
+ }
+
+ // Not found, sorry
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+
+ // Cleanup
+ SetLastError(nError);
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// SFileOpenFileEx
+//
+// hMpq - Handle of opened MPQ archive
+// szFileName - Name of file to open
+// dwSearchScope - Where to search
+// phFile - Pointer to store opened file handle
+
+bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry = NULL;
+ TMPQFile * hf = NULL;
+ DWORD dwFileIndex = 0;
+ bool bOpenByIndex = false;
+ int nError = ERROR_SUCCESS;
+
+ // Don't accept NULL pointer to file handle
+ if(phFile == NULL)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // Prepare the file opening
+ if(nError == ERROR_SUCCESS)
+ {
+ switch(dwSearchScope)
+ {
+ case SFILE_OPEN_PATCHED_FILE:
+
+ // We want to open the updated version of the file
+ return OpenPatchedFile(hMpq, szFileName, 0, phFile);
+
+ case SFILE_OPEN_FROM_MPQ:
+
+ if(!IsValidMpqHandle(ha))
+ {
+ nError = ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ if(szFileName == NULL || *szFileName == 0)
+ {
+ nError = ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ // First of all, check the name as-is
+ if(!IsPseudoFileName(szFileName, &dwFileIndex))
+ {
+ pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
+ if(pFileEntry == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+ else
+ {
+ bOpenByIndex = true;
+ pFileEntry = GetFileEntryByIndex(ha, dwFileIndex);
+ if(pFileEntry == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ }
+ break;
+
+ case SFILE_OPEN_ANY_LOCALE:
+
+ // This open option is reserved for opening MPQ internal listfile.
+ // No argument validation. Tries to open file with neutral locale first,
+ // then any other available.
+ dwSearchScope = SFILE_OPEN_FROM_MPQ;
+ pFileEntry = GetFileEntryAny(ha, szFileName);
+ if(pFileEntry == NULL)
+ nError = ERROR_FILE_NOT_FOUND;
+ break;
+
+ case SFILE_OPEN_LOCAL_FILE:
+
+ if(szFileName == NULL || *szFileName == 0)
+ {
+ nError = ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ return OpenLocalFile(szFileName, phFile);
+
+ default:
+
+ // Don't accept any other value
+ nError = ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ // Quick return if something failed
+ if(nError != ERROR_SUCCESS)
+ {
+ SetLastError(nError);
+ return false;
+ }
+ }
+
+ // Test if the file was not already deleted.
+ if(nError == ERROR_SUCCESS)
+ {
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
+ nError = ERROR_FILE_NOT_FOUND;
+ if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
+ nError = ERROR_NOT_SUPPORTED;
+ }
+
+ // Allocate file handle
+ if(nError == ERROR_SUCCESS)
+ {
+ if((hf = STORM_ALLOC(TMPQFile, 1)) == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Initialize file handle
+ if(nError == ERROR_SUCCESS)
+ {
+ memset(hf, 0, sizeof(TMPQFile));
+ hf->pFileEntry = pFileEntry;
+ hf->dwMagic = ID_MPQ_FILE;
+ hf->ha = ha;
+
+ hf->MpqFilePos = pFileEntry->ByteOffset;
+ hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
+ hf->dwDataSize = pFileEntry->dwFileSize;
+
+ // If the MPQ has sector CRC enabled, enable if for the file
+ if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
+ hf->bCheckSectorCRCs = true;
+
+ // If we know the real file name, copy it to the file entry
+ if(bOpenByIndex == false)
+ {
+ // If there is no file name yet, allocate it
+ AllocateFileName(pFileEntry, szFileName);
+
+ // If the file is encrypted, we should detect the file key
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ hf->dwFileKey = DecryptFileKey(szFileName,
+ pFileEntry->ByteOffset,
+ pFileEntry->dwFileSize,
+ pFileEntry->dwFlags);
+ }
+ }
+ else
+ {
+ // Try to auto-detect the file name
+ if(!SFileGetFileName(hf, NULL))
+ nError = GetLastError();
+ }
+ }
+
+ // If the file is actually a patch file, we have to load the patch file header
+ if(nError == ERROR_SUCCESS && pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
+ {
+ assert(hf->pPatchInfo == NULL);
+ nError = AllocatePatchInfo(hf, true);
+ }
+
+ // Cleanup
+ if(nError != ERROR_SUCCESS)
+ {
+ SetLastError(nError);
+ FreeMPQFile(hf);
+ }
+
+ *phFile = hf;
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// bool WINAPI SFileCloseFile(HANDLE hFile);
+
+bool WINAPI SFileCloseFile(HANDLE hFile)
+{
+ TMPQFile * hf = (TMPQFile *)hFile;
+
+ if(!IsValidFileHandle(hf))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // Free the structure
+ FreeMPQFile(hf);
+ return true;
+}
diff --git a/dep/StormLib/src/SFilePatchArchives.cpp b/dep/StormLib/src/SFilePatchArchives.cpp
new file mode 100644
index 00000000000..24ae2c52c37
--- /dev/null
+++ b/dep/StormLib/src/SFilePatchArchives.cpp
@@ -0,0 +1,587 @@
+/*****************************************************************************/
+/* SFilePatchArchives.cpp Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* Description: */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 18.08.10 1.00 Lad The first version of SFilePatchArchives.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+typedef struct _BLIZZARD_BSDIFF40_FILE
+{
+ ULONGLONG Signature;
+ ULONGLONG CtrlBlockSize;
+ ULONGLONG DataBlockSize;
+ ULONGLONG NewFileSize;
+} BLIZZARD_BSDIFF40_FILE, *PBLIZZARD_BSDIFF40_FILE;
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static bool GetDefaultPatchPrefix(
+ const TCHAR * szBaseMpqName,
+ char * szBuffer)
+{
+ const TCHAR * szExtension;
+ const TCHAR * szDash;
+
+ // Ensure that both names are plain names
+ szBaseMpqName = GetPlainFileNameT(szBaseMpqName);
+
+ // Patch prefix is for the Cataclysm MPQs, whose names
+ // are like "locale-enGB.MPQ" or "speech-enGB.MPQ"
+ szExtension = _tcsrchr(szBaseMpqName, _T('.'));
+ szDash = _tcsrchr(szBaseMpqName, _T('-'));
+ strcpy(szBuffer, "Base");
+
+ // If the length of the prefix doesn't match, use default one
+ if(szExtension != NULL && szDash != NULL && (szExtension - szDash) == 5)
+ {
+ // Copy the prefix
+ szBuffer[0] = (char)szDash[1];
+ szBuffer[1] = (char)szDash[2];
+ szBuffer[2] = (char)szDash[3];
+ szBuffer[3] = (char)szDash[4];
+ szBuffer[4] = 0;
+ }
+
+ return true;
+}
+
+static void Decompress_RLE(LPBYTE pbDecompressed, DWORD cbDecompressed, LPBYTE pbCompressed, DWORD cbCompressed)
+{
+ LPBYTE pbDecompressedEnd = pbDecompressed + cbDecompressed;
+ LPBYTE pbCompressedEnd = pbCompressed + cbCompressed;
+ BYTE RepeatCount;
+ BYTE OneByte;
+
+ // Cut the initial DWORD from the compressed chunk
+ pbCompressed += sizeof(DWORD);
+ cbCompressed -= sizeof(DWORD);
+
+ // Pre-fill decompressed buffer with zeros
+ memset(pbDecompressed, 0, cbDecompressed);
+
+ // Unpack
+ while(pbCompressed < pbCompressedEnd && pbDecompressed < pbDecompressedEnd)
+ {
+ OneByte = *pbCompressed++;
+
+ // Is it a repetition byte ?
+ if(OneByte & 0x80)
+ {
+ RepeatCount = (OneByte & 0x7F) + 1;
+ for(BYTE i = 0; i < RepeatCount; i++)
+ {
+ if(pbDecompressed == pbDecompressedEnd || pbCompressed == pbCompressedEnd)
+ break;
+
+ *pbDecompressed++ = *pbCompressed++;
+ }
+ }
+ else
+ {
+ pbDecompressed += (OneByte + 1);
+ }
+ }
+}
+
+static int LoadMpqPatch_COPY(TMPQFile * hf, TPatchHeader * pPatchHeader)
+{
+ int nError = ERROR_SUCCESS;
+
+ // Allocate space for patch header and compressed data
+ hf->pPatchHeader = (TPatchHeader *)STORM_ALLOC(BYTE, pPatchHeader->dwSizeOfPatchData);
+ if(hf->pPatchHeader == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ // Load the patch data and decide if they are compressed or not
+ if(nError == ERROR_SUCCESS)
+ {
+ LPBYTE pbPatchFile = (LPBYTE)hf->pPatchHeader;
+
+ // Copy the patch header itself
+ memcpy(pbPatchFile, pPatchHeader, sizeof(TPatchHeader));
+ pbPatchFile += sizeof(TPatchHeader);
+
+ // Load the rest of the patch
+ if(!SFileReadFile((HANDLE)hf, pbPatchFile, pPatchHeader->dwSizeOfPatchData - sizeof(TPatchHeader)))
+ nError = GetLastError();
+ }
+
+ return nError;
+}
+
+static int LoadMpqPatch_BSD0(TMPQFile * hf, TPatchHeader * pPatchHeader)
+{
+ LPBYTE pbDecompressed = NULL;
+ LPBYTE pbCompressed = NULL;
+ DWORD cbDecompressed = 0;
+ DWORD cbCompressed = 0;
+ DWORD dwBytesRead = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate space for compressed data
+ cbCompressed = pPatchHeader->dwXfrmBlockSize - SIZE_OF_XFRM_HEADER;
+ pbCompressed = STORM_ALLOC(BYTE, cbCompressed);
+ if(pbCompressed == NULL)
+ nError = ERROR_SUCCESS;
+
+ // Read the compressed patch data
+ if(nError == ERROR_SUCCESS)
+ {
+ // Load the rest of the header
+ SFileReadFile((HANDLE)hf, pbCompressed, cbCompressed, &dwBytesRead);
+ if(dwBytesRead != cbCompressed)
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Get the uncompressed size of the patch
+ if(nError == ERROR_SUCCESS)
+ {
+ cbDecompressed = pPatchHeader->dwSizeOfPatchData - sizeof(TPatchHeader);
+ hf->pPatchHeader = (TPatchHeader *)STORM_ALLOC(BYTE, pPatchHeader->dwSizeOfPatchData);
+ if(hf->pPatchHeader == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Now decompress the patch data
+ if(nError == ERROR_SUCCESS)
+ {
+ // Copy the patch header
+ memcpy(hf->pPatchHeader, pPatchHeader, sizeof(TPatchHeader));
+ pbDecompressed = (LPBYTE)hf->pPatchHeader + sizeof(TPatchHeader);
+
+ // Uncompress or copy the patch data
+ if(cbCompressed < cbDecompressed)
+ {
+ Decompress_RLE(pbDecompressed, cbDecompressed, pbCompressed, cbCompressed);
+ }
+ else
+ {
+ assert(cbCompressed == cbDecompressed);
+ memcpy(pbDecompressed, pbCompressed, cbCompressed);
+ }
+ }
+
+ // Free buffers and exit
+ if(pbCompressed != NULL)
+ STORM_FREE(pbCompressed);
+ return nError;
+}
+
+static int ApplyMpqPatch_COPY(
+ TMPQFile * hf,
+ TPatchHeader * pPatchHeader)
+{
+ LPBYTE pbNewFileData;
+ DWORD cbNewFileData;
+
+ // Allocate space for new file data
+ cbNewFileData = pPatchHeader->dwXfrmBlockSize - SIZE_OF_XFRM_HEADER;
+ pbNewFileData = STORM_ALLOC(BYTE, cbNewFileData);
+ if(pbNewFileData == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Copy the patch data as-is
+ memcpy(pbNewFileData, (LPBYTE)pPatchHeader + sizeof(TPatchHeader), cbNewFileData);
+
+ // Free the old file data
+ STORM_FREE(hf->pbFileData);
+
+ // Put the new file data there
+ hf->pbFileData = pbNewFileData;
+ hf->cbFileData = cbNewFileData;
+ return ERROR_SUCCESS;
+}
+
+static int ApplyMpqPatch_BSD0(
+ TMPQFile * hf,
+ TPatchHeader * pPatchHeader)
+{
+ PBLIZZARD_BSDIFF40_FILE pBsdiff;
+ LPDWORD pCtrlBlock;
+ LPBYTE pbPatchData = (LPBYTE)pPatchHeader + sizeof(TPatchHeader);
+ LPBYTE pDataBlock;
+ LPBYTE pExtraBlock;
+ LPBYTE pbNewData = NULL;
+ LPBYTE pbOldData = (LPBYTE)hf->pbFileData;
+ DWORD dwNewOffset = 0; // Current position to patch
+ DWORD dwOldOffset = 0; // Current source position
+ DWORD dwNewSize; // Patched file size
+ DWORD dwOldSize = hf->cbFileData; // File size before patch
+
+ // Get pointer to the patch header
+ // Format of BSDIFF header corresponds to original BSDIFF, which is:
+ // 0000 8 bytes signature "BSDIFF40"
+ // 0008 8 bytes size of the control block
+ // 0010 8 bytes size of the data block
+ // 0018 8 bytes new size of the patched file
+ pBsdiff = (PBLIZZARD_BSDIFF40_FILE)pbPatchData;
+ pbPatchData += sizeof(BLIZZARD_BSDIFF40_FILE);
+
+ // Get pointer to the 32-bit BSDIFF control block
+ // The control block follows immediately after the BSDIFF header
+ // and consists of three 32-bit integers
+ // 0000 4 bytes Length to copy from the BSDIFF data block the new file
+ // 0004 4 bytes Length to copy from the BSDIFF extra block
+ // 0008 4 bytes Size to increment source file offset
+ pCtrlBlock = (LPDWORD)pbPatchData;
+ pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->CtrlBlockSize);
+
+ // Get the pointer to the data block
+ pDataBlock = (LPBYTE)pbPatchData;
+ pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->DataBlockSize);
+
+ // Get the pointer to the extra block
+ pExtraBlock = (LPBYTE)pbPatchData;
+ dwNewSize = (DWORD)BSWAP_INT64_UNSIGNED(pBsdiff->NewFileSize);
+
+ // Allocate new buffer
+ pbNewData = STORM_ALLOC(BYTE, dwNewSize);
+ if(pbNewData == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Now patch the file
+ while(dwNewOffset < dwNewSize)
+ {
+ DWORD dwAddDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[0]);
+ DWORD dwMovDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[1]);
+ DWORD dwOldMoveLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[2]);
+ DWORD i;
+
+ // Sanity check
+ if((dwNewOffset + dwAddDataLength) > dwNewSize)
+ {
+ STORM_FREE(pbNewData);
+ return ERROR_FILE_CORRUPT;
+ }
+
+ // Read the diff string to the target buffer
+ memcpy(pbNewData + dwNewOffset, pDataBlock, dwAddDataLength);
+ pDataBlock += dwAddDataLength;
+
+ // Now combine the patch data with the original file
+ for(i = 0; i < dwAddDataLength; i++)
+ {
+ if(dwOldOffset < dwOldSize)
+ pbNewData[dwNewOffset] = pbNewData[dwNewOffset] + pbOldData[dwOldOffset];
+
+ dwNewOffset++;
+ dwOldOffset++;
+ }
+
+ // Sanity check
+ if((dwNewOffset + dwMovDataLength) > dwNewSize)
+ {
+ STORM_FREE(pbNewData);
+ return ERROR_FILE_CORRUPT;
+ }
+
+ // Copy the data from the extra block in BSDIFF patch
+ memcpy(pbNewData + dwNewOffset, pExtraBlock, dwMovDataLength);
+ pExtraBlock += dwMovDataLength;
+ dwNewOffset += dwMovDataLength;
+
+ // Move the old offset
+ if(dwOldMoveLength & 0x80000000)
+ dwOldMoveLength = 0x80000000 - dwOldMoveLength;
+ dwOldOffset += dwOldMoveLength;
+ pCtrlBlock += 3;
+ }
+
+ // Free the old file data
+ STORM_FREE(hf->pbFileData);
+
+ // Put the new data to the fil structure
+ hf->pbFileData = pbNewData;
+ hf->cbFileData = dwNewSize;
+ return ERROR_SUCCESS;
+}
+
+
+static int LoadMpqPatch(TMPQFile * hf)
+{
+ TPatchHeader PatchHeader;
+ DWORD dwBytesRead;
+ int nError = ERROR_SUCCESS;
+
+ // Read the patch header
+ SFileReadFile((HANDLE)hf, &PatchHeader, sizeof(TPatchHeader), &dwBytesRead);
+ if(dwBytesRead != sizeof(TPatchHeader))
+ nError = ERROR_FILE_CORRUPT;
+
+ // Verify the signatures in the patch header
+ if(nError == ERROR_SUCCESS)
+ {
+ // BSWAP the entire header, if needed
+ BSWAP_ARRAY32_UNSIGNED(&PatchHeader, sizeof(DWORD) * 6);
+ PatchHeader.dwXFRM = BSWAP_INT32_UNSIGNED(PatchHeader.dwXFRM);
+ PatchHeader.dwXfrmBlockSize = BSWAP_INT32_UNSIGNED(PatchHeader.dwXfrmBlockSize);
+ PatchHeader.dwPatchType = BSWAP_INT32_UNSIGNED(PatchHeader.dwPatchType);
+
+ if(PatchHeader.dwSignature != 0x48435450 || PatchHeader.dwMD5 != 0x5f35444d || PatchHeader.dwXFRM != 0x4d524658)
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Read the patch, depending on patch type
+ if(nError == ERROR_SUCCESS)
+ {
+ switch(PatchHeader.dwPatchType)
+ {
+ case 0x59504f43: // 'COPY'
+ nError = LoadMpqPatch_COPY(hf, &PatchHeader);
+ break;
+
+ case 0x30445342: // 'BSD0'
+ nError = LoadMpqPatch_BSD0(hf, &PatchHeader);
+ break;
+
+ default:
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+ }
+
+ return nError;
+}
+
+static int ApplyMpqPatch(
+ TMPQFile * hf,
+ TPatchHeader * pPatchHeader)
+{
+ int nError = ERROR_SUCCESS;
+
+ // Verify the original file before patching
+ if(pPatchHeader->dwSizeBeforePatch != 0)
+ {
+ if(!VerifyDataBlockHash(hf->pbFileData, hf->cbFileData, pPatchHeader->md5_before_patch))
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Apply the patch
+ if(nError == ERROR_SUCCESS)
+ {
+ switch(pPatchHeader->dwPatchType)
+ {
+ case 0x59504f43: // 'COPY'
+ nError = ApplyMpqPatch_COPY(hf, pPatchHeader);
+ break;
+
+ case 0x30445342: // 'BSD0'
+ nError = ApplyMpqPatch_BSD0(hf, pPatchHeader);
+ break;
+
+ default:
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+ }
+
+ // Verify MD5 after patch
+ if(nError == ERROR_SUCCESS && pPatchHeader->dwSizeAfterPatch != 0)
+ {
+ // Verify the patched file
+ if(!VerifyDataBlockHash(hf->pbFileData, hf->cbFileData, pPatchHeader->md5_after_patch))
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Public functions (StormLib internals)
+
+bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize)
+{
+ TPatchHeader * pPatchHeader = (TPatchHeader *)pvData;
+ BLIZZARD_BSDIFF40_FILE DiffFile;
+ DWORD dwPatchType;
+
+ if(cbData >= sizeof(TPatchHeader) + sizeof(BLIZZARD_BSDIFF40_FILE))
+ {
+ dwPatchType = BSWAP_INT32_UNSIGNED(pPatchHeader->dwPatchType);
+ if(dwPatchType == 0x30445342)
+ {
+ // Give the caller the patch file size
+ if(pdwPatchedFileSize != NULL)
+ {
+ Decompress_RLE((LPBYTE)&DiffFile, sizeof(BLIZZARD_BSDIFF40_FILE), (LPBYTE)(pPatchHeader + 1), sizeof(BLIZZARD_BSDIFF40_FILE));
+ DiffFile.NewFileSize = BSWAP_INT64_UNSIGNED(DiffFile.NewFileSize);
+ *pdwPatchedFileSize = (DWORD)DiffFile.NewFileSize;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+int PatchFileData(TMPQFile * hf)
+{
+ TMPQFile * hfBase = hf;
+ int nError = ERROR_SUCCESS;
+
+ // Move to the first patch
+ hf = hf->hfPatchFile;
+
+ // Now go through all patches and patch the original data
+ while(hf != NULL)
+ {
+ // This must be true
+ assert(hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE);
+
+ // Make sure that the patch data is loaded
+ nError = LoadMpqPatch(hf);
+ if(nError != ERROR_SUCCESS)
+ break;
+
+ // Apply the patch
+ nError = ApplyMpqPatch(hfBase, hf->pPatchHeader);
+ if(nError != ERROR_SUCCESS)
+ break;
+
+ // Move to the next patch
+ hf = hf->hfPatchFile;
+ }
+
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+//
+// Patch prefix is the path subdirectory where the patched files are within MPQ.
+//
+// Example 1:
+// Main MPQ: locale-enGB.MPQ
+// Patch MPQ: wow-update-12694.MPQ
+// File in main MPQ: DBFilesClient\Achievement.dbc
+// File in patch MPQ: enGB\DBFilesClient\Achievement.dbc
+// Path prefix: enGB
+//
+// Example 2:
+// Main MPQ: expansion1.MPQ
+// Patch MPQ: wow-update-12694.MPQ
+// File in main MPQ: DBFilesClient\Achievement.dbc
+// File in patch MPQ: Base\DBFilesClient\Achievement.dbc
+// Path prefix: Base
+//
+
+bool WINAPI SFileOpenPatchArchive(
+ HANDLE hMpq,
+ const TCHAR * szPatchMpqName,
+ const char * szPatchPathPrefix,
+ DWORD dwFlags)
+{
+ TMPQArchive * haPatch;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ HANDLE hPatchMpq = NULL;
+ char szPatchPrefixBuff[MPQ_PATCH_PREFIX_LEN];
+ int nError = ERROR_SUCCESS;
+
+ // Keep compiler happy
+ dwFlags = dwFlags;
+
+ // Verify input parameters
+ if(!IsValidMpqHandle(ha))
+ nError = ERROR_INVALID_HANDLE;
+ if(szPatchMpqName == NULL || *szPatchMpqName == 0)
+ nError = ERROR_INVALID_PARAMETER;
+
+ // If the user didn't give the patch prefix, get default one
+ if(szPatchPathPrefix != NULL)
+ {
+ // Save length of the patch prefix
+ if(strlen(szPatchPathPrefix) > MPQ_PATCH_PREFIX_LEN - 2)
+ nError = ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // We don't allow adding patches to archives that have been open for write
+ //
+ // Error scenario:
+ //
+ // 1) Open archive for writing
+ // 2) Modify or replace a file
+ // 3) Add patch archive to the opened MPQ
+ // 4) Read patched file
+ // 5) Now what ?
+ //
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!FileStream_IsReadOnly(ha->pStream))
+ nError = ERROR_ACCESS_DENIED;
+ }
+
+ // Open the archive like it is normal archive
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileOpenArchive(szPatchMpqName, 0, MPQ_OPEN_READ_ONLY, &hPatchMpq))
+ return false;
+ haPatch = (TMPQArchive *)hPatchMpq;
+
+ // Older WoW patches (build 13914) used to have
+ // several language versions in one patch file
+ // Those patches needed to have a path prefix
+ // We can distinguish such patches by not having the (patch_metadata) file
+ if(szPatchPathPrefix == NULL)
+ {
+ if(!SFileHasFile(hPatchMpq, PATCH_METADATA_NAME))
+ {
+ GetDefaultPatchPrefix(FileStream_GetFileName(ha->pStream), szPatchPrefixBuff);
+ szPatchPathPrefix = szPatchPrefixBuff;
+ }
+ }
+
+ // Save the prefix for patch file names.
+ // Make sure that there is backslash after it
+ if(szPatchPathPrefix != NULL && *szPatchPathPrefix != 0)
+ {
+ strcpy(haPatch->szPatchPrefix, szPatchPathPrefix);
+ strcat(haPatch->szPatchPrefix, "\\");
+ haPatch->cchPatchPrefix = strlen(haPatch->szPatchPrefix);
+ }
+
+ // Now add the patch archive to the list of patches to the original MPQ
+ while(ha != NULL)
+ {
+ if(ha->haPatch == NULL)
+ {
+ haPatch->haBase = ha;
+ ha->haPatch = haPatch;
+ return true;
+ }
+
+ // Move to the next archive
+ ha = ha->haPatch;
+ }
+
+ // Should never happen
+ nError = ERROR_CAN_NOT_COMPLETE;
+ }
+
+ SetLastError(nError);
+ return false;
+}
+
+bool WINAPI SFileIsPatchedArchive(HANDLE hMpq)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ // Verify input parameters
+ if(!IsValidMpqHandle(ha))
+ return false;
+
+ return (ha->haPatch != NULL);
+}
diff --git a/dep/StormLib/src/SFileReadFile.cpp b/dep/StormLib/src/SFileReadFile.cpp
new file mode 100644
index 00000000000..5570fd466c5
--- /dev/null
+++ b/dep/StormLib/src/SFileReadFile.cpp
@@ -0,0 +1,1183 @@
+/*****************************************************************************/
+/* SFileReadFile.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.99 1.00 Lad The first version of SFileReadFile.cpp */
+/* 24.03.99 1.00 Lad Added the SFileGetFileInfo function */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+struct TFileHeader2Ext
+{
+ DWORD dwOffset00Data; // Required data at offset 00 (32-bits)
+ DWORD dwOffset00Mask; // Mask for data at offset 00 (32 bits). 0 = data are ignored
+ DWORD dwOffset04Data; // Required data at offset 04 (32-bits)
+ DWORD dwOffset04Mask; // Mask for data at offset 04 (32 bits). 0 = data are ignored
+ const char * szExt; // Supplied extension, if the condition is true
+};
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static void CopyFileName(char * szTarget, const TCHAR * szSource)
+{
+ while(*szSource != 0)
+ *szTarget++ = (char)*szSource++;
+ *szTarget = 0;
+}
+
+static DWORD GetMpqFileCount(TMPQArchive * ha)
+{
+ TFileEntry * pFileTableEnd;
+ TFileEntry * pFileEntry;
+ DWORD dwFileCount = 0;
+
+ // Go through all open MPQs, including patches
+ while(ha != NULL)
+ {
+ // Only count files that are not patch files
+ pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // If the file is patch file and this is not primary archive, skip it
+ // BUGBUG: This errorneously counts non-patch files that are in both
+ // base MPQ and in patches, and increases the number of files by cca 50%
+ if((pFileEntry->dwFlags & (MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE)) == MPQ_FILE_EXISTS)
+ dwFileCount++;
+ }
+
+ // Move to the next patch archive
+ ha = ha->haPatch;
+ }
+
+ return dwFileCount;
+}
+
+static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded)
+{
+ TMPQFile * hfTemp;
+ TCHAR * szPatchChain = (TCHAR *)pvFileInfo;
+ TCHAR * szFileName;
+ size_t cchCharsNeeded = 1;
+ size_t nLength;
+ DWORD cbLengthNeeded;
+
+ // Check if the "hf" is a MPQ file
+ if(hf->pStream != NULL)
+ {
+ // Calculate the length needed
+ szFileName = FileStream_GetFileName(hf->pStream);
+ cchCharsNeeded += _tcslen(szFileName) + 1;
+ cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR));
+
+ // If we have enough space, copy the file name
+ if(cbFileInfo >= cbLengthNeeded)
+ {
+ nLength = _tcslen(szFileName) + 1;
+ memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR));
+ szPatchChain += nLength;
+
+ // Terminate the multi-string
+ *szPatchChain = 0;
+ }
+ }
+ else
+ {
+ // Calculate number of characters needed
+ for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile)
+ cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1;
+ cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR));
+
+ // If we have enough space, the copy the patch chain
+ if(cbFileInfo >= cbLengthNeeded)
+ {
+ for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile)
+ {
+ szFileName = FileStream_GetFileName(hfTemp->ha->pStream);
+ nLength = _tcslen(szFileName) + 1;
+ memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR));
+ szPatchChain += nLength;
+ }
+
+ // Terminate the multi-string
+ *szPatchChain = 0;
+ }
+ }
+
+ // Give result length, terminate multi-string and return
+ *pcbLengthNeeded = cbLengthNeeded;
+ return true;
+}
+
+// hf - MPQ File handle.
+// pbBuffer - Pointer to target buffer to store sectors.
+// dwByteOffset - Position of sector in the file (relative to file begin)
+// dwBytesToRead - Number of bytes to read. Must be multiplier of sector size.
+// pdwBytesRead - Stored number of bytes loaded
+static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
+{
+ ULONGLONG RawFilePos;
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ LPBYTE pbRawSector = NULL;
+ LPBYTE pbOutSector = pbBuffer;
+ LPBYTE pbInSector = pbBuffer;
+ DWORD dwRawBytesToRead;
+ DWORD dwRawSectorOffset = dwByteOffset;
+ DWORD dwSectorsToRead = dwBytesToRead / ha->dwSectorSize;
+ DWORD dwSectorIndex = dwByteOffset / ha->dwSectorSize;
+ DWORD dwSectorsDone = 0;
+ DWORD dwBytesRead = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Note that dwByteOffset must be aligned to size of one sector
+ // Note that dwBytesToRead must be a multiplier of one sector size
+ // This is local function, so we won't check if that's true.
+ // Note that files stored in single units are processed by a separate function
+
+ // If there is not enough bytes remaining, cut dwBytesToRead
+ if((dwByteOffset + dwBytesToRead) > hf->dwDataSize)
+ dwBytesToRead = hf->dwDataSize - dwByteOffset;
+ dwRawBytesToRead = dwBytesToRead;
+
+ // Perform all necessary work to do with compressed files
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ {
+ // If the sector positions are not loaded yet, do it
+ if(hf->SectorOffsets == NULL)
+ {
+ nError = AllocateSectorOffsets(hf, true);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+ }
+
+ // If the sector checksums are not loaded yet, load them now.
+ if(hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->bLoadedSectorCRCs == false)
+ {
+ //
+ // Sector CRCs is plain crap feature. It is almost never present,
+ // often it's empty, or the end offset of sector CRCs is zero.
+ // We only try to load sector CRCs once, and regardless if it fails
+ // or not, we won't try that again for the given file.
+ //
+
+ AllocateSectorChecksums(hf, true);
+ hf->bLoadedSectorCRCs = true;
+ }
+
+ // TODO: If the raw data MD5s are not loaded yet, load them now
+ // Only do it if the MPQ is of format 4.0
+// if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4 && ha->pHeader->dwRawChunkSize != 0)
+// {
+// nError = AllocateRawMD5s(hf, true);
+// if(nError != ERROR_SUCCESS)
+// return nError;
+// }
+
+ // If the file is compressed, also allocate secondary buffer
+ pbInSector = pbRawSector = STORM_ALLOC(BYTE, dwBytesToRead);
+ if(pbRawSector == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Assign the temporary buffer as target for read operation
+ dwRawSectorOffset = hf->SectorOffsets[dwSectorIndex];
+ dwRawBytesToRead = hf->SectorOffsets[dwSectorIndex + dwSectorsToRead] - dwRawSectorOffset;
+ }
+
+ // Calculate raw file offset where the sector(s) are stored.
+ CalculateRawSectorOffset(RawFilePos, hf, dwRawSectorOffset);
+
+ // Set file pointer and read all required sectors
+ if(!FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead))
+ return GetLastError();
+ dwBytesRead = 0;
+
+ // Now we have to decrypt and decompress all file sectors that have been loaded
+ for(DWORD i = 0; i < dwSectorsToRead; i++)
+ {
+ DWORD dwRawBytesInThisSector = ha->dwSectorSize;
+ DWORD dwBytesInThisSector = ha->dwSectorSize;
+ DWORD dwIndex = dwSectorIndex + i;
+
+ // If there is not enough bytes in the last sector,
+ // cut the number of bytes in this sector
+ if(dwRawBytesInThisSector > dwBytesToRead)
+ dwRawBytesInThisSector = dwBytesToRead;
+ if(dwBytesInThisSector > dwBytesToRead)
+ dwBytesInThisSector = dwBytesToRead;
+
+ // If the file is compressed, we have to adjust the raw sector size
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex];
+
+ // If the file is encrypted, we have to decrypt the sector
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
+
+ // If we don't know the key, try to detect it by file content
+ if(hf->dwFileKey == 0)
+ {
+ hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector);
+ if(hf->dwFileKey == 0)
+ {
+ nError = ERROR_UNKNOWN_FILE_KEY;
+ break;
+ }
+ }
+
+ DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex);
+ BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
+ }
+
+ // If the file has sector CRC check turned on, perform it
+ if(hf->bCheckSectorCRCs && hf->SectorChksums != NULL)
+ {
+ DWORD dwAdlerExpected = hf->SectorChksums[dwIndex];
+ DWORD dwAdlerValue = 0;
+
+ // We can only check sector CRC when it's not zero
+ // Neither can we check it if it's 0xFFFFFFFF.
+ if(dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF)
+ {
+ dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector);
+ if(dwAdlerValue != dwAdlerExpected)
+ {
+ nError = ERROR_CHECKSUM_ERROR;
+ break;
+ }
+ }
+ }
+
+ // If the sector is really compressed, decompress it.
+ // WARNING : Some sectors may not be compressed, it can be determined only
+ // by comparing uncompressed and compressed size !!!
+ if(dwRawBytesInThisSector < dwBytesInThisSector)
+ {
+ int cbOutSector = dwBytesInThisSector;
+ int cbInSector = dwRawBytesInThisSector;
+ int nResult = 0;
+
+ // Is the file compressed by Blizzard's multiple compression ?
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
+ {
+ if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ nResult = SCompDecompress2((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector);
+ else
+ nResult = SCompDecompress((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector);
+ }
+
+ // Is the file compressed by PKWARE Data Compression Library ?
+ else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
+ {
+ nResult = SCompExplode((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector);
+ }
+
+ // Did the decompression fail ?
+ if(nResult == 0)
+ {
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+ }
+ else
+ {
+ if(pbOutSector != pbInSector)
+ memcpy(pbOutSector, pbInSector, dwBytesInThisSector);
+ }
+
+ // Move pointers
+ dwBytesToRead -= dwBytesInThisSector;
+ dwByteOffset += dwBytesInThisSector;
+ dwBytesRead += dwBytesInThisSector;
+ pbOutSector += dwBytesInThisSector;
+ pbInSector += dwRawBytesInThisSector;
+ dwSectorsDone++;
+ }
+
+ // Free all used buffers
+ if(pbRawSector != NULL)
+ STORM_FREE(pbRawSector);
+
+ // Give the caller thenumber of bytes read
+ *pdwBytesRead = dwBytesRead;
+ return nError;
+}
+
+static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
+{
+ ULONGLONG RawFilePos = hf->RawFilePos;
+ TMPQArchive * ha = hf->ha;
+ TFileEntry * pFileEntry = hf->pFileEntry;
+ LPBYTE pbCompressed = NULL;
+ LPBYTE pbRawData = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // If the file buffer is not allocated yet, do it.
+ if(hf->pbFileSector == NULL)
+ {
+ nError = AllocateSectorBuffer(hf);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+ pbRawData = hf->pbFileSector;
+ }
+
+ // If the file is a patch file, adjust raw data offset
+ if(hf->pPatchInfo != NULL)
+ RawFilePos += hf->pPatchInfo->dwLength;
+
+ // If the file sector is not loaded yet, do it
+ if(hf->dwSectorOffs != 0)
+ {
+ // Is the file compressed?
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ {
+ // Allocate space for compressed data
+ pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize);
+ if(pbCompressed == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+ pbRawData = pbCompressed;
+ }
+
+ // Load the raw (compressed, encrypted) data
+ if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize))
+ {
+ STORM_FREE(pbCompressed);
+ return GetLastError();
+ }
+
+ // If the file is encrypted, we have to decrypt the data first
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ {
+ BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
+ DecryptMpqBlock(pbRawData, pFileEntry->dwCmpSize, hf->dwFileKey);
+ BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
+ }
+
+ // If the file is compressed, we have to decompress it now
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
+ {
+ int cbOutBuffer = (int)hf->dwDataSize;
+ int cbInBuffer = (int)pFileEntry->dwCmpSize;
+ int nResult = 0;
+
+ //
+ // If the file is an incremental patch, the size of compressed data
+ // is determined as pFileEntry->dwCmpSize - sizeof(TPatchInfo)
+ //
+ // In "wow-update-12694.MPQ" from Wow-Cataclysm BETA:
+ //
+ // File CmprSize DcmpSize DataSize Compressed?
+ // -------------------------------------- ---------- -------- -------- ---------------
+ // esES\DBFilesClient\LightSkyBox.dbc 0xBE->0xA2 0xBC 0xBC Yes
+ // deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No
+ //
+
+ if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
+ cbInBuffer = cbInBuffer - sizeof(TPatchInfo);
+
+ // Is the file compressed by Blizzard's multiple compression ?
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
+ {
+ if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ nResult = SCompDecompress2((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer);
+ else
+ nResult = SCompDecompress((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer);
+ }
+
+ // Is the file compressed by PKWARE Data Compression Library ?
+ // Note: Single unit files compressed with IMPLODE are not supported by Blizzard
+ else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
+ nResult = SCompExplode((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer);
+
+ nError = (nResult != 0) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT;
+ }
+ else
+ {
+ if(pbRawData != hf->pbFileSector)
+ memcpy(hf->pbFileSector, pbRawData, hf->dwDataSize);
+ }
+
+ // Free the decompression buffer.
+ if(pbCompressed != NULL)
+ STORM_FREE(pbCompressed);
+
+ // The file sector is now properly loaded
+ hf->dwSectorOffs = 0;
+ }
+
+ // At this moment, we have the file loaded into the file buffer.
+ // Copy as much as the caller wants
+ if(nError == ERROR_SUCCESS && hf->dwSectorOffs == 0)
+ {
+ // File position is greater or equal to file size ?
+ if(dwFilePos >= hf->dwDataSize)
+ {
+ *pdwBytesRead = 0;
+ return ERROR_SUCCESS;
+ }
+
+ // If not enough bytes remaining in the file, cut them
+ if((hf->dwDataSize - dwFilePos) < dwToRead)
+ dwToRead = (hf->dwDataSize - dwFilePos);
+
+ // Copy the bytes
+ memcpy(pvBuffer, hf->pbFileSector + dwFilePos, dwToRead);
+
+ // Give the number of bytes read
+ *pdwBytesRead = dwToRead;
+ return ERROR_SUCCESS;
+ }
+
+ // An error, sorry
+ return ERROR_CAN_NOT_COMPLETE;
+}
+
+static int ReadMpqFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
+{
+ TMPQArchive * ha = hf->ha;
+ LPBYTE pbBuffer = (BYTE *)pvBuffer;
+ DWORD dwTotalBytesRead = 0; // Total bytes read in all three parts
+ DWORD dwSectorSizeMask = ha->dwSectorSize - 1; // Mask for block size, usually 0x0FFF
+ DWORD dwFileSectorPos; // File offset of the loaded sector
+ DWORD dwBytesRead; // Number of bytes read (temporary variable)
+ int nError;
+
+ // If the file position is at or beyond end of file, do nothing
+ if(dwFilePos >= hf->dwDataSize)
+ {
+ *pdwBytesRead = 0;
+ return ERROR_SUCCESS;
+ }
+
+ // If not enough bytes in the file remaining, cut them
+ if(dwBytesToRead > (hf->dwDataSize - dwFilePos))
+ dwBytesToRead = (hf->dwDataSize - dwFilePos);
+
+ // Compute sector position in the file
+ dwFileSectorPos = dwFilePos & ~dwSectorSizeMask; // Position in the block
+
+ // If the file sector buffer is not allocated yet, do it now
+ if(hf->pbFileSector == NULL)
+ {
+ nError = AllocateSectorBuffer(hf);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+ }
+
+ // Load the first (incomplete) file sector
+ if(dwFilePos & dwSectorSizeMask)
+ {
+ DWORD dwBytesInSector = ha->dwSectorSize;
+ DWORD dwBufferOffs = dwFilePos & dwSectorSizeMask;
+ DWORD dwToCopy;
+
+ // Is the file sector already loaded ?
+ if(hf->dwSectorOffs != dwFileSectorPos)
+ {
+ // Load one MPQ sector into archive buffer
+ nError = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesInSector);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ // Remember that the data loaded to the sector have new file offset
+ hf->dwSectorOffs = dwFileSectorPos;
+ }
+ else
+ {
+ if((dwFileSectorPos + dwBytesInSector) > hf->dwDataSize)
+ dwBytesInSector = hf->dwDataSize - dwFileSectorPos;
+ }
+
+ // Copy the data from the offset in the loaded sector to the end of the sector
+ dwToCopy = dwBytesInSector - dwBufferOffs;
+ if(dwToCopy > dwBytesToRead)
+ dwToCopy = dwBytesToRead;
+
+ // Copy data from sector buffer into target buffer
+ memcpy(pbBuffer, hf->pbFileSector + dwBufferOffs, dwToCopy);
+
+ // Update pointers and byte counts
+ dwTotalBytesRead += dwToCopy;
+ dwFileSectorPos += dwBytesInSector;
+ pbBuffer += dwToCopy;
+ dwBytesToRead -= dwToCopy;
+ }
+
+ // Load the whole ("middle") sectors only if there is at least one full sector to be read
+ if(dwBytesToRead >= ha->dwSectorSize)
+ {
+ DWORD dwBlockBytes = dwBytesToRead & ~dwSectorSizeMask;
+
+ // Load all sectors to the output buffer
+ nError = ReadMpqSectors(hf, pbBuffer, dwFileSectorPos, dwBlockBytes, &dwBytesRead);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ // Update pointers
+ dwTotalBytesRead += dwBytesRead;
+ dwFileSectorPos += dwBytesRead;
+ pbBuffer += dwBytesRead;
+ dwBytesToRead -= dwBytesRead;
+ }
+
+ // Read the terminating sector
+ if(dwBytesToRead > 0)
+ {
+ DWORD dwToCopy = ha->dwSectorSize;
+
+ // Is the file sector already loaded ?
+ if(hf->dwSectorOffs != dwFileSectorPos)
+ {
+ // Load one MPQ sector into archive buffer
+ nError = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesRead);
+ if(nError != ERROR_SUCCESS)
+ return nError;
+
+ // Remember that the data loaded to the sector have new file offset
+ hf->dwSectorOffs = dwFileSectorPos;
+ }
+
+ // Check number of bytes read
+ if(dwToCopy > dwBytesToRead)
+ dwToCopy = dwBytesToRead;
+
+ // Copy the data from the cached last sector to the caller's buffer
+ memcpy(pbBuffer, hf->pbFileSector, dwToCopy);
+
+ // Update pointers
+ dwTotalBytesRead += dwToCopy;
+ }
+
+ // Store total number of bytes read to the caller
+ *pdwBytesRead = dwTotalBytesRead;
+ return ERROR_SUCCESS;
+}
+
+static int ReadMpqFilePatchFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
+{
+ DWORD dwBytesToRead = dwToRead;
+ DWORD dwBytesRead = 0;
+ int nError = ERROR_SUCCESS;
+
+ // Make sure that the patch file is loaded completely
+ if(hf->pbFileData == NULL)
+ {
+ // Load the original file and store its content to "pbOldData"
+ hf->pbFileData = STORM_ALLOC(BYTE, hf->pFileEntry->dwFileSize);
+ hf->cbFileData = hf->pFileEntry->dwFileSize;
+ if(hf->pbFileData == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Read the file data
+ if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
+ nError = ReadMpqFileSingleUnit(hf, hf->pbFileData, 0, hf->cbFileData, &dwBytesRead);
+ else
+ nError = ReadMpqFile(hf, hf->pbFileData, 0, hf->cbFileData, &dwBytesRead);
+
+ // Fix error code
+ if(nError == ERROR_SUCCESS && dwBytesRead != hf->cbFileData)
+ nError = ERROR_FILE_CORRUPT;
+
+ // Patch the file data
+ if(nError == ERROR_SUCCESS)
+ nError = PatchFileData(hf);
+
+ // Reset number of bytes read to zero
+ dwBytesRead = 0;
+ }
+
+ // If there is something to read, do it
+ if(nError == ERROR_SUCCESS)
+ {
+ if(dwFilePos < hf->cbFileData)
+ {
+ // Make sure we don't copy more than file size
+ if((dwFilePos + dwToRead) > hf->cbFileData)
+ dwToRead = hf->cbFileData - dwFilePos;
+
+ // Copy the appropriate amount of the file data to the caller's buffer
+ memcpy(pvBuffer, hf->pbFileData + dwFilePos, dwToRead);
+ dwBytesRead = dwToRead;
+ }
+
+ // Set the proper error code
+ nError = (dwBytesRead == dwBytesToRead) ? ERROR_SUCCESS : ERROR_HANDLE_EOF;
+ }
+
+ // Give the result to the caller
+ if(pdwBytesRead != NULL)
+ *pdwBytesRead = dwBytesRead;
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// SFileReadFile
+
+bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped)
+{
+ TMPQFile * hf = (TMPQFile *)hFile;
+ DWORD dwBytesRead = 0; // Number of bytes read
+ int nError = ERROR_SUCCESS;
+
+ // Keep compilers happy
+ lpOverlapped = lpOverlapped;
+
+ // Check valid parameters
+ if(!IsValidFileHandle(hf))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ if(pvBuffer == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // If the file is local file, read the data directly from the stream
+ if(hf->pStream != NULL)
+ {
+ ULONGLONG FilePosition1;
+ ULONGLONG FilePosition2;
+
+ // Because stream I/O functions are designed to read
+ // "all or nothing", we compare file position before and after,
+ // and if they differ, we assume that number of bytes read
+ // is the difference between them
+
+ FileStream_GetPos(hf->pStream, FilePosition1);
+ if(!FileStream_Read(hf->pStream, NULL, pvBuffer, dwToRead))
+ {
+ // If not all bytes have been read, then return the number
+ // of bytes read
+ if((nError = GetLastError()) == ERROR_HANDLE_EOF)
+ {
+ FileStream_GetPos(hf->pStream, FilePosition2);
+ dwBytesRead = (DWORD)(FilePosition2 - FilePosition1);
+ }
+ else
+ {
+ nError = GetLastError();
+ }
+ }
+ else
+ {
+ dwBytesRead = dwToRead;
+ }
+ }
+ else
+ {
+ // If the file is a patch file, we have to read it special way
+ if(hf->hfPatchFile != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ {
+ nError = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
+ }
+
+ // If the file is single unit file, redirect it to read file
+ else if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
+ {
+ nError = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
+ }
+
+ // Otherwise read it as sector based MPQ file
+ else
+ {
+ nError = ReadMpqFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
+ }
+
+ // Increment the file position
+ hf->dwFilePos += dwBytesRead;
+ }
+
+ // Give the caller the number of bytes read
+ if(pdwRead != NULL)
+ *pdwRead = dwBytesRead;
+
+ // If the read operation succeeded, but not full number of bytes was read,
+ // set the last error to ERROR_HANDLE_EOF
+ if(nError == ERROR_SUCCESS && (dwBytesRead < dwToRead))
+ nError = ERROR_HANDLE_EOF;
+
+ // If something failed, set the last error value
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// SFileGetFileSize
+
+DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
+{
+ ULONGLONG FileSize;
+ TMPQFile * hf = (TMPQFile *)hFile;
+
+ // Validate the file handle before we go on
+ if(IsValidFileHandle(hf))
+ {
+ // Make sure that the variable is initialized
+ FileSize = 0;
+
+ // If the file is patched file, we have to get the size of the last version
+ if(hf->hfPatchFile != NULL)
+ {
+ // Walk through the entire patch chain, take the last version
+ while(hf != NULL)
+ {
+ // Get the size of the currently pointed version
+ FileSize = hf->pFileEntry->dwFileSize;
+
+ // Move to the next patch file in the hierarchy
+ hf = hf->hfPatchFile;
+ }
+ }
+ else
+ {
+ // Is it a local file ?
+ if(hf->pStream != NULL)
+ {
+ FileStream_GetSize(hf->pStream, FileSize);
+ }
+ else
+ {
+ FileSize = hf->dwDataSize;
+ }
+ }
+
+ // If opened from archive, return file size
+ if(pdwFileSizeHigh != NULL)
+ *pdwFileSizeHigh = (DWORD)(FileSize >> 32);
+ return (DWORD)FileSize;
+ }
+
+ SetLastError(ERROR_INVALID_HANDLE);
+ return SFILE_INVALID_SIZE;
+}
+
+DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod)
+{
+ TMPQFile * hf = (TMPQFile *)hFile;
+ ULONGLONG FilePosition;
+ ULONGLONG MoveOffset;
+ DWORD dwFilePosHi;
+
+ // If the hFile is not a valid file handle, return an error.
+ if(!IsValidFileHandle(hf))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return SFILE_INVALID_POS;
+ }
+
+ // Get the relative point where to move from
+ switch(dwMoveMethod)
+ {
+ case FILE_BEGIN:
+ FilePosition = 0;
+ break;
+
+ case FILE_CURRENT:
+ if(hf->pStream != NULL)
+ {
+ FileStream_GetPos(hf->pStream, FilePosition);
+ }
+ else
+ {
+ FilePosition = hf->dwFilePos;
+ }
+ break;
+
+ case FILE_END:
+ if(hf->pStream != NULL)
+ {
+ FileStream_GetSize(hf->pStream, FilePosition);
+ }
+ else
+ {
+ FilePosition = SFileGetFileSize(hFile, NULL);
+ }
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return SFILE_INVALID_POS;
+ }
+
+ // Now get the move offset. Note that both values form
+ // a signed 64-bit value (a file pointer can be moved backwards)
+ if(plFilePosHigh != NULL)
+ dwFilePosHi = *plFilePosHigh;
+ else
+ dwFilePosHi = (lFilePos & 0x80000000) ? 0xFFFFFFFF : 0;
+ MoveOffset = MAKE_OFFSET64(dwFilePosHi, lFilePos);
+
+ // Now calculate the new file pointer
+ // Do not allow the file pointer to go before the begin of the file
+ FilePosition += MoveOffset;
+ if(FilePosition < 0)
+ FilePosition = 0;
+
+ // Now apply the file pointer to the file
+ if(hf->pStream != NULL)
+ {
+ // Apply the new file position
+ if(!FileStream_Read(hf->pStream, &FilePosition, NULL, 0))
+ return SFILE_INVALID_POS;
+
+ // Return the new file position
+ if(plFilePosHigh != NULL)
+ *plFilePosHigh = (LONG)(FilePosition >> 32);
+ return (DWORD)FilePosition;
+ }
+ else
+ {
+ // Files in MPQ can't be bigger than 4 GB.
+ // We don't allow to go past 4 GB
+ if(FilePosition >> 32)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return SFILE_INVALID_POS;
+ }
+
+ // Change the file position
+ hf->dwFilePos = (DWORD)FilePosition;
+
+ // Return the new file position
+ if(plFilePosHigh != NULL)
+ *plFilePosHigh = 0;
+ return (DWORD)FilePosition;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Tries to retrieve the file name
+
+static TFileHeader2Ext data2ext[] =
+{
+ {0x00005A4D, 0x0000FFFF, 0x00000000, 0x00000000, "exe"}, // EXE files
+ {0x00000006, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, "dc6"}, // EXE files
+ {0x1A51504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mpq"}, // MPQ archive header ID ('MPQ\x1A')
+ {0x46464952, 0xFFFFFFFF, 0x00000000, 0x00000000, "wav"}, // WAVE header 'RIFF'
+ {0x324B4D53, 0xFFFFFFFF, 0x00000000, 0x00000000, "smk"}, // Old "Smacker Video" files 'SMK2'
+ {0x694B4942, 0xFFFFFFFF, 0x00000000, 0x00000000, "bik"}, // Bink video files (new)
+ {0x0801050A, 0xFFFFFFFF, 0x00000000, 0x00000000, "pcx"}, // PCX images used in Diablo I
+ {0x544E4F46, 0xFFFFFFFF, 0x00000000, 0x00000000, "fnt"}, // Font files used in Diablo II
+ {0x6D74683C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<htm'
+ {0x4D54483C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<HTM
+ {0x216F6F57, 0xFFFFFFFF, 0x00000000, 0x00000000, "tbl"}, // Table files
+ {0x31504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures
+ {0x32504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures (v2)
+ {0x584C444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mdx"}, // MDX files
+ {0x45505954, 0xFFFFFFFF, 0x00000000, 0x00000000, "pud"}, // Warcraft II maps
+ {0x38464947, 0xFFFFFFFF, 0x00000000, 0x00000000, "gif"}, // GIF images 'GIF8'
+ {0x3032444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "m2"}, // WoW ??? .m2
+ {0x43424457, 0xFFFFFFFF, 0x00000000, 0x00000000, "dbc"}, // ??? .dbc
+ {0x47585053, 0xFFFFFFFF, 0x00000000, 0x00000000, "bls"}, // WoW pixel shaders
+ {0xE0FFD8FF, 0xFFFFFFFF, 0x00000000, 0x00000000, "jpg"}, // JPEG image
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, "xxx"}, // Default extension
+ {0, 0, 0, 0, NULL} // Terminator
+};
+
+bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName)
+{
+ TFileEntry * pFileEntry;
+ TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
+ char szPseudoName[20];
+ DWORD FirstBytes[2]; // The first 4 bytes of the file
+ DWORD dwFilePos; // Saved file position
+ int nError = ERROR_SUCCESS;
+ int i;
+
+ // Pre-zero the output buffer
+ if(szFileName != NULL)
+ *szFileName = 0;
+
+ // Check valid parameters
+ if(!IsValidFileHandle(hf))
+ nError = ERROR_INVALID_HANDLE;
+ pFileEntry = hf->pFileEntry;
+
+ // Only do something if the file name is not filled
+ if(nError == ERROR_SUCCESS && pFileEntry != NULL && pFileEntry->szFileName == NULL)
+ {
+ // Read the first 2 DWORDs bytes from the file
+ FirstBytes[0] = FirstBytes[1] = 0;
+ dwFilePos = SFileSetFilePointer(hf, 0, NULL, FILE_CURRENT);
+ SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), NULL);
+ BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes));
+ SFileSetFilePointer(hf, dwFilePos, NULL, FILE_BEGIN);
+
+ // Try to guess file extension from those 2 DWORDs
+ for(i = 0; data2ext[i].szExt != NULL; i++)
+ {
+ if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data &&
+ (FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data)
+ {
+ sprintf(szPseudoName, "File%08u.%s", (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt);
+ break;
+ }
+ }
+
+ // Put the file name to the file table
+ AllocateFileName(pFileEntry, szPseudoName);
+ }
+
+ // Now put the file name to the file structure
+ if(nError == ERROR_SUCCESS && szFileName != NULL)
+ {
+ if(pFileEntry != NULL && pFileEntry->szFileName != NULL)
+ strcpy(szFileName, pFileEntry->szFileName);
+ else if(hf->pStream != NULL)
+ CopyFileName(szFileName, FileStream_GetFileName(hf->pStream));
+ }
+ return (nError == ERROR_SUCCESS);
+}
+
+//-----------------------------------------------------------------------------
+// Retrieves an information about an archive or about a file within the archive
+//
+// hMpqOrFile - Handle to an MPQ archive or to a file
+// dwInfoType - Information to obtain
+
+#define VERIFY_MPQ_HANDLE(h) \
+ if(!IsValidMpqHandle(h)) \
+ { \
+ nError = ERROR_INVALID_HANDLE; \
+ break; \
+ }
+
+#define VERIFY_FILE_HANDLE(h) \
+ if(!IsValidFileHandle(h)) \
+ { \
+ nError = ERROR_INVALID_HANDLE; \
+ break; \
+ }
+
+bool WINAPI SFileGetFileInfo(
+ HANDLE hMpqOrFile,
+ DWORD dwInfoType,
+ void * pvFileInfo,
+ DWORD cbFileInfo,
+ LPDWORD pcbLengthNeeded)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpqOrFile;
+ TMPQBlock * pBlock;
+ TMPQFile * hf = (TMPQFile *)hMpqOrFile;
+ void * pvSrcFileInfo = NULL;
+ DWORD cbLengthNeeded = 0;
+ DWORD dwIsReadOnly;
+ DWORD dwFileCount = 0;
+ DWORD dwFileIndex;
+ DWORD dwFileKey;
+ DWORD i;
+ int nError = ERROR_SUCCESS;
+
+ switch(dwInfoType)
+ {
+ case SFILE_INFO_ARCHIVE_NAME:
+ VERIFY_MPQ_HANDLE(ha);
+
+ // pvFileInfo receives the name of the archive, terminated by 0
+ pvSrcFileInfo = FileStream_GetFileName(ha->pStream);
+ cbLengthNeeded = (DWORD)(_tcslen((TCHAR *)pvSrcFileInfo) + 1) * sizeof(TCHAR);
+ break;
+
+ case SFILE_INFO_ARCHIVE_SIZE: // Size of the archive
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &ha->pHeader->dwArchiveSize;
+ break;
+
+ case SFILE_INFO_MAX_FILE_COUNT: // Max. number of files in the MPQ
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &ha->dwMaxFileCount;
+ break;
+
+ case SFILE_INFO_HASH_TABLE_SIZE: // Size of the hash table
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &ha->pHeader->dwHashTableSize;
+ break;
+
+ case SFILE_INFO_BLOCK_TABLE_SIZE: // Size of the block table
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &ha->pHeader->dwBlockTableSize;
+ break;
+
+ case SFILE_INFO_SECTOR_SIZE:
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &ha->dwSectorSize;
+ break;
+
+ case SFILE_INFO_HASH_TABLE:
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
+ pvSrcFileInfo = ha->pHashTable;
+ break;
+
+ case SFILE_INFO_BLOCK_TABLE:
+ VERIFY_MPQ_HANDLE(ha);
+ cbLengthNeeded = ha->dwFileTableSize * sizeof(TMPQBlock);
+ if(cbFileInfo < cbLengthNeeded)
+ {
+ nError = ERROR_INSUFFICIENT_BUFFER;
+ break;
+ }
+
+ // Construct block table from file table size
+ pBlock = (TMPQBlock *)pvFileInfo;
+ for(i = 0; i < ha->dwFileTableSize; i++)
+ {
+ pBlock->dwFilePos = (DWORD)ha->pFileTable[i].ByteOffset;
+ pBlock->dwFSize = ha->pFileTable[i].dwFileSize;
+ pBlock->dwCSize = ha->pFileTable[i].dwCmpSize;
+ pBlock->dwFlags = ha->pFileTable[i].dwFlags;
+ pBlock++;
+ }
+ break;
+
+ case SFILE_INFO_NUM_FILES:
+ VERIFY_MPQ_HANDLE(ha);
+ dwFileCount = GetMpqFileCount(ha);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &dwFileCount;
+ break;
+
+ case SFILE_INFO_STREAM_FLAGS: // Deprecated
+ nError = ERROR_INVALID_PARAMETER;
+ break;
+
+ case SFILE_INFO_IS_READ_ONLY:
+ VERIFY_MPQ_HANDLE(ha);
+ dwIsReadOnly = (FileStream_IsReadOnly(ha->pStream) || (ha->dwFlags & MPQ_FLAG_READ_ONLY));
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &dwIsReadOnly;
+ break;
+
+ case SFILE_INFO_HASH_INDEX:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->dwHashIndex;
+ break;
+
+ case SFILE_INFO_CODENAME1:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->dwHashIndex;
+ if(ha->pHashTable != NULL)
+ pvSrcFileInfo = &ha->pHashTable[hf->pFileEntry->dwHashIndex].dwName1;
+ break;
+
+ case SFILE_INFO_CODENAME2:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ if(ha->pHashTable != NULL)
+ pvSrcFileInfo = &ha->pHashTable[hf->pFileEntry->dwHashIndex].dwName2;
+ break;
+
+ case SFILE_INFO_LOCALEID:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->lcLocale;
+ break;
+
+ case SFILE_INFO_BLOCKINDEX:
+ VERIFY_FILE_HANDLE(hf);
+ dwFileIndex = (DWORD)(hf->pFileEntry - hf->ha->pFileTable);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &dwFileIndex;
+ break;
+
+ case SFILE_INFO_FILE_SIZE:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->dwFileSize;
+ break;
+
+ case SFILE_INFO_COMPRESSED_SIZE:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->dwCmpSize;
+ break;
+
+ case SFILE_INFO_FLAGS:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->pFileEntry->dwFlags;
+ break;
+
+ case SFILE_INFO_POSITION:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(ULONGLONG);
+ pvSrcFileInfo = &hf->pFileEntry->ByteOffset;
+ break;
+
+ case SFILE_INFO_KEY:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &hf->dwFileKey;
+ break;
+
+ case SFILE_INFO_KEY_UNFIXED:
+ VERIFY_FILE_HANDLE(hf);
+ dwFileKey = hf->dwFileKey;
+ if(hf->pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
+ dwFileKey = (dwFileKey ^ hf->pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos;
+ cbLengthNeeded = sizeof(DWORD);
+ pvSrcFileInfo = &dwFileKey;
+ break;
+
+ case SFILE_INFO_FILETIME:
+ VERIFY_FILE_HANDLE(hf);
+ cbLengthNeeded = sizeof(ULONGLONG);
+ pvSrcFileInfo = &hf->pFileEntry->FileTime;
+ break;
+
+ case SFILE_INFO_PATCH_CHAIN:
+ VERIFY_FILE_HANDLE(hf);
+ GetFilePatchChain(hf, pvFileInfo, cbFileInfo, &cbLengthNeeded);
+ break;
+
+ default:
+ nError = ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ // If everything is OK so far, copy the information
+ if(nError == ERROR_SUCCESS)
+ {
+ // Is the output buffer large enough?
+ if(cbFileInfo >= cbLengthNeeded)
+ {
+ // Copy the data
+ if(pvSrcFileInfo != NULL)
+ memcpy(pvFileInfo, pvSrcFileInfo, cbLengthNeeded);
+ }
+ else
+ {
+ nError = ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Give the size to the caller
+ if(pcbLengthNeeded != NULL)
+ *pcbLengthNeeded = cbLengthNeeded;
+ }
+
+ // Set the last error value, if needed
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
diff --git a/dep/StormLib/src/SFileVerify.cpp b/dep/StormLib/src/SFileVerify.cpp
new file mode 100644
index 00000000000..7457171d88f
--- /dev/null
+++ b/dep/StormLib/src/SFileVerify.cpp
@@ -0,0 +1,921 @@
+/*****************************************************************************/
+/* SFileVerify.cpp Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* MPQ files and MPQ archives verification. */
+/* */
+/* The MPQ signature verification has been written by Jean-Francois Roy */
+/* <bahamut@macstorm.org> and Justin Olbrantz (Quantam). */
+/* The MPQ public keys have been created by MPQKit, using OpenSSL library. */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 04.05.10 1.00 Lad The first version of SFileVerify.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#include "StormCommon.h"
+
+//-----------------------------------------------------------------------------
+// Local defines
+
+#define SIGNATURE_TYPE_NONE 0
+#define SIGNATURE_TYPE_WEAK 1
+#define SIGNATURE_TYPE_STRONG 2
+
+#define MPQ_DIGEST_UNIT_SIZE 0x10000
+
+typedef struct _MPQ_SIGNATURE_INFO
+{
+ ULONGLONG BeginMpqData; // File offset where the hashing starts
+ ULONGLONG BeginExclude; // Begin of the excluded area (used for (signature) file)
+ ULONGLONG EndExclude; // End of the excluded area (used for (signature) file)
+ ULONGLONG EndMpqData; // File offset where the hashing ends
+ ULONGLONG EndOfFile; // Size of the entire file
+ BYTE Signature[MPQ_STRONG_SIGNATURE_SIZE + 0x10];
+ DWORD cbSignatureSize; // Length of the signature
+ int nSignatureType; // See SIGNATURE_TYPE_XXX
+
+} MPQ_SIGNATURE_INFO, *PMPQ_SIGNATURE_INFO;
+
+//-----------------------------------------------------------------------------
+// Known Blizzard public keys
+// Created by Jean-Francois Roy using OpenSSL
+
+static const char * szBlizzardWeakPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJJidwS/uILMBSO5DLGsBFknIXWWjQJe"
+ "2kfdfEk3G/j66w4KkhZ1V61Rt4zLaMVCYpDun7FLwRjkMDSepO1q2DcCAwEAAQ=="
+ "-----END PUBLIC KEY-----";
+
+static const char * szBlizzardStrongPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsQZ+ziT2h8h+J/iMQpgd"
+ "tH1HaJzOBE3agjU4yMPcrixaPOZoA4t8bwfey7qczfWywocYo3pleytFF+IuD4HD"
+ "Fl9OXN1SFyupSgMx1EGZlgbFAomnbq9MQJyMqQtMhRAjFgg4TndS7YNb+JMSAEKp"
+ "kXNqY28n/EVBHD5TsMuVCL579gIenbr61dI92DDEdy790IzIG0VKWLh/KOTcTJfm"
+ "Ds/7HQTkGouVW+WUsfekuqNQo7ND9DBnhLjLjptxeFE2AZqYcA1ao3S9LN3GL1tW"
+ "lVXFIX9c7fWqaVTQlZ2oNsI/ARVApOK3grNgqvwH6YoVYVXjNJEo5sQJsPsdV/hk"
+ "dwIDAQAB"
+ "-----END PUBLIC KEY-----";
+
+static const char * szWarcraft3MapPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1BwklUUQ3UvjizOBRoF5"
+ "yyOVc7KD+oGOQH5i6eUk1yfs0luCC70kNucNrfqhmviywVtahRse1JtXCPrx2bd3"
+ "iN8Dx91fbkxjYIOGTsjYoHKTp0BbaFkJih776fcHgnFSb+7mJcDuJVvJOXxEH6w0"
+ "1vo6VtujCqj1arqbyoal+xtAaczF3us5cOEp45sR1zAWTn1+7omN7VWV4QqJPaDS"
+ "gBSESc0l1grO0i1VUSumayk7yBKIkb+LBvcG6WnYZHCi7VdLmaxER5m8oZfER66b"
+ "heHoiSQIZf9PAY6Guw2DT5BTc54j/AaLQAKf2qcRSgQLVo5kQaddF3rCpsXoB/74"
+ "6QIDAQAB"
+ "-----END PUBLIC KEY-----";
+
+static const char * szWowPatchPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOsMV0LagAWPEtEQM6b9"
+ "6FHFkUyGbbyda2/Dfc9dyl21E9QvX+Yw7qKRMAKPzA2TlQQLZKvXpnKXF/YIK5xa"
+ "5uwg9CEHCEAYolLG4xn0FUOE0E/0PuuytI0p0ICe6rk00PifZzTr8na2wI/l/GnQ"
+ "bvnIVF1ck6cslATpQJ5JJVMXzoFlUABS19WESw4MXuJAS3AbMhxNWdEhVv7eO51c"
+ "yGjRLy9QjogZODZTY0fSEksgBqQxNCoYVJYI/sF5K2flDsGqrIp0OdJ6teJlzg1Y"
+ "UjYnb6bKjlidXoHEXI2TgA/mD6O3XFIt08I9s3crOCTgICq7cgX35qrZiIVWZdRv"
+ "TwIDAQAB"
+ "-----END PUBLIC KEY-----";
+
+static const char * szWowSurveyPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnIt1DR6nRyyKsy2qahHe"
+ "MKLtacatn/KxieHcwH87wLBxKy+jZ0gycTmJ7SaTdBAEMDs/V5IPIXEtoqYnid2c"
+ "63TmfGDU92oc3Ph1PWUZ2PWxBhT06HYxRdbrgHw9/I29pNPi/607x+lzPORITOgU"
+ "BR6MR8au8HsQP4bn4vkJNgnSgojh48/XQOB/cAln7As1neP61NmVimoLR4Bwi3zt"
+ "zfgrZaUpyeNCUrOYJmH09YIjbBySTtXOUidoPHjFrMsCWpr6xs8xbETbs7MJFL6a"
+ "vcUfTT67qfIZ9RsuKfnXJTIrV0kwDSjjuNXiPTmWAehSsiHIsrUXX5RNcwsSjClr"
+ "nQIDAQAB"
+ "-----END PUBLIC KEY-----";
+
+static const char * szStarcraft2MapPublicKey =
+ "-----BEGIN PUBLIC KEY-----"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmk4GT8zb+ICC25a17KZB"
+ "q/ygKGJ2VSO6IT5PGHJlm1KfnHBA4B6SH3xMlJ4c6eG2k7QevZv+FOhjsAHubyWq"
+ "2VKqWbrIFKv2ILc2RfMn8J9EDVRxvcxh6slRrVL69D0w1tfVGjMiKq2Fym5yGoRT"
+ "E7CRgDqbAbXP9LBsCNWHiJLwfxMGzHbk8pIl9oia5pvM7ofZamSHchxlpy6xa4GJ"
+ "7xKN01YCNvklTL1D7uol3wkwcHc7vrF8QwuJizuA5bSg4poEGtH62BZOYi+UL/z0"
+ "31YK+k9CbQyM0X0pJoJoYz1TK+Y5J7vBnXCZtfcTYQ/ZzN6UcxTa57dJaiOlCh9z"
+ "nQIDAQAB"
+ "-----END PUBLIC KEY-----";
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static void memrev(unsigned char *buf, size_t count)
+{
+ unsigned char *r;
+
+ for (r = buf + count - 1; buf < r; buf++, r--)
+ {
+ *buf ^= *r;
+ *r ^= *buf;
+ *buf ^= *r;
+ }
+}
+
+static bool is_valid_md5(void * pvMd5)
+{
+ LPDWORD Md5 = (LPDWORD)pvMd5;
+
+ return (Md5[0] | Md5[1] | Md5[2] | Md5[3]) ? true : false;
+}
+
+static bool decode_base64_key(const char * szKeyBase64, rsa_key * key)
+{
+ unsigned char decoded_key[0x200];
+ const char * szBase64Begin;
+ const char * szBase64End;
+ unsigned long decoded_length = sizeof(decoded_key);
+ unsigned long length;
+
+ // Find out the begin of the BASE64 data
+ szBase64Begin = szKeyBase64 + strlen("-----BEGIN PUBLIC KEY-----");
+ szBase64End = szBase64Begin + strlen(szBase64Begin) - strlen("-----END PUBLIC KEY-----");
+ if(szBase64End[0] != '-')
+ return false;
+
+ // decode the base64 string
+ length = (unsigned long)(szBase64End - szBase64Begin);
+ if(base64_decode((unsigned char *)szBase64Begin, length, decoded_key, &decoded_length) != CRYPT_OK)
+ return false;
+
+ // Create RSA key
+ if(rsa_import(decoded_key, decoded_length, key) != CRYPT_OK)
+ return false;
+
+ return true;
+}
+
+static void GetPlainAnsiFileName(
+ const TCHAR * szFileName,
+ char * szPlainName)
+{
+ const TCHAR * szPlainNameT = GetPlainFileNameT(szFileName);
+
+ // Convert the plain name to ANSI
+ while(*szPlainNameT != 0)
+ *szPlainName++ = (char)*szPlainNameT++;
+ *szPlainName = 0;
+}
+
+// Calculate begin and end of the MPQ archive
+static void CalculateArchiveRange(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI)
+{
+ ULONGLONG TempPos = 0;
+ char szMapHeader[0x200];
+
+ // Get the MPQ begin
+ pSI->BeginMpqData = ha->MpqPos;
+
+ // Warcraft III maps are signed from the map header to the end
+ if(FileStream_Read(ha->pStream, &TempPos, szMapHeader, sizeof(szMapHeader)))
+ {
+ // Is it a map header ?
+ if(szMapHeader[0] == 'H' && szMapHeader[1] == 'M' && szMapHeader[2] == '3' && szMapHeader[3] == 'W')
+ {
+ // We will have to hash since the map header
+ pSI->BeginMpqData = 0;
+ }
+ }
+
+ // Get the MPQ data end. This is stored in our MPQ header,
+ // and it's been already prepared by SFileOpenArchive,
+ pSI->EndMpqData = ha->MpqPos + ha->pHeader->ArchiveSize64;
+
+ // Get the size of the entire file
+ FileStream_GetSize(ha->pStream, pSI->EndOfFile);
+}
+
+static bool QueryMpqSignatureInfo(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI)
+{
+ ULONGLONG ExtraBytes;
+ TMPQFile * hf;
+ HANDLE hFile;
+ DWORD dwFileSize;
+
+ // Calculate the range of the MPQ
+ CalculateArchiveRange(ha, pSI);
+
+ // If there is "(signature)" file in the MPQ, it has a weak signature
+ if(SFileOpenFileEx((HANDLE)ha, SIGNATURE_NAME, SFILE_OPEN_FROM_MPQ, &hFile))
+ {
+ // Get the content of the signature
+ SFileReadFile(hFile, pSI->Signature, sizeof(pSI->Signature), &pSI->cbSignatureSize);
+
+ // Verify the size of the signature
+ hf = (TMPQFile *)hFile;
+
+ // We have to exclude the signature file from the digest
+ pSI->BeginExclude = ha->MpqPos + hf->pFileEntry->ByteOffset;
+ pSI->EndExclude = pSI->BeginExclude + hf->pFileEntry->dwCmpSize;
+ dwFileSize = hf->dwDataSize;
+
+ // Close the file
+ SFileCloseFile(hFile);
+ pSI->nSignatureType = SIGNATURE_TYPE_WEAK;
+ return (dwFileSize == (MPQ_WEAK_SIGNATURE_SIZE + 8)) ? true : false;
+ }
+
+ // If there is extra bytes beyond the end of the archive,
+ // it's the strong signature
+ ExtraBytes = pSI->EndOfFile - pSI->EndMpqData;
+ if(ExtraBytes >= (MPQ_STRONG_SIGNATURE_SIZE + 4))
+ {
+ // Read the strong signature
+ if(!FileStream_Read(ha->pStream, &pSI->EndMpqData, pSI->Signature, (MPQ_STRONG_SIGNATURE_SIZE + 4)))
+ return false;
+
+ // Check the signature header "NGIS"
+ if(pSI->Signature[0] != 'N' || pSI->Signature[1] != 'G' || pSI->Signature[2] != 'I' || pSI->Signature[3] != 'S')
+ return false;
+
+ pSI->nSignatureType = SIGNATURE_TYPE_STRONG;
+ return true;
+ }
+
+ // Succeeded, but no known signature found
+ return true;
+}
+
+static bool CalculateMpqHashMd5(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI,
+ LPBYTE pMd5Digest)
+{
+ hash_state md5_state;
+ ULONGLONG BeginBuffer;
+ ULONGLONG EndBuffer;
+ LPBYTE pbDigestBuffer = NULL;
+
+ // Allocate buffer for creating the MPQ digest.
+ pbDigestBuffer = STORM_ALLOC(BYTE, MPQ_DIGEST_UNIT_SIZE);
+ if(pbDigestBuffer == NULL)
+ return false;
+
+ // Initialize the MD5 hash state
+ md5_init(&md5_state);
+
+ // Set the byte offset of begin of the data
+ BeginBuffer = pSI->BeginMpqData;
+
+ // Create the digest
+ for(;;)
+ {
+ ULONGLONG BytesRemaining;
+ LPBYTE pbSigBegin = NULL;
+ LPBYTE pbSigEnd = NULL;
+ DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;
+
+ // Check the number of bytes remaining
+ BytesRemaining = pSI->EndMpqData - BeginBuffer;
+ if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
+ dwToRead = (DWORD)BytesRemaining;
+ if(dwToRead == 0)
+ break;
+
+ // Read the next chunk
+ if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
+ {
+ STORM_FREE(pbDigestBuffer);
+ return false;
+ }
+
+ // Move the current byte offset
+ EndBuffer = BeginBuffer + dwToRead;
+
+ // Check if the signature is within the loaded digest
+ if(BeginBuffer <= pSI->BeginExclude && pSI->BeginExclude < EndBuffer)
+ pbSigBegin = pbDigestBuffer + (size_t)(pSI->BeginExclude - BeginBuffer);
+ if(BeginBuffer <= pSI->EndExclude && pSI->EndExclude < EndBuffer)
+ pbSigEnd = pbDigestBuffer + (size_t)(pSI->EndExclude - BeginBuffer);
+
+ // Zero the part that belongs to the signature
+ if(pbSigBegin != NULL || pbSigEnd != NULL)
+ {
+ if(pbSigBegin == NULL)
+ pbSigBegin = pbDigestBuffer;
+ if(pbSigEnd == NULL)
+ pbSigEnd = pbDigestBuffer + dwToRead;
+
+ memset(pbSigBegin, 0, (pbSigEnd - pbSigBegin));
+ }
+
+ // Pass the buffer to the hashing function
+ md5_process(&md5_state, pbDigestBuffer, dwToRead);
+
+ // Move pointers
+ BeginBuffer += dwToRead;
+ }
+
+ // Finalize the MD5 hash
+ md5_done(&md5_state, pMd5Digest);
+ STORM_FREE(pbDigestBuffer);
+ return true;
+}
+
+static void AddTailToSha1(
+ hash_state * psha1_state,
+ const char * szTail)
+{
+ unsigned char szUpperCase[0x200];
+ unsigned long nLength = 0;
+
+ // Convert the tail to uppercase
+ // Note that we don't need to terminate the string with zero
+ while(*szTail != 0)
+ {
+ szUpperCase[nLength++] = (unsigned char)toupper(*szTail++);
+ }
+
+ // Append the tail to the SHA1
+ sha1_process(psha1_state, szUpperCase, nLength);
+}
+
+static bool CalculateMpqHashSha1(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI,
+ unsigned char * sha1_tail0,
+ unsigned char * sha1_tail1,
+ unsigned char * sha1_tail2)
+{
+ ULONGLONG BeginBuffer;
+ hash_state sha1_state_temp;
+ hash_state sha1_state;
+ LPBYTE pbDigestBuffer = NULL;
+ char szPlainName[MAX_PATH];
+
+ // Allocate buffer for creating the MPQ digest.
+ pbDigestBuffer = STORM_ALLOC(BYTE, MPQ_DIGEST_UNIT_SIZE);
+ if(pbDigestBuffer == NULL)
+ return false;
+
+ // Initialize SHA1 state structure
+ sha1_init(&sha1_state);
+
+ // Calculate begin of data to be hashed
+ BeginBuffer = pSI->BeginMpqData;
+
+ // Create the digest
+ for(;;)
+ {
+ ULONGLONG BytesRemaining;
+ DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;
+
+ // Check the number of bytes remaining
+ BytesRemaining = pSI->EndMpqData - BeginBuffer;
+ if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
+ dwToRead = (DWORD)BytesRemaining;
+ if(dwToRead == 0)
+ break;
+
+ // Read the next chunk
+ if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
+ {
+ STORM_FREE(pbDigestBuffer);
+ return false;
+ }
+
+ // Pass the buffer to the hashing function
+ sha1_process(&sha1_state, pbDigestBuffer, dwToRead);
+
+ // Move pointers
+ BeginBuffer += dwToRead;
+ }
+
+ // Add all three known tails and generate three hashes
+ memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
+ sha1_done(&sha1_state_temp, sha1_tail0);
+
+ memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
+ GetPlainAnsiFileName(FileStream_GetFileName(ha->pStream), szPlainName);
+ AddTailToSha1(&sha1_state_temp, szPlainName);
+ sha1_done(&sha1_state_temp, sha1_tail1);
+
+ memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
+ AddTailToSha1(&sha1_state_temp, "ARCHIVE");
+ sha1_done(&sha1_state_temp, sha1_tail2);
+
+ // Finalize the MD5 hash
+ STORM_FREE(pbDigestBuffer);
+ return true;
+}
+
+static int VerifyRawMpqData(
+ TMPQArchive * ha,
+ ULONGLONG ByteOffset,
+ DWORD dwDataSize)
+{
+ ULONGLONG DataOffset = ha->MpqPos + ByteOffset;
+ LPBYTE pbDataChunk;
+ LPBYTE pbMD5Array1; // Calculated MD5 array
+ LPBYTE pbMD5Array2; // MD5 array loaded from the MPQ
+ DWORD dwBytesInChunk;
+ DWORD dwChunkCount;
+ DWORD dwChunkSize = ha->pHeader->dwRawChunkSize;
+ DWORD dwMD5Size;
+ int nError = ERROR_SUCCESS;
+
+ // Don't verify zero-sized blocks
+ if(dwDataSize == 0)
+ return ERROR_SUCCESS;
+
+ // Get the number of data chunks to calculate MD5
+ assert(dwChunkSize != 0);
+ dwChunkCount = ((dwDataSize - 1) / dwChunkSize) + 1;
+ dwMD5Size = dwChunkCount * MD5_DIGEST_SIZE;
+
+ // Allocate space for data chunk and for the MD5 array
+ pbDataChunk = STORM_ALLOC(BYTE, dwChunkSize);
+ if(pbDataChunk == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Allocate space for MD5 array
+ pbMD5Array1 = STORM_ALLOC(BYTE, dwMD5Size);
+ pbMD5Array2 = STORM_ALLOC(BYTE, dwMD5Size);
+ if(pbMD5Array1 == NULL || pbMD5Array2 == NULL)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ // Calculate MD5 of each data chunk
+ if(nError == ERROR_SUCCESS)
+ {
+ LPBYTE pbMD5 = pbMD5Array1;
+
+ for(DWORD i = 0; i < dwChunkCount; i++)
+ {
+ // Get the number of bytes in the chunk
+ dwBytesInChunk = STORMLIB_MIN(dwChunkSize, dwDataSize);
+
+ // Read the data chunk
+ if(!FileStream_Read(ha->pStream, &DataOffset, pbDataChunk, dwBytesInChunk))
+ {
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
+
+ // Calculate MD5
+ CalculateDataBlockHash(pbDataChunk, dwBytesInChunk, pbMD5);
+
+ // Move pointers and offsets
+ DataOffset += dwBytesInChunk;
+ dwDataSize -= dwBytesInChunk;
+ pbMD5 += MD5_DIGEST_SIZE;
+ }
+ }
+
+ // Read the MD5 array
+ if(nError == ERROR_SUCCESS)
+ {
+ // Read the array of MD5
+ if(!FileStream_Read(ha->pStream, &DataOffset, pbMD5Array2, dwMD5Size))
+ nError = GetLastError();
+ }
+
+ // Compare the array of MD5
+ if(nError == ERROR_SUCCESS)
+ {
+ // Compare the MD5
+ if(memcmp(pbMD5Array1, pbMD5Array2, dwMD5Size))
+ nError = ERROR_FILE_CORRUPT;
+ }
+
+ // Free memory and return result
+ if(pbMD5Array2 != NULL)
+ STORM_FREE(pbMD5Array2);
+ if(pbMD5Array1 != NULL)
+ STORM_FREE(pbMD5Array1);
+ if(pbDataChunk != NULL)
+ STORM_FREE(pbDataChunk);
+ return nError;
+}
+
+static DWORD VerifyWeakSignature(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI)
+{
+ BYTE RevSignature[MPQ_WEAK_SIGNATURE_SIZE];
+ BYTE Md5Digest[MD5_DIGEST_SIZE];
+ rsa_key key;
+ int hash_idx = find_hash("md5");
+ int result = 0;
+
+ // Calculate hash of the entire archive, skipping the (signature) file
+ if(!CalculateMpqHashMd5(ha, pSI, Md5Digest))
+ return ERROR_VERIFY_FAILED;
+
+ // Import the Blizzard key in OpenSSL format
+ if(!decode_base64_key(szBlizzardWeakPublicKey, &key))
+ return ERROR_VERIFY_FAILED;
+
+ // Verify the signature
+ memcpy(RevSignature, &pSI->Signature[8], MPQ_WEAK_SIGNATURE_SIZE);
+ memrev(RevSignature, MPQ_WEAK_SIGNATURE_SIZE);
+ rsa_verify_hash_ex(RevSignature, MPQ_WEAK_SIGNATURE_SIZE, Md5Digest, sizeof(Md5Digest), LTC_LTC_PKCS_1_V1_5, hash_idx, 0, &result, &key);
+ rsa_free(&key);
+
+ // Return the result
+ return result ? ERROR_WEAK_SIGNATURE_OK : ERROR_WEAK_SIGNATURE_ERROR;
+}
+
+static DWORD VerifyStrongSignatureWithKey(
+ unsigned char * reversed_signature,
+ unsigned char * padded_digest,
+ const char * szPublicKey)
+{
+ rsa_key key;
+ int result = 0;
+
+ // Import the Blizzard key in OpenSSL format
+ if(!decode_base64_key(szPublicKey, &key))
+ {
+ assert(false);
+ return ERROR_VERIFY_FAILED;
+ }
+
+ // Verify the signature
+ if(rsa_verify_simple(reversed_signature, MPQ_STRONG_SIGNATURE_SIZE, padded_digest, MPQ_STRONG_SIGNATURE_SIZE, &result, &key) != CRYPT_OK)
+ return ERROR_VERIFY_FAILED;
+
+ // Free the key and return result
+ rsa_free(&key);
+ return result ? ERROR_STRONG_SIGNATURE_OK : ERROR_STRONG_SIGNATURE_ERROR;
+}
+
+static DWORD VerifyStrongSignature(
+ TMPQArchive * ha,
+ PMPQ_SIGNATURE_INFO pSI)
+{
+ unsigned char reversed_signature[MPQ_STRONG_SIGNATURE_SIZE];
+ unsigned char Sha1Digest_tail0[SHA1_DIGEST_SIZE];
+ unsigned char Sha1Digest_tail1[SHA1_DIGEST_SIZE];
+ unsigned char Sha1Digest_tail2[SHA1_DIGEST_SIZE];
+ unsigned char padded_digest[MPQ_STRONG_SIGNATURE_SIZE];
+ DWORD dwResult;
+ size_t digest_offset;
+
+ // Calculate SHA1 hash of the archive
+ if(!CalculateMpqHashSha1(ha, pSI, Sha1Digest_tail0, Sha1Digest_tail1, Sha1Digest_tail2))
+ return ERROR_VERIFY_FAILED;
+
+ // Prepare the signature for decryption
+ memcpy(reversed_signature, &pSI->Signature[4], MPQ_STRONG_SIGNATURE_SIZE);
+ memrev(reversed_signature, MPQ_STRONG_SIGNATURE_SIZE);
+
+ // Prepare the padded digest for comparison
+ digest_offset = sizeof(padded_digest) - SHA1_DIGEST_SIZE;
+ memset(padded_digest, 0xbb, digest_offset);
+ padded_digest[0] = 0x0b;
+
+ // Try Blizzard Strong public key with no SHA1 tail
+ memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
+ memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
+ dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szBlizzardStrongPublicKey);
+ if(dwResult == ERROR_STRONG_SIGNATURE_OK)
+ return dwResult;
+
+ // Try War 3 map public key with plain file name as SHA1 tail
+ memcpy(padded_digest + digest_offset, Sha1Digest_tail1, SHA1_DIGEST_SIZE);
+ memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
+ dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWarcraft3MapPublicKey);
+ if(dwResult == ERROR_STRONG_SIGNATURE_OK)
+ return dwResult;
+
+ // Try WoW-TBC public key with "ARCHIVE" as SHA1 tail
+ memcpy(padded_digest + digest_offset, Sha1Digest_tail2, SHA1_DIGEST_SIZE);
+ memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
+ dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWowPatchPublicKey);
+ if(dwResult == ERROR_STRONG_SIGNATURE_OK)
+ return dwResult;
+
+ // Try Survey public key with no SHA1 tail
+ memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
+ memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
+ dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWowSurveyPublicKey);
+ if(dwResult == ERROR_STRONG_SIGNATURE_OK)
+ return dwResult;
+
+ // Try Starcraft II public key with no SHA1 tail
+ memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
+ memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
+ dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szStarcraft2MapPublicKey);
+ if(dwResult == ERROR_STRONG_SIGNATURE_OK)
+ return dwResult;
+
+ return ERROR_STRONG_SIGNATURE_ERROR;
+}
+
+static DWORD VerifyFile(
+ HANDLE hMpq,
+ const char * szFileName,
+ LPDWORD pdwCrc32,
+ char * pMD5,
+ DWORD dwFlags)
+{
+ hash_state md5_state;
+ unsigned char * pFileMd5;
+ unsigned char md5[MD5_DIGEST_SIZE];
+ TFileEntry * pFileEntry;
+ TMPQFile * hf;
+ BYTE Buffer[0x1000];
+ HANDLE hFile = NULL;
+ DWORD dwVerifyResult = 0;
+ DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ;
+ DWORD dwTotalBytes = 0;
+ DWORD dwBytesRead;
+ DWORD dwCrc32 = 0;
+
+ // Fix the open type for patched archives
+ if(SFileIsPatchedArchive(hMpq))
+ dwSearchScope = SFILE_OPEN_PATCHED_FILE;
+
+ // If we have to verify raw data MD5, do it before file open
+ if(dwFlags & SFILE_VERIFY_RAW_MD5)
+ {
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ // Parse the base MPQ and all patches
+ while(ha != NULL)
+ {
+ // Does the archive have support for raw MD5?
+ if(ha->pHeader->dwRawChunkSize != 0)
+ {
+ // The file has raw MD5 if the archive supports it
+ dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5;
+
+ // Find file entry for the file
+ pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
+ if(pFileEntry != NULL)
+ {
+ // If the file's raw MD5 doesn't match, don't bother with more checks
+ if(VerifyRawMpqData(ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS)
+ return dwVerifyResult | VERIFY_FILE_RAW_MD5_ERROR;
+ }
+ }
+
+ // Move to the next patch
+ ha = ha->haPatch;
+ }
+ }
+
+ // Attempt to open the file
+ if(SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile))
+ {
+ // Get the file size
+ hf = (TMPQFile *)hFile;
+ pFileEntry = hf->pFileEntry;
+ dwTotalBytes = SFileGetFileSize(hFile, NULL);
+
+ // Initialize the CRC32 and MD5 contexts
+ md5_init(&md5_state);
+ dwCrc32 = crc32(0, Z_NULL, 0);
+
+ // Also turn on sector checksum verification
+ if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
+ hf->bCheckSectorCRCs = true;
+
+ // Go through entire file and update both CRC32 and MD5
+ for(;;)
+ {
+ // Read data from file
+ SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
+ if(dwBytesRead == 0)
+ {
+ if(GetLastError() == ERROR_CHECKSUM_ERROR)
+ dwVerifyResult |= VERIFY_FILE_SECTOR_CRC_ERROR;
+ break;
+ }
+
+ // Update CRC32 value
+ if(dwFlags & SFILE_VERIFY_FILE_CRC)
+ dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
+
+ // Update MD5 value
+ if(dwFlags & SFILE_VERIFY_FILE_MD5)
+ md5_process(&md5_state, Buffer, dwBytesRead);
+
+ // Decrement the total size
+ dwTotalBytes -= dwBytesRead;
+ }
+
+ // If the file has sector checksums, indicate it in the flags
+ if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
+ {
+ if((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0)
+ dwVerifyResult |= VERIFY_FILE_HAS_SECTOR_CRC;
+ }
+
+ // Check if the entire file has been read
+ // No point in checking CRC32 and MD5 if not
+ // Skip checksum checks if the file has patches
+ if(dwTotalBytes == 0)
+ {
+ // Check CRC32 and MD5 only if there is no patches
+ if(hf->hfPatchFile == NULL)
+ {
+ // Check if the CRC32 matches.
+ if(dwFlags & SFILE_VERIFY_FILE_CRC)
+ {
+ // Only check the CRC32 if it is valid
+ if(pFileEntry->dwCrc32 != 0)
+ {
+ dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM;
+ if(dwCrc32 != pFileEntry->dwCrc32)
+ dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR;
+ }
+ }
+
+ // Check if MD5 matches
+ if(dwFlags & SFILE_VERIFY_FILE_MD5)
+ {
+ // Patch files have their MD5 saved in the patch info
+ pFileMd5 = (hf->pPatchInfo != NULL) ? hf->pPatchInfo->md5 : pFileEntry->md5;
+ md5_done(&md5_state, md5);
+
+ // Only check the MD5 if it is valid
+ if(is_valid_md5(pFileMd5))
+ {
+ dwVerifyResult |= VERIFY_FILE_HAS_MD5;
+ if(memcmp(md5, pFileMd5, MD5_DIGEST_SIZE))
+ dwVerifyResult |= VERIFY_FILE_MD5_ERROR;
+ }
+ }
+ }
+ else
+ {
+ // Patched files are MD5-checked automatically
+ dwVerifyResult |= VERIFY_FILE_HAS_MD5;
+ }
+ }
+ else
+ {
+ dwVerifyResult |= VERIFY_READ_ERROR;
+ }
+
+ SFileCloseFile(hFile);
+ }
+ else
+ {
+ // Remember that the file couldn't be open
+ dwVerifyResult |= VERIFY_OPEN_ERROR;
+ }
+
+ // If the caller required CRC32 and/or MD5, give it to him
+ if(pdwCrc32 != NULL)
+ *pdwCrc32 = dwCrc32;
+ if(pMD5 != NULL)
+ memcpy(pMD5, md5, MD5_DIGEST_SIZE);
+
+ return dwVerifyResult;
+}
+
+//-----------------------------------------------------------------------------
+// Public (exported) functions
+
+bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5)
+{
+ DWORD dwVerifyResult;
+ DWORD dwVerifyFlags = 0;
+
+ if(pdwCrc32 != NULL)
+ dwVerifyFlags |= SFILE_VERIFY_FILE_CRC;
+ if(pMD5 != NULL)
+ dwVerifyFlags |= SFILE_VERIFY_FILE_MD5;
+
+ dwVerifyResult = VerifyFile(hMpq,
+ szFileName,
+ pdwCrc32,
+ pMD5,
+ dwVerifyFlags);
+
+ // If verification failed, return zero
+ if(dwVerifyResult & VERIFY_FILE_ERROR_MASK)
+ {
+ SetLastError(ERROR_FILE_CORRUPT);
+ return false;
+ }
+
+ return true;
+}
+
+
+DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags)
+{
+ return VerifyFile(hMpq,
+ szFileName,
+ NULL,
+ NULL,
+ dwFlags);
+}
+
+// Verifies raw data of the archive Only works for MPQs version 4 or newer
+int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName)
+{
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry;
+ TMPQHeader * pHeader;
+
+ // Verify input parameters
+ if(!IsValidMpqHandle(ha))
+ return ERROR_INVALID_PARAMETER;
+ pHeader = ha->pHeader;
+
+ // If the archive doesn't have raw data MD5, report it as OK
+ if(pHeader->dwRawChunkSize == 0)
+ return ERROR_SUCCESS;
+
+ // If we have to verify MPQ header, do it
+ switch(dwWhatToVerify)
+ {
+ case SFILE_VERIFY_MPQ_HEADER:
+
+ // Only if the header is of version 4 or newer
+ if(pHeader->dwHeaderSize >= (MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE))
+ return VerifyRawMpqData(ha, 0, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE);
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_HET_TABLE:
+
+ // Only if we have HET table
+ if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
+ return VerifyRawMpqData(ha, pHeader->HetTablePos64, (DWORD)pHeader->HetTableSize64);
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_BET_TABLE:
+
+ // Only if we have BET table
+ if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
+ return VerifyRawMpqData(ha, pHeader->BetTablePos64, (DWORD)pHeader->BetTableSize64);
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_HASH_TABLE:
+
+ // Hash table is not protected by MD5
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_BLOCK_TABLE:
+
+ // Block table is not protected by MD5
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_HIBLOCK_TABLE:
+
+ // It is unknown if the hi-block table is protected my MD5 or not.
+ return ERROR_SUCCESS;
+
+ case SFILE_VERIFY_FILE:
+
+ // Verify parameters
+ if(szFileName == NULL || *szFileName == 0)
+ return ERROR_INVALID_PARAMETER;
+
+ // Get the offset of a file
+ pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
+ if(pFileEntry == NULL)
+ return ERROR_FILE_NOT_FOUND;
+
+ return VerifyRawMpqData(ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize);
+ }
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+// Verifies the archive against the signature
+DWORD WINAPI SFileVerifyArchive(HANDLE hMpq)
+{
+ MPQ_SIGNATURE_INFO si;
+ TMPQArchive * ha = (TMPQArchive *)hMpq;
+
+ // Verify input parameters
+ if(!IsValidMpqHandle(ha))
+ return ERROR_VERIFY_FAILED;
+
+ // Get the MPQ signature and signature type
+ memset(&si, 0, sizeof(MPQ_SIGNATURE_INFO));
+ if(!QueryMpqSignatureInfo(ha, &si))
+ return ERROR_VERIFY_FAILED;
+
+ // Verify the signature
+ switch(si.nSignatureType)
+ {
+ case SIGNATURE_TYPE_NONE:
+ return ERROR_NO_SIGNATURE;
+
+ case SIGNATURE_TYPE_WEAK:
+ return VerifyWeakSignature(ha, &si);
+
+ case SIGNATURE_TYPE_STRONG:
+ return VerifyStrongSignature(ha, &si);
+ }
+
+ return ERROR_VERIFY_FAILED;
+}
diff --git a/dep/StormLib/src/StormCommon.h b/dep/StormLib/src/StormCommon.h
new file mode 100644
index 00000000000..9a85c4bd5ac
--- /dev/null
+++ b/dep/StormLib/src/StormCommon.h
@@ -0,0 +1,274 @@
+/*****************************************************************************/
+/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Common functions for encryption/decryption from Storm.dll. Included by */
+/* SFile*** functions, do not include and do not use this file directly */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
+/* 12.06.04 1.00 Lad Renamed to SCommon.h */
+/* 06.09.10 1.00 Lad Renamed to StormCommon.h */
+/*****************************************************************************/
+
+#ifndef __STORMCOMMON_H__
+#define __STORMCOMMON_H__
+
+//-----------------------------------------------------------------------------
+// Compression support
+
+// Include functions from Pkware Data Compression Library
+#include "pklib/pklib.h"
+
+// Include functions from Huffmann compression
+#include "huffman/huff.h"
+
+// Include functions from IMA ADPCM compression
+#include "adpcm/adpcm.h"
+
+// Include functions from SPARSE compression
+#include "sparse/sparse.h"
+
+// Include functions from LZMA compression
+#include "lzma/C/LzmaEnc.h"
+#include "lzma/C/LzmaDec.h"
+
+// Include functions from zlib
+#ifndef __SYS_ZLIB
+ #include "zlib/zlib.h"
+#else
+ #include <zlib.h>
+#endif
+
+// Include functions from bzlib
+#ifndef __SYS_BZLIB
+ #include "bzip2/bzlib.h"
+#else
+ #include <bzlib.h>
+#endif
+
+//-----------------------------------------------------------------------------
+// Cryptography support
+
+// Headers from LibTomCrypt
+#include "libtomcrypt/src/headers/tomcrypt.h"
+
+// For HashStringJenkins
+#include "jenkins/lookup.h"
+
+//-----------------------------------------------------------------------------
+// StormLib private defines
+
+#define ID_MPQ_FILE 0x46494c45 // Used internally for checking TMPQFile ('FILE')
+
+#define MPQ_WEAK_SIGNATURE_SIZE 64
+#define MPQ_STRONG_SIGNATURE_SIZE 256
+
+// Prevent problems with CRT "min" and "max" functions,
+// as they are not defined on all platforms
+#define STORMLIB_MIN(a, b) ((a < b) ? a : b)
+#define STORMLIB_MAX(a, b) ((a > b) ? a : b)
+
+// Macro for building 64-bit file offset from two 32-bit
+#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | lo)
+
+//-----------------------------------------------------------------------------
+// Memory management
+//
+// We use our own macros for allocating/freeing memory. If you want
+// to redefine them, please keep the following rules
+//
+// - The memory allocation must return NULL if not enough memory
+// (i.e not to throw exception)
+// - It is not necessary to fill the allocated buffer with zeros
+// - Memory freeing function doesn't have to test the pointer to NULL.
+//
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+__inline void * DebugMalloc(char * /* szFile */, int /* nLine */, size_t nSize)
+{
+// return new BYTE[nSize];
+ return HeapAlloc(GetProcessHeap(), 0, nSize);
+}
+
+__inline void DebugFree(void * ptr)
+{
+// delete [] ptr;
+ HeapFree(GetProcessHeap(), 0, ptr);
+}
+
+#define STORM_ALLOC(type, nitems) (type *)DebugMalloc(__FILE__, __LINE__, (nitems) * sizeof(type))
+#define STORM_FREE(ptr) DebugFree(ptr)
+#else
+
+#define STORM_ALLOC(type, nitems) (type *)malloc((nitems) * sizeof(type))
+#define STORM_FREE(ptr) free(ptr)
+
+#endif
+
+//-----------------------------------------------------------------------------
+// StormLib internal global variables
+
+extern LCID lcFileLocale; // Preferred file locale
+
+//-----------------------------------------------------------------------------
+// Encryption and decryption functions
+
+#define MPQ_HASH_TABLE_INDEX 0x000
+#define MPQ_HASH_NAME_A 0x100
+#define MPQ_HASH_NAME_B 0x200
+#define MPQ_HASH_FILE_KEY 0x300
+
+DWORD HashString(const char * szFileName, DWORD dwHashType);
+
+void InitializeMpqCryptography();
+
+DWORD GetHashTableSizeForFileCount(DWORD dwFileCount);
+
+bool IsPseudoFileName(const char * szFileName, LPDWORD pdwFileIndex);
+ULONGLONG HashStringJenkins(const char * szFileName);
+
+int ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
+
+DWORD GetDefaultSpecialFileFlags(TMPQArchive * ha, DWORD dwFileSize);
+
+void EncryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey);
+void DecryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey);
+
+DWORD DetectFileKeyBySectorSize(LPDWORD SectorOffsets, DWORD decrypted);
+DWORD DetectFileKeyByContent(void * pvFileContent, DWORD dwFileSize);
+DWORD DecryptFileKey(const char * szFileName, ULONGLONG MpqPos, DWORD dwFileSize, DWORD dwFlags);
+
+bool IsValidMD5(LPBYTE pbMd5);
+bool VerifyDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5);
+void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_hash);
+
+//-----------------------------------------------------------------------------
+// Handle validation functions
+
+bool IsValidMpqHandle(TMPQArchive * ha);
+bool IsValidFileHandle(TMPQFile * hf);
+
+//-----------------------------------------------------------------------------
+// Hash table and block table manipulation
+
+TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName);
+TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash);
+DWORD AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
+DWORD AllocateHetEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
+
+void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos);
+
+// Functions that loads and verifies MPQ data bitmap
+int LoadMpqDataBitmap(TMPQArchive * ha, ULONGLONG FileSize, bool * pbFileIsComplete);
+
+// Functions that load the HET and BET tables
+int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize);
+int LoadAnyHashTable(TMPQArchive * ha);
+int BuildFileTable(TMPQArchive * ha, ULONGLONG FileSize);
+int SaveMPQTables(TMPQArchive * ha);
+
+TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bCreateEmpty);
+void FreeHetTable(TMPQHetTable * pHetTable);
+
+TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount);
+void FreeBetTable(TMPQBetTable * pBetTable);
+
+// Functions for finding files in the file table
+TFileEntry * GetFileEntryAny(TMPQArchive * ha, const char * szFileName);
+TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
+TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
+TFileEntry * GetFileEntryByIndex(TMPQArchive * ha, DWORD dwIndex);
+
+// Allocates file name in the file entry
+void AllocateFileName(TFileEntry * pFileEntry, const char * szFileName);
+
+// Allocates new file entry in the MPQ tables. Reuses existing, if possible
+TFileEntry * FindFreeFileEntry(TMPQArchive * ha);
+TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
+int RenameFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szNewFileName);
+void ClearFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
+int FreeFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
+
+// Invalidates entries for (listfile) and (attributes)
+void InvalidateInternalFiles(TMPQArchive * ha);
+
+//-----------------------------------------------------------------------------
+// Common functions - MPQ File
+
+TMPQFile * CreateMpqFile(TMPQArchive * ha);
+int LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, void * pvTable, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey);
+int AllocateSectorBuffer(TMPQFile * hf);
+int AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile);
+int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile);
+int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile);
+void CalculateRawSectorOffset(ULONGLONG & RawFilePos, TMPQFile * hf, DWORD dwSectorOffset);
+int WritePatchInfo(TMPQFile * hf);
+int WriteSectorOffsets(TMPQFile * hf);
+int WriteSectorChecksums(TMPQFile * hf);
+int WriteMemDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, void * pvRawData, DWORD dwRawDataSize, DWORD dwChunkSize, LPDWORD pcbTotalSize);
+int WriteMpqDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, DWORD dwRawDataSize, DWORD dwChunkSize);
+void FreeMPQFile(TMPQFile *& hf);
+
+bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize);
+int PatchFileData(TMPQFile * hf);
+
+void FreeMPQArchive(TMPQArchive *& ha);
+
+//-----------------------------------------------------------------------------
+// Utility functions
+
+bool CheckWildCard(const char * szString, const char * szWildCard);
+const char * GetPlainFileNameA(const char * szFileName);
+const TCHAR * GetPlainFileNameT(const TCHAR * szFileName);
+bool IsInternalMpqFileName(const char * szFileName);
+
+//-----------------------------------------------------------------------------
+// Support for adding files to the MPQ
+
+int SFileAddFile_Init(
+ TMPQArchive * ha,
+ const char * szArchivedName,
+ ULONGLONG ft,
+ DWORD dwFileSize,
+ LCID lcLocale,
+ DWORD dwFlags,
+ TMPQFile ** phf
+ );
+
+int SFileAddFile_Write(
+ TMPQFile * hf,
+ const void * pvData,
+ DWORD dwSize,
+ DWORD dwCompression
+ );
+
+int SFileAddFile_Finish(
+ TMPQFile * hf
+ );
+
+//-----------------------------------------------------------------------------
+// Attributes support
+
+int SAttrLoadAttributes(TMPQArchive * ha);
+int SAttrFileSaveToMpq(TMPQArchive * ha);
+
+//-----------------------------------------------------------------------------
+// Listfile functions
+
+int SListFileSaveToMpq(TMPQArchive * ha);
+
+//-----------------------------------------------------------------------------
+// Dump data support
+
+#ifdef __STORMLIB_DUMP_DATA__
+void DumpMpqHeader(TMPQHeader * pHeader);
+void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable);
+
+#else
+#define DumpMpqHeader(h) /* */
+#define DumpHetAndBetTable(h, b) /* */
+#endif
+
+#endif // __STORMCOMMON_H__
+
diff --git a/dep/StormLib/src/StormLib.h b/dep/StormLib/src/StormLib.h
new file mode 100644
index 00000000000..a07ae46ca48
--- /dev/null
+++ b/dep/StormLib/src/StormLib.h
@@ -0,0 +1,984 @@
+/*****************************************************************************/
+/* StormLib.h Copyright (c) Ladislav Zezula 1999-2010 */
+/*---------------------------------------------------------------------------*/
+/* StormLib library v 7.02 */
+/* */
+/* Author : Ladislav Zezula */
+/* E-mail : ladik@zezula.net */
+/* WWW : http://www.zezula.net */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.99 1.00 Lad Created */
+/* 24.03.03 2.50 Lad Version 2.50 */
+/* 02.04.03 3.00 Lad Version 3.00 with compression */
+/* 11.04.03 3.01 Lad Renamed to StormLib.h for compatibility with */
+/* original headers for Storm.dll */
+/* 10.05.03 3.02 Lad Added Pkware DCL compression */
+/* 26.05.03 4.00 Lad Completed all compressions */
+/* 18.06.03 4.01 Lad Added SFileSetFileLocale */
+/* Added SFileExtractFile */
+/* 26.07.03 4.02 Lad Implemented nameless rename and delete */
+/* 26.07.03 4.03 Lad Added support for protected MPQs */
+/* 28.08.03 4.10 Lad Fixed bugs that caused StormLib incorrectly work */
+/* with Diablo I savegames and with files having full */
+/* hash table */
+/* 08.12.03 4.11 DCH Fixed bug in reading file sector larger than 0x1000 */
+/* on certain files. */
+/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */
+/* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/
+/* 21.12.03 4.50 Lad Completed port for Mac */
+/* Fixed bug in compacting (if fsize is mul of 0x1000) */
+/* Fixed bug in SCompCompress */
+/* 27.05.04 4.51 Lad Changed memory management from new/delete to our */
+/* own macros */
+/* 22.06.04 4.60 Lad Optimized search. Support for multiple listfiles. */
+/* 30.09.04 4.61 Lad Fixed some bugs (Aaargh !!!) */
+/* Correctly works if HashTableSize > BlockTableSize */
+/* 29.12.04 4.70 Lad Fixed compatibility problem with MPQs from WoW */
+/* 14.07.05 5.00 Lad Added the BZLIB compression support */
+/* Added suport of files stored as single unit */
+/* 17.04.06 5.01 Lad Converted to MS Visual Studio 8.0 */
+/* Fixed issue with protected Warcraft 3 protected maps */
+/* 15.05.06 5.02 Lad Fixed issue with WoW 1.10+ */
+/* 07.09.06 5.10 Lad Fixed processing files longer than 2GB */
+/* 22.11.06 6.00 Lad Support for MPQ archives V2 */
+/* 12.06.07 6.10 Lad Support for (attributes) file */
+/* 10.09.07 6.12 Lad Support for MPQs protected by corrupting hash table */
+/* 03.12.07 6.13 Lad Support for MPQs with hash tbl size > block tbl size */
+/* 07.04.08 6.20 Lad Added SFileFlushArchive */
+/* 09.04.08 Lad Removed FilePointer variable from MPQ handle */
+/* structure, as it caused more problems than benefits */
+/* 12.05.08 6.22 Lad Support for w3xMaster map protector */
+/* 05.10.08 6.23 Lad Support for protectors who set negative values in */
+/* the table of file blocks */
+/* 26.05.09 6.24 Lad Fixed search for multiple lang files with deleted */
+/* entries */
+/* 03.09.09 6.25 Lad Fixed decompression bug in huffmann decompression */
+/* 22.03.10 6.50 Lad New compressions in Starcraft II (LZMA, sparse) */
+/* Fixed compacting MPQs that contain single unit files */
+/* 26.04.10 7.00 Lad Major rewrite */
+/* 08.06.10 7.10 Lad Support for partial MPQs */
+/* 08.07.10 7.11 Lad Support for MPQs v 3.0 */
+/* 20.08.10 7.20 Lad Support for opening multiple MPQs in patch mode */
+/* 20.09.10 8.00 Lad MPQs v 4, HET and BET tables */
+/* 07.01.11 8.01 Lad Write support for MPQs v 3 and 4 */
+/* 15.09.11 8.04 Lad Bug fixes, testing for Diablo III MPQs */
+/* 26.04.12 8.10 Lad Support for data map, added SFileGetArchiveBitmap */
+/*****************************************************************************/
+
+#ifndef __STORMLIB_H__
+#define __STORMLIB_H__
+
+#ifdef _MSC_VER
+#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+#pragma warning(disable:4820) // 'XXX' : '2' bytes padding added after data member 'XXX::yyy'
+#endif
+
+#include "StormPort.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//-----------------------------------------------------------------------------
+// Use the apropriate library
+//
+// The library type is encoded in the library name as the following
+// StormLibXYZ.lib
+//
+// X - D for Debug version, R for Release version
+// Y - A for ANSI version, U for Unicode version
+// Z - S for static-linked CRT library, D for multithreaded DLL CRT library
+//
+
+#if 0 && defined(_MSC_VER) && !defined(__STORMLIB_SELF__)
+
+ #ifdef _DEBUG // DEBUG VERSIONS
+ #ifndef _UNICODE
+ #ifdef _DLL
+ #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version
+ #else
+ #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version
+ #endif
+ #else
+ #ifdef _DLL
+ #pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version
+ #else
+ #pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version
+ #endif
+ #endif
+ #else // RELEASE VERSIONS
+ #ifndef _UNICODE
+ #ifdef _DLL
+ #pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version
+ #else
+ #pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version
+ #endif
+ #else
+ #ifdef _DLL
+ #pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version
+ #else
+ #pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version
+ #endif
+ #endif
+ #endif
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
+#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B')
+
+#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file.
+#define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by SFileReadFile when can't find file key
+#define ERROR_CHECKSUM_ERROR 10002 // Returned by SFileReadFile when sector CRC doesn't match
+#define ERROR_INTERNAL_FILE 10003 // The given operation is not allowed on internal file
+#define ERROR_BASE_FILE_MISSING 10004 // The file is present as incremental patch file, but base file is missing
+#define ERROR_MARKED_FOR_DELETE 10005 // The file was marked as "deleted" in the MPQ
+
+// Values for SFileCreateArchive
+#define HASH_TABLE_SIZE_MIN 0x00000004 // Minimum acceptable hash table size
+#define HASH_TABLE_SIZE_DEFAULT 0x00001000 // Default hash table size for empty MPQs
+#define HASH_TABLE_SIZE_MAX 0x00080000 // Maximum acceptable hash table size
+
+#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted entry in the hash table
+#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free entry in the hash table
+
+#define HET_ENTRY_DELETED 0x80 // HET hash value for a deleted entry
+#define HET_ENTRY_FREE 0x00 // HET hash value for free entry
+
+#define HASH_STATE_SIZE 0x60 // Size of LibTomCrypt's hash_state structure
+
+#define MPQ_PATCH_PREFIX_LEN 0x20 // Maximum length of the patch prefix
+
+// Values for SFileOpenArchive
+#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD
+#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM
+
+// Values for SFileOpenFile
+#define SFILE_OPEN_FROM_MPQ 0x00000000 // Open the file from the MPQ archive
+#define SFILE_OPEN_PATCHED_FILE 0x00000001 // Open the file from the MPQ archive
+#define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use
+#define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file
+
+// Flags for TMPQArchive::dwFlags
+#define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access
+#define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed
+#define MPQ_FLAG_PROTECTED 0x00000004 // Set on protected MPQs (like W3M maps)
+#define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000008 // Checking sector CRC when reading files
+#define MPQ_FLAG_NEED_FIX_SIZE 0x00000010 // Used during opening the archive
+#define MPQ_FLAG_INV_LISTFILE 0x00000020 // If set, it means that the (listfile) has been invalidated
+#define MPQ_FLAG_INV_ATTRIBUTES 0x00000040 // If set, it means that the (attributes) has been invalidated
+
+// Return value for SFileGetFileSize and SFileSetFilePointer
+#define SFILE_INVALID_SIZE 0xFFFFFFFF
+#define SFILE_INVALID_POS 0xFFFFFFFF
+#define SFILE_INVALID_ATTRIBUTES 0xFFFFFFFF
+
+// Flags for SFileAddFile
+#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library)
+#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods)
+#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed
+#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
+#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed
+#define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure
+#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam)
+#define MPQ_FILE_DELETE_MARKER 0x02000000 // File is a deletion marker. Used in MPQ patches, indicating that the file no longer exists.
+#define MPQ_FILE_SECTOR_CRC 0x04000000 // File has checksums for each sector.
+ // Ignored if file is not compressed or imploded.
+#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted
+#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile)
+
+#define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \
+ MPQ_FILE_COMPRESS | \
+ MPQ_FILE_ENCRYPTED | \
+ MPQ_FILE_FIX_KEY | \
+ MPQ_FILE_PATCH_FILE | \
+ MPQ_FILE_SINGLE_UNIT | \
+ MPQ_FILE_DELETE_MARKER | \
+ MPQ_FILE_SECTOR_CRC | \
+ MPQ_FILE_EXISTS)
+
+// Compression types for multiple compressions
+#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)
+#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression
+#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression
+#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression (added in Warcraft III)
+#define MPQ_COMPRESSION_SPARSE 0x20 // Sparse compression (added in Starcraft 2)
+#define MPQ_COMPRESSION_ADPCM_MONO 0x40 // IMA ADPCM compression (mono)
+#define MPQ_COMPRESSION_ADPCM_STEREO 0x80 // IMA ADPCM compression (stereo)
+#define MPQ_COMPRESSION_LZMA 0x12 // LZMA compression. Added in Starcraft 2. This value is NOT a combination of flags.
+#define MPQ_COMPRESSION_NEXT_SAME 0xFFFFFFFF // Same compression
+
+// Constants for SFileAddWave
+#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression
+#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression
+#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression
+
+// Signatures for HET and BET table
+#define HET_TABLE_SIGNATURE 0x1A544548 // 'HET\x1a'
+#define BET_TABLE_SIGNATURE 0x1A544542 // 'BET\x1a'
+
+// Decryption keys for MPQ tables
+#define MPQ_KEY_HASH_TABLE 0xC3AF3770 // Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY)
+#define MPQ_KEY_BLOCK_TABLE 0xEC83B3A3 // Obtained by HashString("(block table)", MPQ_HASH_FILE_KEY)
+
+// Block map defines
+#define MPQ_DATA_BITMAP_SIGNATURE 0x33767470 // Signature of the MPQ data bitmap ('ptv3')
+
+// Constants for SFileGetFileInfo
+#define SFILE_INFO_ARCHIVE_NAME 1 // MPQ size (value from header)
+#define SFILE_INFO_ARCHIVE_SIZE 2 // MPQ size (value from header)
+#define SFILE_INFO_MAX_FILE_COUNT 3 // Max number of files in the MPQ
+#define SFILE_INFO_HASH_TABLE_SIZE 4 // Size of hash table, in entries
+#define SFILE_INFO_BLOCK_TABLE_SIZE 5 // Number of entries in the block table
+#define SFILE_INFO_SECTOR_SIZE 6 // Size of file sector (in bytes)
+#define SFILE_INFO_HASH_TABLE 7 // Pointer to Hash table (TMPQHash *)
+#define SFILE_INFO_BLOCK_TABLE 8 // Pointer to Block Table (TMPQBlock *)
+#define SFILE_INFO_NUM_FILES 9 // Real number of files within archive
+#define SFILE_INFO_STREAM_FLAGS 10 // Stream flags for the MPQ. See STREAM_FLAG_XXX
+#define SFILE_INFO_IS_READ_ONLY 11 // TRUE of the MPQ was open as read only
+//------
+#define SFILE_INFO_HASH_INDEX 100 // Hash index of file in MPQ
+#define SFILE_INFO_CODENAME1 101 // The first codename of the file
+#define SFILE_INFO_CODENAME2 102 // The second codename of the file
+#define SFILE_INFO_LOCALEID 103 // Locale ID of file in MPQ
+#define SFILE_INFO_BLOCKINDEX 104 // Index to Block Table
+#define SFILE_INFO_FILE_SIZE 105 // Original file size (from the block table)
+#define SFILE_INFO_COMPRESSED_SIZE 106 // Compressed file size (from the block table)
+#define SFILE_INFO_FLAGS 107 // File flags
+#define SFILE_INFO_POSITION 108 // File position within archive
+#define SFILE_INFO_KEY 109 // File decryption key
+#define SFILE_INFO_KEY_UNFIXED 110 // Decryption key not fixed to file pos and size
+#define SFILE_INFO_FILETIME 111 // TMPQFileTime
+#define SFILE_INFO_PATCH_CHAIN 112 // Chain of patches
+
+#define LISTFILE_NAME "(listfile)" // Name of internal listfile
+#define SIGNATURE_NAME "(signature)" // Name of internal signature
+#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file
+#define PATCH_METADATA_NAME "(patch_metadata)"
+
+#define STORMLIB_VERSION 0x080A // Current version of StormLib (8.10)
+#define STORMLIB_VERSION_STRING "8.10"
+
+#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade
+#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
+#define MPQ_FORMAT_VERSION_3 2 // WoW Cataclysm Beta
+#define MPQ_FORMAT_VERSION_4 3 // WoW Cataclysm and newer
+
+// Flags for MPQ attributes
+#define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contains CRC32 for each file
+#define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contains file time for each file
+#define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contains MD5 for each file
+#define MPQ_ATTRIBUTE_PATCH_BIT 0x00000008 // The "(attributes)" contains a patch bit for each file
+#define MPQ_ATTRIBUTE_ALL 0x0000000F // Summary mask
+
+#define MPQ_ATTRIBUTES_V1 100 // (attributes) format version 1.00
+
+// Flags for SFileOpenArchive
+#define BASE_PROVIDER_FILE 0x00000000 // Base data source is a file
+#define BASE_PROVIDER_MAP 0x00000001 // Base data source is memory-mapped file
+#define BASE_PROVIDER_HTTP 0x00000002 // Base data source is a file on web server
+#define BASE_PROVIDER_MASK 0x0000000F // Mask for base provider value
+
+#define STREAM_PROVIDER_LINEAR 0x00000000 // Stream is linear with no offset mapping
+#define STREAM_PROVIDER_PARTIAL 0x00000010 // Stream is partial file (.part)
+#define STREAM_PROVIDER_ENCRYPTED 0x00000020 // Stream is an encrypted MPQ
+#define STREAM_PROVIDER_MASK 0x000000F0 // Mask for stream provider value
+
+#define STREAM_FLAG_READ_ONLY 0x00000100 // Stream is read only
+#define STREAM_FLAG_WRITE_SHARE 0x00000200 // Allow write sharing when open for write
+#define STREAM_FLAG_MASK 0x0000FF00 // Mask for stream flags
+#define STREAM_OPTIONS_MASK 0x0000FFFF // Mask for all stream options
+
+#define MPQ_OPEN_NO_LISTFILE 0x00010000 // Don't load the internal listfile
+#define MPQ_OPEN_NO_ATTRIBUTES 0x00020000 // Don't open the attributes
+#define MPQ_OPEN_FORCE_MPQ_V1 0x00040000 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header
+#define MPQ_OPEN_CHECK_SECTOR_CRC 0x00080000 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file
+
+// Deprecated
+#define MPQ_OPEN_READ_ONLY STREAM_FLAG_READ_ONLY
+#define MPQ_OPEN_ENCRYPTED STREAM_PROVIDER_ENCRYPTED
+
+// Flags for SFileCreateArchive
+#define MPQ_CREATE_ATTRIBUTES 0x00100000 // Also add the (attributes) file
+#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive of version 1 (size up to 4GB)
+#define MPQ_CREATE_ARCHIVE_V2 0x01000000 // Creates archive of version 2 (larger than 4 GB)
+#define MPQ_CREATE_ARCHIVE_V3 0x02000000 // Creates archive of version 3
+#define MPQ_CREATE_ARCHIVE_V4 0x03000000 // Creates archive of version 4
+#define MPQ_CREATE_ARCHIVE_VMASK 0x0F000000 // Mask for archive version
+
+#define FLAGS_TO_FORMAT_SHIFT 24 // (MPQ_CREATE_ARCHIVE_V4 >> FLAGS_TO_FORMAT_SHIFT) => MPQ_FORMAT_VERSION_4
+
+// Flags for SFileVerifyFile
+#define SFILE_VERIFY_SECTOR_CRC 0x00000001 // Verify sector checksum for the file, if available
+#define SFILE_VERIFY_FILE_CRC 0x00000002 // Verify file CRC, if available
+#define SFILE_VERIFY_FILE_MD5 0x00000004 // Verify file MD5, if available
+#define SFILE_VERIFY_RAW_MD5 0x00000008 // Verify raw file MD5, if available
+#define SFILE_VERIFY_ALL 0x0000000F // Verify every checksum possible
+
+// Return values for SFileVerifyFile
+#define VERIFY_OPEN_ERROR 0x0001 // Failed to open the file
+#define VERIFY_READ_ERROR 0x0002 // Failed to read all data from the file
+#define VERIFY_FILE_HAS_SECTOR_CRC 0x0004 // File has sector CRC
+#define VERIFY_FILE_SECTOR_CRC_ERROR 0x0008 // Sector CRC check failed
+#define VERIFY_FILE_HAS_CHECKSUM 0x0010 // File has CRC32
+#define VERIFY_FILE_CHECKSUM_ERROR 0x0020 // CRC32 check failed
+#define VERIFY_FILE_HAS_MD5 0x0040 // File has data MD5
+#define VERIFY_FILE_MD5_ERROR 0x0080 // MD5 check failed
+#define VERIFY_FILE_HAS_RAW_MD5 0x0100 // File has raw data MD5
+#define VERIFY_FILE_RAW_MD5_ERROR 0x0200 // Raw MD5 check failed
+#define VERIFY_FILE_ERROR_MASK (VERIFY_OPEN_ERROR | VERIFY_READ_ERROR | VERIFY_FILE_SECTOR_CRC_ERROR | VERIFY_FILE_CHECKSUM_ERROR | VERIFY_FILE_MD5_ERROR | VERIFY_FILE_RAW_MD5_ERROR)
+
+// Flags for SFileVerifyRawData (for MPQs version 4.0 or higher)
+#define SFILE_VERIFY_MPQ_HEADER 0x0001 // Verify raw MPQ header
+#define SFILE_VERIFY_HET_TABLE 0x0002 // Verify raw data of the HET table
+#define SFILE_VERIFY_BET_TABLE 0x0003 // Verify raw data of the BET table
+#define SFILE_VERIFY_HASH_TABLE 0x0004 // Verify raw data of the hash table
+#define SFILE_VERIFY_BLOCK_TABLE 0x0005 // Verify raw data of the block table
+#define SFILE_VERIFY_HIBLOCK_TABLE 0x0006 // Verify raw data of the hi-block table
+#define SFILE_VERIFY_FILE 0x0007 // Verify raw data of a file
+
+// Return values for SFileVerifyArchive
+#define ERROR_NO_SIGNATURE 0 // There is no signature in the MPQ
+#define ERROR_VERIFY_FAILED 1 // There was an error during verifying signature (like no memory)
+#define ERROR_WEAK_SIGNATURE_OK 2 // There is a weak signature and sign check passed
+#define ERROR_WEAK_SIGNATURE_ERROR 3 // There is a weak signature but sign check failed
+#define ERROR_STRONG_SIGNATURE_OK 4 // There is a strong signature and sign check passed
+#define ERROR_STRONG_SIGNATURE_ERROR 5 // There is a strong signature but sign check failed
+
+#ifndef MD5_DIGEST_SIZE
+#define MD5_DIGEST_SIZE 0x10
+#endif
+
+#ifndef SHA1_DIGEST_SIZE
+#define SHA1_DIGEST_SIZE 0x14 // 160 bits
+#endif
+
+#ifndef LANG_NEUTRAL
+#define LANG_NEUTRAL 0x00 // Neutral locale
+#endif
+
+//-----------------------------------------------------------------------------
+// Callback functions
+
+// Values for compact callback
+#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total)
+#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total)
+#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used
+#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total)
+#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used
+
+typedef void (WINAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesWritten, DWORD dwTotalBytes, bool bFinalCall);
+typedef void (WINAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes);
+
+struct TFileStream;
+
+//-----------------------------------------------------------------------------
+// Structure for bit arrays used for HET and BET tables
+
+struct TBitArray
+{
+ void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
+ void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
+
+ DWORD NumberOfBits; // Total number of bits that are available
+ BYTE Elements[1]; // Array of elements (variable length)
+};
+
+// Structure for file bitmap. Used by SFileGetArchiveBitmap
+struct TFileBitmap
+{
+ ULONGLONG StartOffset; // Starting offset of the file, covered by bitmap
+ ULONGLONG EndOffset; // Ending offset of the file, covered by bitmap
+ DWORD IsComplete; // If nonzero, no blocks are missing
+ DWORD BitmapSize; // Size of the file bitmap (in bytes)
+ DWORD BlockSize; // Size of one block, in bytes
+ DWORD Reserved; // Alignment
+
+ // Followed by file bitmap (variable length), array of BYTEs)
+};
+
+//-----------------------------------------------------------------------------
+// Structures related to MPQ format
+//
+// Note: All structures in this header file are supposed to remain private
+// to StormLib. The structures may (and will) change over time, as the MPQ
+// file format evolves. Programmers directly using these structures need to
+// be aware of this. And the last, but not least, NEVER do any modifications
+// to those structures directly, always use SFile* functions.
+//
+
+#define MPQ_HEADER_SIZE_V1 0x20
+#define MPQ_HEADER_SIZE_V2 0x2C
+#define MPQ_HEADER_SIZE_V3 0x44
+#define MPQ_HEADER_SIZE_V4 0xD0
+
+struct TMPQUserData
+{
+ // The ID_MPQ_USERDATA ('MPQ\x1B') signature
+ DWORD dwID;
+
+ // Maximum size of the user data
+ DWORD cbUserDataSize;
+
+ // Offset of the MPQ header, relative to the begin of this header
+ DWORD dwHeaderOffs;
+
+ // Appears to be size of user data header (Starcraft II maps)
+ DWORD cbUserDataHeader;
+};
+
+// MPQ file header
+//
+// We have to make sure that the header is packed OK.
+// Reason: A 64-bit integer at the beginning of 3.0 part,
+// which is offset 0x2C
+#pragma pack(push, 1)
+struct TMPQHeader
+{
+ // The ID_MPQ ('MPQ\x1A') signature
+ DWORD dwID;
+
+ // Size of the archive header
+ DWORD dwHeaderSize;
+
+ // 32-bit size of MPQ archive
+ // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive
+ // is calculated as the size from the beginning of the archive to the end of the hash table,
+ // block table, or hi-block table (whichever is largest).
+ DWORD dwArchiveSize;
+
+ // 0 = Format 1 (up to The Burning Crusade)
+ // 1 = Format 2 (The Burning Crusade and newer)
+ // 2 = Format 3 (WoW - Cataclysm beta or newer)
+ // 3 = Format 4 (WoW - Cataclysm beta or newer)
+ USHORT wFormatVersion;
+
+ // Power of two exponent specifying the number of 512-byte disk sectors in each file sector
+ // in the archive. The size of each file sector in the archive is 512 * 2 ^ wSectorSize.
+ USHORT wSectorSize;
+
+ // Offset to the beginning of the hash table, relative to the beginning of the archive.
+ DWORD dwHashTablePos;
+
+ // Offset to the beginning of the block table, relative to the beginning of the archive.
+ DWORD dwBlockTablePos;
+
+ // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
+ // the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
+ DWORD dwHashTableSize;
+
+ // Number of entries in the block table
+ DWORD dwBlockTableSize;
+
+ //-- MPQ HEADER v 2 -------------------------------------------
+
+ // Offset to the beginning of array of 16-bit high parts of file offsets.
+ ULONGLONG HiBlockTablePos64;
+
+ // High 16 bits of the hash table offset for large archives.
+ USHORT wHashTablePosHi;
+
+ // High 16 bits of the block table offset for large archives.
+ USHORT wBlockTablePosHi;
+
+ //-- MPQ HEADER v 3 -------------------------------------------
+
+ // 64-bit version of the archive size
+ ULONGLONG ArchiveSize64;
+
+ // 64-bit position of the BET table
+ ULONGLONG BetTablePos64;
+
+ // 64-bit position of the HET table
+ ULONGLONG HetTablePos64;
+
+ //-- MPQ HEADER v 4 -------------------------------------------
+
+ // Compressed size of the hash table
+ ULONGLONG HashTableSize64;
+
+ // Compressed size of the block table
+ ULONGLONG BlockTableSize64;
+
+ // Compressed size of the hi-block table
+ ULONGLONG HiBlockTableSize64;
+
+ // Compressed size of the HET block
+ ULONGLONG HetTableSize64;
+
+ // Compressed size of the BET block
+ ULONGLONG BetTableSize64;
+
+ // Size of raw data chunk to calculate MD5.
+ // MD5 of each data chunk follows the raw file data.
+ DWORD dwRawChunkSize;
+
+ // MD5 of MPQ tables
+ unsigned char MD5_BlockTable[MD5_DIGEST_SIZE]; // MD5 of the block table before decryption
+ unsigned char MD5_HashTable[MD5_DIGEST_SIZE]; // MD5 of the hash table before decryption
+ unsigned char MD5_HiBlockTable[MD5_DIGEST_SIZE]; // MD5 of the hi-block table
+ unsigned char MD5_BetTable[MD5_DIGEST_SIZE]; // MD5 of the BET table before decryption
+ unsigned char MD5_HetTable[MD5_DIGEST_SIZE]; // MD5 of the HET table before decryption
+ unsigned char MD5_MpqHeader[MD5_DIGEST_SIZE]; // MD5 of the MPQ header from signature to (including) MD5_HetTable
+};
+#pragma pack(pop)
+
+
+// Hash entry. All files in the archive are searched by their hashes.
+struct TMPQHash
+{
+ // The hash of the file path, using method A.
+ DWORD dwName1;
+
+ // The hash of the file path, using method B.
+ DWORD dwName2;
+
+#ifdef PLATFORM_LITTLE_ENDIAN
+
+ // The language of the file. This is a Windows LANGID data type, and uses the same values.
+ // 0 indicates the default language (American English), or that the file is language-neutral.
+ USHORT lcLocale;
+
+ // The platform the file is used for. 0 indicates the default platform.
+ // No other values have been observed.
+ // Note: wPlatform is actually just BYTE, but since it has never been used, we don't care.
+ USHORT wPlatform;
+
+#else
+
+ USHORT wPlatform;
+ USHORT lcLocale;
+
+#endif
+
+ // If the hash table entry is valid, this is the index into the block table of the file.
+ // Otherwise, one of the following two values:
+ // - FFFFFFFFh: Hash table entry is empty, and has always been empty.
+ // Terminates searches for a given file.
+ // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
+ // Does not terminate searches for a given file.
+ DWORD dwBlockIndex;
+};
+
+
+// File description block contains informations about the file
+struct TMPQBlock
+{
+ // Offset of the beginning of the file, relative to the beginning of the archive.
+ DWORD dwFilePos;
+
+ // Compressed file size
+ DWORD dwCSize;
+
+ // Only valid if the block is a file; otherwise meaningless, and should be 0.
+ // If the file is compressed, this is the size of the uncompressed file data.
+ DWORD dwFSize;
+
+ // Flags for the file. See MPQ_FILE_XXXX constants
+ DWORD dwFlags;
+};
+
+// Patch file information, preceding the sector offset table
+struct TPatchInfo
+{
+ DWORD dwLength; // Length of patch info header, in bytes
+ DWORD dwFlags; // Flags. 0x80000000 = MD5 (?)
+ DWORD dwDataSize; // Uncompressed size of the patch file
+ BYTE md5[0x10]; // MD5 of the entire patch file after decompression
+
+ // Followed by the sector table (variable length)
+};
+
+// Header for PTCH files
+struct TPatchHeader
+{
+ //-- PATCH header -----------------------------------
+ DWORD dwSignature; // 'PTCH'
+ DWORD dwSizeOfPatchData; // Size of the entire patch (decompressed)
+ DWORD dwSizeBeforePatch; // Size of the file before patch
+ DWORD dwSizeAfterPatch; // Size of file after patch
+
+ //-- MD5 block --------------------------------------
+ DWORD dwMD5; // 'MD5_'
+ DWORD dwMd5BlockSize; // Size of the MD5 block, including the signature and size itself
+ BYTE md5_before_patch[0x10]; // MD5 of the original (unpached) file
+ BYTE md5_after_patch[0x10]; // MD5 of the patched file
+
+ //-- XFRM block -------------------------------------
+ DWORD dwXFRM; // 'XFRM'
+ DWORD dwXfrmBlockSize; // Size of the XFRM block, includes XFRM header and patch data
+ DWORD dwPatchType; // Type of patch ('BSD0' or 'COPY')
+
+ // Followed by the patch data
+};
+
+#define SIZE_OF_XFRM_HEADER 0x0C
+
+// This is the combined file entry for maintaining file list in the MPQ.
+// This structure is combined from block table, hi-block table,
+// (attributes) file and from (listfile).
+struct TFileEntry
+{
+ ULONGLONG ByteOffset; // Position of the file content in the MPQ, relative to the MPQ header
+ ULONGLONG FileTime; // FileTime from the (attributes) file. 0 if not present.
+ ULONGLONG BetHash; // Lower part of the file name hash. Only used when the MPQ has BET table.
+ DWORD dwHashIndex; // Index to the hash table. Only used when the MPQ has classic hash table
+ DWORD dwHetIndex; // Index to the HET table. Only used when the MPQ has HET table
+ DWORD dwFileSize; // Decompressed size of the file
+ DWORD dwCmpSize; // Compressed size of the file (i.e., size of the file data in the MPQ)
+ DWORD dwFlags; // File flags (from block table)
+ USHORT lcLocale; // Locale ID for the file
+ USHORT wPlatform; // Platform ID for the file
+ DWORD dwCrc32; // CRC32 from (attributes) file. 0 if not present.
+ unsigned char md5[MD5_DIGEST_SIZE]; // File MD5 from the (attributes) file. 0 if not present.
+ char * szFileName; // File name. NULL if not known.
+};
+
+// Common header for HET and BET tables
+struct TMPQExtTable
+{
+ DWORD dwSignature; // 'HET\x1A' or 'BET\x1A'
+ DWORD dwVersion; // Version. Seems to be always 1
+ DWORD dwDataSize; // Size of the contained table
+
+ // Followed by the table header
+ // Followed by the table data
+
+};
+
+//
+// MPQ data bitmap, can be found at (FileSize - sizeof(TMPQBlockMap))
+//
+// There is bit map of the entire MPQ before TMPQBitmap. Each 0x4000-byte
+// block is represented by one bit (including the last, eventually incomplete block).
+//
+struct TMPQBitmap
+{
+ DWORD dwSignature; // 'ptv3' (MPQ_BLOCK_MAP_SIGNATURE)
+ DWORD dwAlways3; // Unknown, seems to always have value of 3
+ DWORD dwBuildNumber; // Game build number for that MPQ
+ DWORD dwMapOffsetLo; // Low 32-bits of the offset of the bit map
+ DWORD dwMapOffsetHi; // High 32-bits of the offset of the bit map
+ DWORD dwBlockSize; // Size of one block (usually 0x4000 bytes)
+};
+
+// Structure for parsed HET table
+struct TMPQHetTable
+{
+ TBitArray * pBetIndexes; // Bit array of indexes to BET tables
+ LPBYTE pHetHashes; // Array of HET hashes. Each entry has size of 1 byte
+ ULONGLONG AndMask64; // AND mask used for calculating file name hash
+ ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash
+
+ DWORD dwIndexSizeTotal; // Total size of one entry in pBetIndexes (in bits)
+ DWORD dwIndexSizeExtra; // Extra bits in the entry in pBetIndexes
+ DWORD dwIndexSize; // Effective size of one entry in pBetIndexes (in bits)
+ DWORD dwMaxFileCount; // Maximum number of files in the MPQ
+ DWORD dwHashTableSize; // Number of entries in pBetHashes
+ DWORD dwHashBitSize; // Effective number of bits in the hash
+};
+
+// Structure for parsed BET table
+struct TMPQBetTable
+{
+ TBitArray * pBetHashes; // Array of BET hashes
+ TBitArray * pFileTable; // Bit-based file table
+ LPDWORD pFileFlags; // Array of file flags
+
+ DWORD dwTableEntrySize; // Size of one table entry, in bits
+ DWORD dwBitIndex_FilePos; // Bit index of the file position in the table entry
+ DWORD dwBitIndex_FileSize; // Bit index of the file size in the table entry
+ DWORD dwBitIndex_CmpSize; // Bit index of the compressed size in the table entry
+ DWORD dwBitIndex_FlagIndex; // Bit index of the flag index in the table entry
+ DWORD dwBitIndex_Unknown; // Bit index of ??? in the table entry
+ DWORD dwBitCount_FilePos; // Size of file offset (in bits) within table entry
+ DWORD dwBitCount_FileSize; // Size of file size (in bits) within table entry
+ DWORD dwBitCount_CmpSize; // Size of compressed file size (in bits) within table entry
+ DWORD dwBitCount_FlagIndex; // Size of flag index (in bits) within table entry
+ DWORD dwBitCount_Unknown; // Size of ??? (in bits) within table entry
+ DWORD dwBetHashSizeTotal; // Total size of bet hash
+ DWORD dwBetHashSizeExtra; // Extra bits in the bet hash
+ DWORD dwBetHashSize; // Effective size of the bet hash
+ DWORD dwFileCount; // Number of files (usually equal to maximum number of files)
+ DWORD dwFlagCount; // Number of entries in pFileFlags
+};
+
+// Archive handle structure
+struct TMPQArchive
+{
+ TFileStream * pStream; // Open stream for the MPQ
+
+ ULONGLONG UserDataPos; // Position of user data (relative to the begin of the file)
+ ULONGLONG MpqPos; // MPQ header offset (relative to the begin of the file)
+
+ TMPQArchive * haPatch; // Pointer to patch archive, if any
+ TMPQArchive * haBase; // Pointer to base ("previous version") archive, if any
+ char szPatchPrefix[MPQ_PATCH_PREFIX_LEN]; // Prefix for file names in patch MPQs
+ size_t cchPatchPrefix; // Length of the patch prefix, in characters
+
+ TMPQUserData * pUserData; // MPQ user data (NULL if not present in the file)
+ TMPQHeader * pHeader; // MPQ file header
+ TMPQBitmap * pBitmap; // MPQ bitmap
+ TMPQHash * pHashTable; // Hash table
+ TMPQHetTable * pHetTable; // Het table
+ TFileEntry * pFileTable; // File table
+
+ TMPQUserData UserData; // MPQ user data. Valid only when ID_MPQ_USERDATA has been found
+ BYTE HeaderData[MPQ_HEADER_SIZE_V4]; // Storage for MPQ header
+
+ DWORD dwHETBlockSize;
+ DWORD dwBETBlockSize;
+ DWORD dwFileTableSize; // Current size of the file table, e.g. index of the entry past the last occupied one
+ DWORD dwMaxFileCount; // Maximum number of files in the MPQ
+ DWORD dwSectorSize; // Default size of one file sector
+ DWORD dwFileFlags1; // Flags for (listfile)
+ DWORD dwFileFlags2; // Flags for (attributes)
+ DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX
+ DWORD dwFlags; // See MPQ_FLAG_XXXXX
+};
+
+// File handle structure
+struct TMPQFile
+{
+ TFileStream * pStream; // File stream. Only used on local files
+ TMPQArchive * ha; // Archive handle
+ TFileEntry * pFileEntry; // File entry for the file
+ DWORD dwFileKey; // Decryption key
+ DWORD dwFilePos; // Current file position
+ ULONGLONG RawFilePos; // Offset in MPQ archive (relative to file begin)
+ ULONGLONG MpqFilePos; // Offset in MPQ archive (relative to MPQ header)
+ DWORD dwMagic; // 'FILE'
+
+ TMPQFile * hfPatchFile; // Pointer to opened patch file
+ TPatchHeader * pPatchHeader; // Patch header. Only used if the file is a patch file
+ LPBYTE pbFileData; // Loaded and patched file data. Only used if the file is a patch file
+ DWORD cbFileData; // Size of loaded patched data
+
+ TPatchInfo * pPatchInfo; // Patch info block, preceding the sector table
+ DWORD * SectorOffsets; // Position of each file sector, relative to the begin of the file. Only for compressed files.
+ DWORD * SectorChksums; // Array of sector checksums (either ADLER32 or MD5) values for each file sector
+ DWORD dwSectorCount; // Number of sectors in the file
+ DWORD dwPatchedFileSize; // Size of patched file. Used when saving patch file to the MPQ
+ DWORD dwDataSize; // Size of data in the file (on patch files, this differs from file size in block table entry)
+
+ LPBYTE pbFileSector; // Last loaded file sector. For single unit files, entire file content
+ DWORD dwSectorOffs; // File position of currently loaded file sector
+ DWORD dwSectorSize; // Size of the file sector. For single unit files, this is equal to the file size
+
+ unsigned char hctx[HASH_STATE_SIZE];// Hash state for MD5. Used when saving file to MPQ
+ DWORD dwCrc32; // CRC32 value, used when saving file to MPQ
+
+ bool bLoadedSectorCRCs; // If true, we already tried to load sector CRCs
+ bool bCheckSectorCRCs; // If true, then SFileReadFile will check sector CRCs when reading the file
+ bool bIsWriteHandle; // If true, this handle has been created by SFileCreateFile
+ bool bErrorOccured; // If true, then at least one error occured during saving the file to the archive
+};
+
+// Structure for SFileFindFirstFile and SFileFindNextFile
+typedef struct _SFILE_FIND_DATA
+{
+ char cFileName[MAX_PATH]; // Full name of the found file
+ char * szPlainName; // Plain name of the found file
+ DWORD dwHashIndex; // Hash table index for the file
+ DWORD dwBlockIndex; // Block table index for the file
+ DWORD dwFileSize; // File size in bytes
+ DWORD dwFileFlags; // MPQ file flags
+ DWORD dwCompSize; // Compressed file size
+ DWORD dwFileTimeLo; // Low 32-bits of the file time (0 if not present)
+ DWORD dwFileTimeHi; // High 32-bits of the file time (0 if not present)
+ LCID lcLocale; // Locale version
+
+} SFILE_FIND_DATA, *PSFILE_FIND_DATA;
+
+typedef struct _SFILE_CREATE_MPQ
+{
+ DWORD cbSize; // Size of this structure, in bytes
+ DWORD dwMpqVersion; // Version of the MPQ to be created
+ void *pvUserData; // Reserved, must be NULL
+ DWORD cbUserData; // Reserved, must be 0
+ DWORD dwStreamFlags; // Stream flags for creating the MPQ
+ DWORD dwFileFlags1; // File flags for (listfile). 0 = default
+ DWORD dwFileFlags2; // File flags for (attributes). 0 = default
+ DWORD dwAttrFlags; // Flags for the (attributes) file. If 0, no attributes will be created
+ DWORD dwSectorSize; // Sector size for compressed files
+ DWORD dwRawChunkSize; // Size of raw data chunk
+ DWORD dwMaxFileCount; // File limit for the MPQ
+
+} SFILE_CREATE_MPQ, *PSFILE_CREATE_MPQ;
+
+//-----------------------------------------------------------------------------
+// Stream support - functions
+
+TFileStream * FileStream_CreateFile(const TCHAR * szFileName, DWORD dwStreamFlags);
+TFileStream * FileStream_OpenFile(const TCHAR * szFileName, DWORD dwStreamFlags);
+TCHAR * FileStream_GetFileName(TFileStream * pStream);
+bool FileStream_IsReadOnly(TFileStream * pStream);
+bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead);
+bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite);
+bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset);
+bool FileStream_SetPos(TFileStream * pStream, ULONGLONG ByteOffset);
+bool FileStream_GetSize(TFileStream * pStream, ULONGLONG & FileSize);
+bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize);
+bool FileStream_GetTime(TFileStream * pStream, ULONGLONG * pFT);
+bool FileStream_Switch(TFileStream * pStream, TFileStream * pTempStream);
+bool FileStream_SetBitmap(TFileStream * pStream, TFileBitmap * pBitmap);
+bool FileStream_GetBitmap(TFileStream * pStream, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded);
+void FileStream_Close(TFileStream * pStream);
+
+//-----------------------------------------------------------------------------
+// Functions prototypes for Storm.dll
+
+// Typedefs for functions exported by Storm.dll
+typedef LCID (WINAPI * SFILESETLOCALE)(LCID);
+typedef bool (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
+typedef bool (WINAPI * SFILECLOSEARCHIVE)(HANDLE);
+typedef bool (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
+typedef bool (WINAPI * SFILECLOSEFILE)(HANDLE);
+typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, LPDWORD);
+typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
+typedef bool (WINAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAPPED);
+
+//-----------------------------------------------------------------------------
+// Functions for manipulation with StormLib global flags
+
+LCID WINAPI SFileGetLocale();
+LCID WINAPI SFileSetLocale(LCID lcNewLocale);
+
+//-----------------------------------------------------------------------------
+// Functions for archive manipulation
+
+bool WINAPI SFileOpenArchive(const TCHAR * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
+bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq);
+bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq);
+
+bool WINAPI SFileGetArchiveBitmap(HANDLE hMpq, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded);
+bool WINAPI SFileFlushArchive(HANDLE hMpq);
+bool WINAPI SFileCloseArchive(HANDLE hMpq);
+
+// Adds another listfile into MPQ. The currently added listfile(s) remain,
+// so you can use this API to combining more listfiles.
+// Note that this function is internally called by SFileFindFirstFile
+int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile);
+
+// Archive compacting
+bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK CompactCB, void * pvData);
+bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile = NULL, bool bReserved = 0);
+
+// Changing the maximum file count
+DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq);
+bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount);
+
+// Changing (attributes) file
+DWORD WINAPI SFileGetAttributes(HANDLE hMpq);
+bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags);
+bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName);
+
+//-----------------------------------------------------------------------------
+// Functions for manipulation with patch archives
+
+bool WINAPI SFileOpenPatchArchive(HANDLE hMpq, const TCHAR * szPatchMpqName, const char * szPatchPathPrefix, DWORD dwFlags);
+bool WINAPI SFileIsPatchedArchive(HANDLE hMpq);
+
+//-----------------------------------------------------------------------------
+// Functions for file manipulation
+
+// Reading from MPQ file
+bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
+DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh = NULL);
+DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod);
+bool WINAPI SFileReadFile(HANDLE hFile, void * lpBuffer, DWORD dwToRead, LPDWORD pdwRead = NULL, LPOVERLAPPED lpOverlapped = NULL);
+bool WINAPI SFileCloseFile(HANDLE hFile);
+
+// Retrieving info about the file
+bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName);
+bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName);
+bool WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded = NULL);
+
+// High-level extract function
+bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ);
+
+//-----------------------------------------------------------------------------
+// Functions for file and archive verification
+
+// Generates file CRC32
+bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5);
+
+// Verifies file against its checksums stored in (attributes) attributes (depending on dwFlags).
+// For dwFlags, use one or more of MPQ_ATTRIBUTE_MD5
+DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
+
+// Verifies raw data of the archive. Only works for MPQs version 4 or newer
+int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName);
+
+// Verifies the signature, if present
+DWORD WINAPI SFileVerifyArchive(HANDLE hMpq);
+
+//-----------------------------------------------------------------------------
+// Functions for file searching
+
+HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile);
+bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
+bool WINAPI SFileFindClose(HANDLE hFind);
+
+HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
+bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
+bool WINAPI SListFileFindClose(HANDLE hFind);
+
+// Locale support
+int WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, LPDWORD pdwMaxLocales, DWORD dwSearchScope);
+
+//-----------------------------------------------------------------------------
+// Support for adding files to the MPQ
+
+bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, HANDLE * phFile);
+bool WINAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression);
+bool WINAPI SFileFinishFile(HANDLE hFile);
+
+bool WINAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = MPQ_COMPRESSION_NEXT_SAME);
+bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags);
+bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
+bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ);
+bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
+bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
+bool WINAPI SFileSetDataCompression(DWORD DataCompression);
+
+bool WINAPI SFileSetAddFileCallback(HANDLE hMpq, SFILE_ADDFILE_CALLBACK AddFileCB, void * pvData);
+
+//-----------------------------------------------------------------------------
+// Compression and decompression
+
+int WINAPI SCompImplode (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
+int WINAPI SCompExplode (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
+int WINAPI SCompCompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel);
+int WINAPI SCompDecompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
+int WINAPI SCompDecompress2(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
+
+//-----------------------------------------------------------------------------
+// Non-Windows support for SetLastError/GetLastError
+
+#ifndef PLATFORM_WINDOWS
+
+void SetLastError(int err);
+int GetLastError();
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Functions from Storm.dll. They use slightly different names for keeping
+// possibility to use them together with StormLib (StormXXX instead of SFileXXX)
+
+#ifdef __LINK_STORM_DLL__
+ #define STORM_ALTERNATE_NAMES // Force storm_dll.h to use alternate fnc names
+ #include "..\storm_dll\storm_dll.h"
+#endif // __LINK_STORM_DLL__
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // __STORMLIB_H__
diff --git a/dep/StormLib/src/StormPort.h b/dep/StormLib/src/StormPort.h
new file mode 100644
index 00000000000..0914654b9af
--- /dev/null
+++ b/dep/StormLib/src/StormPort.h
@@ -0,0 +1,235 @@
+/*****************************************************************************/
+/* StormPort.h Copyright (c) Marko Friedemann 2001 */
+/*---------------------------------------------------------------------------*/
+/* Portability module for the StormLib library. Contains a wrapper symbols */
+/* to make the compilation under Linux work */
+/* */
+/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
+/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
+/* Computer: whiplash.flachland-chemnitz.de */
+/* System: Linux 2.4.0 on i686 */
+/* */
+/* Author: Sam Wilkins <swilkins1337@gmail.com> */
+/* System: Mac OS X and port to big endian processor */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 29.01.01 1.00 Mar Created */
+/* 24.03.03 1.01 Lad Some cosmetic changes */
+/* 12.11.03 1.02 Dan Macintosh compatibility */
+/* 24.07.04 1.03 Sam Mac OS X compatibility */
+/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
+/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
+/*****************************************************************************/
+
+#ifndef __STORMPORT_H__
+#define __STORMPORT_H__
+
+#ifndef __cplusplus
+ #define bool char
+ #define true 1
+ #define false 0
+#endif
+
+// Defines for Windows
+#if !defined(PLATFORM_DEFINED) && (defined(WIN32) || defined(WIN64))
+
+ // In MSVC 8.0, there are some functions declared as deprecated.
+ #if _MSC_VER >= 1400
+ #define _CRT_SECURE_NO_DEPRECATE
+ #define _CRT_NON_CONFORMING_SWPRINTFS
+ #endif
+
+ #include <tchar.h>
+ #include <assert.h>
+ #include <ctype.h>
+ #include <stdio.h>
+ #include <windows.h>
+ #include <wininet.h>
+ #define PLATFORM_LITTLE_ENDIAN
+
+ #ifdef WIN64
+ #define PLATFORM_64BIT
+ #else
+ #define PLATFORM_32BIT
+ #endif
+
+ #define PLATFORM_WINDOWS
+ #define PLATFORM_DEFINED // The platform is known now
+
+#endif
+
+// Defines for Mac
+#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API
+
+ // Macintosh
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <stdlib.h>
+ #include <errno.h>
+
+ #define PKEXPORT
+ #define __SYS_ZLIB
+ #define __SYS_BZLIB
+
+ #ifndef __BIG_ENDIAN__
+ #define PLATFORM_LITTLE_ENDIAN
+ #endif
+
+ #define PLATFORM_MAC
+ #define PLATFORM_DEFINED // The platform is known now
+
+#endif
+
+// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*
+#if !defined(PLATFORM_DEFINED)
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <assert.h>
+ #include <errno.h>
+
+ #define PLATFORM_LITTLE_ENDIAN
+ #define PLATFORM_LINUX
+ #define PLATFORM_DEFINED
+
+#endif
+
+// Definition of Windows-specific structures for non-Windows platforms
+#ifndef PLATFORM_WINDOWS
+ #if __LP64__
+ #define PLATFORM_64BIT
+ #else
+ #define PLATFORM_32BIT
+ #endif
+
+ // Typedefs for ANSI C
+ typedef unsigned char BYTE;
+ typedef unsigned short USHORT;
+ typedef int LONG;
+ typedef unsigned int DWORD;
+ typedef unsigned long DWORD_PTR;
+ typedef long LONG_PTR;
+ typedef long INT_PTR;
+ typedef long long LONGLONG;
+ typedef unsigned long long ULONGLONG;
+ typedef void * HANDLE;
+ typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
+ typedef char TCHAR;
+ typedef unsigned int LCID;
+ typedef LONG * PLONG;
+ typedef DWORD * LPDWORD;
+ typedef BYTE * LPBYTE;
+
+ #ifdef PLATFORM_32BIT
+ #define _LZMA_UINT32_IS_ULONG
+ #endif
+
+ // Some Windows-specific defines
+ #ifndef MAX_PATH
+ #define MAX_PATH 1024
+ #endif
+
+ #define WINAPI
+
+ #define FILE_BEGIN SEEK_SET
+ #define FILE_CURRENT SEEK_CUR
+ #define FILE_END SEEK_END
+
+ #define _T(x) x
+ #define _tcslen strlen
+ #define _tcscpy strcpy
+ #define _tcscat strcat
+ #define _tcsrchr strrchr
+ #define _tprintf printf
+ #define _stprintf sprintf
+ #define _tremove remove
+
+ #define _stricmp strcasecmp
+ #define _strnicmp strncasecmp
+ #define _tcsnicmp strncasecmp
+
+#endif // !WIN32
+
+// 64-bit calls are supplied by "normal" calls on Mac
+#if defined(PLATFORM_MAC)
+ #define stat64 stat
+ #define fstat64 fstat
+ #define lseek64 lseek
+ #define off64_t off_t
+ #define O_LARGEFILE 0
+#endif
+
+// Platform-specific error codes for UNIX-based platforms
+#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
+ #define ERROR_SUCCESS 0
+ #define ERROR_FILE_NOT_FOUND ENOENT
+ #define ERROR_ACCESS_DENIED EPERM
+ #define ERROR_INVALID_HANDLE EBADF
+ #define ERROR_NOT_ENOUGH_MEMORY ENOMEM
+ #define ERROR_BAD_FORMAT 105 // No such error code under Linux
+ #define ERROR_NO_MORE_FILES 106
+ #define ERROR_HANDLE_EOF 107 // No such error code under Linux
+ #define ERROR_NOT_SUPPORTED ENOTSUP
+ #define ERROR_INVALID_PARAMETER EINVAL
+ #define ERROR_DISK_FULL ENOSPC
+ #define ERROR_ALREADY_EXISTS EEXIST
+ #define ERROR_CAN_NOT_COMPLETE 108 // No such error code under Linux
+ #define ERROR_FILE_CORRUPT 109 // No such error code under Linux
+ #define ERROR_INSUFFICIENT_BUFFER ENOBUFS
+#endif
+
+#ifdef PLATFORM_LITTLE_ENDIAN
+ #define BSWAP_INT16_UNSIGNED(a) (a)
+ #define BSWAP_INT16_SIGNED(a) (a)
+ #define BSWAP_INT32_UNSIGNED(a) (a)
+ #define BSWAP_INT32_SIGNED(a) (a)
+ #define BSWAP_INT64_SIGNED(a) (a)
+ #define BSWAP_INT64_UNSIGNED(a) (a)
+ #define BSWAP_ARRAY16_UNSIGNED(a,b) {}
+ #define BSWAP_ARRAY32_UNSIGNED(a,b) {}
+ #define BSWAP_ARRAY64_UNSIGNED(a,b) {}
+ #define BSWAP_PART_HEADER(a) {}
+ #define BSWAP_TMPQUSERDATA(a) {}
+ #define BSWAP_TMPQHEADER(a) {}
+#else
+ int16_t SwapInt16(uint16_t);
+ uint16_t SwapUInt16(uint16_t);
+ int32_t SwapInt32(uint32_t);
+ uint32_t SwapUInt32(uint32_t);
+ int64_t SwapInt64(uint64_t);
+ uint64_t SwapUInt64(uint64_t);
+ void ConvertUInt16Buffer(void * ptr, size_t length);
+ void ConvertUInt32Buffer(void * ptr, size_t length);
+ void ConvertUInt64Buffer(void * ptr, size_t length);
+ void ConvertPartHeader(void * partHeader);
+ void ConvertTMPQUserData(void *userData);
+ void ConvertTMPQHeader(void *header);
+ #define BSWAP_INT16_SIGNED(a) SwapInt16((a))
+ #define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
+ #define BSWAP_INT32_SIGNED(a) SwapInt32((a))
+ #define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
+ #define BSWAP_INT64_SIGNED(a) SwapInt64((a))
+ #define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
+ #define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
+ #define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
+ #define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
+ #define BSWAP_PART_HEADER(a) ConvertPartHeader(a)
+ #define BSWAP_TMPQUSERDATA(a) ConvertTMPQUserData((a))
+ #define BSWAP_TMPQHEADER(a) ConvertTMPQHeader((a))
+#endif
+
+#endif // __STORMPORT_H__
diff --git a/dep/StormLib/src/adpcm/adpcm.cpp b/dep/StormLib/src/adpcm/adpcm.cpp
new file mode 100644
index 00000000000..916fa3811a8
--- /dev/null
+++ b/dep/StormLib/src/adpcm/adpcm.cpp
@@ -0,0 +1,358 @@
+/*****************************************************************************/
+/* adpcm.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains implementation of adpcm decompression method used by */
+/* Storm.dll to decompress WAVE files. Thanks to Tom Amigo for releasing */
+/* his sources. */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
+/* 20.05.03 2.00 Lad Added compression */
+/* 19.11.03 2.01 Dan Big endian handling */
+/*****************************************************************************/
+
+#include "adpcm.h"
+
+//------------------------------------------------------------------------------
+// Structures
+
+typedef union _BYTE_AND_WORD_PTR
+{
+ short * pw;
+ unsigned char * pb;
+} BYTE_AND_WORD_PTR;
+
+typedef union _WORD_AND_BYTE_ARRAY
+{
+ short w;
+ unsigned char b[2];
+} WORD_AND_BYTE_ARRAY;
+
+//-----------------------------------------------------------------------------
+// Tables necessary dor decompression
+
+static long Table1503F120[] =
+{
+ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
+};
+
+static long step_table[] =
+{
+ 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
+ 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
+ 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
+ 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
+ 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
+ 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
+ 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
+ 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
+ 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
+ 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
+ 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
+ 0x00007FFF
+};
+
+//----------------------------------------------------------------------------
+// CompressWave
+
+// 1500EF70
+int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel)
+// ECX EDX
+{
+ WORD_AND_BYTE_ARRAY Wcmp;
+ BYTE_AND_WORD_PTR out; // Pointer to the output buffer
+ long SInt32Array1[2];
+ long SInt32Array2[2];
+ long SInt32Array3[2];
+ long nBytesRemains = dwOutLength; // Number of bytes remaining
+ long nWordsRemains; // Number of words remaining
+// unsigned char * pbSaveOutBuffer; // Copy of output buffer (actually not used)
+ unsigned long dwBitBuff;
+ unsigned long dwStopBit;
+ unsigned long dwBit;
+ unsigned long ebx;
+ unsigned long esi;
+ long nTableValue;
+ long nOneWord;
+ long var_1C;
+ long var_2C;
+ int nLength;
+ int nIndex;
+ int nValue;
+ int i, chnl;
+
+ // If less than 2 bytes remain, don't decompress anything
+// pbSaveOutBuffer = pbOutBuffer;
+ out.pb = pbOutBuffer;
+ if(nBytesRemains < 2)
+ return 2;
+
+ Wcmp.b[1] = (unsigned char)(nCmpLevel - 1);
+ Wcmp.b[0] = (unsigned char)0;
+
+ *out.pw++ = BSWAP_INT16_SIGNED(Wcmp.w);
+ if((out.pb - pbOutBuffer + (nChannels * 2)) > nBytesRemains)
+ return (int)(out.pb - pbOutBuffer + (nChannels * 2));
+
+ SInt32Array1[0] = SInt32Array1[1] = 0x2C;
+
+ for(i = 0; i < nChannels; i++)
+ {
+ nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++);
+ *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
+ SInt32Array2[i] = nOneWord;
+ }
+
+ // Weird. But it's there
+ nLength = dwInLength;
+ if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx;
+ nLength++;
+
+ nLength = (nLength / 2) - (int)(out.pb - pbOutBuffer);
+ nLength = (nLength < 0) ? 0 : nLength;
+
+ nIndex = nChannels - 1; // edi
+ nWordsRemains = dwInLength / 2; // eax
+
+ // ebx - nChannels
+ // ecx - pwOutPos
+ for(chnl = nChannels; chnl < nWordsRemains; chnl++)
+ {
+ // 1500F030
+ if((out.pb - pbOutBuffer + 2) > nBytesRemains)
+ return (int)(out.pb - pbOutBuffer + 2);
+
+ // Switch index
+ if(nChannels == 2)
+ nIndex = (nIndex == 0) ? 1 : 0;
+
+ // Load one word from the input stream
+ nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); // ecx - nOneWord
+ SInt32Array3[nIndex] = nOneWord;
+
+ // esi - SInt32Array2[nIndex]
+ // eax - nValue
+ nValue = nOneWord - SInt32Array2[nIndex];
+ nValue = (nValue < 0) ? ((nValue ^ 0xFFFFFFFF) + 1) : nValue;
+
+ ebx = (nOneWord >= SInt32Array2[nIndex]) ? 0 : 0x40;
+
+ // esi - SInt32Array2[nIndex]
+ // edx - step_table[SInt32Array2[nIndex]]
+ // edi - (step_table[SInt32Array1[nIndex]] >> nCmpLevel)
+ nTableValue = step_table[SInt32Array1[nIndex]];
+ dwStopBit = (unsigned long)nCmpLevel;
+
+ // edi - nIndex;
+ if(nValue < (nTableValue >> nCmpLevel))
+ {
+ if(SInt32Array1[nIndex] != 0)
+ SInt32Array1[nIndex]--;
+ *out.pb++ = 0x80;
+ }
+ else
+ {
+ while(nValue > nTableValue * 2)
+ {
+ if(SInt32Array1[nIndex] >= 0x58 || nLength == 0)
+ break;
+
+ SInt32Array1[nIndex] += 8;
+ if(SInt32Array1[nIndex] > 0x58)
+ SInt32Array1[nIndex] = 0x58;
+
+ nTableValue = step_table[SInt32Array1[nIndex]];
+ *out.pb++ = 0x81;
+ nLength--;
+ }
+
+ var_2C = nTableValue >> Wcmp.b[1];
+ dwBitBuff = 0;
+
+ esi = (1 << (dwStopBit - 2));
+ dwStopBit = (esi <= 0x20) ? esi : 0x20;
+
+ for(var_1C = 0, dwBit = 1; ; dwBit <<= 1)
+ {
+// esi = var_1C + nTableValue;
+ if((var_1C + nTableValue) <= nValue)
+ {
+ var_1C += nTableValue;
+ dwBitBuff |= dwBit;
+ }
+ if(dwBit == dwStopBit)
+ break;
+
+ nTableValue >>= 1;
+ }
+
+ nValue = SInt32Array2[nIndex];
+ if(ebx != 0)
+ {
+ nValue -= (var_1C + var_2C);
+ if(nValue < -32768)
+ nValue = -32768;
+ }
+ else
+ {
+ nValue += (var_1C + var_2C);
+ if(nValue > 32767)
+ nValue = 32767;
+ }
+
+ SInt32Array2[nIndex] = nValue;
+ *out.pb++ = (unsigned char)(dwBitBuff | ebx);
+ nTableValue = Table1503F120[dwBitBuff & 0x1F];
+ SInt32Array1[nIndex] = SInt32Array1[nIndex] + nTableValue;
+ if(SInt32Array1[nIndex] < 0)
+ SInt32Array1[nIndex] = 0;
+ else if(SInt32Array1[nIndex] > 0x58)
+ SInt32Array1[nIndex] = 0x58;
+ }
+ }
+
+ return (int)(out.pb - pbOutBuffer);
+}
+
+//----------------------------------------------------------------------------
+// DecompressADPCM
+
+// 1500F230
+int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels)
+{
+ BYTE_AND_WORD_PTR out; // Output buffer
+ BYTE_AND_WORD_PTR in;
+ unsigned char * pbInBufferEnd = (pbInBuffer + dwInLength);
+ long SInt32Array1[2];
+ long SInt32Array2[2];
+ long nOneWord;
+ int nIndex;
+ int i;
+
+ SInt32Array1[0] = SInt32Array1[1] = 0x2C;
+ out.pb = pbOutBuffer;
+ in.pb = pbInBuffer;
+ in.pw++;
+
+ // Fill the Uint32Array2 array by channel values.
+ for(i = 0; i < nChannels; i++)
+ {
+ nOneWord = BSWAP_INT16_SIGNED(*in.pw++);
+ SInt32Array2[i] = nOneWord;
+ if(dwOutLength < 2)
+ return (int)(out.pb - pbOutBuffer);
+
+ *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
+ dwOutLength -= sizeof(short);
+ }
+
+ // Get the initial index
+ nIndex = nChannels - 1;
+
+ // Perform the decompression
+ while(in.pb < pbInBufferEnd)
+ {
+ unsigned char nOneByte = *in.pb++;
+
+ // Switch index
+ if(nChannels == 2)
+ nIndex = (nIndex == 0) ? 1 : 0;
+
+ // 1500F2A2: Get one byte from input buffer
+ if(nOneByte & 0x80)
+ {
+ switch(nOneByte & 0x7F)
+ {
+ case 0: // 1500F315
+ if(SInt32Array1[nIndex] != 0)
+ SInt32Array1[nIndex]--;
+
+ if(dwOutLength < 2)
+ return (int)(out.pb - pbOutBuffer);
+
+ *out.pw++ = BSWAP_INT16_SIGNED((unsigned short)SInt32Array2[nIndex]);
+ dwOutLength -= sizeof(unsigned short);
+ break;
+
+ case 1: // 1500F2E8
+ SInt32Array1[nIndex] += 8;
+ if(SInt32Array1[nIndex] > 0x58)
+ SInt32Array1[nIndex] = 0x58;
+
+ if(nChannels == 2)
+ nIndex = (nIndex == 0) ? 1 : 0;
+ break;
+
+ case 2: // 1500F41E
+ break;
+
+ default: // 1500F2C4
+ SInt32Array1[nIndex] -= 8;
+ if(SInt32Array1[nIndex] < 0)
+ SInt32Array1[nIndex] = 0;
+
+ if(nChannels == 2)
+ nIndex = (nIndex == 0) ? 1 : 0;
+ break;
+ }
+ }
+ else
+ {
+ // 1500F349
+ long temp1 = step_table[SInt32Array1[nIndex]]; // EDI
+ long temp2 = temp1 >> pbInBuffer[1]; // ESI
+ long temp3 = SInt32Array2[nIndex]; // ECX
+
+ if(nOneByte & 0x01) // EBX = nOneByte
+ temp2 += (temp1 >> 0);
+
+ if(nOneByte & 0x02)
+ temp2 += (temp1 >> 1);
+
+ if(nOneByte & 0x04)
+ temp2 += (temp1 >> 2);
+
+ if(nOneByte & 0x08)
+ temp2 += (temp1 >> 3);
+
+ if(nOneByte & 0x10)
+ temp2 += (temp1 >> 4);
+
+ if(nOneByte & 0x20)
+ temp2 += (temp1 >> 5);
+
+ if(nOneByte & 0x40)
+ {
+ temp3 = temp3 - temp2;
+ if(temp3 <= -32768)
+ temp3 = -32768;
+ }
+ else
+ {
+ temp3 = temp3 + temp2;
+ if(temp3 >= 32767)
+ temp3 = 32767;
+ }
+
+ SInt32Array2[nIndex] = temp3;
+ if(dwOutLength < 2)
+ break;
+
+ // Store the output 16-bit value
+ *out.pw++ = BSWAP_INT16_SIGNED((short)SInt32Array2[nIndex]);
+ dwOutLength -= 2;
+
+ SInt32Array1[nIndex] += Table1503F120[nOneByte & 0x1F];
+
+ if(SInt32Array1[nIndex] < 0)
+ SInt32Array1[nIndex] = 0;
+ else if(SInt32Array1[nIndex] > 0x58)
+ SInt32Array1[nIndex] = 0x58;
+ }
+ }
+ return (int)(out.pb - pbOutBuffer);
+}
diff --git a/dep/StormLib/src/adpcm/adpcm.h b/dep/StormLib/src/adpcm/adpcm.h
new file mode 100644
index 00000000000..beb96159720
--- /dev/null
+++ b/dep/StormLib/src/adpcm/adpcm.h
@@ -0,0 +1,22 @@
+/*****************************************************************************/
+/* adpcm.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Header file for adpcm decompress functions */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 31.03.03 1.00 Lad The first version of adpcm.h */
+/*****************************************************************************/
+
+#ifndef __ADPCM_H__
+#define __ADPCM_H__
+
+//-----------------------------------------------------------------------------
+// Functions
+
+#include "../StormPort.h"
+
+int CompressADPCM (unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nCmpType, int nChannels);
+int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels);
+
+#endif // __ADPCM_H__
diff --git a/dep/StormLib/src/bzip2/blocksort.c b/dep/StormLib/src/bzip2/blocksort.c
new file mode 100644
index 00000000000..bd2dec157fa
--- /dev/null
+++ b/dep/StormLib/src/bzip2/blocksort.c
@@ -0,0 +1,1094 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery ---*/
+/*--- blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting ---*/
+/*--- algorithm, for repetitive blocks ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+void fallbackSimpleSort ( UInt32* fmap,
+ UInt32* eclass,
+ Int32 lo,
+ Int32 hi )
+{
+ Int32 i, j, tmp;
+ UInt32 ec_tmp;
+
+ if (lo == hi) return;
+
+ if (hi - lo > 3) {
+ for ( i = hi-4; i >= lo; i-- ) {
+ tmp = fmap[i];
+ ec_tmp = eclass[tmp];
+ for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+ fmap[j-4] = fmap[j];
+ fmap[j-4] = tmp;
+ }
+ }
+
+ for ( i = hi-1; i >= lo; i-- ) {
+ tmp = fmap[i];
+ ec_tmp = eclass[tmp];
+ for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+ fmap[j-1] = fmap[j];
+ fmap[j-1] = tmp;
+ }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn) \
+{ \
+ Int32 yyp1 = (zzp1); \
+ Int32 yyp2 = (zzp2); \
+ Int32 yyn = (zzn); \
+ while (yyn > 0) { \
+ fswap(fmap[yyp1], fmap[yyp2]); \
+ yyp1++; yyp2++; yyn--; \
+ } \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+ stackHi[sp] = hz; \
+ sp++; }
+
+#define fpop(lz,hz) { sp--; \
+ lz = stackLo[sp]; \
+ hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE 100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap,
+ UInt32* eclass,
+ Int32 loSt,
+ Int32 hiSt )
+{
+ Int32 unLo, unHi, ltLo, gtHi, n, m;
+ Int32 sp, lo, hi;
+ UInt32 med, r, r3;
+ Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+ Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+ r = 0;
+
+ sp = 0;
+ fpush ( loSt, hiSt );
+
+ while (sp > 0) {
+
+ AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
+
+ fpop ( lo, hi );
+ if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+ fallbackSimpleSort ( fmap, eclass, lo, hi );
+ continue;
+ }
+
+ /* Random partitioning. Median of 3 sometimes fails to
+ avoid bad cases. Median of 9 seems to help but
+ looks rather expensive. This too seems to work but
+ is cheaper. Guidance for the magic constants
+ 7621 and 32768 is taken from Sedgewick's algorithms
+ book, chapter 35.
+ */
+ r = ((r * 7621) + 1) % 32768;
+ r3 = r % 3;
+ if (r3 == 0) med = eclass[fmap[lo]]; else
+ if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+ med = eclass[fmap[hi]];
+
+ unLo = ltLo = lo;
+ unHi = gtHi = hi;
+
+ while (1) {
+ while (1) {
+ if (unLo > unHi) break;
+ n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+ if (n == 0) {
+ fswap(fmap[unLo], fmap[ltLo]);
+ ltLo++; unLo++;
+ continue;
+ };
+ if (n > 0) break;
+ unLo++;
+ }
+ while (1) {
+ if (unLo > unHi) break;
+ n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+ if (n == 0) {
+ fswap(fmap[unHi], fmap[gtHi]);
+ gtHi--; unHi--;
+ continue;
+ };
+ if (n < 0) break;
+ unHi--;
+ }
+ if (unLo > unHi) break;
+ fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+ }
+
+ AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+ if (gtHi < ltLo) continue;
+
+ n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+ m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - (gtHi - unHi) + 1;
+
+ if (n - lo > hi - m) {
+ fpush ( lo, n );
+ fpush ( m, hi );
+ } else {
+ fpush ( m, hi );
+ fpush ( lo, n );
+ }
+ }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > 0
+ eclass exists for [0 .. nblock-1]
+ ((UChar*)eclass) [0 .. nblock-1] holds block
+ ptr exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)eclass) [0 .. nblock-1] holds block
+ All other areas of eclass destroyed
+ fmap [0 .. nblock-1] holds sorted order
+ bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define WORD_BH(zz) bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz) ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap,
+ UInt32* eclass,
+ UInt32* bhtab,
+ Int32 nblock,
+ Int32 verb )
+{
+ Int32 ftab[257];
+ Int32 ftabCopy[256];
+ Int32 H, i, j, k, l, r, cc, cc1;
+ Int32 nNotDone;
+ Int32 nBhtab;
+ UChar* eclass8 = (UChar*)eclass;
+
+ /*--
+ Initial 1-char radix sort to generate
+ initial fmap and initial BH bits.
+ --*/
+ if (verb >= 4)
+ VPrintf0 ( " bucket sorting ...\n" );
+ for (i = 0; i < 257; i++) ftab[i] = 0;
+ for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+ for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i];
+ for (i = 1; i < 257; i++) ftab[i] += ftab[i-1];
+
+ for (i = 0; i < nblock; i++) {
+ j = eclass8[i];
+ k = ftab[j] - 1;
+ ftab[j] = k;
+ fmap[k] = i;
+ }
+
+ nBhtab = 2 + (nblock / 32);
+ for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+ for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+ /*--
+ Inductively refine the buckets. Kind-of an
+ "exponential radix sort" (!), inspired by the
+ Manber-Myers suffix array construction algorithm.
+ --*/
+
+ /*-- set sentinel bits for block-end detection --*/
+ for (i = 0; i < 32; i++) {
+ SET_BH(nblock + 2*i);
+ CLEAR_BH(nblock + 2*i + 1);
+ }
+
+ /*-- the log(N) loop --*/
+ H = 1;
+ while (1) {
+
+ if (verb >= 4)
+ VPrintf1 ( " depth %6d has ", H );
+
+ j = 0;
+ for (i = 0; i < nblock; i++) {
+ if (ISSET_BH(i)) j = i;
+ k = fmap[i] - H; if (k < 0) k += nblock;
+ eclass[k] = j;
+ }
+
+ nNotDone = 0;
+ r = -1;
+ while (1) {
+
+ /*-- find the next non-singleton bucket --*/
+ k = r + 1;
+ while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+ if (ISSET_BH(k)) {
+ while (WORD_BH(k) == 0xffffffff) k += 32;
+ while (ISSET_BH(k)) k++;
+ }
+ l = k - 1;
+ if (l >= nblock) break;
+ while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+ if (!ISSET_BH(k)) {
+ while (WORD_BH(k) == 0x00000000) k += 32;
+ while (!ISSET_BH(k)) k++;
+ }
+ r = k - 1;
+ if (r >= nblock) break;
+
+ /*-- now [l, r] bracket current bucket --*/
+ if (r > l) {
+ nNotDone += (r - l + 1);
+ fallbackQSort3 ( fmap, eclass, l, r );
+
+ /*-- scan bucket and generate header bits-- */
+ cc = -1;
+ for (i = l; i <= r; i++) {
+ cc1 = eclass[fmap[i]];
+ if (cc != cc1) { SET_BH(i); cc = cc1; };
+ }
+ }
+ }
+
+ if (verb >= 4)
+ VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+ H *= 2;
+ if (H > nblock || nNotDone == 0) break;
+ }
+
+ /*--
+ Reconstruct the original block in
+ eclass8 [0 .. nblock-1], since the
+ previous phase destroyed it.
+ --*/
+ if (verb >= 4)
+ VPrintf0 ( " reconstructing block ...\n" );
+ j = 0;
+ for (i = 0; i < nblock; i++) {
+ while (ftabCopy[j] == 0) j++;
+ ftabCopy[j]--;
+ eclass8[fmap[i]] = (UChar)j;
+ }
+ AssertH ( j < 256, 1005 );
+}
+
+#undef SET_BH
+#undef CLEAR_BH
+#undef ISSET_BH
+#undef WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting ---*/
+/*--- algorithm. Faster for "normal" ---*/
+/*--- non-repetitive blocks. ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32 i1,
+ UInt32 i2,
+ UChar* block,
+ UInt16* quadrant,
+ UInt32 nblock,
+ Int32* budget )
+{
+ Int32 k;
+ UChar c1, c2;
+ UInt16 s1, s2;
+
+ AssertD ( i1 != i2, "mainGtU" );
+ /* 1 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 2 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 3 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 4 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 5 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 6 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 7 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 8 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 9 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 10 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 11 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 12 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+
+ k = nblock + 8;
+
+ do {
+ /* 1 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 2 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 3 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 4 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 5 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 6 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 7 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 8 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+
+ if (i1 >= nblock) i1 -= nblock;
+ if (i2 >= nblock) i2 -= nblock;
+
+ k -= 8;
+ (*budget)--;
+ }
+ while (k >= 0);
+
+ return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+ Knuth's increments seem to work better
+ than Incerpi-Sedgewick here. Possibly
+ because the number of elems to sort is
+ usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+ 9841, 29524, 88573, 265720,
+ 797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ Int32 nblock,
+ Int32 lo,
+ Int32 hi,
+ Int32 d,
+ Int32* budget )
+{
+ Int32 i, j, h, bigN, hp;
+ UInt32 v;
+
+ bigN = hi - lo + 1;
+ if (bigN < 2) return;
+
+ hp = 0;
+ while (incs[hp] < bigN) hp++;
+ hp--;
+
+ for (; hp >= 0; hp--) {
+ h = incs[hp];
+
+ i = lo + h;
+ while (True) {
+
+ /*-- copy 1 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ /*-- copy 2 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ /*-- copy 3 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ if (*budget < 0) return;
+ }
+ }
+}
+
+
+/*---------------------------------------------*/
+/*--
+ The following is an implementation of
+ an elegant 3-way quicksort for strings,
+ described in a paper "Fast Algorithms for
+ Sorting and Searching Strings", by Robert
+ Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn) \
+{ \
+ Int32 yyp1 = (zzp1); \
+ Int32 yyp2 = (zzp2); \
+ Int32 yyn = (zzn); \
+ while (yyn > 0) { \
+ mswap(ptr[yyp1], ptr[yyp2]); \
+ yyp1++; yyp2++; yyn--; \
+ } \
+}
+
+static
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+ UChar t;
+ if (a > b) { t = a; a = b; b = t; };
+ if (b > c) {
+ b = c;
+ if (a > b) b = a;
+ }
+ return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+ stackHi[sp] = hz; \
+ stackD [sp] = dz; \
+ sp++; }
+
+#define mpop(lz,hz,dz) { sp--; \
+ lz = stackLo[sp]; \
+ hz = stackHi[sp]; \
+ dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz) \
+ { Int32 tz; \
+ tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+ tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+ tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ Int32 nblock,
+ Int32 loSt,
+ Int32 hiSt,
+ Int32 dSt,
+ Int32* budget )
+{
+ Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+ Int32 sp, lo, hi, d;
+
+ Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+ Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+ Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+ Int32 nextLo[3];
+ Int32 nextHi[3];
+ Int32 nextD [3];
+
+ sp = 0;
+ mpush ( loSt, hiSt, dSt );
+
+ while (sp > 0) {
+
+ AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
+
+ mpop ( lo, hi, d );
+ if (hi - lo < MAIN_QSORT_SMALL_THRESH ||
+ d > MAIN_QSORT_DEPTH_THRESH) {
+ mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+ if (*budget < 0) return;
+ continue;
+ }
+
+ med = (Int32)
+ mmed3 ( block[ptr[ lo ]+d],
+ block[ptr[ hi ]+d],
+ block[ptr[ (lo+hi)>>1 ]+d] );
+
+ unLo = ltLo = lo;
+ unHi = gtHi = hi;
+
+ while (True) {
+ while (True) {
+ if (unLo > unHi) break;
+ n = ((Int32)block[ptr[unLo]+d]) - med;
+ if (n == 0) {
+ mswap(ptr[unLo], ptr[ltLo]);
+ ltLo++; unLo++; continue;
+ };
+ if (n > 0) break;
+ unLo++;
+ }
+ while (True) {
+ if (unLo > unHi) break;
+ n = ((Int32)block[ptr[unHi]+d]) - med;
+ if (n == 0) {
+ mswap(ptr[unHi], ptr[gtHi]);
+ gtHi--; unHi--; continue;
+ };
+ if (n < 0) break;
+ unHi--;
+ }
+ if (unLo > unHi) break;
+ mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+ }
+
+ AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+ if (gtHi < ltLo) {
+ mpush(lo, hi, d+1 );
+ continue;
+ }
+
+ n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+ m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - (gtHi - unHi) + 1;
+
+ nextLo[0] = lo; nextHi[0] = n; nextD[0] = d;
+ nextLo[1] = m; nextHi[1] = hi; nextD[1] = d;
+ nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+ if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+ AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+ AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+ mpush (nextLo[0], nextHi[0], nextD[0]);
+ mpush (nextLo[1], nextHi[1], nextD[1]);
+ mpush (nextLo[2], nextHi[2], nextD[2]);
+ }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > N_OVERSHOOT
+ block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+ ((UChar*)block32) [0 .. nblock-1] holds block
+ ptr exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)block32) [0 .. nblock-1] holds block
+ All other areas of block32 destroyed
+ ftab [0 .. 65536 ] destroyed
+ ptr [0 .. nblock-1] holds sorted order
+ if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ UInt32* ftab,
+ Int32 nblock,
+ Int32 verb,
+ Int32* budget )
+{
+ Int32 i, j, k, ss, sb;
+ Int32 runningOrder[256];
+ Bool bigDone[256];
+ Int32 copyStart[256];
+ Int32 copyEnd [256];
+ UChar c1;
+ Int32 numQSorted;
+ UInt16 s;
+ if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" );
+
+ /*-- set up the 2-byte frequency table --*/
+ for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+ j = block[0] << 8;
+ i = nblock-1;
+ for (; i >= 3; i -= 4) {
+ quadrant[i] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+ ftab[j]++;
+ quadrant[i-1] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+ ftab[j]++;
+ quadrant[i-2] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+ ftab[j]++;
+ quadrant[i-3] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+ ftab[j]++;
+ }
+ for (; i >= 0; i--) {
+ quadrant[i] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+ ftab[j]++;
+ }
+
+ /*-- (emphasises close relationship of block & quadrant) --*/
+ for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+ block [nblock+i] = block[i];
+ quadrant[nblock+i] = 0;
+ }
+
+ if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" );
+
+ /*-- Complete the initial radix sort --*/
+ for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+ s = block[0] << 8;
+ i = nblock-1;
+ for (; i >= 3; i -= 4) {
+ s = (s >> 8) | (block[i] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i;
+ s = (s >> 8) | (block[i-1] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-1;
+ s = (s >> 8) | (block[i-2] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-2;
+ s = (s >> 8) | (block[i-3] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-3;
+ }
+ for (; i >= 0; i--) {
+ s = (s >> 8) | (block[i] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i;
+ }
+
+ /*--
+ Now ftab contains the first loc of every small bucket.
+ Calculate the running order, from smallest to largest
+ big bucket.
+ --*/
+ for (i = 0; i <= 255; i++) {
+ bigDone [i] = False;
+ runningOrder[i] = i;
+ }
+
+ {
+ Int32 vv;
+ Int32 h = 1;
+ do h = 3 * h + 1; while (h <= 256);
+ do {
+ h = h / 3;
+ for (i = h; i <= 255; i++) {
+ vv = runningOrder[i];
+ j = i;
+ while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+ runningOrder[j] = runningOrder[j-h];
+ j = j - h;
+ if (j <= (h - 1)) goto zero;
+ }
+ zero:
+ runningOrder[j] = vv;
+ }
+ } while (h != 1);
+ }
+
+ /*--
+ The main sorting loop.
+ --*/
+
+ numQSorted = 0;
+
+ for (i = 0; i <= 255; i++) {
+
+ /*--
+ Process big buckets, starting with the least full.
+ Basically this is a 3-step process in which we call
+ mainQSort3 to sort the small buckets [ss, j], but
+ also make a big effort to avoid the calls if we can.
+ --*/
+ ss = runningOrder[i];
+
+ /*--
+ Step 1:
+ Complete the big bucket [ss] by quicksorting
+ any unsorted small buckets [ss, j], for j != ss.
+ Hopefully previous pointer-scanning phases have already
+ completed many of the small buckets [ss, j], so
+ we don't have to sort them at all.
+ --*/
+ for (j = 0; j <= 255; j++) {
+ if (j != ss) {
+ sb = (ss << 8) + j;
+ if ( ! (ftab[sb] & SETMASK) ) {
+ Int32 lo = ftab[sb] & CLEARMASK;
+ Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+ if (hi > lo) {
+ if (verb >= 4)
+ VPrintf4 ( " qsort [0x%x, 0x%x] "
+ "done %d this %d\n",
+ ss, j, numQSorted, hi - lo + 1 );
+ mainQSort3 (
+ ptr, block, quadrant, nblock,
+ lo, hi, BZ_N_RADIX, budget
+ );
+ numQSorted += (hi - lo + 1);
+ if (*budget < 0) return;
+ }
+ }
+ ftab[sb] |= SETMASK;
+ }
+ }
+
+ AssertH ( !bigDone[ss], 1006 );
+
+ /*--
+ Step 2:
+ Now scan this big bucket [ss] so as to synthesise the
+ sorted order for small buckets [t, ss] for all t,
+ including, magically, the bucket [ss,ss] too.
+ This will avoid doing Real Work in subsequent Step 1's.
+ --*/
+ {
+ for (j = 0; j <= 255; j++) {
+ copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK;
+ copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+ }
+ for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+ k = ptr[j]-1; if (k < 0) k += nblock;
+ c1 = block[k];
+ if (!bigDone[c1])
+ ptr[ copyStart[c1]++ ] = k;
+ }
+ for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+ k = ptr[j]-1; if (k < 0) k += nblock;
+ c1 = block[k];
+ if (!bigDone[c1])
+ ptr[ copyEnd[c1]-- ] = k;
+ }
+ }
+
+ AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+ ||
+ /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+ Necessity for this case is demonstrated by compressing
+ a sequence of approximately 48.5 million of character
+ 251; 1.0.0/1.0.1 will then die here. */
+ (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+ 1007 )
+
+ for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+ /*--
+ Step 3:
+ The [ss] big bucket is now done. Record this fact,
+ and update the quadrant descriptors. Remember to
+ update quadrants in the overshoot area too, if
+ necessary. The "if (i < 255)" test merely skips
+ this updating for the last bucket processed, since
+ updating for the last bucket is pointless.
+
+ The quadrant array provides a way to incrementally
+ cache sort orderings, as they appear, so as to
+ make subsequent comparisons in fullGtU() complete
+ faster. For repetitive blocks this makes a big
+ difference (but not big enough to be able to avoid
+ the fallback sorting mechanism, exponential radix sort).
+
+ The precise meaning is: at all times:
+
+ for 0 <= i < nblock and 0 <= j <= nblock
+
+ if block[i] != block[j],
+
+ then the relative values of quadrant[i] and
+ quadrant[j] are meaningless.
+
+ else {
+ if quadrant[i] < quadrant[j]
+ then the string starting at i lexicographically
+ precedes the string starting at j
+
+ else if quadrant[i] > quadrant[j]
+ then the string starting at j lexicographically
+ precedes the string starting at i
+
+ else
+ the relative ordering of the strings starting
+ at i and j has not yet been determined.
+ }
+ --*/
+ bigDone[ss] = True;
+
+ if (i < 255) {
+ Int32 bbStart = ftab[ss << 8] & CLEARMASK;
+ Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+ Int32 shifts = 0;
+
+ while ((bbSize >> shifts) > 65534) shifts++;
+
+ for (j = bbSize-1; j >= 0; j--) {
+ Int32 a2update = ptr[bbStart + j];
+ UInt16 qVal = (UInt16)(j >> shifts);
+ quadrant[a2update] = qVal;
+ if (a2update < BZ_N_OVERSHOOT)
+ quadrant[a2update + nblock] = qVal;
+ }
+ AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+ }
+
+ }
+
+ if (verb >= 4)
+ VPrintf3 ( " %d pointers, %d sorted, %d scanned\n",
+ nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > 0
+ arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+ ((UChar*)arr2) [0 .. nblock-1] holds block
+ arr1 exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)arr2) [0 .. nblock-1] holds block
+ All other areas of block destroyed
+ ftab [ 0 .. 65536 ] destroyed
+ arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+ UInt32* ptr = s->ptr;
+ UChar* block = s->block;
+ UInt32* ftab = s->ftab;
+ Int32 nblock = s->nblock;
+ Int32 verb = s->verbosity;
+ Int32 wfact = s->workFactor;
+ UInt16* quadrant;
+ Int32 budget;
+ Int32 budgetInit;
+ Int32 i;
+
+ if (nblock < 10000) {
+ fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+ } else {
+ /* Calculate the location for quadrant, remembering to get
+ the alignment right. Assumes that &(block[0]) is at least
+ 2-byte aligned -- this should be ok since block is really
+ the first section of arr2.
+ */
+ i = nblock+BZ_N_OVERSHOOT;
+ if (i & 1) i++;
+ quadrant = (UInt16*)(&(block[i]));
+
+ /* (wfact-1) / 3 puts the default-factor-30
+ transition point at very roughly the same place as
+ with v0.1 and v0.9.0.
+ Not that it particularly matters any more, since the
+ resulting compressed stream is now the same regardless
+ of whether or not we use the main sort or fallback sort.
+ */
+ if (wfact < 1 ) wfact = 1;
+ if (wfact > 100) wfact = 100;
+ budgetInit = nblock * ((wfact-1) / 3);
+ budget = budgetInit;
+
+ mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+ if (verb >= 3)
+ VPrintf3 ( " %d work, %d block, ratio %5.2f\n",
+ budgetInit - budget,
+ nblock,
+ (float)(budgetInit - budget) /
+ (float)(nblock==0 ? 1 : nblock) );
+ if (budget < 0) {
+ if (verb >= 2)
+ VPrintf0 ( " too repetitive; using fallback"
+ " sorting algorithm\n" );
+ fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+ }
+ }
+
+ s->origPtr = -1;
+ for (i = 0; i < s->nblock; i++)
+ if (ptr[i] == 0)
+ { s->origPtr = i; break; };
+
+ AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end blocksort.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/bzlib.c b/dep/StormLib/src/bzip2/bzlib.c
new file mode 100644
index 00000000000..b98f3e586bc
--- /dev/null
+++ b/dep/StormLib/src/bzip2/bzlib.c
@@ -0,0 +1,1573 @@
+
+/*-------------------------------------------------------------*/
+/*--- Library top-level functions. ---*/
+/*--- bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+/* CHANGES
+ 0.9.0 -- original version.
+ 0.9.0a/b -- no changes in this file.
+ 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
+ fixed bzWrite/bzRead to ignore zero-length requests.
+ fixed bzread to correctly handle read requests after EOF.
+ wrong parameter order in call to bzDecompressInit in
+ bzBuffToBuffDecompress. Fixed.
+*/
+
+#define _CRT_SECURE_NO_WARNINGS
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Compression stuff ---*/
+/*---------------------------------------------------*/
+
+
+/*---------------------------------------------------*/
+#ifndef BZ_NO_STDIO
+void BZ2_bz__AssertH__fail ( int errcode )
+{
+ fprintf(stderr,
+ "\n\nbzip2/libbzip2: internal error number %d.\n"
+ "This is a bug in bzip2/libbzip2, %s.\n"
+ "Please report it to me at: jseward@bzip.org. If this happened\n"
+ "when you were using some program which uses libbzip2 as a\n"
+ "component, you should also report this bug to the author(s)\n"
+ "of that program. Please make an effort to report this bug;\n"
+ "timely and accurate bug reports eventually lead to higher\n"
+ "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
+ errcode,
+ BZ2_bzlibVersion()
+ );
+
+ if (errcode == 1007) {
+ fprintf(stderr,
+ "\n*** A special note about internal error number 1007 ***\n"
+ "\n"
+ "Experience suggests that a common cause of i.e. 1007\n"
+ "is unreliable memory or other hardware. The 1007 assertion\n"
+ "just happens to cross-check the results of huge numbers of\n"
+ "memory reads/writes, and so acts (unintendedly) as a stress\n"
+ "test of your memory system.\n"
+ "\n"
+ "I suggest the following: try compressing the file again,\n"
+ "possibly monitoring progress in detail with the -vv flag.\n"
+ "\n"
+ "* If the error cannot be reproduced, and/or happens at different\n"
+ " points in compression, you may have a flaky memory system.\n"
+ " Try a memory-test program. I have used Memtest86\n"
+ " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
+ " Memtest86 tests memory much more thorougly than your BIOSs\n"
+ " power-on test, and may find failures that the BIOS doesn't.\n"
+ "\n"
+ "* If the error can be repeatably reproduced, this is a bug in\n"
+ " bzip2, and I would very much like to hear about it. Please\n"
+ " let me know, and, ideally, save a copy of the file causing the\n"
+ " problem -- without which I will be unable to investigate it.\n"
+ "\n"
+ );
+ }
+
+ exit(3);
+}
+#endif
+
+
+/*---------------------------------------------------*/
+static
+int bz_config_ok ( void )
+{
+ if (sizeof(int) != 4) return 0;
+ if (sizeof(short) != 2) return 0;
+ if (sizeof(char) != 1) return 0;
+ return 1;
+}
+
+
+/*---------------------------------------------------*/
+static
+void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
+{
+ void* v = malloc ( items * size );
+ return v;
+}
+
+static
+void default_bzfree ( void* opaque, void* addr )
+{
+ if (addr != NULL) free ( addr );
+}
+
+
+/*---------------------------------------------------*/
+static
+void prepare_new_block ( EState* s )
+{
+ Int32 i;
+ s->nblock = 0;
+ s->numZ = 0;
+ s->state_out_pos = 0;
+ BZ_INITIALISE_CRC ( s->blockCRC );
+ for (i = 0; i < 256; i++) s->inUse[i] = False;
+ s->blockNo++;
+}
+
+
+/*---------------------------------------------------*/
+static
+void init_RL ( EState* s )
+{
+ s->state_in_ch = 256;
+ s->state_in_len = 0;
+}
+
+
+static
+Bool isempty_RL ( EState* s )
+{
+ if (s->state_in_ch < 256 && s->state_in_len > 0)
+ return False; else
+ return True;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressInit)
+ ( bz_stream* strm,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ Int32 n;
+ EState* s;
+
+ if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+ if (strm == NULL ||
+ blockSize100k < 1 || blockSize100k > 9 ||
+ workFactor < 0 || workFactor > 250)
+ return BZ_PARAM_ERROR;
+
+ if (workFactor == 0) workFactor = 30;
+ if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+ if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+ s = BZALLOC( sizeof(EState) );
+ if (s == NULL) return BZ_MEM_ERROR;
+ s->strm = strm;
+
+ s->arr1 = NULL;
+ s->arr2 = NULL;
+ s->ftab = NULL;
+
+ n = 100000 * blockSize100k;
+ s->arr1 = BZALLOC( n * sizeof(UInt32) );
+ s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
+ s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
+
+ if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
+ if (s->arr1 != NULL) BZFREE(s->arr1);
+ if (s->arr2 != NULL) BZFREE(s->arr2);
+ if (s->ftab != NULL) BZFREE(s->ftab);
+ if (s != NULL) BZFREE(s);
+ return BZ_MEM_ERROR;
+ }
+
+ s->blockNo = 0;
+ s->state = BZ_S_INPUT;
+ s->mode = BZ_M_RUNNING;
+ s->combinedCRC = 0;
+ s->blockSize100k = blockSize100k;
+ s->nblockMAX = 100000 * blockSize100k - 19;
+ s->verbosity = verbosity;
+ s->workFactor = workFactor;
+
+ s->block = (UChar*)s->arr2;
+ s->mtfv = (UInt16*)s->arr1;
+ s->zbits = NULL;
+ s->ptr = (UInt32*)s->arr1;
+
+ strm->state = s;
+ strm->total_in_lo32 = 0;
+ strm->total_in_hi32 = 0;
+ strm->total_out_lo32 = 0;
+ strm->total_out_hi32 = 0;
+ init_RL ( s );
+ prepare_new_block ( s );
+ return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void add_pair_to_block ( EState* s )
+{
+ Int32 i;
+ UChar ch = (UChar)(s->state_in_ch);
+ for (i = 0; i < s->state_in_len; i++) {
+ BZ_UPDATE_CRC( s->blockCRC, ch );
+ }
+ s->inUse[s->state_in_ch] = True;
+ switch (s->state_in_len) {
+ case 1:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ case 2:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ case 3:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ default:
+ s->inUse[s->state_in_len-4] = True;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = ((UChar)(s->state_in_len-4));
+ s->nblock++;
+ break;
+ }
+}
+
+
+/*---------------------------------------------------*/
+static
+void flush_RL ( EState* s )
+{
+ if (s->state_in_ch < 256) add_pair_to_block ( s );
+ init_RL ( s );
+}
+
+
+/*---------------------------------------------------*/
+#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
+{ \
+ UInt32 zchh = (UInt32)(zchh0); \
+ /*-- fast track the common case --*/ \
+ if (zchh != zs->state_in_ch && \
+ zs->state_in_len == 1) { \
+ UChar ch = (UChar)(zs->state_in_ch); \
+ BZ_UPDATE_CRC( zs->blockCRC, ch ); \
+ zs->inUse[zs->state_in_ch] = True; \
+ zs->block[zs->nblock] = (UChar)ch; \
+ zs->nblock++; \
+ zs->state_in_ch = zchh; \
+ } \
+ else \
+ /*-- general, uncommon cases --*/ \
+ if (zchh != zs->state_in_ch || \
+ zs->state_in_len == 255) { \
+ if (zs->state_in_ch < 256) \
+ add_pair_to_block ( zs ); \
+ zs->state_in_ch = zchh; \
+ zs->state_in_len = 1; \
+ } else { \
+ zs->state_in_len++; \
+ } \
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_input_until_stop ( EState* s )
+{
+ Bool progress_in = False;
+
+ if (s->mode == BZ_M_RUNNING) {
+
+ /*-- fast track the common case --*/
+ while (True) {
+ /*-- block full? --*/
+ if (s->nblock >= s->nblockMAX) break;
+ /*-- no input? --*/
+ if (s->strm->avail_in == 0) break;
+ progress_in = True;
+ ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
+ s->strm->next_in++;
+ s->strm->avail_in--;
+ s->strm->total_in_lo32++;
+ if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+ }
+
+ } else {
+
+ /*-- general, uncommon case --*/
+ while (True) {
+ /*-- block full? --*/
+ if (s->nblock >= s->nblockMAX) break;
+ /*-- no input? --*/
+ if (s->strm->avail_in == 0) break;
+ /*-- flush/finish end? --*/
+ if (s->avail_in_expect == 0) break;
+ progress_in = True;
+ ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
+ s->strm->next_in++;
+ s->strm->avail_in--;
+ s->strm->total_in_lo32++;
+ if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+ s->avail_in_expect--;
+ }
+ }
+ return progress_in;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_output_until_stop ( EState* s )
+{
+ Bool progress_out = False;
+
+ while (True) {
+
+ /*-- no output space? --*/
+ if (s->strm->avail_out == 0) break;
+
+ /*-- block done? --*/
+ if (s->state_out_pos >= s->numZ) break;
+
+ progress_out = True;
+ *(s->strm->next_out) = s->zbits[s->state_out_pos];
+ s->state_out_pos++;
+ s->strm->avail_out--;
+ s->strm->next_out++;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ return progress_out;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool handle_compress ( bz_stream* strm )
+{
+ Bool progress_in = False;
+ Bool progress_out = False;
+ EState* s = strm->state;
+
+ while (True) {
+
+ if (s->state == BZ_S_OUTPUT) {
+ progress_out |= copy_output_until_stop ( s );
+ if (s->state_out_pos < s->numZ) break;
+ if (s->mode == BZ_M_FINISHING &&
+ s->avail_in_expect == 0 &&
+ isempty_RL(s)) break;
+ prepare_new_block ( s );
+ s->state = BZ_S_INPUT;
+ if (s->mode == BZ_M_FLUSHING &&
+ s->avail_in_expect == 0 &&
+ isempty_RL(s)) break;
+ }
+
+ if (s->state == BZ_S_INPUT) {
+ progress_in |= copy_input_until_stop ( s );
+ if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
+ flush_RL ( s );
+ BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
+ s->state = BZ_S_OUTPUT;
+ }
+ else
+ if (s->nblock >= s->nblockMAX) {
+ BZ2_compressBlock ( s, False );
+ s->state = BZ_S_OUTPUT;
+ }
+ else
+ if (s->strm->avail_in == 0) {
+ break;
+ }
+ }
+
+ }
+
+ return progress_in || progress_out;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
+{
+ Bool progress;
+ EState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ preswitch:
+ switch (s->mode) {
+
+ case BZ_M_IDLE:
+ return BZ_SEQUENCE_ERROR;
+
+ case BZ_M_RUNNING:
+ if (action == BZ_RUN) {
+ progress = handle_compress ( strm );
+ return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
+ }
+ else
+ if (action == BZ_FLUSH) {
+ s->avail_in_expect = strm->avail_in;
+ s->mode = BZ_M_FLUSHING;
+ goto preswitch;
+ }
+ else
+ if (action == BZ_FINISH) {
+ s->avail_in_expect = strm->avail_in;
+ s->mode = BZ_M_FINISHING;
+ goto preswitch;
+ }
+ else
+ return BZ_PARAM_ERROR;
+
+ case BZ_M_FLUSHING:
+ if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect != s->strm->avail_in)
+ return BZ_SEQUENCE_ERROR;
+ progress = handle_compress ( strm );
+ if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+ s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
+ s->mode = BZ_M_RUNNING;
+ return BZ_RUN_OK;
+
+ case BZ_M_FINISHING:
+ if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect != s->strm->avail_in)
+ return BZ_SEQUENCE_ERROR;
+ progress = handle_compress ( strm );
+ if (!progress) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+ s->state_out_pos < s->numZ) return BZ_FINISH_OK;
+ s->mode = BZ_M_IDLE;
+ return BZ_STREAM_END;
+ }
+ return BZ_OK; /*--not reached--*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
+{
+ EState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ if (s->arr1 != NULL) BZFREE(s->arr1);
+ if (s->arr2 != NULL) BZFREE(s->arr2);
+ if (s->ftab != NULL) BZFREE(s->ftab);
+ BZFREE(strm->state);
+
+ strm->state = NULL;
+
+ return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/*--- Decompression stuff ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressInit)
+ ( bz_stream* strm,
+ int verbosity,
+ int small )
+{
+ DState* s;
+
+ if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ if (small != 0 && small != 1) return BZ_PARAM_ERROR;
+ if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
+
+ if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+ if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+ s = BZALLOC( sizeof(DState) );
+ if (s == NULL) return BZ_MEM_ERROR;
+ s->strm = strm;
+ strm->state = s;
+ s->state = BZ_X_MAGIC_1;
+ s->bsLive = 0;
+ s->bsBuff = 0;
+ s->calculatedCombinedCRC = 0;
+ strm->total_in_lo32 = 0;
+ strm->total_in_hi32 = 0;
+ strm->total_out_lo32 = 0;
+ strm->total_out_hi32 = 0;
+ s->smallDecompress = (Bool)small;
+ s->ll4 = NULL;
+ s->ll16 = NULL;
+ s->tt = NULL;
+ s->currBlockNo = 0;
+ s->verbosity = verbosity;
+
+ return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/* Return True iff data corruption is discovered.
+ Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_FAST ( DState* s )
+{
+ UChar k1;
+
+ if (s->blockRandomised) {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return False;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return False;
+
+ /* Only caused by corrupt data stream? */
+ if (s->nblock_used > s->save_nblock+1)
+ return True;
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
+ s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+ }
+
+ } else {
+
+ /* restore */
+ UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
+ UChar c_state_out_ch = s->state_out_ch;
+ Int32 c_state_out_len = s->state_out_len;
+ Int32 c_nblock_used = s->nblock_used;
+ Int32 c_k0 = s->k0;
+ UInt32* c_tt = s->tt;
+ UInt32 c_tPos = s->tPos;
+ char* cs_next_out = s->strm->next_out;
+ unsigned int cs_avail_out = s->strm->avail_out;
+ Int32 ro_blockSize100k = s->blockSize100k;
+ /* end restore */
+
+ UInt32 avail_out_INIT = cs_avail_out;
+ Int32 s_save_nblockPP = s->save_nblock+1;
+ unsigned int total_out_lo32_old;
+
+ while (True) {
+
+ /* try to finish existing run */
+ if (c_state_out_len > 0) {
+ while (True) {
+ if (cs_avail_out == 0) goto return_notr;
+ if (c_state_out_len == 1) break;
+ *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+ BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+ c_state_out_len--;
+ cs_next_out++;
+ cs_avail_out--;
+ }
+ s_state_out_len_eq_one:
+ {
+ if (cs_avail_out == 0) {
+ c_state_out_len = 1; goto return_notr;
+ };
+ *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+ BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+ cs_next_out++;
+ cs_avail_out--;
+ }
+ }
+ /* Only caused by corrupt data stream? */
+ if (c_nblock_used > s_save_nblockPP)
+ return True;
+
+ /* can a new run be started? */
+ if (c_nblock_used == s_save_nblockPP) {
+ c_state_out_len = 0; goto return_notr;
+ };
+ c_state_out_ch = c_k0;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (k1 != c_k0) {
+ c_k0 = k1; goto s_state_out_len_eq_one;
+ };
+ if (c_nblock_used == s_save_nblockPP)
+ goto s_state_out_len_eq_one;
+
+ c_state_out_len = 2;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (c_nblock_used == s_save_nblockPP) continue;
+ if (k1 != c_k0) { c_k0 = k1; continue; };
+
+ c_state_out_len = 3;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (c_nblock_used == s_save_nblockPP) continue;
+ if (k1 != c_k0) { c_k0 = k1; continue; };
+
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ c_state_out_len = ((Int32)k1) + 4;
+ BZ_GET_FAST_C(c_k0); c_nblock_used++;
+ }
+
+ return_notr:
+ total_out_lo32_old = s->strm->total_out_lo32;
+ s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
+ if (s->strm->total_out_lo32 < total_out_lo32_old)
+ s->strm->total_out_hi32++;
+
+ /* save */
+ s->calculatedBlockCRC = c_calculatedBlockCRC;
+ s->state_out_ch = c_state_out_ch;
+ s->state_out_len = c_state_out_len;
+ s->nblock_used = c_nblock_used;
+ s->k0 = c_k0;
+ s->tt = c_tt;
+ s->tPos = c_tPos;
+ s->strm->next_out = cs_next_out;
+ s->strm->avail_out = cs_avail_out;
+ /* end save */
+ }
+ return False;
+}
+
+
+
+/*---------------------------------------------------*/
+__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
+{
+ Int32 nb, na, mid;
+ nb = 0;
+ na = 256;
+ do {
+ mid = (nb + na) >> 1;
+ if (indx >= cftab[mid]) nb = mid; else na = mid;
+ }
+ while (na - nb != 1);
+ return nb;
+}
+
+
+/*---------------------------------------------------*/
+/* Return True iff data corruption is discovered.
+ Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_SMALL ( DState* s )
+{
+ UChar k1;
+
+ if (s->blockRandomised) {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return False;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return False;
+
+ /* Only caused by corrupt data stream? */
+ if (s->nblock_used > s->save_nblock+1)
+ return True;
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
+ s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+ }
+
+ } else {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return False;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return False;
+
+ /* Only caused by corrupt data stream? */
+ if (s->nblock_used > s->save_nblock+1)
+ return True;
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ }
+
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
+{
+ Bool corrupt;
+ DState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ while (True) {
+ if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
+ if (s->state == BZ_X_OUTPUT) {
+ if (s->smallDecompress)
+ corrupt = unRLE_obuf_to_output_SMALL ( s ); else
+ corrupt = unRLE_obuf_to_output_FAST ( s );
+ if (corrupt) return BZ_DATA_ERROR;
+ if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
+ BZ_FINALISE_CRC ( s->calculatedBlockCRC );
+ if (s->verbosity >= 3)
+ VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
+ s->calculatedBlockCRC );
+ if (s->verbosity >= 2) VPrintf0 ( "]" );
+ if (s->calculatedBlockCRC != s->storedBlockCRC)
+ return BZ_DATA_ERROR;
+ s->calculatedCombinedCRC
+ = (s->calculatedCombinedCRC << 1) |
+ (s->calculatedCombinedCRC >> 31);
+ s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
+ s->state = BZ_X_BLKHDR_1;
+ } else {
+ return BZ_OK;
+ }
+ }
+ if (s->state >= BZ_X_MAGIC_1) {
+ Int32 r = BZ2_decompress ( s );
+ if (r == BZ_STREAM_END) {
+ if (s->verbosity >= 3)
+ VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
+ s->storedCombinedCRC, s->calculatedCombinedCRC );
+ if (s->calculatedCombinedCRC != s->storedCombinedCRC)
+ return BZ_DATA_ERROR;
+ return r;
+ }
+ if (s->state != BZ_X_OUTPUT) return r;
+ }
+ }
+
+ AssertH ( 0, 6001 );
+
+ return 0; /*NOTREACHED*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
+{
+ DState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ if (s->tt != NULL) BZFREE(s->tt);
+ if (s->ll16 != NULL) BZFREE(s->ll16);
+ if (s->ll4 != NULL) BZFREE(s->ll4);
+
+ BZFREE(strm->state);
+ strm->state = NULL;
+
+ return BZ_OK;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+/*--- File I/O stuff ---*/
+/*---------------------------------------------------*/
+
+#define BZ_SETERR(eee) \
+{ \
+ if (bzerror != NULL) *bzerror = eee; \
+ if (bzf != NULL) bzf->lastErr = eee; \
+}
+
+typedef
+ struct {
+ FILE* handle;
+ Char buf[BZ_MAX_UNUSED];
+ Int32 bufN;
+ Bool writing;
+ bz_stream strm;
+ Int32 lastErr;
+ Bool initialisedOk;
+ }
+ bzFile;
+
+
+/*---------------------------------------------*/
+static Bool myfeof ( FILE* f )
+{
+ Int32 c = fgetc ( f );
+ if (c == EOF) return True;
+ ungetc ( c, f );
+ return False;
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzWriteOpen)
+ ( int* bzerror,
+ FILE* f,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ Int32 ret;
+ bzFile* bzf = NULL;
+
+ BZ_SETERR(BZ_OK);
+
+ if (f == NULL ||
+ (blockSize100k < 1 || blockSize100k > 9) ||
+ (workFactor < 0 || workFactor > 250) ||
+ (verbosity < 0 || verbosity > 4))
+ { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+ if (ferror(f))
+ { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+ bzf = malloc ( sizeof(bzFile) );
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+ BZ_SETERR(BZ_OK);
+ bzf->initialisedOk = False;
+ bzf->bufN = 0;
+ bzf->handle = f;
+ bzf->writing = True;
+ bzf->strm.bzalloc = NULL;
+ bzf->strm.bzfree = NULL;
+ bzf->strm.opaque = NULL;
+
+ if (workFactor == 0) workFactor = 30;
+ ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
+ verbosity, workFactor );
+ if (ret != BZ_OK)
+ { BZ_SETERR(ret); free(bzf); return NULL; };
+
+ bzf->strm.avail_in = 0;
+ bzf->initialisedOk = True;
+ return bzf;
+}
+
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWrite)
+ ( int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len )
+{
+ Int32 n, n2, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+ if (bzf == NULL || buf == NULL || len < 0)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+ if (!(bzf->writing))
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+
+ if (len == 0)
+ { BZ_SETERR(BZ_OK); return; };
+
+ bzf->strm.avail_in = len;
+ bzf->strm.next_in = buf;
+
+ while (True) {
+ bzf->strm.avail_out = BZ_MAX_UNUSED;
+ bzf->strm.next_out = bzf->buf;
+ ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
+ if (ret != BZ_RUN_OK)
+ { BZ_SETERR(ret); return; };
+
+ if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+ n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+ n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
+ n, bzf->handle );
+ if (n != n2 || ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (bzf->strm.avail_in == 0)
+ { BZ_SETERR(BZ_OK); return; };
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWriteClose)
+ ( int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in,
+ unsigned int* nbytes_out )
+{
+ BZ2_bzWriteClose64 ( bzerror, b, abandon,
+ nbytes_in, NULL, nbytes_out, NULL );
+}
+
+
+void BZ_API(BZ2_bzWriteClose64)
+ ( int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in_lo32,
+ unsigned int* nbytes_in_hi32,
+ unsigned int* nbytes_out_lo32,
+ unsigned int* nbytes_out_hi32 )
+{
+ Int32 n, n2, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_OK); return; };
+ if (!(bzf->writing))
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+
+ if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
+ if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
+ if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
+ if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
+
+ if ((!abandon) && bzf->lastErr == BZ_OK) {
+ while (True) {
+ bzf->strm.avail_out = BZ_MAX_UNUSED;
+ bzf->strm.next_out = bzf->buf;
+ ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
+ if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
+ { BZ_SETERR(ret); return; };
+
+ if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+ n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+ n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
+ n, bzf->handle );
+ if (n != n2 || ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (ret == BZ_STREAM_END) break;
+ }
+ }
+
+ if ( !abandon && !ferror ( bzf->handle ) ) {
+ fflush ( bzf->handle );
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (nbytes_in_lo32 != NULL)
+ *nbytes_in_lo32 = bzf->strm.total_in_lo32;
+ if (nbytes_in_hi32 != NULL)
+ *nbytes_in_hi32 = bzf->strm.total_in_hi32;
+ if (nbytes_out_lo32 != NULL)
+ *nbytes_out_lo32 = bzf->strm.total_out_lo32;
+ if (nbytes_out_hi32 != NULL)
+ *nbytes_out_hi32 = bzf->strm.total_out_hi32;
+
+ BZ_SETERR(BZ_OK);
+ BZ2_bzCompressEnd ( &(bzf->strm) );
+ free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzReadOpen)
+ ( int* bzerror,
+ FILE* f,
+ int verbosity,
+ int small,
+ void* unused,
+ int nUnused )
+{
+ bzFile* bzf = NULL;
+ int ret;
+
+ BZ_SETERR(BZ_OK);
+
+ if (f == NULL ||
+ (small != 0 && small != 1) ||
+ (verbosity < 0 || verbosity > 4) ||
+ (unused == NULL && nUnused != 0) ||
+ (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
+ { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+ if (ferror(f))
+ { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+ bzf = malloc ( sizeof(bzFile) );
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+ BZ_SETERR(BZ_OK);
+
+ bzf->initialisedOk = False;
+ bzf->handle = f;
+ bzf->bufN = 0;
+ bzf->writing = False;
+ bzf->strm.bzalloc = NULL;
+ bzf->strm.bzfree = NULL;
+ bzf->strm.opaque = NULL;
+
+ while (nUnused > 0) {
+ bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
+ unused = ((void*)( 1 + ((UChar*)(unused)) ));
+ nUnused--;
+ }
+
+ ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
+ if (ret != BZ_OK)
+ { BZ_SETERR(ret); free(bzf); return NULL; };
+
+ bzf->strm.avail_in = bzf->bufN;
+ bzf->strm.next_in = bzf->buf;
+
+ bzf->initialisedOk = True;
+ return bzf;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
+{
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_OK); return; };
+
+ if (bzf->writing)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+
+ if (bzf->initialisedOk)
+ (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
+ free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzRead)
+ ( int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len )
+{
+ Int32 n, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+
+ if (bzf == NULL || buf == NULL || len < 0)
+ { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
+
+ if (bzf->writing)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
+
+ if (len == 0)
+ { BZ_SETERR(BZ_OK); return 0; };
+
+ bzf->strm.avail_out = len;
+ bzf->strm.next_out = buf;
+
+ while (True) {
+
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return 0; };
+
+ if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
+ n = fread ( bzf->buf, sizeof(UChar),
+ BZ_MAX_UNUSED, bzf->handle );
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return 0; };
+ bzf->bufN = n;
+ bzf->strm.avail_in = bzf->bufN;
+ bzf->strm.next_in = bzf->buf;
+ }
+
+ ret = BZ2_bzDecompress ( &(bzf->strm) );
+
+ if (ret != BZ_OK && ret != BZ_STREAM_END)
+ { BZ_SETERR(ret); return 0; };
+
+ if (ret == BZ_OK && myfeof(bzf->handle) &&
+ bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
+ { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
+
+ if (ret == BZ_STREAM_END)
+ { BZ_SETERR(BZ_STREAM_END);
+ return len - bzf->strm.avail_out; };
+ if (bzf->strm.avail_out == 0)
+ { BZ_SETERR(BZ_OK); return len; };
+
+ }
+
+ return 0; /*not reached*/
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadGetUnused)
+ ( int* bzerror,
+ BZFILE* b,
+ void** unused,
+ int* nUnused )
+{
+ bzFile* bzf = (bzFile*)b;
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+ if (bzf->lastErr != BZ_STREAM_END)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (unused == NULL || nUnused == NULL)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+
+ BZ_SETERR(BZ_OK);
+ *nUnused = bzf->strm.avail_in;
+ *unused = bzf->strm.next_in;
+}
+#endif
+
+
+/*---------------------------------------------------*/
+/*--- Misc convenience stuff ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffCompress)
+ ( char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ bz_stream strm;
+ int ret;
+
+ if (dest == NULL || destLen == NULL ||
+ source == NULL ||
+ blockSize100k < 1 || blockSize100k > 9 ||
+ verbosity < 0 || verbosity > 4 ||
+ workFactor < 0 || workFactor > 250)
+ return BZ_PARAM_ERROR;
+
+ if (workFactor == 0) workFactor = 30;
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+ strm.opaque = NULL;
+ ret = BZ2_bzCompressInit ( &strm, blockSize100k,
+ verbosity, workFactor );
+ if (ret != BZ_OK) return ret;
+
+ strm.next_in = source;
+ strm.next_out = dest;
+ strm.avail_in = sourceLen;
+ strm.avail_out = *destLen;
+
+ ret = BZ2_bzCompress ( &strm, BZ_FINISH );
+ if (ret == BZ_FINISH_OK) goto output_overflow;
+ if (ret != BZ_STREAM_END) goto errhandler;
+
+ /* normal termination */
+ *destLen -= strm.avail_out;
+ BZ2_bzCompressEnd ( &strm );
+ return BZ_OK;
+
+ output_overflow:
+ BZ2_bzCompressEnd ( &strm );
+ return BZ_OUTBUFF_FULL;
+
+ errhandler:
+ BZ2_bzCompressEnd ( &strm );
+ return ret;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffDecompress)
+ ( char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int small,
+ int verbosity )
+{
+ bz_stream strm;
+ int ret;
+
+ if (dest == NULL || destLen == NULL ||
+ source == NULL ||
+ (small != 0 && small != 1) ||
+ verbosity < 0 || verbosity > 4)
+ return BZ_PARAM_ERROR;
+
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+ strm.opaque = NULL;
+ ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
+ if (ret != BZ_OK) return ret;
+
+ strm.next_in = source;
+ strm.next_out = dest;
+ strm.avail_in = sourceLen;
+ strm.avail_out = *destLen;
+
+ ret = BZ2_bzDecompress ( &strm );
+ if (ret == BZ_OK) goto output_overflow_or_eof;
+ if (ret != BZ_STREAM_END) goto errhandler;
+
+ /* normal termination */
+ *destLen -= strm.avail_out;
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_OK;
+
+ output_overflow_or_eof:
+ if (strm.avail_out > 0) {
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_UNEXPECTED_EOF;
+ } else {
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_OUTBUFF_FULL;
+ };
+
+ errhandler:
+ BZ2_bzDecompressEnd ( &strm );
+ return ret;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
+ to support better zlib compatibility.
+ This code is not _officially_ part of libbzip2 (yet);
+ I haven't tested it, documented it, or considered the
+ threading-safeness of it.
+ If this code breaks, please contact both Yoshioka and me.
+--*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+/*--
+ return version like "0.9.5d, 4-Sept-1999".
+--*/
+const char * BZ_API(BZ2_bzlibVersion)(void)
+{
+ return BZ_VERSION;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) _setmode(_fileno(file),O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+static
+BZFILE * bzopen_or_bzdopen
+ ( const char *path, /* no use when bzdopen */
+ int fd, /* no use when bzdopen */
+ const char *mode,
+ int open_mode) /* bzopen: 0, bzdopen:1 */
+{
+ int bzerr;
+ char unused[BZ_MAX_UNUSED];
+ int blockSize100k = 9;
+ int writing = 0;
+ char mode2[10] = "";
+ FILE *fp = NULL;
+ BZFILE *bzfp = NULL;
+ int verbosity = 0;
+ int workFactor = 30;
+ int smallMode = 0;
+ int nUnused = 0;
+
+ if (mode == NULL) return NULL;
+ while (*mode) {
+ switch (*mode) {
+ case 'r':
+ writing = 0; break;
+ case 'w':
+ writing = 1; break;
+ case 's':
+ smallMode = 1; break;
+ default:
+ if (isdigit((int)(*mode))) {
+ blockSize100k = *mode-BZ_HDR_0;
+ }
+ }
+ mode++;
+ }
+ strcat(mode2, writing ? "w" : "r" );
+ strcat(mode2,"b"); /* binary mode */
+
+ if (open_mode==0) {
+ if (path==NULL || strcmp(path,"")==0) {
+ fp = (writing ? stdout : stdin);
+ SET_BINARY_MODE(fp);
+ } else {
+ fp = fopen(path,mode2);
+ }
+ } else {
+#ifdef BZ_STRICT_ANSI
+ fp = NULL;
+#else
+ fp = _fdopen(fd,mode2);
+#endif
+ }
+ if (fp == NULL) return NULL;
+
+ if (writing) {
+ /* Guard against total chaos and anarchy -- JRS */
+ if (blockSize100k < 1) blockSize100k = 1;
+ if (blockSize100k > 9) blockSize100k = 9;
+ bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
+ verbosity,workFactor);
+ } else {
+ bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
+ unused,nUnused);
+ }
+ if (bzfp == NULL) {
+ if (fp != stdin && fp != stdout) fclose(fp);
+ return NULL;
+ }
+ return bzfp;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ open file for read or write.
+ ex) bzopen("file","w9")
+ case path="" or NULL => use stdin or stdout.
+--*/
+BZFILE * BZ_API(BZ2_bzopen)
+ ( const char *path,
+ const char *mode )
+{
+ return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
+}
+
+
+/*---------------------------------------------------*/
+BZFILE * BZ_API(BZ2_bzdopen)
+ ( int fd,
+ const char *mode )
+{
+ return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
+{
+ int bzerr, nread;
+ if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
+ nread = BZ2_bzRead(&bzerr,b,buf,len);
+ if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
+ return nread;
+ } else {
+ return -1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
+{
+ int bzerr;
+
+ BZ2_bzWrite(&bzerr,b,buf,len);
+ if(bzerr == BZ_OK){
+ return len;
+ }else{
+ return -1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzflush) (BZFILE *b)
+{
+ /* do nothing now... */
+ return 0;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzclose) (BZFILE* b)
+{
+ int bzerr;
+ FILE *fp;
+
+ if (b==NULL) {return;}
+ fp = ((bzFile *)b)->handle;
+ if(((bzFile*)b)->writing){
+ BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
+ if(bzerr != BZ_OK){
+ BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
+ }
+ }else{
+ BZ2_bzReadClose(&bzerr,b);
+ }
+ if(fp!=stdin && fp!=stdout){
+ fclose(fp);
+ }
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ return last error code
+--*/
+static const char *bzerrorstrings[] = {
+ "OK"
+ ,"SEQUENCE_ERROR"
+ ,"PARAM_ERROR"
+ ,"MEM_ERROR"
+ ,"DATA_ERROR"
+ ,"DATA_ERROR_MAGIC"
+ ,"IO_ERROR"
+ ,"UNEXPECTED_EOF"
+ ,"OUTBUFF_FULL"
+ ,"CONFIG_ERROR"
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+};
+
+
+const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
+{
+ int err = ((bzFile *)b)->lastErr;
+
+ if(err>0) err = 0;
+ *errnum = err;
+ return bzerrorstrings[err*-1];
+}
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end bzlib.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/bzlib.h b/dep/StormLib/src/bzip2/bzlib.h
new file mode 100644
index 00000000000..c5b75d6d8ff
--- /dev/null
+++ b/dep/StormLib/src/bzip2/bzlib.h
@@ -0,0 +1,282 @@
+
+/*-------------------------------------------------------------*/
+/*--- Public header file for the library. ---*/
+/*--- bzlib.h ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#ifndef _BZLIB_H
+#define _BZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BZ_RUN 0
+#define BZ_FLUSH 1
+#define BZ_FINISH 2
+
+#define BZ_OK 0
+#define BZ_RUN_OK 1
+#define BZ_FLUSH_OK 2
+#define BZ_FINISH_OK 3
+#define BZ_STREAM_END 4
+#define BZ_SEQUENCE_ERROR (-1)
+#define BZ_PARAM_ERROR (-2)
+#define BZ_MEM_ERROR (-3)
+#define BZ_DATA_ERROR (-4)
+#define BZ_DATA_ERROR_MAGIC (-5)
+#define BZ_IO_ERROR (-6)
+#define BZ_UNEXPECTED_EOF (-7)
+#define BZ_OUTBUFF_FULL (-8)
+#define BZ_CONFIG_ERROR (-9)
+
+typedef
+ struct {
+ char *next_in;
+ unsigned int avail_in;
+ unsigned int total_in_lo32;
+ unsigned int total_in_hi32;
+
+ char *next_out;
+ unsigned int avail_out;
+ unsigned int total_out_lo32;
+ unsigned int total_out_hi32;
+
+ void *state;
+
+ void *(*bzalloc)(void *,int,int);
+ void (*bzfree)(void *,void *);
+ void *opaque;
+ }
+ bz_stream;
+
+
+#ifndef BZ_IMPORT
+#define BZ_EXPORT
+#endif
+
+#ifndef BZ_NO_STDIO
+/* Need a definitition for FILE */
+#include <stdio.h>
+#endif
+
+#ifdef _WIN32
+# include <windows.h>
+# ifdef small
+ /* windows.h define small to char */
+# undef small
+# endif
+# ifdef BZ_EXPORT
+# define BZ_API(func) WINAPI func
+# define BZ_EXTERN extern
+# else
+ /* import windows dll dynamically */
+# define BZ_API(func) (WINAPI * func)
+# define BZ_EXTERN
+# endif
+#else
+# define BZ_API(func) func
+# define BZ_EXTERN extern
+#endif
+
+
+/*-- Core (low-level) library functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
+ bz_stream* strm,
+ int blockSize100k,
+ int verbosity,
+ int workFactor
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompress) (
+ bz_stream* strm,
+ int action
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
+ bz_stream* strm
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
+ bz_stream *strm,
+ int verbosity,
+ int small
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
+ bz_stream* strm
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
+ bz_stream *strm
+ );
+
+
+
+/*-- High(er) level library functions --*/
+
+#ifndef BZ_NO_STDIO
+#define BZ_MAX_UNUSED 5000
+
+typedef void BZFILE;
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
+ int* bzerror,
+ FILE* f,
+ int verbosity,
+ int small,
+ void* unused,
+ int nUnused
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
+ int* bzerror,
+ BZFILE* b
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
+ int* bzerror,
+ BZFILE* b,
+ void** unused,
+ int* nUnused
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzRead) (
+ int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len
+ );
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
+ int* bzerror,
+ FILE* f,
+ int blockSize100k,
+ int verbosity,
+ int workFactor
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzWrite) (
+ int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
+ int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in,
+ unsigned int* nbytes_out
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
+ int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in_lo32,
+ unsigned int* nbytes_in_hi32,
+ unsigned int* nbytes_out_lo32,
+ unsigned int* nbytes_out_hi32
+ );
+#endif
+
+
+/*-- Utility functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
+ char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int blockSize100k,
+ int verbosity,
+ int workFactor
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
+ char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int small,
+ int verbosity
+ );
+
+
+/*--
+ Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
+ to support better zlib compatibility.
+ This code is not _officially_ part of libbzip2 (yet);
+ I haven't tested it, documented it, or considered the
+ threading-safeness of it.
+ If this code breaks, please contact both Yoshioka and me.
+--*/
+
+BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
+ void
+ );
+
+#ifndef BZ_NO_STDIO
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
+ const char *path,
+ const char *mode
+ );
+
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
+ int fd,
+ const char *mode
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzread) (
+ BZFILE* b,
+ void* buf,
+ int len
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzwrite) (
+ BZFILE* b,
+ void* buf,
+ int len
+ );
+
+BZ_EXTERN int BZ_API(BZ2_bzflush) (
+ BZFILE* b
+ );
+
+BZ_EXTERN void BZ_API(BZ2_bzclose) (
+ BZFILE* b
+ );
+
+BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
+ BZFILE *b,
+ int *errnum
+ );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*-------------------------------------------------------------*/
+/*--- end bzlib.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/bzlib_private.h b/dep/StormLib/src/bzip2/bzlib_private.h
new file mode 100644
index 00000000000..23427879b18
--- /dev/null
+++ b/dep/StormLib/src/bzip2/bzlib_private.h
@@ -0,0 +1,509 @@
+
+/*-------------------------------------------------------------*/
+/*--- Private header file for the library. ---*/
+/*--- bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#ifndef _BZLIB_PRIVATE_H
+#define _BZLIB_PRIVATE_H
+
+#include <stdlib.h>
+
+#ifndef BZ_NO_STDIO
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#endif
+
+#include "bzlib.h"
+
+
+
+/*-- General stuff. --*/
+
+#define BZ_VERSION "1.0.5, 10-Dec-2007"
+
+typedef char Char;
+typedef unsigned char Bool;
+typedef unsigned char UChar;
+typedef int Int32;
+typedef unsigned int UInt32;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#define True ((Bool)1)
+#define False ((Bool)0)
+
+#ifndef __GNUC__
+#define __inline__ /* */
+#endif
+
+#ifndef BZ_NO_STDIO
+
+extern void BZ2_bz__AssertH__fail ( int errcode );
+#define AssertH(cond,errcode) \
+ { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
+
+#if BZ_DEBUG
+#define AssertD(cond,msg) \
+ { if (!(cond)) { \
+ fprintf ( stderr, \
+ "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
+ exit(1); \
+ }}
+#else
+#define AssertD(cond,msg) /* */
+#endif
+
+#define VPrintf0(zf) \
+ fprintf(stderr,zf)
+#define VPrintf1(zf,za1) \
+ fprintf(stderr,zf,za1)
+#define VPrintf2(zf,za1,za2) \
+ fprintf(stderr,zf,za1,za2)
+#define VPrintf3(zf,za1,za2,za3) \
+ fprintf(stderr,zf,za1,za2,za3)
+#define VPrintf4(zf,za1,za2,za3,za4) \
+ fprintf(stderr,zf,za1,za2,za3,za4)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) \
+ fprintf(stderr,zf,za1,za2,za3,za4,za5)
+
+#else
+
+extern void bz_internal_error ( int errcode );
+#define AssertH(cond,errcode) \
+ { if (!(cond)) bz_internal_error ( errcode ); }
+#define AssertD(cond,msg) do { } while (0)
+#define VPrintf0(zf) do { } while (0)
+#define VPrintf1(zf,za1) do { } while (0)
+#define VPrintf2(zf,za1,za2) do { } while (0)
+#define VPrintf3(zf,za1,za2,za3) do { } while (0)
+#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0)
+
+#endif
+
+
+#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
+#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
+
+
+/*-- Header bytes. --*/
+
+#define BZ_HDR_B 0x42 /* 'B' */
+#define BZ_HDR_Z 0x5a /* 'Z' */
+#define BZ_HDR_h 0x68 /* 'h' */
+#define BZ_HDR_0 0x30 /* '0' */
+
+/*-- Constants for the back end. --*/
+
+#define BZ_MAX_ALPHA_SIZE 258
+#define BZ_MAX_CODE_LEN 23
+
+#define BZ_RUNA 0
+#define BZ_RUNB 1
+
+#define BZ_N_GROUPS 6
+#define BZ_G_SIZE 50
+#define BZ_N_ITERS 4
+
+#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
+
+
+
+/*-- Stuff for randomising repetitive blocks. --*/
+
+extern Int32 BZ2_rNums[512];
+
+#define BZ_RAND_DECLS \
+ Int32 rNToGo; \
+ Int32 rTPos \
+
+#define BZ_RAND_INIT_MASK \
+ s->rNToGo = 0; \
+ s->rTPos = 0 \
+
+#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
+
+#define BZ_RAND_UPD_MASK \
+ if (s->rNToGo == 0) { \
+ s->rNToGo = BZ2_rNums[s->rTPos]; \
+ s->rTPos++; \
+ if (s->rTPos == 512) s->rTPos = 0; \
+ } \
+ s->rNToGo--;
+
+
+
+/*-- Stuff for doing CRCs. --*/
+
+extern UInt32 BZ2_crc32Table[256];
+
+#define BZ_INITIALISE_CRC(crcVar) \
+{ \
+ crcVar = 0xffffffffL; \
+}
+
+#define BZ_FINALISE_CRC(crcVar) \
+{ \
+ crcVar = ~(crcVar); \
+}
+
+#define BZ_UPDATE_CRC(crcVar,cha) \
+{ \
+ crcVar = (crcVar << 8) ^ \
+ BZ2_crc32Table[(crcVar >> 24) ^ \
+ ((UChar)cha)]; \
+}
+
+
+
+/*-- States and modes for compression. --*/
+
+#define BZ_M_IDLE 1
+#define BZ_M_RUNNING 2
+#define BZ_M_FLUSHING 3
+#define BZ_M_FINISHING 4
+
+#define BZ_S_OUTPUT 1
+#define BZ_S_INPUT 2
+
+#define BZ_N_RADIX 2
+#define BZ_N_QSORT 12
+#define BZ_N_SHELL 18
+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
+
+
+
+
+/*-- Structure holding all the compression-side stuff. --*/
+
+typedef
+ struct {
+ /* pointer back to the struct bz_stream */
+ bz_stream* strm;
+
+ /* mode this stream is in, and whether inputting */
+ /* or outputting data */
+ Int32 mode;
+ Int32 state;
+
+ /* remembers avail_in when flush/finish requested */
+ UInt32 avail_in_expect;
+
+ /* for doing the block sorting */
+ UInt32* arr1;
+ UInt32* arr2;
+ UInt32* ftab;
+ Int32 origPtr;
+
+ /* aliases for arr1 and arr2 */
+ UInt32* ptr;
+ UChar* block;
+ UInt16* mtfv;
+ UChar* zbits;
+
+ /* for deciding when to use the fallback sorting algorithm */
+ Int32 workFactor;
+
+ /* run-length-encoding of the input */
+ UInt32 state_in_ch;
+ Int32 state_in_len;
+ BZ_RAND_DECLS;
+
+ /* input and output limits and current posns */
+ Int32 nblock;
+ Int32 nblockMAX;
+ Int32 numZ;
+ Int32 state_out_pos;
+
+ /* map of bytes used in block */
+ Int32 nInUse;
+ Bool inUse[256];
+ UChar unseqToSeq[256];
+
+ /* the buffer for bit stream creation */
+ UInt32 bsBuff;
+ Int32 bsLive;
+
+ /* block and combined CRCs */
+ UInt32 blockCRC;
+ UInt32 combinedCRC;
+
+ /* misc administratium */
+ Int32 verbosity;
+ Int32 blockNo;
+ Int32 blockSize100k;
+
+ /* stuff for coding the MTF values */
+ Int32 nMTF;
+ Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
+ UChar selector [BZ_MAX_SELECTORS];
+ UChar selectorMtf[BZ_MAX_SELECTORS];
+
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ /* second dimension: only 3 needed; 4 makes index calculations faster */
+ UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
+
+ }
+ EState;
+
+
+
+/*-- externs for compression. --*/
+
+extern void
+BZ2_blockSort ( EState* );
+
+extern void
+BZ2_compressBlock ( EState*, Bool );
+
+extern void
+BZ2_bsInitWrite ( EState* );
+
+extern void
+BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
+
+extern void
+BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
+
+
+
+/*-- states for decompression. --*/
+
+#define BZ_X_IDLE 1
+#define BZ_X_OUTPUT 2
+
+#define BZ_X_MAGIC_1 10
+#define BZ_X_MAGIC_2 11
+#define BZ_X_MAGIC_3 12
+#define BZ_X_MAGIC_4 13
+#define BZ_X_BLKHDR_1 14
+#define BZ_X_BLKHDR_2 15
+#define BZ_X_BLKHDR_3 16
+#define BZ_X_BLKHDR_4 17
+#define BZ_X_BLKHDR_5 18
+#define BZ_X_BLKHDR_6 19
+#define BZ_X_BCRC_1 20
+#define BZ_X_BCRC_2 21
+#define BZ_X_BCRC_3 22
+#define BZ_X_BCRC_4 23
+#define BZ_X_RANDBIT 24
+#define BZ_X_ORIGPTR_1 25
+#define BZ_X_ORIGPTR_2 26
+#define BZ_X_ORIGPTR_3 27
+#define BZ_X_MAPPING_1 28
+#define BZ_X_MAPPING_2 29
+#define BZ_X_SELECTOR_1 30
+#define BZ_X_SELECTOR_2 31
+#define BZ_X_SELECTOR_3 32
+#define BZ_X_CODING_1 33
+#define BZ_X_CODING_2 34
+#define BZ_X_CODING_3 35
+#define BZ_X_MTF_1 36
+#define BZ_X_MTF_2 37
+#define BZ_X_MTF_3 38
+#define BZ_X_MTF_4 39
+#define BZ_X_MTF_5 40
+#define BZ_X_MTF_6 41
+#define BZ_X_ENDHDR_2 42
+#define BZ_X_ENDHDR_3 43
+#define BZ_X_ENDHDR_4 44
+#define BZ_X_ENDHDR_5 45
+#define BZ_X_ENDHDR_6 46
+#define BZ_X_CCRC_1 47
+#define BZ_X_CCRC_2 48
+#define BZ_X_CCRC_3 49
+#define BZ_X_CCRC_4 50
+
+
+
+/*-- Constants for the fast MTF decoder. --*/
+
+#define MTFA_SIZE 4096
+#define MTFL_SIZE 16
+
+
+
+/*-- Structure holding all the decompression-side stuff. --*/
+
+typedef
+ struct {
+ /* pointer back to the struct bz_stream */
+ bz_stream* strm;
+
+ /* state indicator for this stream */
+ Int32 state;
+
+ /* for doing the final run-length decoding */
+ UChar state_out_ch;
+ Int32 state_out_len;
+ Bool blockRandomised;
+ BZ_RAND_DECLS;
+
+ /* the buffer for bit stream reading */
+ UInt32 bsBuff;
+ Int32 bsLive;
+
+ /* misc administratium */
+ Int32 blockSize100k;
+ Bool smallDecompress;
+ Int32 currBlockNo;
+ Int32 verbosity;
+
+ /* for undoing the Burrows-Wheeler transform */
+ Int32 origPtr;
+ UInt32 tPos;
+ Int32 k0;
+ Int32 unzftab[256];
+ Int32 nblock_used;
+ Int32 cftab[257];
+ Int32 cftabCopy[257];
+
+ /* for undoing the Burrows-Wheeler transform (FAST) */
+ UInt32 *tt;
+
+ /* for undoing the Burrows-Wheeler transform (SMALL) */
+ UInt16 *ll16;
+ UChar *ll4;
+
+ /* stored and calculated CRCs */
+ UInt32 storedBlockCRC;
+ UInt32 storedCombinedCRC;
+ UInt32 calculatedBlockCRC;
+ UInt32 calculatedCombinedCRC;
+
+ /* map of bytes used in block */
+ Int32 nInUse;
+ Bool inUse[256];
+ Bool inUse16[16];
+ UChar seqToUnseq[256];
+
+ /* for decoding the MTF values */
+ UChar mtfa [MTFA_SIZE];
+ Int32 mtfbase[256 / MTFL_SIZE];
+ UChar selector [BZ_MAX_SELECTORS];
+ UChar selectorMtf[BZ_MAX_SELECTORS];
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+
+ Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 minLens[BZ_N_GROUPS];
+
+ /* save area for scalars in the main decompress code */
+ Int32 save_i;
+ Int32 save_j;
+ Int32 save_t;
+ Int32 save_alphaSize;
+ Int32 save_nGroups;
+ Int32 save_nSelectors;
+ Int32 save_EOB;
+ Int32 save_groupNo;
+ Int32 save_groupPos;
+ Int32 save_nextSym;
+ Int32 save_nblockMAX;
+ Int32 save_nblock;
+ Int32 save_es;
+ Int32 save_N;
+ Int32 save_curr;
+ Int32 save_zt;
+ Int32 save_zn;
+ Int32 save_zvec;
+ Int32 save_zj;
+ Int32 save_gSel;
+ Int32 save_gMinlen;
+ Int32* save_gLimit;
+ Int32* save_gBase;
+ Int32* save_gPerm;
+
+ }
+ DState;
+
+
+
+/*-- Macros for decompression. --*/
+
+#define BZ_GET_FAST(cccc) \
+ /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+ if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
+ s->tPos = s->tt[s->tPos]; \
+ cccc = (UChar)(s->tPos & 0xff); \
+ s->tPos >>= 8;
+
+#define BZ_GET_FAST_C(cccc) \
+ /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+ if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \
+ c_tPos = c_tt[c_tPos]; \
+ cccc = (UChar)(c_tPos & 0xff); \
+ c_tPos >>= 8;
+
+#define SET_LL4(i,n) \
+ { if (((i) & 0x1) == 0) \
+ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
+ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
+ }
+
+#define GET_LL4(i) \
+ ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
+
+#define SET_LL(i,n) \
+ { s->ll16[i] = (UInt16)(n & 0x0000ffff); \
+ SET_LL4(i, n >> 16); \
+ }
+
+#define GET_LL(i) \
+ (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
+
+#define BZ_GET_SMALL(cccc) \
+ /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+ if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
+ cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
+ s->tPos = GET_LL(s->tPos);
+
+
+/*-- externs for decompression. --*/
+
+extern Int32
+BZ2_indexIntoF ( Int32, Int32* );
+
+extern Int32
+BZ2_decompress ( DState* );
+
+extern void
+BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
+ Int32, Int32, Int32 );
+
+
+#endif
+
+
+/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
+
+#ifdef BZ_NO_STDIO
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/compress.c b/dep/StormLib/src/bzip2/compress.c
new file mode 100644
index 00000000000..8c80a079700
--- /dev/null
+++ b/dep/StormLib/src/bzip2/compress.c
@@ -0,0 +1,672 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting) ---*/
+/*--- compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+/* CHANGES
+ 0.9.0 -- original version.
+ 0.9.0a/b -- no changes in this file.
+ 0.9.0c -- changed setting of nGroups in sendMTFValues()
+ so as to do a bit better on small files
+*/
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+ s->bsLive = 0;
+ s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+ while (s->bsLive > 0) {
+ s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+ s->numZ++;
+ s->bsBuff <<= 8;
+ s->bsLive -= 8;
+ }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz) \
+{ \
+ while (s->bsLive >= 8) { \
+ s->zbits[s->numZ] \
+ = (UChar)(s->bsBuff >> 24); \
+ s->numZ++; \
+ s->bsBuff <<= 8; \
+ s->bsLive -= 8; \
+ } \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+ bsNEEDW ( n );
+ s->bsBuff |= (v << (32 - s->bsLive - n));
+ s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+ bsW ( s, 8, (u >> 24) & 0xffL );
+ bsW ( s, 8, (u >> 16) & 0xffL );
+ bsW ( s, 8, (u >> 8) & 0xffL );
+ bsW ( s, 8, u & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+ bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+ Int32 i;
+ s->nInUse = 0;
+ for (i = 0; i < 256; i++)
+ if (s->inUse[i]) {
+ s->unseqToSeq[i] = s->nInUse;
+ s->nInUse++;
+ }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+ UChar yy[256];
+ Int32 i, j;
+ Int32 zPend;
+ Int32 wr;
+ Int32 EOB;
+
+ /*
+ After sorting (eg, here),
+ s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+ and
+ ((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
+ holds the original block data.
+
+ The first thing to do is generate the MTF values,
+ and put them in
+ ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+ Because there are strictly fewer or equal MTF values
+ than block values, ptr values in this area are overwritten
+ with MTF values only when they are no longer needed.
+
+ The final compressed bitstream is generated into the
+ area starting at
+ (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+ These storage aliases are set up in bzCompressInit(),
+ except for the last one, which is arranged in
+ compressBlock().
+ */
+ UInt32* ptr = s->ptr;
+ UChar* block = s->block;
+ UInt16* mtfv = s->mtfv;
+
+ makeMaps_e ( s );
+ EOB = s->nInUse+1;
+
+ for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+ wr = 0;
+ zPend = 0;
+ for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+ for (i = 0; i < s->nblock; i++) {
+ UChar ll_i;
+ AssertD ( wr <= i, "generateMTFValues(1)" );
+ j = ptr[i]-1; if (j < 0) j += s->nblock;
+ ll_i = s->unseqToSeq[block[j]];
+ AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+ if (yy[0] == ll_i) {
+ zPend++;
+ } else {
+
+ if (zPend > 0) {
+ zPend--;
+ while (True) {
+ if (zPend & 1) {
+ mtfv[wr] = BZ_RUNB; wr++;
+ s->mtfFreq[BZ_RUNB]++;
+ } else {
+ mtfv[wr] = BZ_RUNA; wr++;
+ s->mtfFreq[BZ_RUNA]++;
+ }
+ if (zPend < 2) break;
+ zPend = (zPend - 2) / 2;
+ };
+ zPend = 0;
+ }
+ {
+ register UChar rtmp;
+ register UChar* ryy_j;
+ register UChar rll_i;
+ rtmp = yy[1];
+ yy[1] = yy[0];
+ ryy_j = &(yy[1]);
+ rll_i = ll_i;
+ while ( rll_i != rtmp ) {
+ register UChar rtmp2;
+ ryy_j++;
+ rtmp2 = rtmp;
+ rtmp = *ryy_j;
+ *ryy_j = rtmp2;
+ };
+ yy[0] = rtmp;
+ j = ryy_j - &(yy[0]);
+ mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+ }
+
+ }
+ }
+
+ if (zPend > 0) {
+ zPend--;
+ while (True) {
+ if (zPend & 1) {
+ mtfv[wr] = BZ_RUNB; wr++;
+ s->mtfFreq[BZ_RUNB]++;
+ } else {
+ mtfv[wr] = BZ_RUNA; wr++;
+ s->mtfFreq[BZ_RUNA]++;
+ }
+ if (zPend < 2) break;
+ zPend = (zPend - 2) / 2;
+ };
+ zPend = 0;
+ }
+
+ mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+ s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST 0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+ Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+ Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+ Int32 nGroups, nBytes;
+
+ /*--
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ is a global since the decoder also needs it.
+
+ Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ are also globals only used in this proc.
+ Made global to keep stack frame size small.
+ --*/
+
+
+ UInt16 cost[BZ_N_GROUPS];
+ Int32 fave[BZ_N_GROUPS];
+
+ UInt16* mtfv = s->mtfv;
+
+ if (s->verbosity >= 3)
+ VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
+ "%d+2 syms in use\n",
+ s->nblock, s->nMTF, s->nInUse );
+
+ alphaSize = s->nInUse+2;
+ for (t = 0; t < BZ_N_GROUPS; t++)
+ for (v = 0; v < alphaSize; v++)
+ s->len[t][v] = BZ_GREATER_ICOST;
+
+ /*--- Decide how many coding tables to use ---*/
+ AssertH ( s->nMTF > 0, 3001 );
+ if (s->nMTF < 200) nGroups = 2; else
+ if (s->nMTF < 600) nGroups = 3; else
+ if (s->nMTF < 1200) nGroups = 4; else
+ if (s->nMTF < 2400) nGroups = 5; else
+ nGroups = 6;
+
+ /*--- Generate an initial set of coding tables ---*/
+ {
+ Int32 nPart, remF, tFreq, aFreq;
+
+ nPart = nGroups;
+ remF = s->nMTF;
+ gs = 0;
+ while (nPart > 0) {
+ tFreq = remF / nPart;
+ ge = gs-1;
+ aFreq = 0;
+ while (aFreq < tFreq && ge < alphaSize-1) {
+ ge++;
+ aFreq += s->mtfFreq[ge];
+ }
+
+ if (ge > gs
+ && nPart != nGroups && nPart != 1
+ && ((nGroups-nPart) % 2 == 1)) {
+ aFreq -= s->mtfFreq[ge];
+ ge--;
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf5( " initial group %d, [%d .. %d], "
+ "has %d syms (%4.1f%%)\n",
+ nPart, gs, ge, aFreq,
+ (100.0 * (float)aFreq) / (float)(s->nMTF) );
+
+ for (v = 0; v < alphaSize; v++)
+ if (v >= gs && v <= ge)
+ s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+ s->len[nPart-1][v] = BZ_GREATER_ICOST;
+
+ nPart--;
+ gs = ge+1;
+ remF -= aFreq;
+ }
+ }
+
+ /*---
+ Iterate up to BZ_N_ITERS times to improve the tables.
+ ---*/
+ for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+ for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+ for (t = 0; t < nGroups; t++)
+ for (v = 0; v < alphaSize; v++)
+ s->rfreq[t][v] = 0;
+
+ /*---
+ Set up an auxiliary length table which is used to fast-track
+ the common case (nGroups == 6).
+ ---*/
+ if (nGroups == 6) {
+ for (v = 0; v < alphaSize; v++) {
+ s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+ s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+ s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+ }
+ }
+
+ nSelectors = 0;
+ totc = 0;
+ gs = 0;
+ while (True) {
+
+ /*--- Set group start & end marks. --*/
+ if (gs >= s->nMTF) break;
+ ge = gs + BZ_G_SIZE - 1;
+ if (ge >= s->nMTF) ge = s->nMTF-1;
+
+ /*--
+ Calculate the cost of this group as coded
+ by each of the coding tables.
+ --*/
+ for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+ register UInt32 cost01, cost23, cost45;
+ register UInt16 icv;
+ cost01 = cost23 = cost45 = 0;
+
+# define BZ_ITER(nn) \
+ icv = mtfv[gs+(nn)]; \
+ cost01 += s->len_pack[icv][0]; \
+ cost23 += s->len_pack[icv][1]; \
+ cost45 += s->len_pack[icv][2]; \
+
+ BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
+ BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
+ BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+ BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+ BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+ BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+ BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+ BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+ BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+ BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+# undef BZ_ITER
+
+ cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+ cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+ cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++) {
+ UInt16 icv = mtfv[i];
+ for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+ }
+ }
+
+ /*--
+ Find the coding table which is best for this group,
+ and record its identity in the selector table.
+ --*/
+ bc = 999999999; bt = -1;
+ for (t = 0; t < nGroups; t++)
+ if (cost[t] < bc) { bc = cost[t]; bt = t; };
+ totc += bc;
+ fave[bt]++;
+ s->selector[nSelectors] = bt;
+ nSelectors++;
+
+ /*--
+ Increment the symbol frequencies for the selected table.
+ --*/
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+
+# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+ BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
+ BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
+ BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+ BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+ BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+ BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+ BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+ BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+ BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+ BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+# undef BZ_ITUR
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++)
+ s->rfreq[bt][ mtfv[i] ]++;
+ }
+
+ gs = ge+1;
+ }
+ if (s->verbosity >= 3) {
+ VPrintf2 ( " pass %d: size is %d, grp uses are ",
+ iter+1, totc/8 );
+ for (t = 0; t < nGroups; t++)
+ VPrintf1 ( "%d ", fave[t] );
+ VPrintf0 ( "\n" );
+ }
+
+ /*--
+ Recompute the tables based on the accumulated frequencies.
+ --*/
+ /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
+ comment in huffman.c for details. */
+ for (t = 0; t < nGroups; t++)
+ BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
+ alphaSize, 17 /*20*/ );
+ }
+
+
+ AssertH( nGroups < 8, 3002 );
+ AssertH( nSelectors < 32768 &&
+ nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+ 3003 );
+
+
+ /*--- Compute MTF values for the selectors. ---*/
+ {
+ UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+ for (i = 0; i < nGroups; i++) pos[i] = i;
+ for (i = 0; i < nSelectors; i++) {
+ ll_i = s->selector[i];
+ j = 0;
+ tmp = pos[j];
+ while ( ll_i != tmp ) {
+ j++;
+ tmp2 = tmp;
+ tmp = pos[j];
+ pos[j] = tmp2;
+ };
+ pos[0] = tmp;
+ s->selectorMtf[i] = j;
+ }
+ };
+
+ /*--- Assign actual codes for the tables. --*/
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+ if (s->len[t][i] < minLen) minLen = s->len[t][i];
+ }
+ AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+ AssertH ( !(minLen < 1), 3005 );
+ BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
+ minLen, maxLen, alphaSize );
+ }
+
+ /*--- Transmit the mapping table. ---*/
+ {
+ Bool inUse16[16];
+ for (i = 0; i < 16; i++) {
+ inUse16[i] = False;
+ for (j = 0; j < 16; j++)
+ if (s->inUse[i * 16 + j]) inUse16[i] = True;
+ }
+
+ nBytes = s->numZ;
+ for (i = 0; i < 16; i++)
+ if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+ for (i = 0; i < 16; i++)
+ if (inUse16[i])
+ for (j = 0; j < 16; j++) {
+ if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
+ }
+
+ /*--- Now the selectors. ---*/
+ nBytes = s->numZ;
+ bsW ( s, 3, nGroups );
+ bsW ( s, 15, nSelectors );
+ for (i = 0; i < nSelectors; i++) {
+ for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+ bsW(s,1,0);
+ }
+ if (s->verbosity >= 3)
+ VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+ /*--- Now the coding tables. ---*/
+ nBytes = s->numZ;
+
+ for (t = 0; t < nGroups; t++) {
+ Int32 curr = s->len[t][0];
+ bsW ( s, 5, curr );
+ for (i = 0; i < alphaSize; i++) {
+ while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+ while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+ bsW ( s, 1, 0 );
+ }
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+ /*--- And finally, the block data proper ---*/
+ nBytes = s->numZ;
+ selCtr = 0;
+ gs = 0;
+ while (True) {
+ if (gs >= s->nMTF) break;
+ ge = gs + BZ_G_SIZE - 1;
+ if (ge >= s->nMTF) ge = s->nMTF-1;
+ AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+ UInt16 mtfv_i;
+ UChar* s_len_sel_selCtr
+ = &(s->len[s->selector[selCtr]][0]);
+ Int32* s_code_sel_selCtr
+ = &(s->code[s->selector[selCtr]][0]);
+
+# define BZ_ITAH(nn) \
+ mtfv_i = mtfv[gs+(nn)]; \
+ bsW ( s, \
+ s_len_sel_selCtr[mtfv_i], \
+ s_code_sel_selCtr[mtfv_i] )
+
+ BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
+ BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
+ BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+ BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+ BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+ BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+ BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+ BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+ BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+ BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+# undef BZ_ITAH
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++) {
+ bsW ( s,
+ s->len [s->selector[selCtr]] [mtfv[i]],
+ s->code [s->selector[selCtr]] [mtfv[i]] );
+ }
+ }
+
+
+ gs = ge+1;
+ selCtr++;
+ }
+ AssertH( selCtr == nSelectors, 3007 );
+
+ if (s->verbosity >= 3)
+ VPrintf1( "codes %d\n", s->numZ-nBytes );
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+ if (s->nblock > 0) {
+
+ BZ_FINALISE_CRC ( s->blockCRC );
+ s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+ s->combinedCRC ^= s->blockCRC;
+ if (s->blockNo > 1) s->numZ = 0;
+
+ if (s->verbosity >= 2)
+ VPrintf4( " block %d: crc = 0x%08x, "
+ "combined CRC = 0x%08x, size = %d\n",
+ s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+ BZ2_blockSort ( s );
+ }
+
+ s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+ /*-- If this is the first block, create the stream header. --*/
+ if (s->blockNo == 1) {
+ BZ2_bsInitWrite ( s );
+ bsPutUChar ( s, BZ_HDR_B );
+ bsPutUChar ( s, BZ_HDR_Z );
+ bsPutUChar ( s, BZ_HDR_h );
+ bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+ }
+
+ if (s->nblock > 0) {
+
+ bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+ bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+ bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+ /*-- Now the block's CRC, so it is in a known place. --*/
+ bsPutUInt32 ( s, s->blockCRC );
+
+ /*--
+ Now a single bit indicating (non-)randomisation.
+ As of version 0.9.5, we use a better sorting algorithm
+ which makes randomisation unnecessary. So always set
+ the randomised bit to 'no'. Of course, the decoder
+ still needs to be able to handle randomised blocks
+ so as to maintain backwards compatibility with
+ older versions of bzip2.
+ --*/
+ bsW(s,1,0);
+
+ bsW ( s, 24, s->origPtr );
+ generateMTFValues ( s );
+ sendMTFValues ( s );
+ }
+
+
+ /*-- If this is the last block, add the stream trailer. --*/
+ if (is_last_block) {
+
+ bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+ bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+ bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+ bsPutUInt32 ( s, s->combinedCRC );
+ if (s->verbosity >= 2)
+ VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
+ bsFinishWrite ( s );
+ }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end compress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/crctable.c b/dep/StormLib/src/bzip2/crctable.c
new file mode 100644
index 00000000000..215687b2c05
--- /dev/null
+++ b/dep/StormLib/src/bzip2/crctable.c
@@ -0,0 +1,104 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for doing CRCs ---*/
+/*--- crctable.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+/*--
+ I think this is an implementation of the AUTODIN-II,
+ Ethernet & FDDI 32-bit CRC standard. Vaguely derived
+ from code by Rob Warnock, in Section 51 of the
+ comp.compression FAQ.
+--*/
+
+UInt32 BZ2_crc32Table[256] = {
+
+ /*-- Ugly, innit? --*/
+
+ 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
+ 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
+ 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
+ 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
+ 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
+ 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
+ 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
+ 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
+ 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
+ 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
+ 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
+ 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
+ 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
+ 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
+ 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
+ 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
+ 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
+ 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
+ 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
+ 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
+ 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
+ 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
+ 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
+ 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
+ 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
+ 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
+ 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
+ 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
+ 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
+ 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
+ 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
+ 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
+ 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
+ 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
+ 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
+ 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
+ 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
+ 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
+ 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
+ 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
+ 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
+ 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
+ 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
+ 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
+ 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
+ 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
+ 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
+ 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
+ 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
+ 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
+ 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
+ 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
+ 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
+ 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
+ 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
+ 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
+ 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
+ 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
+ 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
+ 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
+ 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
+ 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
+ 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
+ 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end crctable.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/decompress.c b/dep/StormLib/src/bzip2/decompress.c
new file mode 100644
index 00000000000..bba5e0fa36d
--- /dev/null
+++ b/dep/StormLib/src/bzip2/decompress.c
@@ -0,0 +1,626 @@
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery ---*/
+/*--- decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+ Int32 i;
+ s->nInUse = 0;
+ for (i = 0; i < 256; i++)
+ if (s->inUse[i]) {
+ s->seqToUnseq[s->nInUse] = i;
+ s->nInUse++;
+ }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr) \
+ { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn) \
+ case lll: s->state = lll; \
+ while (True) { \
+ if (s->bsLive >= nnn) { \
+ UInt32 v; \
+ v = (s->bsBuff >> \
+ (s->bsLive-nnn)) & ((1 << nnn)-1); \
+ s->bsLive -= nnn; \
+ vvv = v; \
+ break; \
+ } \
+ if (s->strm->avail_in == 0) RETURN(BZ_OK); \
+ s->bsBuff \
+ = (s->bsBuff << 8) | \
+ ((UInt32) \
+ (*((UChar*)(s->strm->next_in)))); \
+ s->bsLive += 8; \
+ s->strm->next_in++; \
+ s->strm->avail_in--; \
+ s->strm->total_in_lo32++; \
+ if (s->strm->total_in_lo32 == 0) \
+ s->strm->total_in_hi32++; \
+ }
+
+#define GET_UCHAR(lll,uuu) \
+ GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu) \
+ GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval) \
+{ \
+ if (groupPos == 0) { \
+ groupNo++; \
+ if (groupNo >= nSelectors) \
+ RETURN(BZ_DATA_ERROR); \
+ groupPos = BZ_G_SIZE; \
+ gSel = s->selector[groupNo]; \
+ gMinlen = s->minLens[gSel]; \
+ gLimit = &(s->limit[gSel][0]); \
+ gPerm = &(s->perm[gSel][0]); \
+ gBase = &(s->base[gSel][0]); \
+ } \
+ groupPos--; \
+ zn = gMinlen; \
+ GET_BITS(label1, zvec, zn); \
+ while (1) { \
+ if (zn > 20 /* the longest code */) \
+ RETURN(BZ_DATA_ERROR); \
+ if (zvec <= gLimit[zn]) break; \
+ zn++; \
+ GET_BIT(label2, zj); \
+ zvec = (zvec << 1) | zj; \
+ }; \
+ if (zvec - gBase[zn] < 0 \
+ || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
+ RETURN(BZ_DATA_ERROR); \
+ lval = gPerm[zvec - gBase[zn]]; \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+ UChar uc;
+ Int32 retVal;
+ Int32 minLen, maxLen;
+ bz_stream* strm = s->strm;
+
+ /* stuff that needs to be saved/restored */
+ Int32 i;
+ Int32 j;
+ Int32 t;
+ Int32 alphaSize;
+ Int32 nGroups;
+ Int32 nSelectors;
+ Int32 EOB;
+ Int32 groupNo;
+ Int32 groupPos;
+ Int32 nextSym;
+ Int32 nblockMAX;
+ Int32 nblock;
+ Int32 es;
+ Int32 N;
+ Int32 curr;
+ Int32 zt;
+ Int32 zn;
+ Int32 zvec;
+ Int32 zj;
+ Int32 gSel;
+ Int32 gMinlen;
+ Int32* gLimit;
+ Int32* gBase;
+ Int32* gPerm;
+
+ if (s->state == BZ_X_MAGIC_1) {
+ /*initialise the save area*/
+ s->save_i = 0;
+ s->save_j = 0;
+ s->save_t = 0;
+ s->save_alphaSize = 0;
+ s->save_nGroups = 0;
+ s->save_nSelectors = 0;
+ s->save_EOB = 0;
+ s->save_groupNo = 0;
+ s->save_groupPos = 0;
+ s->save_nextSym = 0;
+ s->save_nblockMAX = 0;
+ s->save_nblock = 0;
+ s->save_es = 0;
+ s->save_N = 0;
+ s->save_curr = 0;
+ s->save_zt = 0;
+ s->save_zn = 0;
+ s->save_zvec = 0;
+ s->save_zj = 0;
+ s->save_gSel = 0;
+ s->save_gMinlen = 0;
+ s->save_gLimit = NULL;
+ s->save_gBase = NULL;
+ s->save_gPerm = NULL;
+ }
+
+ /*restore from the save area*/
+ i = s->save_i;
+ j = s->save_j;
+ t = s->save_t;
+ alphaSize = s->save_alphaSize;
+ nGroups = s->save_nGroups;
+ nSelectors = s->save_nSelectors;
+ EOB = s->save_EOB;
+ groupNo = s->save_groupNo;
+ groupPos = s->save_groupPos;
+ nextSym = s->save_nextSym;
+ nblockMAX = s->save_nblockMAX;
+ nblock = s->save_nblock;
+ es = s->save_es;
+ N = s->save_N;
+ curr = s->save_curr;
+ zt = s->save_zt;
+ zn = s->save_zn;
+ zvec = s->save_zvec;
+ zj = s->save_zj;
+ gSel = s->save_gSel;
+ gMinlen = s->save_gMinlen;
+ gLimit = s->save_gLimit;
+ gBase = s->save_gBase;
+ gPerm = s->save_gPerm;
+
+ retVal = BZ_OK;
+
+ switch (s->state) {
+
+ GET_UCHAR(BZ_X_MAGIC_1, uc);
+ if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_2, uc);
+ if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_3, uc)
+ if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+ if (s->blockSize100k < (BZ_HDR_0 + 1) ||
+ s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
+ s->blockSize100k -= BZ_HDR_0;
+
+ if (s->smallDecompress) {
+ s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+ s->ll4 = BZALLOC(
+ ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
+ );
+ if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+ } else {
+ s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+ if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+ }
+
+ GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+ if (uc == 0x17) goto endhdr_2;
+ if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_2, uc);
+ if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_3, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_4, uc);
+ if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_5, uc);
+ if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_6, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+ s->currBlockNo++;
+ if (s->verbosity >= 2)
+ VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
+
+ s->storedBlockCRC = 0;
+ GET_UCHAR(BZ_X_BCRC_1, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_2, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_3, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_4, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+ GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+ s->origPtr = 0;
+ GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+ if (s->origPtr < 0)
+ RETURN(BZ_DATA_ERROR);
+ if (s->origPtr > 10 + 100000*s->blockSize100k)
+ RETURN(BZ_DATA_ERROR);
+
+ /*--- Receive the mapping table ---*/
+ for (i = 0; i < 16; i++) {
+ GET_BIT(BZ_X_MAPPING_1, uc);
+ if (uc == 1)
+ s->inUse16[i] = True; else
+ s->inUse16[i] = False;
+ }
+
+ for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+ for (i = 0; i < 16; i++)
+ if (s->inUse16[i])
+ for (j = 0; j < 16; j++) {
+ GET_BIT(BZ_X_MAPPING_2, uc);
+ if (uc == 1) s->inUse[i * 16 + j] = True;
+ }
+ makeMaps_d ( s );
+ if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+ alphaSize = s->nInUse+2;
+
+ /*--- Now the selectors ---*/
+ GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+ if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+ GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+ if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+ for (i = 0; i < nSelectors; i++) {
+ j = 0;
+ while (True) {
+ GET_BIT(BZ_X_SELECTOR_3, uc);
+ if (uc == 0) break;
+ j++;
+ if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+ }
+ s->selectorMtf[i] = j;
+ }
+
+ /*--- Undo the MTF values for the selectors. ---*/
+ {
+ UChar pos[BZ_N_GROUPS], tmp, v;
+ for (v = 0; v < nGroups; v++) pos[v] = v;
+
+ for (i = 0; i < nSelectors; i++) {
+ v = s->selectorMtf[i];
+ tmp = pos[v];
+ while (v > 0) { pos[v] = pos[v-1]; v--; }
+ pos[0] = tmp;
+ s->selector[i] = tmp;
+ }
+ }
+
+ /*--- Now the coding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ GET_BITS(BZ_X_CODING_1, curr, 5);
+ for (i = 0; i < alphaSize; i++) {
+ while (True) {
+ if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+ GET_BIT(BZ_X_CODING_2, uc);
+ if (uc == 0) break;
+ GET_BIT(BZ_X_CODING_3, uc);
+ if (uc == 0) curr++; else curr--;
+ }
+ s->len[t][i] = curr;
+ }
+ }
+
+ /*--- Create the Huffman decoding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+ if (s->len[t][i] < minLen) minLen = s->len[t][i];
+ }
+ BZ2_hbCreateDecodeTables (
+ &(s->limit[t][0]),
+ &(s->base[t][0]),
+ &(s->perm[t][0]),
+ &(s->len[t][0]),
+ minLen, maxLen, alphaSize
+ );
+ s->minLens[t] = minLen;
+ }
+
+ /*--- Now the MTF values ---*/
+
+ EOB = s->nInUse+1;
+ nblockMAX = 100000 * s->blockSize100k;
+ groupNo = -1;
+ groupPos = 0;
+
+ for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+ /*-- MTF init --*/
+ {
+ Int32 ii, jj, kk;
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ /*-- end MTF init --*/
+
+ nblock = 0;
+ GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+ while (True) {
+
+ if (nextSym == EOB) break;
+
+ if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+ es = -1;
+ N = 1;
+ do {
+ if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+ if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+ N = N * 2;
+ GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+ }
+ while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+ es++;
+ uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+ s->unzftab[uc] += es;
+
+ if (s->smallDecompress)
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->ll16[nblock] = (UInt16)uc;
+ nblock++;
+ es--;
+ }
+ else
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->tt[nblock] = (UInt32)uc;
+ nblock++;
+ es--;
+ };
+
+ continue;
+
+ } else {
+
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+ /*-- uc = MTF ( nextSym-1 ) --*/
+ {
+ Int32 ii, jj, kk, pp, lno, off;
+ UInt32 nn;
+ nn = (UInt32)(nextSym - 1);
+
+ if (nn < MTFL_SIZE) {
+ /* avoid general-case expense */
+ pp = s->mtfbase[0];
+ uc = s->mtfa[pp+nn];
+ while (nn > 3) {
+ Int32 z = pp+nn;
+ s->mtfa[(z) ] = s->mtfa[(z)-1];
+ s->mtfa[(z)-1] = s->mtfa[(z)-2];
+ s->mtfa[(z)-2] = s->mtfa[(z)-3];
+ s->mtfa[(z)-3] = s->mtfa[(z)-4];
+ nn -= 4;
+ }
+ while (nn > 0) {
+ s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
+ };
+ s->mtfa[pp] = uc;
+ } else {
+ /* general case */
+ lno = nn / MTFL_SIZE;
+ off = nn % MTFL_SIZE;
+ pp = s->mtfbase[lno] + off;
+ uc = s->mtfa[pp];
+ while (pp > s->mtfbase[lno]) {
+ s->mtfa[pp] = s->mtfa[pp-1]; pp--;
+ };
+ s->mtfbase[lno]++;
+ while (lno > 0) {
+ s->mtfbase[lno]--;
+ s->mtfa[s->mtfbase[lno]]
+ = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+ lno--;
+ }
+ s->mtfbase[0]--;
+ s->mtfa[s->mtfbase[0]] = uc;
+ if (s->mtfbase[0] == 0) {
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ }
+ }
+ /*-- end uc = MTF ( nextSym-1 ) --*/
+
+ s->unzftab[s->seqToUnseq[uc]]++;
+ if (s->smallDecompress)
+ s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+ s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
+ nblock++;
+
+ GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+ continue;
+ }
+ }
+
+ /* Now we know what nblock is, we can do a better sanity
+ check on s->origPtr.
+ */
+ if (s->origPtr < 0 || s->origPtr >= nblock)
+ RETURN(BZ_DATA_ERROR);
+
+ /*-- Set up cftab to facilitate generation of T^(-1) --*/
+ s->cftab[0] = 0;
+ for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+ for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+ for (i = 0; i <= 256; i++) {
+ if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
+ /* s->cftab[i] can legitimately be == nblock */
+ RETURN(BZ_DATA_ERROR);
+ }
+ }
+
+ s->state_out_len = 0;
+ s->state_out_ch = 0;
+ BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+ s->state = BZ_X_OUTPUT;
+ if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+ if (s->smallDecompress) {
+
+ /*-- Make a copy of cftab, used in generation of T --*/
+ for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+ /*-- compute the T vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->ll16[i]);
+ SET_LL(i, s->cftabCopy[uc]);
+ s->cftabCopy[uc]++;
+ }
+
+ /*-- Compute T^(-1) by pointer reversal on T --*/
+ i = s->origPtr;
+ j = GET_LL(i);
+ do {
+ Int32 tmp = GET_LL(j);
+ SET_LL(j, i);
+ i = j;
+ j = tmp;
+ }
+ while (i != s->origPtr);
+
+ s->tPos = s->origPtr;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ }
+
+ } else {
+
+ /*-- compute the T^(-1) vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->tt[i] & 0xff);
+ s->tt[s->cftab[uc]] |= (i << 8);
+ s->cftab[uc]++;
+ }
+
+ s->tPos = s->tt[s->origPtr] >> 8;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ }
+
+ }
+
+ RETURN(BZ_OK);
+
+
+
+ endhdr_2:
+
+ GET_UCHAR(BZ_X_ENDHDR_2, uc);
+ if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_3, uc);
+ if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_4, uc);
+ if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_5, uc);
+ if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_6, uc);
+ if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+ s->storedCombinedCRC = 0;
+ GET_UCHAR(BZ_X_CCRC_1, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_2, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_3, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_4, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+ s->state = BZ_X_IDLE;
+ RETURN(BZ_STREAM_END);
+
+ default: AssertH ( False, 4001 );
+ }
+
+ AssertH ( False, 4002 );
+
+ save_state_and_return:
+
+ s->save_i = i;
+ s->save_j = j;
+ s->save_t = t;
+ s->save_alphaSize = alphaSize;
+ s->save_nGroups = nGroups;
+ s->save_nSelectors = nSelectors;
+ s->save_EOB = EOB;
+ s->save_groupNo = groupNo;
+ s->save_groupPos = groupPos;
+ s->save_nextSym = nextSym;
+ s->save_nblockMAX = nblockMAX;
+ s->save_nblock = nblock;
+ s->save_es = es;
+ s->save_N = N;
+ s->save_curr = curr;
+ s->save_zt = zt;
+ s->save_zn = zn;
+ s->save_zvec = zvec;
+ s->save_zj = zj;
+ s->save_gSel = gSel;
+ s->save_gMinlen = gMinlen;
+ s->save_gLimit = gLimit;
+ s->save_gBase = gBase;
+ s->save_gPerm = gPerm;
+
+ return retVal;
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end decompress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/huffman.c b/dep/StormLib/src/bzip2/huffman.c
new file mode 100644
index 00000000000..87e79e38af0
--- /dev/null
+++ b/dep/StormLib/src/bzip2/huffman.c
@@ -0,0 +1,205 @@
+
+/*-------------------------------------------------------------*/
+/*--- Huffman coding low-level stuff ---*/
+/*--- huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------------*/
+#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
+#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
+#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
+
+#define ADDWEIGHTS(zw1,zw2) \
+ (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
+ (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
+
+#define UPHEAP(z) \
+{ \
+ Int32 zz, tmp; \
+ zz = z; tmp = heap[zz]; \
+ while (weight[tmp] < weight[heap[zz >> 1]]) { \
+ heap[zz] = heap[zz >> 1]; \
+ zz >>= 1; \
+ } \
+ heap[zz] = tmp; \
+}
+
+#define DOWNHEAP(z) \
+{ \
+ Int32 zz, yy, tmp; \
+ zz = z; tmp = heap[zz]; \
+ while (True) { \
+ yy = zz << 1; \
+ if (yy > nHeap) break; \
+ if (yy < nHeap && \
+ weight[heap[yy+1]] < weight[heap[yy]]) \
+ yy++; \
+ if (weight[tmp] < weight[heap[yy]]) break; \
+ heap[zz] = heap[yy]; \
+ zz = yy; \
+ } \
+ heap[zz] = tmp; \
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbMakeCodeLengths ( UChar *len,
+ Int32 *freq,
+ Int32 alphaSize,
+ Int32 maxLen )
+{
+ /*--
+ Nodes and heap entries run from 1. Entry 0
+ for both the heap and nodes is a sentinel.
+ --*/
+ Int32 nNodes, nHeap, n1, n2, i, j, k;
+ Bool tooLong;
+
+ Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
+ Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
+ Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
+
+ for (i = 0; i < alphaSize; i++)
+ weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+
+ while (True) {
+
+ nNodes = alphaSize;
+ nHeap = 0;
+
+ heap[0] = 0;
+ weight[0] = 0;
+ parent[0] = -2;
+
+ for (i = 1; i <= alphaSize; i++) {
+ parent[i] = -1;
+ nHeap++;
+ heap[nHeap] = i;
+ UPHEAP(nHeap);
+ }
+
+ AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
+
+ while (nHeap > 1) {
+ n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+ n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+ nNodes++;
+ parent[n1] = parent[n2] = nNodes;
+ weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
+ parent[nNodes] = -1;
+ nHeap++;
+ heap[nHeap] = nNodes;
+ UPHEAP(nHeap);
+ }
+
+ AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
+
+ tooLong = False;
+ for (i = 1; i <= alphaSize; i++) {
+ j = 0;
+ k = i;
+ while (parent[k] >= 0) { k = parent[k]; j++; }
+ len[i-1] = j;
+ if (j > maxLen) tooLong = True;
+ }
+
+ if (! tooLong) break;
+
+ /* 17 Oct 04: keep-going condition for the following loop used
+ to be 'i < alphaSize', which missed the last element,
+ theoretically leading to the possibility of the compressor
+ looping. However, this count-scaling step is only needed if
+ one of the generated Huffman code words is longer than
+ maxLen, which up to and including version 1.0.2 was 20 bits,
+ which is extremely unlikely. In version 1.0.3 maxLen was
+ changed to 17 bits, which has minimal effect on compression
+ ratio, but does mean this scaling step is used from time to
+ time, enough to verify that it works.
+
+ This means that bzip2-1.0.3 and later will only produce
+ Huffman codes with a maximum length of 17 bits. However, in
+ order to preserve backwards compatibility with bitstreams
+ produced by versions pre-1.0.3, the decompressor must still
+ handle lengths of up to 20. */
+
+ for (i = 1; i <= alphaSize; i++) {
+ j = weight[i] >> 8;
+ j = 1 + (j / 2);
+ weight[i] = j << 8;
+ }
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbAssignCodes ( Int32 *code,
+ UChar *length,
+ Int32 minLen,
+ Int32 maxLen,
+ Int32 alphaSize )
+{
+ Int32 n, vec, i;
+
+ vec = 0;
+ for (n = minLen; n <= maxLen; n++) {
+ for (i = 0; i < alphaSize; i++)
+ if (length[i] == n) { code[i] = vec; vec++; };
+ vec <<= 1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbCreateDecodeTables ( Int32 *limit,
+ Int32 *base,
+ Int32 *perm,
+ UChar *length,
+ Int32 minLen,
+ Int32 maxLen,
+ Int32 alphaSize )
+{
+ Int32 pp, i, j, vec;
+
+ pp = 0;
+ for (i = minLen; i <= maxLen; i++)
+ for (j = 0; j < alphaSize; j++)
+ if (length[j] == i) { perm[pp] = j; pp++; };
+
+ for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
+ for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
+
+ for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
+
+ for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
+ vec = 0;
+
+ for (i = minLen; i <= maxLen; i++) {
+ vec += (base[i+1] - base[i]);
+ limit[i] = vec-1;
+ vec <<= 1;
+ }
+ for (i = minLen + 1; i <= maxLen; i++)
+ base[i] = ((limit[i-1] + 1) << 1) - base[i];
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end huffman.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/bzip2/randtable.c b/dep/StormLib/src/bzip2/randtable.c
new file mode 100644
index 00000000000..068b76367bc
--- /dev/null
+++ b/dep/StormLib/src/bzip2/randtable.c
@@ -0,0 +1,84 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for randomising repetitive blocks ---*/
+/*--- randtable.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------*/
+Int32 BZ2_rNums[512] = {
+ 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+ 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+ 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+ 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+ 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+ 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+ 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+ 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+ 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+ 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+ 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+ 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+ 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+ 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+ 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+ 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+ 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+ 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+ 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+ 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+ 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+ 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+ 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+ 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+ 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+ 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+ 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+ 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+ 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+ 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+ 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+ 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+ 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+ 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+ 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+ 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+ 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+ 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+ 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+ 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+ 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+ 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+ 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+ 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+ 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+ 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+ 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+ 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+ 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+ 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+ 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+ 936, 638
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end randtable.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/dep/StormLib/src/huffman/huff.cpp b/dep/StormLib/src/huffman/huff.cpp
new file mode 100644
index 00000000000..66a46b3fa55
--- /dev/null
+++ b/dep/StormLib/src/huffman/huff.cpp
@@ -0,0 +1,1303 @@
+/*****************************************************************************/
+/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains Huffmann (de)compression methods */
+/* */
+/* Authors : Ladislav Zezula (ladik@zezula.net) */
+/* ShadowFlare (BlakFlare@hotmail.com) */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */
+/* 03.05.03 1.00 Lad Added compression methods */
+/* 19.11.03 1.01 Dan Big endian handling */
+/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
+/*****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "huff.h"
+
+// Special for Mac - we have to know if normal pointer greater or less
+// than 0x80000000. This variable is used in the PTR_VALID and PTR_INVALID
+// macros
+static long mul = 1;
+
+#define PTR_VALID(ptr) (((LONG_PTR)(ptr) * mul) > 0)
+#define PTR_INVALID(ptr) (((LONG_PTR)(ptr) * mul) < 0)
+#define PTR_INVALID_OR_NULL(ptr) (((LONG_PTR)(ptr) * mul) <= 0)
+
+
+//-----------------------------------------------------------------------------
+// Methods of the THTreeItem struct
+
+// 1501DB70
+THTreeItem * THTreeItem::Call1501DB70(THTreeItem * pLast)
+{
+ if(pLast == NULL)
+ pLast = this + 1;
+ return pLast;
+}
+
+// Gets previous Huffman tree item (?)
+THTreeItem * THTreeItem::GetPrevItem(LONG_PTR value)
+{
+ if(PTR_INVALID(prev))
+ return PTR_NOT(prev);
+
+ if(value == -1 || PTR_INVALID(value))
+ value = (LONG_PTR)(this - next->prev);
+ return prev + value;
+
+// OLD VERSION
+// if(PTR_INT(value) < 0)
+// value = PTR_INT((item - item->next->prev));
+// return (THTreeItem *)((char *)prev + value);
+}
+
+// 1500F5E0
+void THTreeItem::ClearItemLinks()
+{
+ next = prev = NULL;
+}
+
+// 1500BC90
+void THTreeItem::RemoveItem()
+{
+ THTreeItem * pTemp; // EDX
+
+ if(next != NULL)
+ {
+ pTemp = prev;
+
+ if(PTR_INVALID_OR_NULL(pTemp))
+ pTemp = PTR_NOT(pTemp);
+ else
+ pTemp += (this - next->prev);
+
+ pTemp->next = next;
+ next->prev = prev;
+ next = prev = NULL;
+ }
+}
+
+/*
+// OLD VERSION : Removes item from the tree (?)
+static void RemoveItem(THTreeItem * item)
+{
+ THTreeItem * next = item->next; // ESI
+ THTreeItem * prev = item->prev; // EDX
+
+ if(next == NULL)
+ return;
+
+ if(PTR_INT(prev) < 0)
+ prev = PTR_NOT(prev);
+ else
+ // ??? usually item == next->prev, so what is it ?
+ prev = (THTreeItem *)((unsigned char *)prev + (unsigned long)((unsigned char *)item - (unsigned char *)(next->prev)));
+
+ // Remove HTree item from the chain
+ prev->next = next; // Sets the 'first' pointer
+ next->prev = item->prev;
+
+ // Invalidate pointers
+ item->next = NULL;
+ item->prev = NULL;
+}
+*/
+
+//-----------------------------------------------------------------------------
+// TOutputStream functions
+
+void TOutputStream::PutBits(unsigned long dwBuff, unsigned int nPutBits)
+{
+ dwBitBuff |= (dwBuff << nBits);
+ nBits += nPutBits;
+
+ // Flush completed bytes
+ while(nBits >= 8)
+ {
+ if(cbOutSize != 0)
+ {
+ *pbOutPos++ = (unsigned char)dwBitBuff;
+ cbOutSize--;
+ }
+
+ dwBitBuff >>= 8;
+ nBits -= 8;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TInputStream functions
+
+// Gets one bit from input stream
+unsigned long TInputStream::GetBit()
+{
+ unsigned long dwOneBit = 0;
+
+ // Ensure that the input stream is reloaded, if there are no bits left
+ if(BitCount == 0)
+ {
+ // Refill the bit buffer
+ BitBuffer = *pbInBuffer++;
+ BitCount = 8;
+ }
+
+ // Copy the bit from bit buffer to the variable
+ dwOneBit = (BitBuffer & 0x01);
+ BitBuffer >>= 1;
+ BitCount--;
+
+ return dwOneBit;
+}
+
+// Gets 7 bits from the stream. DOES NOT remove the bits from input stream
+unsigned long TInputStream::Get7Bits()
+{
+ unsigned long dwReloadByte = 0;
+
+ // If there is not enough bits to get the value,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < 7)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Return the first available 7 bits. DO NOT remove them from the input stream
+ return (BitBuffer & 0x7F);
+}
+
+// Gets the whole byte from the input stream.
+unsigned long TInputStream::Get8Bits()
+{
+ unsigned long dwReloadByte = 0;
+ unsigned long dwOneByte = 0;
+
+ // If there is not enough bits to get the value,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < 8)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Return the lowest 8 its
+ dwOneByte = (BitBuffer & 0xFF);
+ BitBuffer >>= 8;
+ BitCount -= 8;
+ return dwOneByte;
+}
+
+void TInputStream::SkipBits(unsigned int dwBitsToSkip)
+{
+ unsigned long dwReloadByte = 0;
+
+ // If there is not enough bits in the buffer,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < dwBitsToSkip)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Skip the remaining bits
+ BitBuffer >>= dwBitsToSkip;
+ BitCount -= dwBitsToSkip;
+}
+
+//-----------------------------------------------------------------------------
+// Functions for huffmann tree items
+
+// Inserts item into the tree (?)
+static void InsertItem(THTreeItem ** itemPtr, THTreeItem * item, unsigned long nWhere, THTreeItem * item2)
+{
+ THTreeItem * next = item->next; // EDI - next to the first item
+ THTreeItem * prev = item->prev; // ESI - prev to the first item
+ THTreeItem * prev2; // Pointer to previous item
+ LONG_PTR next2; // Pointer to the next item
+
+ // The same code like in RemoveItem(item);
+ if(next != 0) // If the first item already has next one
+ {
+ if(PTR_INVALID(prev))
+ prev = PTR_NOT(prev);
+ else
+ prev += (item - next->prev);
+
+ // 150083C1
+ // Remove the item from the tree
+ prev->next = next;
+ next->prev = prev;
+
+ // Invalidate 'prev' and 'next' pointer
+ item->next = 0;
+ item->prev = 0;
+ }
+
+ if(item2 == NULL) // EDX - If the second item is not entered,
+ item2 = PTR_PTR(&itemPtr[1]); // take the first tree item
+
+ switch(nWhere)
+ {
+ case SWITCH_ITEMS : // Switch the two items
+ item->next = item2->next; // item2->next (Pointer to pointer to first)
+ item->prev = item2->next->prev;
+ item2->next->prev = item;
+ item2->next = item; // Set the first item
+ return;
+
+ case INSERT_ITEM: // Insert as the last item
+ item->next = item2; // Set next item (or pointer to pointer to first item)
+ item->prev = item2->prev; // Set prev item (or last item in the tree)
+
+ next2 = PTR_INT(itemPtr[0]);// Usually NULL
+ prev2 = item2->prev; // Prev item to the second (or last tree item)
+
+ if(PTR_INVALID(prev2))
+ {
+ if(prev != NULL)
+ {
+ prev2 = PTR_NOT(prev);
+ if(prev2 != NULL)
+ {
+ prev2->next = item;
+ item2->prev = item; // Next after last item
+ }
+ }
+ return;
+ }
+
+ if(PTR_INVALID(next2))
+ next2 = (LONG_PTR)(item2 - item2->next->prev);
+// next2 = (THTreeItem *)(unsigned long)((unsigned char *)item2 - (unsigned char *)(item2->next->prev));
+
+// prev2 = (THTreeItem *)((char *)prev2 + (unsigned long)next2);// ???
+ prev2 += next2;
+ prev2->next = item;
+ item2->prev = item; // Set the next/last item
+ return;
+
+ default:
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// THuffmannTree class functions
+
+THuffmannTree::THuffmannTree()
+{
+ // We have to check if the "this" pointer is less than zero
+ if((LONG_PTR)this < 0)
+ mul = -1;
+}
+
+void THuffmannTree::InitTree(bool bCompression)
+{
+ THTreeItem * pItem;
+ unsigned int nCount;
+
+ // Clear links for all the items in the tree
+ for(pItem = items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
+ pItem->ClearItemLinks();
+
+ pItem3050 = NULL;
+ pItem3054 = PTR_PTR(&pItem3054);
+ pItem3058 = PTR_NOT(pItem3054);
+
+ pItem305C = NULL;
+ pFirst = PTR_PTR(&pFirst);
+ pLast = PTR_NOT(pFirst);
+
+ offs0004 = 1;
+ nItems = 0;
+
+ // Clear all TQDecompress items. Do this only if preparing for decompression
+ if(bCompression == false)
+ {
+ for(nCount = 0; nCount < sizeof(qd3474) / sizeof(TQDecompress); nCount++)
+ qd3474[nCount].offs00 = 0;
+ }
+}
+
+// Builds Huffman tree. Called with the first 8 bits loaded from input stream
+void THuffmannTree::BuildTree(unsigned int nCmpType)
+{
+ unsigned long maxByte; // [ESP+10] - The greatest character found in table
+ THTreeItem ** itemPtr; // [ESP+14] - Pointer to Huffman tree item pointer array
+ unsigned char * byteArray; // [ESP+1C] - Pointer to unsigned char in Table1502A630
+ THTreeItem * child1;
+ unsigned long i; // egcs in linux doesn't like multiple for loops without an explicit i
+
+ // Loop while pointer has a valid value
+ while(PTR_VALID(pLast)) // ESI - Last entry
+ {
+ THTreeItem * temp; // EAX
+
+ if(pLast->next != NULL) // ESI->next
+ pLast->RemoveItem();
+ // EDI = &offs3054
+ pItem3058 = PTR_PTR(&pItem3054); // [EDI+4]
+ pLast->prev = pItem3058; // EAX
+
+ temp = PTR_PTR(&pItem3054)->GetPrevItem(PTR_INT(&pItem3050));
+
+ temp->next = pLast;
+ pItem3054 = pLast;
+ }
+
+ // Clear all pointers in HTree item array
+ memset(items306C, 0, sizeof(items306C));
+
+ maxByte = 0; // Greatest character found init to zero.
+ itemPtr = (THTreeItem **)&items306C; // Pointer to current entry in HTree item pointer array
+
+ // Ensure we have low 8 bits only
+ nCmpType &= 0xFF;
+ byteArray = Table1502A630 + nCmpType * 258; // EDI also
+
+ for(i = 0; i < 0x100; i++, itemPtr++)
+ {
+ THTreeItem * item = pItem3058; // Item to be created
+ THTreeItem * pItem3 = pItem3058;
+ unsigned char oneByte = byteArray[i];
+
+ // Skip all the bytes which are zero.
+ if(byteArray[i] == 0)
+ continue;
+
+ // If not valid pointer, take the first available item in the array
+ if(PTR_INVALID_OR_NULL(item))
+ item = &items0008[nItems++];
+
+ // Insert this item as the top of the tree
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ item->parent = NULL; // Invalidate child and parent
+ item->child = NULL;
+ *itemPtr = item; // Store pointer into pointer array
+
+ item->dcmpByte = i; // Store counter
+ item->byteValue = oneByte; // Store byte value
+ if(oneByte >= maxByte)
+ {
+ maxByte = oneByte;
+ continue;
+ }
+
+ // Find the first item which has byte value greater than current one byte
+ if(PTR_VALID(pItem3 = pLast)) // EDI - Pointer to the last item
+ {
+ // 15006AF7
+ if(pItem3 != NULL)
+ {
+ do // 15006AFB
+ {
+ if(pItem3->byteValue >= oneByte)
+ goto _15006B09;
+ pItem3 = pItem3->prev;
+ }
+ while(PTR_VALID(pItem3));
+ }
+ }
+ pItem3 = NULL;
+
+ // 15006B09
+ _15006B09:
+ if(item->next != NULL)
+ item->RemoveItem();
+
+ // 15006B15
+ if(pItem3 == NULL)
+ pItem3 = PTR_PTR(&pFirst);
+
+ // 15006B1F
+ item->next = pItem3->next;
+ item->prev = pItem3->next->prev;
+ pItem3->next->prev = item;
+ pItem3->next = item;
+ }
+
+ // 15006B4A
+ for(; i < 0x102; i++)
+ {
+ THTreeItem ** itemPtr = &items306C[i]; // EDI
+
+ // 15006B59
+ THTreeItem * item = pItem3058; // ESI
+ if(PTR_INVALID_OR_NULL(item))
+ item = &items0008[nItems++];
+
+ InsertItem(&pItem305C, item, INSERT_ITEM, NULL);
+
+ // 15006B89
+ item->dcmpByte = i;
+ item->byteValue = 1;
+ item->parent = NULL;
+ item->child = NULL;
+ *itemPtr++ = item;
+ }
+
+ // 15006BAA
+ if(PTR_VALID(child1 = pLast)) // EDI - last item (first child to item
+ {
+ THTreeItem * child2; // EBP
+ THTreeItem * item; // ESI
+
+ // 15006BB8
+ while(PTR_VALID(child2 = child1->prev))
+ {
+ if(PTR_INVALID_OR_NULL(item = pItem3058))
+ item = &items0008[nItems++];
+
+ // 15006BE3
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ // 15006BF3
+ item->parent = NULL;
+ item->child = NULL;
+
+ //EDX = child2->byteValue + child1->byteValue;
+ //EAX = child1->byteValue;
+ //ECX = maxByte; // The greatest character (0xFF usually)
+
+ item->byteValue = child1->byteValue + child2->byteValue; // 0x02
+ item->child = child1; // Prev item in the
+ child1->parent = item;
+ child2->parent = item;
+
+ // EAX = item->byteValue;
+ if(item->byteValue >= maxByte)
+ maxByte = item->byteValue;
+ else
+ {
+ THTreeItem * pItem2 = child2->prev; // EDI
+
+ // 15006C2D
+ while(PTR_VALID(pItem2))
+ {
+ if(pItem2->byteValue >= item->byteValue)
+ goto _15006C3B;
+ pItem2 = pItem2->prev;
+ }
+ pItem2 = NULL;
+
+ _15006C3B:
+ if(item->next != 0)
+ {
+ THTreeItem * temp4 = item->GetPrevItem(-1);
+
+ temp4->next = item->next; // The first item changed
+ item->next->prev = item->prev; // First->prev changed to negative value
+ item->next = NULL;
+ item->prev = NULL;
+ }
+
+ // 15006C62
+ if(pItem2 == NULL)
+ pItem2 = PTR_PTR(&pFirst);
+
+ item->next = pItem2->next; // Set item with 0x100 byte value
+ item->prev = pItem2->next->prev; // Set item with 0x17 byte value
+ pItem2->next->prev = item; // Changed prev of item with
+ pItem2->next = item;
+ }
+
+ // 15006C7B
+ if(PTR_INVALID_OR_NULL(child1 = child2->prev))
+ break;
+ }
+ }
+ // 15006C88
+ offs0004 = 1;
+}
+/*
+// Modifies Huffman tree. Adds new item and changes
+void THuffmannTree::ModifyTree(unsigned long dwIndex)
+{
+ THTreeItem * pItem1 = pItem3058; // ESI
+ THTreeItem * pSaveLast = (PTR_INT(pLast) <= 0) ? NULL : pLast; // EBX
+ THTreeItem * temp; // EAX
+
+ // Prepare the first item to insert to the tree
+ if(PTR_INT(pItem1) <= 0)
+ pItem1 = &items0008[nItems++];
+
+ // If item has any next item, remove it from the chain
+ if(pItem1->next != NULL)
+ {
+ THTreeItem * temp = pItem1->GetPrevItem(-1); // EAX
+
+ temp->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ pItem1->next = PTR_PTR(&pFirst);
+ pItem1->prev = pLast;
+ temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C));
+
+ // 150068E9
+ temp->next = pItem1;
+ pLast = pItem1;
+
+ pItem1->parent = NULL;
+ pItem1->child = NULL;
+
+ // 150068F6
+ pItem1->dcmpByte = pSaveLast->dcmpByte; // Copy item index
+ pItem1->byteValue = pSaveLast->byteValue; // Copy item byte value
+ pItem1->parent = pSaveLast; // Set parent to last item
+ items306C[pSaveLast->dcmpByte] = pItem1; // Insert item into item pointer array
+
+ // Prepare the second item to insert into the tree
+ if(PTR_INT((pItem1 = pItem3058)) <= 0)
+ pItem1 = &items0008[nItems++];
+
+ // 1500692E
+ if(pItem1->next != NULL)
+ {
+ temp = pItem1->GetPrevItem(-1); // EAX
+
+ temp->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+ // 1500694C
+ pItem1->next = PTR_PTR(&pFirst);
+ pItem1->prev = pLast;
+ temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C));
+
+ // 15006968
+ temp->next = pItem1;
+ pLast = pItem1;
+
+ // 1500696E
+ pItem1->child = NULL;
+ pItem1->dcmpByte = dwIndex;
+ pItem1->byteValue = 0;
+ pItem1->parent = pSaveLast;
+ pSaveLast->child = pItem1;
+ items306C[dwIndex] = pItem1;
+
+ do
+ {
+ THTreeItem * pItem2 = pItem1;
+ THTreeItem * pItem3;
+ unsigned long byteValue;
+
+ // 15006993
+ byteValue = ++pItem1->byteValue;
+
+ // Pass through all previous which have its value greater than byteValue
+ while(PTR_INT((pItem3 = pItem2->prev)) > 0) // EBX
+ {
+ if(pItem3->byteValue >= byteValue)
+ goto _150069AE;
+
+ pItem2 = pItem2->prev;
+ }
+ // 150069AC
+ pItem3 = NULL;
+
+ _150069AE:
+ if(pItem2 == pItem1)
+ continue;
+
+ // 150069B2
+ // Switch pItem2 with item
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ // 150069D0
+ // Switch parents of pItem1 and pItem2
+ temp = pItem2->parent->child;
+ if(pItem1 == pItem1->parent->child)
+ pItem1->parent->child = pItem2;
+
+ if(pItem2 == temp)
+ pItem2->parent->child = pItem1;
+
+ // 150069ED
+ // Switch parents of pItem1 and pItem3
+ temp = pItem1->parent;
+ pItem1 ->parent = pItem2->parent;
+ pItem2->parent = temp;
+ offs0004++;
+ }
+ while(PTR_INT((pItem1 = pItem1->parent)) > 0);
+}
+
+void THuffmannTree::UninitTree()
+{
+ while(PTR_INT(pLast) > 0)
+ {
+ pItem = pItem305C->Call1501DB70(pLast);
+ pItem->RemoveItem();
+ }
+
+ for(pItem = pFirst; PTR_INT(pItem3058) > 0; pItem = pItem3058)
+ pItem->RemoveItem();
+ PTR_PTR(&pItem3054)->RemoveItem();
+
+ for(pItem = items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
+ {
+ pItem--;
+ pItem->RemoveItem();
+ pItem->RemoveItem();
+ }
+}
+*/
+
+THTreeItem * THuffmannTree::Call1500E740(unsigned int nValue)
+{
+ THTreeItem * pItem1 = pItem3058; // EDX
+ THTreeItem * pItem2; // EAX
+ THTreeItem * pNext;
+ THTreeItem * pPrev;
+ THTreeItem ** ppItem;
+
+ if(PTR_INVALID_OR_NULL(pItem1) || (pItem2 = pItem1) == NULL)
+ {
+ if((pItem2 = &items0008[nItems++]) != NULL)
+ pItem1 = pItem2;
+ else
+ pItem1 = pFirst;
+ }
+ else
+ pItem1 = pItem2;
+
+ pNext = pItem1->next;
+ if(pNext != NULL)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INVALID_OR_NULL(pPrev))
+ pPrev = PTR_NOT(pPrev);
+ else
+ pPrev += (pItem1 - pItem1->next->prev);
+
+ pPrev->next = pNext;
+ pNext->prev = pPrev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ ppItem = &pFirst; // esi
+ if(nValue > 1)
+ {
+ // ecx = pFirst->next;
+ pItem1->next = *ppItem;
+ pItem1->prev = (*ppItem)->prev;
+
+ (*ppItem)->prev = pItem2;
+ *ppItem = pItem1;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ pItem1->next = (THTreeItem *)ppItem;
+ pItem1->prev = ppItem[1];
+ // edi = pItem305C;
+ pPrev = ppItem[1]; // ecx
+ if(PTR_INVALID_OR_NULL(pPrev))
+ {
+ pPrev = PTR_NOT(pPrev);
+ pPrev->next = pItem1;
+ pPrev->prev = pItem2;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ if(PTR_INVALID(pItem305C))
+ pPrev += (THTreeItem *)ppItem - (*ppItem)->prev;
+ else
+ pPrev += PTR_INT(pItem305C);
+
+ pPrev->next = pItem1;
+ ppItem[1] = pItem2;
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ }
+ return pItem2;
+}
+
+void THuffmannTree::Call1500E820(THTreeItem * pItem)
+{
+ THTreeItem * pItem1; // edi
+ THTreeItem * pItem2 = NULL; // eax
+ THTreeItem * pItem3; // edx
+ THTreeItem * pPrev; // ebx
+
+ for(; pItem != NULL; pItem = pItem->parent)
+ {
+ pItem->byteValue++;
+
+ for(pItem1 = pItem; ; pItem1 = pPrev)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INVALID_OR_NULL(pPrev))
+ {
+ pPrev = NULL;
+ break;
+ }
+
+ if(pPrev->byteValue >= pItem->byteValue)
+ break;
+ }
+
+ if(pItem1 == pItem)
+ continue;
+
+ if(pItem1->next != NULL)
+ {
+ pItem2 = pItem1->GetPrevItem(-1);
+ pItem2->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ pItem2 = pItem->next;
+ pItem1->next = pItem2;
+ pItem1->prev = pItem2->prev;
+ pItem2->prev = pItem1;
+ pItem->next = pItem1;
+ if((pItem2 = pItem1) != NULL)
+ {
+ pItem2 = pItem->GetPrevItem(-1);
+ pItem2->next = pItem->next;
+ pItem->next->prev = pItem->prev;
+ pItem->next = NULL;
+ pItem->prev = NULL;
+ }
+
+ if(pPrev == NULL)
+ pPrev = PTR_PTR(&pFirst);
+
+ pItem2 = pPrev->next;
+ pItem->next = pItem2;
+ pItem->prev = pItem2->prev;
+ pItem2->prev = pItem;
+ pPrev->next = pItem;
+
+ pItem3 = pItem1->parent->child;
+ pItem2 = pItem->parent;
+ if(pItem2->child == pItem)
+ pItem2->child = pItem1;
+ if(pItem3 == pItem1)
+ pItem1->parent->child = pItem;
+
+ pItem2 = pItem->parent;
+ pItem->parent = pItem1->parent;
+ pItem1->parent = pItem2;
+ offs0004++;
+ }
+}
+
+// 1500E920
+unsigned int THuffmannTree::DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType)
+{
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ THTreeItem * pItem3;
+ THTreeItem * pTemp;
+ unsigned long dwBitBuff;
+ unsigned int nBits;
+ unsigned int nBit;
+
+ BuildTree(nCmpType);
+ bIsCmp0 = (nCmpType == 0);
+
+ // Store the compression type into output buffer
+ os->dwBitBuff |= (nCmpType << os->nBits);
+ os->nBits += 8;
+
+ // Flush completed bytes
+ while(os->nBits >= 8)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ for(; nInLength != 0; nInLength--)
+ {
+ unsigned char bOneByte = *pbInBuffer++;
+
+ if((pItem1 = items306C[bOneByte]) == NULL)
+ {
+ pItem2 = items306C[0x101]; // ecx
+ pItem3 = pItem2->parent; // eax
+ dwBitBuff = 0;
+ nBits = 0;
+
+ for(; pItem3 != NULL; pItem3 = pItem3->parent)
+ {
+ nBit = (pItem3->child != pItem2) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem2 = pItem3;
+ }
+ os->PutBits(dwBitBuff, nBits);
+
+ // Store the loaded byte into output stream
+ os->dwBitBuff |= (bOneByte << os->nBits);
+ os->nBits += 8;
+
+ // Flush the whole byte(s)
+ while(os->nBits >= 8)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast;
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = bOneByte;
+ pItem2->byteValue = 0;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+ pItem1->child = pItem2;
+
+ Call1500E820(pItem2);
+
+ if(bIsCmp0 != 0)
+ {
+ Call1500E820(items306C[bOneByte]);
+ continue;
+ }
+
+ for(pItem1 = items306C[bOneByte]; pItem1 != NULL; pItem1 = pItem1->parent)
+ {
+ pItem1->byteValue++;
+ pItem2 = pItem1;
+
+ for(;;)
+ {
+ pItem3 = pItem2->prev;
+ if(PTR_INVALID_OR_NULL(pItem3))
+ {
+ pItem3 = NULL;
+ break;
+ }
+ if(pItem3->byteValue >= pItem1->byteValue)
+ break;
+ pItem2 = pItem3;
+ }
+
+ if(pItem2 != pItem1)
+ {
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ pItem3 = pItem2->parent->child;
+ if(pItem1->parent->child == pItem1)
+ pItem1->parent->child = pItem2;
+
+ if(pItem3 == pItem2)
+ pItem2->parent->child = pItem1;
+
+ pTemp = pItem1->parent;
+ pItem1->parent = pItem2->parent;
+ pItem2->parent = pTemp;
+ offs0004++;
+ }
+ }
+ }
+// 1500EB62
+ else
+ {
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+ os->PutBits(dwBitBuff, nBits);
+ }
+
+// 1500EB98
+ if(bIsCmp0 != 0)
+ Call1500E820(items306C[bOneByte]); // 1500EB9D
+// 1500EBAF
+ } // for(; nInLength != 0; nInLength--)
+
+// 1500EBB8
+ pItem1 = items306C[0x100];
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+
+// 1500EBE6
+ os->PutBits(dwBitBuff, nBits);
+
+// 1500EBEF
+ // Flush the remaining bits
+ while(os->nBits != 0)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= ((os->nBits > 8) ? 8 : os->nBits);
+ }
+
+ return (unsigned int)(os->pbOutPos - os->pbOutBuffer);
+}
+
+// Decompression using Huffman tree (1500E450)
+unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is)
+{
+ TQDecompress * qd;
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ unsigned char * pbOutPos = pbOutBuffer;
+ unsigned long nBitCount;
+ unsigned int nDcmpByte = 0;
+ unsigned int n8Bits; // 8 bits loaded from input stream
+ unsigned int n7Bits; // 7 bits loaded from input stream
+ bool bHasQdEntry;
+
+ // Test the output length. Must not be NULL.
+ if(dwOutLength == 0)
+ return 0;
+
+ // Get the compression type from the input stream
+ n8Bits = is->Get8Bits();
+
+ // Build the Huffman tree
+ BuildTree(n8Bits);
+ bIsCmp0 = (n8Bits == 0) ? 1 : 0;
+
+ for(;;)
+ {
+ // Security check: If we are at the end of the input buffer,
+ // it means that the data is corrupt
+ if(is->BitCount == 0 && is->pbInBuffer >= is->pbInBufferEnd)
+ return 0;
+
+ // Get 7 bits from input stream
+ n7Bits = is->Get7Bits();
+
+ // Try to use quick decompression. Check TQDecompress array for corresponding item.
+ // If found, ise the result byte instead.
+ qd = &qd3474[n7Bits];
+
+ // If there is a quick-pass possible (ebx)
+ bHasQdEntry = (qd->offs00 >= offs0004) ? true : false;
+
+ // If we can use quick decompress, use it.
+ if(bHasQdEntry)
+ {
+ if(qd->nBits > 7)
+ {
+ is->SkipBits(7);
+ pItem1 = qd->pItem;
+ goto _1500E549;
+ }
+ is->SkipBits(qd->nBits);
+ nDcmpByte = qd->dcmpByte;
+ }
+ else
+ {
+ pItem1 = pFirst->next->prev;
+ if(PTR_INVALID_OR_NULL(pItem1))
+ pItem1 = NULL;
+_1500E549:
+ nBitCount = 0;
+ pItem2 = NULL;
+
+ do
+ {
+ if(pItem1 == NULL)
+ return 0;
+
+ pItem1 = pItem1->child; // Move down by one level
+ if(is->GetBit()) // If current bit is set, move to previous
+ pItem1 = pItem1->prev;
+
+ if(++nBitCount == 7) // If we are at 7th bit, save current HTree item.
+ pItem2 = pItem1;
+ }
+ while(pItem1->child != NULL); // Walk until tree has no deeper level
+
+ if(bHasQdEntry == false)
+ {
+ if(nBitCount > 7)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->pItem = pItem2;
+ }
+ else
+ {
+ unsigned long nIndex = n7Bits & (0xFFFFFFFF >> (32 - nBitCount));
+ unsigned long nAdd = (1 << nBitCount);
+
+ for(qd = &qd3474[nIndex]; nIndex <= 0x7F; nIndex += nAdd, qd += nAdd)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->dcmpByte = pItem1->dcmpByte;
+ }
+ }
+ }
+ nDcmpByte = pItem1->dcmpByte;
+ }
+
+ if(nDcmpByte == 0x101) // Huffman tree needs to be modified
+ {
+ n8Bits = is->Get8Bits();
+ pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = n8Bits;
+ pItem2->byteValue = 0;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem1->child = pItem2;
+ Call1500E820(pItem2);
+ if(bIsCmp0 == 0)
+ Call1500E820(items306C[n8Bits]);
+
+ nDcmpByte = n8Bits;
+ }
+
+ if(nDcmpByte == 0x100)
+ break;
+
+ *pbOutPos++ = (unsigned char)nDcmpByte;
+ if(--dwOutLength == 0)
+ break;
+
+ if(bIsCmp0)
+ Call1500E820(items306C[nDcmpByte]);
+ }
+
+ return (unsigned int)(pbOutPos - pbOutBuffer);
+}
+
+
+// Table for (de)compression. Every compression type has 258 entries
+unsigned char THuffmannTree::Table1502A630[] =
+{
+ // Data for compression type 0x00
+ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00,
+
+ // Data for compression type 0x01
+ 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
+ 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
+ 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
+ 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
+ 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
+ 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
+ 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
+ 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
+ 0x00, 0x00,
+
+ // Data for compression type 0x02
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
+ 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
+ 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
+ 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x03
+ 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
+ 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
+ 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
+ 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
+ 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
+ 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
+ 0x00, 0x00,
+
+ // Data for compression type 0x04
+ 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x05
+ 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
+ 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
+ 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
+ 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x06
+ 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x07
+ 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x08
+ 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
+ 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
+ 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};
diff --git a/dep/StormLib/src/huffman/huff.h b/dep/StormLib/src/huffman/huff.h
new file mode 100644
index 00000000000..83e9b2cdad0
--- /dev/null
+++ b/dep/StormLib/src/huffman/huff.h
@@ -0,0 +1,142 @@
+/*****************************************************************************/
+/* huffman.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of huffman.h */
+/* 03.05.03 2.00 Lad Added compression */
+/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
+/*****************************************************************************/
+
+#ifndef __HUFFMAN_H__
+#define __HUFFMAN_H__
+
+#include "../StormPort.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define INSERT_ITEM 1
+#define SWITCH_ITEMS 2 // Switch the item1 and item2
+
+#define PTR_NOT(ptr) (THTreeItem *)(~(DWORD_PTR)(ptr))
+#define PTR_PTR(ptr) ((THTreeItem *)(ptr))
+#define PTR_INT(ptr) (INT_PTR)(ptr)
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Structures and classes
+
+// Input stream for Huffmann decompression
+class TInputStream
+{
+ public:
+
+ unsigned long GetBit();
+ unsigned long Get7Bits();
+ unsigned long Get8Bits();
+ void SkipBits(unsigned int BitCount);
+
+ unsigned char * pbInBuffer; // Input data
+ unsigned char * pbInBufferEnd; // End of the input buffer
+ unsigned long BitBuffer; // Input bit buffer
+ unsigned int BitCount; // Number of bits remaining in 'dwBitBuff'
+};
+
+// Output stream for Huffmann compression
+class TOutputStream
+{
+ public:
+
+ void PutBits(unsigned long dwBuff, unsigned int nPutBits);
+
+ unsigned char * pbOutBuffer; // 00 : Output buffer
+ unsigned long cbOutSize; // 04 : Size of output buffer
+ unsigned char * pbOutPos; // 08 : Current output position
+ unsigned long dwBitBuff; // 0C : Bit buffer
+ unsigned long nBits; // 10 : Number of bits in the bit buffer
+};
+
+// Huffmann tree item (?)
+struct THTreeItem
+{
+ THTreeItem * Call1501DB70(THTreeItem * pLast);
+ THTreeItem * GetPrevItem(LONG_PTR value);
+ void ClearItemLinks();
+ void RemoveItem();
+
+ THTreeItem * next; // 00 - Pointer to next THTreeItem
+ THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none)
+ unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value
+ unsigned long byteValue; // 0C - Some byte value
+ THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none)
+ THTreeItem * child; // 14 - Pointer to child THTreeItem
+ int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
+};
+
+// Structure used for quick decompress. The 'bitCount' contains number of bits
+// and byte value contains result decompressed byte value.
+// After each walk through Huffman tree are filled all entries which are
+// multiplies of number of bits loaded from input stream. These entries
+// contain number of bits and result value. At the next 7 bits is tested this
+// structure first. If corresponding entry found, decompression routine will
+// not walk through Huffman tree and directly stores output byte to output stream.
+struct TQDecompress
+{
+ unsigned long offs00; // 00 - 1 if resolved
+ unsigned long nBits; // 04 - Bit count
+ union
+ {
+ unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7)
+ THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7
+ };
+};
+
+// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
+// for the decompression, I do not know actually if the class is really a Hufmann
+// tree. If someone knows the decompression details, please let me know
+class THuffmannTree
+{
+ public:
+
+ THuffmannTree();
+ void InitTree(bool bCompression);
+ void BuildTree(unsigned int nCmpType);
+// void ModifyTree(unsigned long dwIndex);
+// void UninitTree();
+
+// void Call15007010(Bit32 dwInLength, THTreeItem * item);
+ THTreeItem * Call1500E740(unsigned int nValue);
+ void Call1500E820(THTreeItem * pItem);
+ unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType);
+ unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is);
+
+ unsigned long bIsCmp0; // 0000 - 1 if compression type 0
+ unsigned long offs0004; // 0004 - Some flag
+ THTreeItem items0008[0x203]; // 0008 - HTree items
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem3050; // 3050 - Always NULL (?)
+ THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item
+ THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid)
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem305C; // 305C - Usually NULL
+ THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item
+ THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid)
+ unsigned long nItems; // 3068 - Number of used HTree items
+
+ //-------------------------------------------
+ THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array
+ TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression
+ int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
+
+ static unsigned char Table1502A630[];// Some table
+};
+
+#endif // __HUFFMAN_H__
diff --git a/dep/StormLib/src/huffman/huff_patch.cpp b/dep/StormLib/src/huffman/huff_patch.cpp
new file mode 100644
index 00000000000..6176a9b1f77
--- /dev/null
+++ b/dep/StormLib/src/huffman/huff_patch.cpp
@@ -0,0 +1,1120 @@
+/*****************************************************************************/
+/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains Huffmann (de)compression methods */
+/* */
+/* Authors : Ladislav Zezula (ladik@zezula.net) */
+/* ShadowFlare (BlakFlare@hotmail.com) */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */
+/* 03.05.03 1.00 Lad Added compression methods */
+/* 19.11.03 1.01 Dan Big endian handling */
+/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
+/*****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "huff.h"
+
+THTreeItem * gcpFirst, * gpFirst, * gcpItem3054, * gpItem3054;
+
+#define PTR_VALID(ptr) ((ptr) != gcpFirst && (ptr) != gcpItem3054)
+#define PTR_INVALID(ptr) (!PTR_VALID(ptr))
+#define PTR_INVALID_OR_NULL(ptr) (0 == (ptr) || PTR_INVALID(ptr))
+
+//-----------------------------------------------------------------------------
+// Methods of the THTreeItem struct
+
+// 1501DB70
+THTreeItem * THTreeItem::Call1501DB70(THTreeItem * pLast)
+{
+ if(pLast == NULL)
+ pLast = this + 1;
+ return pLast;
+}
+
+// Gets previous Huffman tree item (?)
+THTreeItem * THTreeItem::GetPrevItem(SIntPtr value)
+{
+ if(PTR_INVALID(prev))
+ return PTR_NOT(prev);
+
+ if(value == -1 || PTR_INVALID((THTreeItem *) value))
+ value = (SIntPtr)(this - next->prev);
+ return prev + value;
+}
+
+// 1500F5E0
+void THTreeItem::ClearItemLinks()
+{
+ next = prev = NULL;
+}
+
+// 1500BC90
+void THTreeItem::RemoveItem()
+{
+ THTreeItem * pTemp; // EDX
+
+ if(next != NULL)
+ {
+ pTemp = prev;
+
+ if(PTR_INVALID(pTemp))
+ pTemp = PTR_NOT(pTemp);
+ else
+ pTemp += (this - next->prev);
+
+ pTemp->next = next;
+ next->prev = prev;
+ next = prev = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TOutputStream functions
+
+void TOutputStream::PutBits(unsigned long dwBuff, unsigned int nPutBits)
+{
+ dwBitBuff |= (dwBuff << nBits);
+ nBits += nPutBits;
+
+ // Flush completed bytes
+ while(nBits >= 8)
+ {
+ if(cbOutSize != 0)
+ {
+ *pbOutPos++ = (unsigned char)dwBitBuff;
+ cbOutSize--;
+ }
+
+ dwBitBuff >>= 8;
+ nBits -= 8;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TInputStream functions
+
+// Gets one bit from input stream
+unsigned long TInputStream::GetBit()
+{
+ unsigned long dwOneBit = 0;
+
+ // Ensure that the input stream is reloaded, if there are no bits left
+ if(BitCount == 0)
+ {
+ // Refill the bit buffer
+ BitBuffer = *pbInBuffer++;
+ BitCount = 8;
+ }
+
+ // Copy the bit from bit buffer to the variable
+ dwOneBit = (BitBuffer & 0x01);
+ BitBuffer >>= 1;
+ BitCount--;
+
+ return dwOneBit;
+}
+
+// Gets 7 bits from the stream. DOES NOT remove the bits from input stream
+unsigned long TInputStream::Get7Bits()
+{
+ unsigned long dwReloadByte = 0;
+
+ // If there is not enough bits to get the value,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < 7)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Return the first available 7 bits. DO NOT remove them from the input stream
+ return (BitBuffer & 0x7F);
+}
+
+// Gets the whole byte from the input stream.
+unsigned long TInputStream::Get8Bits()
+{
+ unsigned long dwReloadByte = 0;
+ unsigned long dwOneByte = 0;
+
+ // If there is not enough bits to get the value,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < 8)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Return the lowest 8 its
+ dwOneByte = (BitBuffer & 0xFF);
+ BitBuffer >>= 8;
+ BitCount -= 8;
+ return dwOneByte;
+}
+
+void TInputStream::SkipBits(unsigned int dwBitsToSkip)
+{
+ unsigned long dwReloadByte = 0;
+
+ // If there is not enough bits in the buffer,
+ // we have to add 8 more bits from the input buffer
+ if(BitCount < dwBitsToSkip)
+ {
+ dwReloadByte = *pbInBuffer++;
+ BitBuffer |= dwReloadByte << BitCount;
+ BitCount += 8;
+ }
+
+ // Skip the remaining bits
+ BitBuffer >>= dwBitsToSkip;
+ BitCount -= dwBitsToSkip;
+}
+
+//-----------------------------------------------------------------------------
+// Functions for huffmann tree items
+
+// Inserts item into the tree (?)
+static void InsertItem(THTreeItem ** itemPtr, THTreeItem * item, unsigned long where, THTreeItem * item2)
+{
+ THTreeItem * next = item->next; // EDI - next to the first item
+ THTreeItem * prev = item->prev; // ESI - prev to the first item
+ THTreeItem * prev2; // Pointer to previous item
+ THTreeItem * next2; // Pointer to the next item
+
+ // The same code like in RemoveItem(item);
+ if(next != 0) // If the first item already has next one
+ {
+ if(PTR_INVALID(prev))
+ prev = PTR_NOT(prev);
+ else
+ prev += (item - next->prev);
+
+ // 150083C1
+ // Remove the item from the tree
+ prev->next = next;
+ next->prev = prev;
+
+ // Invalidate 'prev' and 'next' pointer
+ item->next = 0;
+ item->prev = 0;
+ }
+
+ if(item2 == NULL) // EDX - If the second item is not entered,
+ item2 = PTR_PTR(&itemPtr[1]); // take the first tree item
+
+ switch(where)
+ {
+ case SWITCH_ITEMS : // Switch the two items
+ item->next = item2->next; // item2->next (Pointer to pointer to first)
+ item->prev = item2->next->prev;
+ item2->next->prev = item;
+ item2->next = item; // Set the first item
+ return;
+
+ case INSERT_ITEM: // Insert as the last item
+ item->next = item2; // Set next item (or pointer to pointer to first item)
+ item->prev = item2->prev; // Set prev item (or last item in the tree)
+
+ next2 = itemPtr[0];// Usually NULL
+ prev2 = item2->prev; // Prev item to the second (or last tree item)
+
+ if(PTR_INVALID(prev2))
+ {
+ prev2 = PTR_NOT(prev);
+
+ prev2->next = item;
+ item2->prev = item; // Next after last item
+ return;
+ }
+
+ if(PTR_INVALID(next2))
+ next2 = (THTreeItem *)(item2 - item2->next->prev);
+
+ prev2 += (long) next2;
+ prev2->next = item;
+ item2->prev = item; // Set the next/last item
+ return;
+
+ default:
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// THuffmannTree class functions
+
+THuffmannTree::THuffmannTree()
+{
+}
+
+void THuffmannTree::InitTree(bool bCompression)
+{
+ THTreeItem * pItem;
+ unsigned int nCount;
+
+ // Clear links for all the items in the tree
+ for(pItem = items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
+ pItem->ClearItemLinks();
+
+ gcpItem3054 = (THTreeItem *) &gcpItem3054;
+ pItem3050 = NULL;
+ pItem3054 = PTR_PTR(&pItem3054);
+ pItem3058 = gcpItem3054;
+ gpItem3054 = pItem3054;
+
+ gcpFirst = (THTreeItem *) &gcpFirst;
+ pItem305C = NULL;
+ pFirst = PTR_PTR(&pFirst);
+ pLast = gcpFirst;
+ gpFirst = pFirst;
+
+ offs0004 = 1;
+ nItems = 0;
+
+ // Clear all TQDecompress items. Do this only if preparing for decompression
+ if(bCompression == false)
+ {
+ for(nCount = 0; nCount < sizeof(qd3474) / sizeof(TQDecompress); nCount++)
+ qd3474[nCount].offs00 = 0;
+ }
+}
+
+// Builds Huffman tree. Called with the first 8 bits loaded from input stream
+void THuffmannTree::BuildTree(unsigned int nCmpType)
+{
+ unsigned long maxByte; // [ESP+10] - The greatest character found in table
+ THTreeItem ** itemPtr; // [ESP+14] - Pointer to Huffman tree item pointer array
+ unsigned char * byteArray; // [ESP+1C] - Pointer to unsigned char in Table1502A630
+ THTreeItem * child1;
+ unsigned long i; // egcs in linux doesn't like multiple for loops without an explicit i
+
+ // Loop while pointer has a valid value
+ while(PTR_VALID(pLast)) // ESI - Last entry
+ {
+ THTreeItem * temp; // EAX
+
+ if(pLast->next != NULL) // ESI->next
+ pLast->RemoveItem();
+ // EDI = &offs3054
+ pItem3058 = PTR_PTR(&pItem3054); // [EDI+4]
+ pLast->prev = pItem3058; // EAX
+
+ temp = PTR_PTR(&pItem3054)->GetPrevItem((SIntPtr)(&pItem3050));
+
+ temp->next = pLast;
+ pItem3054 = pLast;
+ }
+
+ // Clear all pointers in HTree item array
+ memset(items306C, 0, sizeof(items306C));
+
+ maxByte = 0; // Greatest character found init to zero.
+ itemPtr = (THTreeItem **)&items306C; // Pointer to current entry in HTree item pointer array
+
+ // Ensure we have low 8 bits only
+ nCmpType &= 0xFF;
+ byteArray = Table1502A630 + nCmpType * 258; // EDI also
+
+ for(i = 0; i < 0x100; i++, itemPtr++)
+ {
+ THTreeItem * item = pItem3058; // Item to be created
+ THTreeItem * pItem3 = pItem3058;
+ unsigned char oneByte = byteArray[i];
+
+ // Skip all the bytes which are zero.
+ if(byteArray[i] == 0)
+ continue;
+
+ // If not valid pointer, take the first available item in the array
+ if(PTR_INVALID_OR_NULL(item))
+ item = &items0008[nItems++];
+
+ // Insert this item as the top of the tree
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ item->parent = NULL; // Invalidate child and parent
+ item->child = NULL;
+ *itemPtr = item; // Store pointer into pointer array
+
+ item->dcmpByte = i; // Store counter
+ item->byteValue = oneByte; // Store byte value
+ if(oneByte >= maxByte)
+ {
+ maxByte = oneByte;
+ continue;
+ }
+
+ // Find the first item which has byte value greater than current one byte
+ if(PTR_VALID(pItem3 = pLast)) // EDI - Pointer to the last item
+ {
+ // 15006AF7
+ if(pItem3 != NULL)
+ {
+ do // 15006AFB
+ {
+ if(pItem3->byteValue >= oneByte)
+ goto _15006B09;
+ pItem3 = pItem3->prev;
+ }
+ while(PTR_VALID(pItem3));
+ }
+ }
+ pItem3 = NULL;
+
+ // 15006B09
+ _15006B09:
+ if(item->next != NULL)
+ item->RemoveItem();
+
+ // 15006B15
+ if(pItem3 == NULL)
+ pItem3 = PTR_PTR(&pFirst);
+
+ // 15006B1F
+ item->next = pItem3->next;
+ item->prev = pItem3->next->prev;
+ pItem3->next->prev = item;
+ pItem3->next = item;
+ }
+
+ // 15006B4A
+ for(; i < 0x102; i++)
+ {
+ THTreeItem ** itemPtr = &items306C[i]; // EDI
+
+ // 15006B59
+ THTreeItem * item = pItem3058; // ESI
+ if(PTR_INVALID_OR_NULL(item))
+ item = &items0008[nItems++];
+
+ InsertItem(&pItem305C, item, INSERT_ITEM, NULL);
+
+ // 15006B89
+ item->dcmpByte = i;
+ item->byteValue = 1;
+ item->parent = NULL;
+ item->child = NULL;
+ *itemPtr++ = item;
+ }
+
+ // 15006BAA
+ if(PTR_VALID(child1 = pLast)) // EDI - last item (first child to item
+ {
+ THTreeItem * child2; // EBP
+ THTreeItem * item; // ESI
+
+ // 15006BB8
+ while(PTR_VALID(child2 = child1->prev))
+ {
+ if(PTR_INVALID_OR_NULL(item = pItem3058))
+ item = &items0008[nItems++];
+
+ // 15006BE3
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ // 15006BF3
+ item->parent = NULL;
+ item->child = NULL;
+
+ //EDX = child2->byteValue + child1->byteValue;
+ //EAX = child1->byteValue;
+ //ECX = maxByte; // The greatest character (0xFF usually)
+
+ item->byteValue = child1->byteValue + child2->byteValue; // 0x02
+ item->child = child1; // Prev item in the
+ child1->parent = item;
+ child2->parent = item;
+
+ // EAX = item->byteValue;
+ if(item->byteValue >= maxByte)
+ maxByte = item->byteValue;
+ else
+ {
+ THTreeItem * pItem2 = child2->prev; // EDI
+
+ // 15006C2D
+ while(PTR_VALID(pItem2))
+ {
+ if(pItem2->byteValue >= item->byteValue)
+ goto _15006C3B;
+ pItem2 = pItem2->prev;
+ }
+ pItem2 = NULL;
+
+ _15006C3B:
+ if(item->next != 0)
+ {
+ THTreeItem * temp4 = item->GetPrevItem(-1);
+
+ temp4->next = item->next; // The first item changed
+ item->next->prev = item->prev; // First->prev changed to negative value
+ item->next = NULL;
+ item->prev = NULL;
+ }
+
+ // 15006C62
+ if(pItem2 == NULL)
+ pItem2 = PTR_PTR(&pFirst);
+
+ item->next = pItem2->next; // Set item with 0x100 byte value
+ item->prev = pItem2->next->prev; // Set item with 0x17 byte value
+ pItem2->next->prev = item; // Changed prev of item with
+ pItem2->next = item;
+ }
+
+ // 15006C7B
+ if(PTR_INVALID_OR_NULL(child1 = child2->prev))
+ break;
+ }
+ }
+ // 15006C88
+ offs0004 = 1;
+}
+
+THTreeItem * THuffmannTree::Call1500E740(unsigned int nValue)
+{
+ THTreeItem * pItem1 = pItem3058; // EDX
+ THTreeItem * pItem2; // EAX
+ THTreeItem * pNext;
+ THTreeItem * pPrev;
+ THTreeItem ** ppItem;
+
+ if(PTR_INVALID_OR_NULL(pItem1) || (pItem2 = pItem1) == NULL)
+ {
+ if((pItem2 = &items0008[nItems++]) != NULL)
+ pItem1 = pItem2;
+ else
+ pItem1 = pFirst;
+ }
+ else
+ pItem1 = pItem2;
+
+ pNext = pItem1->next;
+ if(pNext != NULL)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INVALID(pPrev))
+ pPrev = PTR_NOT(pPrev);
+ else
+ pPrev += (pItem1 - pItem1->next->prev);
+
+ pPrev->next = pNext;
+ pNext->prev = pPrev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ ppItem = &pFirst; // esi
+ if(nValue > 1)
+ {
+ // ecx = pFirst->next;
+ pItem1->next = *ppItem;
+ pItem1->prev = (*ppItem)->prev;
+
+ (*ppItem)->prev = pItem2;
+ *ppItem = pItem1;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ pItem1->next = (THTreeItem *)ppItem;
+ pItem1->prev = ppItem[1];
+ // edi = pItem305C;
+ pPrev = ppItem[1]; // ecx
+ if(PTR_INVALID(pPrev))
+ {
+ pPrev = PTR_NOT(pPrev);
+ pPrev->next = pItem1;
+ pPrev->prev = pItem2;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ if(PTR_INVALID(pItem305C))
+ pPrev += (THTreeItem *)ppItem - (*ppItem)->prev;
+ else
+ pPrev += (long)pItem305C;
+
+ pPrev->next = pItem1;
+ ppItem[1] = pItem2;
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ }
+ return pItem2;
+}
+
+void THuffmannTree::Call1500E820(THTreeItem * pItem)
+{
+ THTreeItem * pItem1; // edi
+ THTreeItem * pItem2 = NULL; // eax
+ THTreeItem * pItem3; // edx
+ THTreeItem * pPrev; // ebx
+
+ for(; pItem != NULL; pItem = pItem->parent)
+ {
+ pItem->byteValue++;
+
+ for(pItem1 = pItem; ; pItem1 = pPrev)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INVALID_OR_NULL(pPrev))
+ {
+ pPrev = NULL;
+ break;
+ }
+
+ if(pPrev->byteValue >= pItem->byteValue)
+ break;
+ }
+
+ if(pItem1 == pItem)
+ continue;
+
+ if(pItem1->next != NULL)
+ {
+ pItem2 = pItem1->GetPrevItem(-1);
+ pItem2->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ pItem2 = pItem->next;
+ pItem1->next = pItem2;
+ pItem1->prev = pItem2->prev;
+ pItem2->prev = pItem1;
+ pItem->next = pItem1;
+ if((pItem2 = pItem1) != NULL)
+ {
+ pItem2 = pItem->GetPrevItem(-1);
+ pItem2->next = pItem->next;
+ pItem->next->prev = pItem->prev;
+ pItem->next = NULL;
+ pItem->prev = NULL;
+ }
+
+ if(pPrev == NULL)
+ pPrev = PTR_PTR(&pFirst);
+
+ pItem2 = pPrev->next;
+ pItem->next = pItem2;
+ pItem->prev = pItem2->prev;
+ pItem2->prev = pItem;
+ pPrev->next = pItem;
+
+ pItem3 = pItem1->parent->child;
+ pItem2 = pItem->parent;
+ if(pItem2->child == pItem)
+ pItem2->child = pItem1;
+ if(pItem3 == pItem1)
+ pItem1->parent->child = pItem;
+
+ pItem2 = pItem->parent;
+ pItem->parent = pItem1->parent;
+ pItem1->parent = pItem2;
+ offs0004++;
+ }
+}
+
+// 1500E920
+unsigned int THuffmannTree::DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType)
+{
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ THTreeItem * pItem3;
+ THTreeItem * pTemp;
+ unsigned long dwBitBuff;
+ unsigned int nBits;
+ unsigned int nBit;
+
+ BuildTree(nCmpType);
+ bIsCmp0 = (nCmpType == 0);
+
+ // Store the compression type into output buffer
+ os->dwBitBuff |= (nCmpType << os->nBits);
+ os->nBits += 8;
+
+ // Flush completed bytes
+ while(os->nBits >= 8)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ for(; nInLength != 0; nInLength--)
+ {
+ unsigned char bOneByte = *pbInBuffer++;
+
+ if((pItem1 = items306C[bOneByte]) == NULL)
+ {
+ pItem2 = items306C[0x101]; // ecx
+ pItem3 = pItem2->parent; // eax
+ dwBitBuff = 0;
+ nBits = 0;
+
+ for(; pItem3 != NULL; pItem3 = pItem3->parent)
+ {
+ nBit = (pItem3->child != pItem2) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem2 = pItem3;
+ }
+ os->PutBits(dwBitBuff, nBits);
+
+ // Store the loaded byte into output stream
+ os->dwBitBuff |= (bOneByte << os->nBits);
+ os->nBits += 8;
+
+ // Flush the whole byte(s)
+ while(os->nBits >= 8)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast;
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = bOneByte;
+ pItem2->byteValue = 0;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+ pItem1->child = pItem2;
+
+ Call1500E820(pItem2);
+
+ if(bIsCmp0 != 0)
+ {
+ Call1500E820(items306C[bOneByte]);
+ continue;
+ }
+
+ for(pItem1 = items306C[bOneByte]; pItem1 != NULL; pItem1 = pItem1->parent)
+ {
+ pItem1->byteValue++;
+ pItem2 = pItem1;
+
+ for(;;)
+ {
+ pItem3 = pItem2->prev;
+ if(PTR_INVALID_OR_NULL(pItem3))
+ {
+ pItem3 = NULL;
+ break;
+ }
+ if(pItem3->byteValue >= pItem1->byteValue)
+ break;
+ pItem2 = pItem3;
+ }
+
+ if(pItem2 != pItem1)
+ {
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ pItem3 = pItem2->parent->child;
+ if(pItem1->parent->child == pItem1)
+ pItem1->parent->child = pItem2;
+
+ if(pItem3 == pItem2)
+ pItem2->parent->child = pItem1;
+
+ pTemp = pItem1->parent;
+ pItem1->parent = pItem2->parent;
+ pItem2->parent = pTemp;
+ offs0004++;
+ }
+ }
+ }
+// 1500EB62
+ else
+ {
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+ os->PutBits(dwBitBuff, nBits);
+ }
+
+// 1500EB98
+ if(bIsCmp0 != 0)
+ Call1500E820(items306C[bOneByte]); // 1500EB9D
+// 1500EBAF
+ } // for(; nInLength != 0; nInLength--)
+
+// 1500EBB8
+ pItem1 = items306C[0x100];
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+
+// 1500EBE6
+ os->PutBits(dwBitBuff, nBits);
+
+// 1500EBEF
+ // Flush the remaining bits
+ while(os->nBits != 0)
+ {
+ if(os->cbOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->cbOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= ((os->nBits > 8) ? 8 : os->nBits);
+ }
+
+ return (unsigned int)(os->pbOutPos - os->pbOutBuffer);
+}
+
+// Decompression using Huffman tree (1500E450)
+unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is)
+{
+ TQDecompress * qd;
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ unsigned char * pbOutPos = pbOutBuffer;
+ unsigned long nBitCount;
+ unsigned int nDcmpByte = 0;
+ unsigned int n8Bits; // 8 bits loaded from input stream
+ unsigned int n7Bits; // 7 bits loaded from input stream
+ bool bHasQdEntry;
+
+ // Test the output length. Must not be NULL.
+ if(dwOutLength == 0)
+ return 0;
+
+ // Get the compression type from the input stream
+ n8Bits = is->Get8Bits();
+
+ // Build the Huffman tree
+ BuildTree(n8Bits);
+ bIsCmp0 = (n8Bits == 0) ? 1 : 0;
+
+ for(;;)
+ {
+ // Security check: If we are at the end of the input buffer,
+ // it means that the data are corrupt.
+ if(is->pbInBuffer > is->pbInBufferEnd)
+ return 0;
+
+ // Get 7 bits from input stream
+ n7Bits = is->Get7Bits();
+
+ // Try to use quick decompression. Check TQDecompress array for corresponding item.
+ // If found, ise the result byte instead.
+ qd = &qd3474[n7Bits];
+
+ // If there is a quick-pass possible (ebx)
+ bHasQdEntry = (qd->offs00 >= offs0004) ? true : false;
+
+ // If we can use quick decompress, use it.
+ if(bHasQdEntry)
+ {
+ if(qd->nBits > 7)
+ {
+ is->SkipBits(7);
+ pItem1 = qd->pItem;
+ goto _1500E549;
+ }
+ is->SkipBits(qd->nBits);
+ nDcmpByte = qd->dcmpByte;
+ }
+ else
+ {
+ pItem1 = pFirst->next->prev;
+ if(PTR_INVALID_OR_NULL(pItem1))
+ pItem1 = NULL;
+_1500E549:
+ nBitCount = 0;
+ pItem2 = NULL;
+
+ do
+ {
+ pItem1 = pItem1->child; // Move down by one level
+ if(is->GetBit()) // If current bit is set, move to previous
+ pItem1 = pItem1->prev;
+
+ if(++nBitCount == 7) // If we are at 7th bit, save current HTree item.
+ pItem2 = pItem1;
+ }
+ while(pItem1->child != NULL); // Walk until tree has no deeper level
+
+ if(bHasQdEntry == false)
+ {
+ if(nBitCount > 7)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->pItem = pItem2;
+ }
+ else
+ {
+ unsigned long nIndex = n7Bits & (0xFFFFFFFF >> (32 - nBitCount));
+ unsigned long nAdd = (1 << nBitCount);
+
+ for(qd = &qd3474[nIndex]; nIndex <= 0x7F; nIndex += nAdd, qd += nAdd)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->dcmpByte = pItem1->dcmpByte;
+ }
+ }
+ }
+ nDcmpByte = pItem1->dcmpByte;
+ }
+
+ if(nDcmpByte == 0x101) // Huffman tree needs to be modified
+ {
+ n8Bits = is->Get8Bits();
+ pItem1 = (PTR_INVALID_OR_NULL(pLast)) ? NULL : pLast;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = n8Bits;
+ pItem2->byteValue = 0;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem1->child = pItem2;
+ Call1500E820(pItem2);
+ if(bIsCmp0 == 0)
+ Call1500E820(items306C[n8Bits]);
+
+ nDcmpByte = n8Bits;
+ }
+
+ if(nDcmpByte == 0x100)
+ break;
+
+ *pbOutPos++ = (unsigned char)nDcmpByte;
+ if(--dwOutLength == 0)
+ break;
+
+ if(bIsCmp0)
+ Call1500E820(items306C[nDcmpByte]);
+ }
+
+ return (unsigned int)(pbOutPos - pbOutBuffer);
+}
+
+
+// Table for (de)compression. Every compression type has 258 entries
+unsigned char THuffmannTree::Table1502A630[] =
+{
+ // Data for compression type 0x00
+ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00,
+
+ // Data for compression type 0x01
+ 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
+ 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
+ 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
+ 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
+ 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
+ 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
+ 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
+ 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
+ 0x00, 0x00,
+
+ // Data for compression type 0x02
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
+ 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
+ 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
+ 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x03
+ 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
+ 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
+ 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
+ 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
+ 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
+ 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
+ 0x00, 0x00,
+
+ // Data for compression type 0x04
+ 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x05
+ 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
+ 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
+ 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
+ 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x06
+ 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x07
+ 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x08
+ 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
+ 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
+ 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};
diff --git a/dep/StormLib/src/huffman/huff_patch.h b/dep/StormLib/src/huffman/huff_patch.h
new file mode 100644
index 00000000000..c1c03e67860
--- /dev/null
+++ b/dep/StormLib/src/huffman/huff_patch.h
@@ -0,0 +1,145 @@
+/*****************************************************************************/
+/* huffman.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of huffman.h */
+/* 03.05.03 2.00 Lad Added compression */
+/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
+/*****************************************************************************/
+
+#ifndef __HUFFMAN_H__
+#define __HUFFMAN_H__
+
+#include <stdint.h>
+
+#define SIntPtr intptr_t
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define INSERT_ITEM 1
+#define SWITCH_ITEMS 2 // Switch the item1 and item2
+
+#define PTR_NOT(ptr) ((ptr) == gcpFirst ? gpFirst : gpItem3054)
+#define PTR_PTR(ptr) ((THTreeItem *)(ptr))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Structures and classes
+
+// Input stream for Huffmann decompression
+class TInputStream
+{
+ public:
+
+ unsigned long GetBit();
+ unsigned long Get7Bits();
+ unsigned long Get8Bits();
+ void SkipBits(unsigned int BitCount);
+
+ unsigned char * pbInBuffer; // Input data
+ unsigned char * pbInBufferEnd; // End of the input buffer
+ unsigned long BitBuffer; // Input bit buffer
+ unsigned int BitCount; // Number of bits remaining in 'dwBitBuff'
+};
+
+// Output stream for Huffmann compression
+class TOutputStream
+{
+ public:
+
+ void PutBits(unsigned long dwBuff, unsigned int nPutBits);
+
+ unsigned char * pbOutBuffer; // 00 : Output buffer
+ unsigned long cbOutSize; // 04 : Size of output buffer
+ unsigned char * pbOutPos; // 08 : Current output position
+ unsigned long dwBitBuff; // 0C : Bit buffer
+ unsigned long nBits; // 10 : Number of bits in the bit buffer
+};
+
+// Huffmann tree item (?)
+struct THTreeItem
+{
+ public:
+
+ THTreeItem * Call1501DB70(THTreeItem * pLast);
+ THTreeItem * GetPrevItem(SIntPtr value);
+ void ClearItemLinks();
+ void RemoveItem();
+
+ THTreeItem * next; // 00 - Pointer to next THTreeItem
+ THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none)
+ unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value
+ unsigned long byteValue; // 0C - Some byte value
+ THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none)
+ THTreeItem * child; // 14 - Pointer to child THTreeItem
+ int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
+};
+
+// Structure used for quick decompress. The 'bitCount' contains number of bits
+// and byte value contains result decompressed byte value.
+// After each walk through Huffman tree are filled all entries which are
+// multiplies of number of bits loaded from input stream. These entries
+// contain number of bits and result value. At the next 7 bits is tested this
+// structure first. If corresponding entry found, decompression routine will
+// not walk through Huffman tree and directly stores output byte to output stream.
+struct TQDecompress
+{
+ unsigned long offs00; // 00 - 1 if resolved
+ unsigned long nBits; // 04 - Bit count
+ union
+ {
+ unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7)
+ THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7
+ };
+};
+
+// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
+// for the decompression, I do not know actually if the class is really a Hufmann
+// tree. If someone knows the decompression details, please let me know
+class THuffmannTree
+{
+ public:
+
+ THuffmannTree();
+ void InitTree(bool bCompression);
+ void BuildTree(unsigned int nCmpType);
+// void ModifyTree(unsigned long dwIndex);
+// void UninitTree();
+
+// void Call15007010(Bit32 dwInLength, THTreeItem * item);
+ THTreeItem * Call1500E740(unsigned int nValue);
+ void Call1500E820(THTreeItem * pItem);
+ unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType);
+ unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is);
+
+ unsigned long bIsCmp0; // 0000 - 1 if compression type 0
+ unsigned long offs0004; // 0004 - Some flag
+ THTreeItem items0008[0x203]; // 0008 - HTree items
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem3050; // 3050 - Always NULL (?)
+ THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item
+ THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid)
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem305C; // 305C - Usually NULL
+ THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item
+ THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid)
+ unsigned long nItems; // 3068 - Number of used HTree items
+
+ //-------------------------------------------
+ THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array
+ TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression
+ int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
+
+ static unsigned char Table1502A630[];// Some table
+};
+
+#endif // __HUFFMAN_H__
diff --git a/dep/StormLib/src/jenkins/lookup.h b/dep/StormLib/src/jenkins/lookup.h
new file mode 100644
index 00000000000..54ccc979ca6
--- /dev/null
+++ b/dep/StormLib/src/jenkins/lookup.h
@@ -0,0 +1,24 @@
+#ifndef __LOOKUP3_H__
+#define __LOOKUP3_H__
+
+#ifdef WIN32
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+#else
+#include <stdint.h> /* defines uint32_t etc */
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+uint32_t hashlittle(const void *key, size_t length, uint32_t initval);
+void hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LOOKUP3_H__
diff --git a/dep/StormLib/src/jenkins/lookup3.c b/dep/StormLib/src/jenkins/lookup3.c
new file mode 100644
index 00000000000..6af56b481ad
--- /dev/null
+++ b/dep/StormLib/src/jenkins/lookup3.c
@@ -0,0 +1,1003 @@
+/*
+-------------------------------------------------------------------------------
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+
+These are functions for producing 32-bit hashes for hash table lookup.
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+are externally useful functions. Routines to test the hash are included
+if SELF_TEST is defined. You can use this free for any purpose. It's in
+the public domain. It has no warranty.
+
+You probably want to use hashlittle(). hashlittle() and hashbig()
+hash byte arrays. hashlittle() is is faster than hashbig() on
+little-endian machines. Intel and AMD are little-endian machines.
+On second thought, you probably want hashlittle2(), which is identical to
+hashlittle() except it returns two 32-bit hashes for the price of one.
+You could implement hashbig2() if you wanted but I haven't bothered here.
+
+If you want to find a hash of, say, exactly 7 integers, do
+ a = i1; b = i2; c = i3;
+ mix(a,b,c);
+ a += i4; b += i5; c += i6;
+ mix(a,b,c);
+ a += i7;
+ final(a,b,c);
+then use c as the hash value. If you have a variable length array of
+4-byte integers to hash, use hashword(). If you have a byte array (like
+a character string), use hashlittle(). If you have several byte arrays, or
+a mix of things, see the comments above hashlittle().
+
+Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
+then mix those integers. This is fast (you can do a lot more thorough
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
+-------------------------------------------------------------------------------
+*/
+//#define SELF_TEST 1
+
+#include <stdio.h> /* defines printf for tests */
+#include <time.h> /* defines time_t for timings in the test */
+
+#ifdef linux
+#include <sys/param.h> /* attempt to define endianness */
+#include <endian.h> /* attempt to define endianness */
+#endif
+
+#include "lookup.h"
+
+/*
+ * My best guess at if you are big-endian or little-endian. This may
+ * need adjustment.
+ */
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+# define HASH_LITTLE_ENDIAN 1
+# define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 1
+#else
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*
+-------------------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+
+This is reversible, so any information in (a,b,c) before mix() is
+still in (a,b,c) after mix().
+
+If four pairs of (a,b,c) inputs are run through mix(), or through
+mix() in reverse, there are at least 32 bits of the output that
+are sometimes the same for one pair and different for another pair.
+This was tested for:
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+satisfy this are
+ 4 6 8 16 19 4
+ 9 15 3 18 27 15
+ 14 9 3 7 17 3
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
+for "differ" defined as + with a one-bit base and a two-bit delta. I
+used http://burtleburtle.net/bob/hash/avalanche.html to choose
+the operations, constants, and arrangements of the variables.
+
+This does not achieve avalanche. There are input bits of (a,b,c)
+that fail to affect some output bits of (a,b,c), especially of a. The
+most thoroughly mixed value is c, but it doesn't really even achieve
+avalanche in c.
+
+This allows some parallelism. Read-after-writes are good at doubling
+the number of bits affected, so the goal of mixing pulls in the opposite
+direction as the goal of parallelism. I did what I could. Rotates
+seem to cost as much as shifts on every machine I could lay my hands
+on, and rotates are much kinder to the top and bottom bits, so I used
+rotates.
+-------------------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+/*
+-------------------------------------------------------------------------------
+final -- final mixing of 3 32-bit values (a,b,c) into c
+
+Pairs of (a,b,c) values differing in only a few bits will usually
+produce values of c that look totally different. This was tested for
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+These constants passed:
+ 14 11 25 16 4 14 24
+ 12 14 25 16 4 14 24
+and these came close:
+ 4 8 15 26 3 22 24
+ 10 8 15 26 3 22 24
+ 11 8 15 26 3 22 24
+-------------------------------------------------------------------------------
+*/
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+/*
+--------------------------------------------------------------------
+ This works on all machines. To be useful, it requires
+ -- that the key be an array of uint32_t's, and
+ -- that the length be the number of uint32_t's in the key
+
+ The function hashword() is identical to hashlittle() on little-endian
+ machines, and identical to hashbig() on big-endian machines,
+ except that the length has to be measured in uint32_ts rather than in
+ bytes. hashlittle() is more complicated than hashword() only because
+ hashlittle() has to dance around fitting the key bytes into registers.
+--------------------------------------------------------------------
+*/
+uint32_t hashword(
+const uint32_t *k, /* the key, an array of uint32_t values */
+size_t length, /* the length of the key, in uint32_ts */
+uint32_t initval) /* the previous hash, or an arbitrary value */
+{
+ uint32_t a,b,c;
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
+
+ /*------------------------------------------------- handle most of the key */
+ while (length > 3)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 3;
+ k += 3;
+ }
+
+ /*------------------------------------------- handle the last 3 uint32_t's */
+ switch(length) /* all the case statements fall through */
+ {
+ case 3 : c+=k[2];
+ case 2 : b+=k[1];
+ case 1 : a+=k[0];
+ final(a,b,c);
+ case 0: /* case 0: nothing left to add */
+ break;
+ }
+ /*------------------------------------------------------ report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+hashword2() -- same as hashword(), but take two seeds and return two
+32-bit values. pc and pb must both be nonnull, and *pc and *pb must
+both be initialized with seeds. If you pass in (*pb)==0, the output
+(*pc) will be the same as the return value from hashword().
+--------------------------------------------------------------------
+*/
+void hashword2 (
+const uint32_t *k, /* the key, an array of uint32_t values */
+size_t length, /* the length of the key, in uint32_ts */
+uint32_t *pc, /* IN: seed OUT: primary hash value */
+uint32_t *pb) /* IN: more seed OUT: secondary hash value */
+{
+ uint32_t a,b,c;
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc;
+ c += *pb;
+
+ /*------------------------------------------------- handle most of the key */
+ while (length > 3)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 3;
+ k += 3;
+ }
+
+ /*------------------------------------------- handle the last 3 uint32_t's */
+ switch(length) /* all the case statements fall through */
+ {
+ case 3 : c+=k[2];
+ case 2 : b+=k[1];
+ case 1 : a+=k[0];
+ final(a,b,c);
+ case 0: /* case 0: nothing left to add */
+ break;
+ }
+ /*------------------------------------------------------ report the result */
+ *pc=c; *pb=b;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+hashlittle() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ length : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
+
+By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable. Do NOT use for cryptographic purposes.
+-------------------------------------------------------------------------------
+*/
+
+uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a,b,c; /* internal state */
+ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+ const uint8_t *k8;
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t)k[1])<<16);
+ b += k[2] + (((uint32_t)k[3])<<16);
+ c += k[4] + (((uint32_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : return c; /* zero length requires no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t)k[1])<<8;
+ a += ((uint32_t)k[2])<<16;
+ a += ((uint32_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t)k[5])<<8;
+ b += ((uint32_t)k[6])<<16;
+ b += ((uint32_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t)k[9])<<8;
+ c += ((uint32_t)k[10])<<16;
+ c += ((uint32_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11])<<24;
+ case 11: c+=((uint32_t)k[10])<<16;
+ case 10: c+=((uint32_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t)k[7])<<24;
+ case 7 : b+=((uint32_t)k[6])<<16;
+ case 6 : b+=((uint32_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t)k[3])<<24;
+ case 3 : a+=((uint32_t)k[2])<<16;
+ case 2 : a+=((uint32_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+
+/*
+ * hashlittle2: return 2 32-bit hash values
+ *
+ * This is identical to hashlittle(), except it returns two 32-bit hash
+ * values instead of just one. This is good enough for hash table
+ * lookup with 2^^64 buckets, or if you want a second hash if you're not
+ * happy with the first, or if you want a probably-unique 64-bit ID for
+ * the key. *pc is better mixed than *pb, so use *pc first. If you want
+ * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
+ */
+void hashlittle2(
+ const void *key, /* the key to hash */
+ size_t length, /* length of the key */
+ uint32_t *pc, /* IN: primary initval, OUT: primary hash */
+ uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */
+{
+ uint32_t a,b,c; /* internal state */
+ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc;
+ c += *pb;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+ const uint8_t *k8;
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t)k[1])<<16);
+ b += k[2] + (((uint32_t)k[3])<<16);
+ c += k[4] + (((uint32_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t)k[1])<<8;
+ a += ((uint32_t)k[2])<<16;
+ a += ((uint32_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t)k[5])<<8;
+ b += ((uint32_t)k[6])<<16;
+ b += ((uint32_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t)k[9])<<8;
+ c += ((uint32_t)k[10])<<16;
+ c += ((uint32_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11])<<24;
+ case 11: c+=((uint32_t)k[10])<<16;
+ case 10: c+=((uint32_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t)k[7])<<24;
+ case 7 : b+=((uint32_t)k[6])<<16;
+ case 6 : b+=((uint32_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t)k[3])<<24;
+ case 3 : a+=((uint32_t)k[2])<<16;
+ case 2 : a+=((uint32_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+ }
+
+ final(a,b,c);
+ *pc=c; *pb=b;
+}
+
+
+
+/*
+ * hashbig():
+ * This is the same as hashword() on big-endian machines. It is different
+ * from hashlittle() on all machines. hashbig() takes advantage of
+ * big-endian byte ordering.
+ */
+uint32_t hashbig( const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a,b,c;
+ union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+ const uint8_t *k8;
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]<<8" actually reads beyond the end of the string, but
+ * then shifts out the part it's not allowed to read. Because the
+ * string is aligned, the illegal read is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff00; break;
+ case 2 : a+=k[0]&0xffff0000; break;
+ case 1 : a+=k[0]&0xff000000; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
+ case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
+ case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
+ case 1 : a+=((uint32_t)k8[0])<<24; break;
+ case 0 : return c;
+ }
+
+#endif /* !VALGRIND */
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += ((uint32_t)k[0])<<24;
+ a += ((uint32_t)k[1])<<16;
+ a += ((uint32_t)k[2])<<8;
+ a += ((uint32_t)k[3]);
+ b += ((uint32_t)k[4])<<24;
+ b += ((uint32_t)k[5])<<16;
+ b += ((uint32_t)k[6])<<8;
+ b += ((uint32_t)k[7]);
+ c += ((uint32_t)k[8])<<24;
+ c += ((uint32_t)k[9])<<16;
+ c += ((uint32_t)k[10])<<8;
+ c += ((uint32_t)k[11]);
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=k[11];
+ case 11: c+=((uint32_t)k[10])<<8;
+ case 10: c+=((uint32_t)k[9])<<16;
+ case 9 : c+=((uint32_t)k[8])<<24;
+ case 8 : b+=k[7];
+ case 7 : b+=((uint32_t)k[6])<<8;
+ case 6 : b+=((uint32_t)k[5])<<16;
+ case 5 : b+=((uint32_t)k[4])<<24;
+ case 4 : a+=k[3];
+ case 3 : a+=((uint32_t)k[2])<<8;
+ case 2 : a+=((uint32_t)k[1])<<16;
+ case 1 : a+=((uint32_t)k[0])<<24;
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+
+#ifdef SELF_TEST
+
+/* used for timings */
+void driver1()
+{
+ uint8_t buf[256];
+ uint32_t i;
+ uint32_t h=0;
+ time_t a,z;
+
+ time(&a);
+ for (i=0; i<256; ++i) buf[i] = 'x';
+ for (i=0; i<1; ++i)
+ {
+ h = hashlittle(&buf[0],1,h);
+ }
+ time(&z);
+ if (z-a > 0) printf("time %d %.8x\n", z-a, h);
+}
+
+/* check that every input bit changes every output bit half the time */
+#define HASHSTATE 1
+#define HASHLEN 1
+#define MAXPAIR 60
+#define MAXLEN 70
+void driver2()
+{
+ uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
+ uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
+ uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
+ uint32_t x[HASHSTATE],y[HASHSTATE];
+ uint32_t hlen;
+
+ printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
+ for (hlen=0; hlen < MAXLEN; ++hlen)
+ {
+ z=0;
+ for (i=0; i<hlen; ++i) /*----------------------- for each input byte, */
+ {
+ for (j=0; j<8; ++j) /*------------------------ for each input bit, */
+ {
+ for (m=1; m<8; ++m) /*------------ for serveral possible initvals, */
+ {
+ for (l=0; l<HASHSTATE; ++l)
+ e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0);
+
+ /*---- check that every output bit is affected by that input bit */
+ for (k=0; k<MAXPAIR; k+=2)
+ {
+ uint32_t finished=1;
+ /* keys have one bit different */
+ for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
+ /* have a and b be two keys differing in only one bit */
+ a[i] ^= (k<<j);
+ a[i] ^= (k>>(8-j));
+ c[0] = hashlittle(a, hlen, m);
+ b[i] ^= ((k+1)<<j);
+ b[i] ^= ((k+1)>>(8-j));
+ d[0] = hashlittle(b, hlen, m);
+ /* check every bit is 1, 0, set, and not set at least once */
+ for (l=0; l<HASHSTATE; ++l)
+ {
+ e[l] &= (c[l]^d[l]);
+ f[l] &= ~(c[l]^d[l]);
+ g[l] &= c[l];
+ h[l] &= ~c[l];
+ x[l] &= d[l];
+ y[l] &= ~d[l];
+ if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
+ }
+ if (finished) break;
+ }
+ if (k>z) z=k;
+ if (k==MAXPAIR)
+ {
+ printf("Some bit didn't change: ");
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
+ e[0],f[0],g[0],h[0],x[0],y[0]);
+ printf("i %d j %d m %d len %d\n", i, j, m, hlen);
+ }
+ if (z==MAXPAIR) goto done;
+ }
+ }
+ }
+ done:
+ if (z < MAXPAIR)
+ {
+ printf("Mix success %2d bytes %2d initvals ",i,m);
+ printf("required %d trials\n", z/2);
+ }
+ }
+ printf("\n");
+}
+
+/* Check for reading beyond the end of the buffer and alignment problems */
+void driver3()
+{
+ uint8_t buf[MAXLEN+20], *b;
+ uint32_t len;
+ uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
+ uint32_t h;
+ uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
+ uint32_t i;
+ uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
+ uint32_t j;
+ uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
+ uint32_t ref,x,y;
+ uint8_t *p;
+
+ printf("Endianness. These lines should all be the same (for values filled in):\n");
+ printf("%.8x %.8x %.8x\n",
+ hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13),
+ hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13),
+ hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13));
+ p = q;
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qq[1];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qqq[2];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qqqq[3];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ printf("\n");
+
+ /* check that hashlittle2 and hashlittle produce the same results */
+ i=47; j=0;
+ hashlittle2(q, sizeof(q), &i, &j);
+ if (hashlittle(q, sizeof(q), 47) != i)
+ printf("hashlittle2 and hashlittle mismatch\n");
+
+ /* check that hashword2 and hashword produce the same results */
+ len = 0xdeadbeef;
+ i=47, j=0;
+ hashword2(&len, 1, &i, &j);
+ if (hashword(&len, 1, 47) != i)
+ printf("hashword2 and hashword mismatch %x %x\n",
+ i, hashword(&len, 1, 47));
+
+ /* check hashlittle doesn't read before or after the ends of the string */
+ for (h=0, b=buf+1; h<8; ++h, ++b)
+ {
+ for (i=0; i<MAXLEN; ++i)
+ {
+ len = i;
+ for (j=0; j<i; ++j) *(b+j)=0;
+
+ /* these should all be equal */
+ ref = hashlittle(b, len, (uint32_t)1);
+ *(b+i)=(uint8_t)~0;
+ *(b-1)=(uint8_t)~0;
+ x = hashlittle(b, len, (uint32_t)1);
+ y = hashlittle(b, len, (uint32_t)1);
+ if ((ref != x) || (ref != y))
+ {
+ printf("alignment error: %.8x %.8x %.8x %d %d\n",ref,x,y,
+ h, i);
+ }
+ }
+ }
+}
+
+/* check for problems with nulls */
+ void driver4()
+{
+ uint8_t buf[1];
+ uint32_t h,i,state[HASHSTATE];
+
+
+ buf[0] = ~0;
+ for (i=0; i<HASHSTATE; ++i) state[i] = 1;
+ printf("These should all be different\n");
+ for (i=0, h=0; i<8; ++i)
+ {
+ h = hashlittle(buf, 0, h);
+ printf("%2ld 0-byte strings, hash is %.8x\n", i, h);
+ }
+}
+
+void driver5()
+{
+ uint32_t b,c;
+ b=0, c=0, hashlittle2("", 0, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* deadbeef deadbeef */
+ b=0xdeadbeef, c=0, hashlittle2("", 0, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* bd5b7dde deadbeef */
+ b=0xdeadbeef, c=0xdeadbeef, hashlittle2("", 0, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* 9c093ccd bd5b7dde */
+ b=0, c=0, hashlittle2("Four score and seven years ago", 30, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* 17770551 ce7226e6 */
+ b=1, c=0, hashlittle2("Four score and seven years ago", 30, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* e3607cae bd371de4 */
+ b=0, c=1, hashlittle2("Four score and seven years ago", 30, &c, &b);
+ printf("hash is %.8lx %.8lx\n", c, b); /* cd628161 6cbea4b3 */
+ c = hashlittle("Four score and seven years ago", 30, 0);
+ printf("hash is %.8lx\n", c); /* 17770551 */
+ c = hashlittle("Four score and seven years ago", 30, 1);
+ printf("hash is %.8lx\n", c); /* cd628161 */
+}
+
+
+int main()
+{
+ driver1(); /* test that the key is hashed: used for timings */
+ driver2(); /* test that whole key is hashed thoroughly */
+ driver3(); /* test that nothing but the key is hashed */
+ driver4(); /* test hashing multiple buffers (all buffers are null) */
+ driver5(); /* test the hash against known vectors */
+ return 1;
+}
+
+#endif /* SELF_TEST */
diff --git a/dep/StormLib/src/libtomcrypt/src/hashes/hash_memory.c b/dep/StormLib/src/libtomcrypt/src/hashes/hash_memory.c
new file mode 100644
index 00000000000..1daf0bffa1b
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/hashes/hash_memory.c
@@ -0,0 +1,69 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file hash_memory.c
+ Hash memory helper, Tom St Denis
+*/
+
+/**
+ Hash a block of memory and store the digest.
+ @param hash The index of the hash you wish to use
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @return CRYPT_OK if successful
+*/
+int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
+{
+ hash_state *md;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash_descriptor[hash].hashsize) {
+ *outlen = hash_descriptor[hash].hashsize;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ md = XMALLOC(sizeof(hash_state));
+ if (md == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ err = hash_descriptor[hash].done(md, out);
+ *outlen = hash_descriptor[hash].hashsize;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ XFREE(md);
+
+ return err;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:23 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/hashes/md5.c b/dep/StormLib/src/libtomcrypt/src/hashes/md5.c
new file mode 100644
index 00000000000..4cbd000c0d4
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/hashes/md5.c
@@ -0,0 +1,368 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+
+/**
+ @file md5.c
+ LTC_MD5 hash function by Tom St Denis
+*/
+
+#ifdef LTC_MD5
+
+const struct ltc_hash_descriptor md5_desc =
+{
+ "md5",
+ 3,
+ 16,
+ 64,
+
+ /* OID */
+ { 1, 2, 840, 113549, 2, 5, },
+ 6,
+
+ &md5_init,
+ &md5_process,
+ &md5_done,
+ &md5_test,
+ NULL
+};
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define G(x,y,z) (y ^ (z & (y ^ x)))
+#define H(x,y,z) (x^y^z)
+#define I(x,y,z) (y^(x|(~z)))
+
+#ifdef LTC_SMALL_CODE
+
+#define FF(a,b,c,d,M,s,t) \
+ a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define GG(a,b,c,d,M,s,t) \
+ a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define HH(a,b,c,d,M,s,t) \
+ a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define II(a,b,c,d,M,s,t) \
+ a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
+
+static const unsigned char Worder[64] = {
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+ 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
+ 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
+ 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
+};
+
+static const unsigned char Rorder[64] = {
+ 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
+ 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
+ 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
+ 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
+};
+
+static const ulong32 Korder[64] = {
+0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
+0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
+0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
+0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
+0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
+0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
+0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
+0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
+};
+
+#else
+
+#define FF(a,b,c,d,M,s,t) \
+ a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define GG(a,b,c,d,M,s,t) \
+ a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define HH(a,b,c,d,M,s,t) \
+ a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+#define II(a,b,c,d,M,s,t) \
+ a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
+
+
+#endif
+
+#ifdef LTC_CLEAN_STACK
+static int _md5_compress(hash_state *md, unsigned char *buf)
+#else
+static int md5_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+ ulong32 i, W[16], a, b, c, d;
+#ifdef LTC_SMALL_CODE
+ ulong32 t;
+#endif
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32L(W[i], buf + (4*i));
+ }
+
+ /* copy state */
+ a = md->md5.state[0];
+ b = md->md5.state[1];
+ c = md->md5.state[2];
+ d = md->md5.state[3];
+
+#ifdef LTC_SMALL_CODE
+ for (i = 0; i < 16; ++i) {
+ FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 32; ++i) {
+ GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 48; ++i) {
+ HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 64; ++i) {
+ II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+ t = d; d = c; c = b; b = a; a = t;
+ }
+
+#else
+ FF(a,b,c,d,W[0],7,0xd76aa478UL)
+ FF(d,a,b,c,W[1],12,0xe8c7b756UL)
+ FF(c,d,a,b,W[2],17,0x242070dbUL)
+ FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
+ FF(a,b,c,d,W[4],7,0xf57c0fafUL)
+ FF(d,a,b,c,W[5],12,0x4787c62aUL)
+ FF(c,d,a,b,W[6],17,0xa8304613UL)
+ FF(b,c,d,a,W[7],22,0xfd469501UL)
+ FF(a,b,c,d,W[8],7,0x698098d8UL)
+ FF(d,a,b,c,W[9],12,0x8b44f7afUL)
+ FF(c,d,a,b,W[10],17,0xffff5bb1UL)
+ FF(b,c,d,a,W[11],22,0x895cd7beUL)
+ FF(a,b,c,d,W[12],7,0x6b901122UL)
+ FF(d,a,b,c,W[13],12,0xfd987193UL)
+ FF(c,d,a,b,W[14],17,0xa679438eUL)
+ FF(b,c,d,a,W[15],22,0x49b40821UL)
+ GG(a,b,c,d,W[1],5,0xf61e2562UL)
+ GG(d,a,b,c,W[6],9,0xc040b340UL)
+ GG(c,d,a,b,W[11],14,0x265e5a51UL)
+ GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
+ GG(a,b,c,d,W[5],5,0xd62f105dUL)
+ GG(d,a,b,c,W[10],9,0x02441453UL)
+ GG(c,d,a,b,W[15],14,0xd8a1e681UL)
+ GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
+ GG(a,b,c,d,W[9],5,0x21e1cde6UL)
+ GG(d,a,b,c,W[14],9,0xc33707d6UL)
+ GG(c,d,a,b,W[3],14,0xf4d50d87UL)
+ GG(b,c,d,a,W[8],20,0x455a14edUL)
+ GG(a,b,c,d,W[13],5,0xa9e3e905UL)
+ GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
+ GG(c,d,a,b,W[7],14,0x676f02d9UL)
+ GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
+ HH(a,b,c,d,W[5],4,0xfffa3942UL)
+ HH(d,a,b,c,W[8],11,0x8771f681UL)
+ HH(c,d,a,b,W[11],16,0x6d9d6122UL)
+ HH(b,c,d,a,W[14],23,0xfde5380cUL)
+ HH(a,b,c,d,W[1],4,0xa4beea44UL)
+ HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
+ HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
+ HH(b,c,d,a,W[10],23,0xbebfbc70UL)
+ HH(a,b,c,d,W[13],4,0x289b7ec6UL)
+ HH(d,a,b,c,W[0],11,0xeaa127faUL)
+ HH(c,d,a,b,W[3],16,0xd4ef3085UL)
+ HH(b,c,d,a,W[6],23,0x04881d05UL)
+ HH(a,b,c,d,W[9],4,0xd9d4d039UL)
+ HH(d,a,b,c,W[12],11,0xe6db99e5UL)
+ HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
+ HH(b,c,d,a,W[2],23,0xc4ac5665UL)
+ II(a,b,c,d,W[0],6,0xf4292244UL)
+ II(d,a,b,c,W[7],10,0x432aff97UL)
+ II(c,d,a,b,W[14],15,0xab9423a7UL)
+ II(b,c,d,a,W[5],21,0xfc93a039UL)
+ II(a,b,c,d,W[12],6,0x655b59c3UL)
+ II(d,a,b,c,W[3],10,0x8f0ccc92UL)
+ II(c,d,a,b,W[10],15,0xffeff47dUL)
+ II(b,c,d,a,W[1],21,0x85845dd1UL)
+ II(a,b,c,d,W[8],6,0x6fa87e4fUL)
+ II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
+ II(c,d,a,b,W[6],15,0xa3014314UL)
+ II(b,c,d,a,W[13],21,0x4e0811a1UL)
+ II(a,b,c,d,W[4],6,0xf7537e82UL)
+ II(d,a,b,c,W[11],10,0xbd3af235UL)
+ II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
+ II(b,c,d,a,W[9],21,0xeb86d391UL)
+#endif
+
+ md->md5.state[0] = md->md5.state[0] + a;
+ md->md5.state[1] = md->md5.state[1] + b;
+ md->md5.state[2] = md->md5.state[2] + c;
+ md->md5.state[3] = md->md5.state[3] + d;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int md5_compress(hash_state *md, unsigned char *buf)
+{
+ int err;
+ err = _md5_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 21);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int md5_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->md5.state[0] = 0x67452301UL;
+ md->md5.state[1] = 0xefcdab89UL;
+ md->md5.state[2] = 0x98badcfeUL;
+ md->md5.state[3] = 0x10325476UL;
+ md->md5.curlen = 0;
+ md->md5.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(md5_process, md5_compress, md5, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (16 bytes)
+ @return CRYPT_OK if successful
+*/
+int md5_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->md5.curlen >= sizeof(md->md5.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->md5.length += md->md5.curlen * 8;
+
+ /* append the '1' bit */
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->md5.curlen > 56) {
+ while (md->md5.curlen < 64) {
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+ }
+ md5_compress(md, md->md5.buf);
+ md->md5.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->md5.curlen < 56) {
+ md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64L(md->md5.length, md->md5.buf+56);
+ md5_compress(md, md->md5.buf);
+
+ /* copy output */
+ for (i = 0; i < 4; i++) {
+ STORE32L(md->md5.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int md5_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ char *msg;
+ unsigned char hash[16];
+ } tests[] = {
+ { "",
+ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+ 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+ { "a",
+ {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+ 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
+ { "abc",
+ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+ 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+ { "message digest",
+ { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+ 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+ 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+ 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
+ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+ 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
+ { NULL, { 0 } }
+ };
+
+ int i;
+ unsigned char tmp[16];
+ hash_state md;
+
+ for (i = 0; tests[i].msg != NULL; i++) {
+ md5_init(&md);
+ md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+ md5_done(&md, tmp);
+ if (XMEMCMP(tmp, tests[i].hash, 16) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:25:28 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/hashes/sha1.c b/dep/StormLib/src/libtomcrypt/src/hashes/sha1.c
new file mode 100644
index 00000000000..409d0954241
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/hashes/sha1.c
@@ -0,0 +1,288 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file sha1.c
+ LTC_SHA1 code by Tom St Denis
+*/
+
+
+#ifdef LTC_SHA1
+
+const struct ltc_hash_descriptor sha1_desc =
+{
+ "sha1",
+ 2,
+ 20,
+ 64,
+
+ /* OID */
+ { 1, 3, 14, 3, 2, 26, },
+ 6,
+
+ &sha1_init,
+ &sha1_process,
+ &sha1_done,
+ &sha1_test,
+ NULL
+};
+
+#define F0(x,y,z) (z ^ (x & (y ^ z)))
+#define F1(x,y,z) (x ^ y ^ z)
+#define F2(x,y,z) ((x & y) | (z & (x | y)))
+#define F3(x,y,z) (x ^ y ^ z)
+
+#ifdef LTC_CLEAN_STACK
+static int _sha1_compress(hash_state *md, unsigned char *buf)
+#else
+static int sha1_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+ ulong32 a,b,c,d,e,W[80],i;
+#ifdef LTC_SMALL_CODE
+ ulong32 t;
+#endif
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD32H(W[i], buf + (4*i));
+ }
+
+ /* copy state */
+ a = md->sha1.state[0];
+ b = md->sha1.state[1];
+ c = md->sha1.state[2];
+ d = md->sha1.state[3];
+ e = md->sha1.state[4];
+
+ /* expand it */
+ for (i = 16; i < 80; i++) {
+ W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
+ }
+
+ /* compress */
+ /* round one */
+ #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
+ #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
+ #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
+ #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
+
+#ifdef LTC_SMALL_CODE
+
+ for (i = 0; i < 20; ) {
+ FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 40; ) {
+ FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 60; ) {
+ FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 80; ) {
+ FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+#else
+
+ for (i = 0; i < 20; ) {
+ FF0(a,b,c,d,e,i++);
+ FF0(e,a,b,c,d,i++);
+ FF0(d,e,a,b,c,i++);
+ FF0(c,d,e,a,b,i++);
+ FF0(b,c,d,e,a,i++);
+ }
+
+ /* round two */
+ for (; i < 40; ) {
+ FF1(a,b,c,d,e,i++);
+ FF1(e,a,b,c,d,i++);
+ FF1(d,e,a,b,c,i++);
+ FF1(c,d,e,a,b,i++);
+ FF1(b,c,d,e,a,i++);
+ }
+
+ /* round three */
+ for (; i < 60; ) {
+ FF2(a,b,c,d,e,i++);
+ FF2(e,a,b,c,d,i++);
+ FF2(d,e,a,b,c,i++);
+ FF2(c,d,e,a,b,i++);
+ FF2(b,c,d,e,a,i++);
+ }
+
+ /* round four */
+ for (; i < 80; ) {
+ FF3(a,b,c,d,e,i++);
+ FF3(e,a,b,c,d,i++);
+ FF3(d,e,a,b,c,i++);
+ FF3(c,d,e,a,b,i++);
+ FF3(b,c,d,e,a,i++);
+ }
+#endif
+
+ #undef FF0
+ #undef FF1
+ #undef FF2
+ #undef FF3
+
+ /* store */
+ md->sha1.state[0] = md->sha1.state[0] + a;
+ md->sha1.state[1] = md->sha1.state[1] + b;
+ md->sha1.state[2] = md->sha1.state[2] + c;
+ md->sha1.state[3] = md->sha1.state[3] + d;
+ md->sha1.state[4] = md->sha1.state[4] + e;
+
+ return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int sha1_compress(hash_state *md, unsigned char *buf)
+{
+ int err;
+ err = _sha1_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 87);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha1_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->sha1.state[0] = 0x67452301UL;
+ md->sha1.state[1] = 0xefcdab89UL;
+ md->sha1.state[2] = 0x98badcfeUL;
+ md->sha1.state[3] = 0x10325476UL;
+ md->sha1.state[4] = 0xc3d2e1f0UL;
+ md->sha1.curlen = 0;
+ md->sha1.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha1_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->sha1.length += md->sha1.curlen * 8;
+
+ /* append the '1' bit */
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha1.curlen > 56) {
+ while (md->sha1.curlen < 64) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+ sha1_compress(md, md->sha1.buf);
+ md->sha1.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->sha1.curlen < 56) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha1.length, md->sha1.buf+56);
+ sha1_compress(md, md->sha1.buf);
+
+ /* copy output */
+ for (i = 0; i < 5; i++) {
+ STORE32H(md->sha1.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha1_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "abc",
+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
+ 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
+ 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
+ 0xE5, 0x46, 0x70, 0xF1 }
+ }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha1_init(&md);
+ sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+ sha1_done(&md, tmp);
+ if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:25:28 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt.h
new file mode 100644
index 00000000000..74cdff47549
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt.h
@@ -0,0 +1,87 @@
+#ifndef TOMCRYPT_H_
+#define TOMCRYPT_H_
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <limits.h>
+
+/* use configuration data */
+#include "tomcrypt_custom.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* version */
+#define CRYPT 0x0117
+#define SCRYPT "1.17"
+
+/* max size of either a cipher/hash block or symmetric key [largest of the two] */
+#define MAXBLOCKSIZE 128
+
+/* descriptor table size */
+#define TAB_SIZE 32
+
+/* error codes [will be expanded in future releases] */
+enum {
+ CRYPT_OK=0, /* Result OK */
+ CRYPT_ERROR, /* Generic Error */
+ CRYPT_NOP, /* Not a failure but no operation was performed */
+
+ CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
+ CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
+ CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
+
+ CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
+ CRYPT_INVALID_PACKET, /* Invalid input packet given */
+
+ CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
+ CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
+
+ CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
+ CRYPT_INVALID_HASH, /* Invalid hash specified */
+ CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
+
+ CRYPT_MEM, /* Out of memory */
+
+ CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
+ CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
+
+ CRYPT_INVALID_ARG, /* Generic invalid argument */
+ CRYPT_FILE_NOTFOUND, /* File Not Found */
+
+ CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
+ CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
+ CRYPT_PK_DUP, /* Duplicate key already in key ring */
+ CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
+ CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
+
+ CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
+ CRYPT_PK_INVALID_PADDING /* Invalid padding on input */
+};
+
+#include "tomcrypt_cfg.h"
+#include "tomcrypt_macros.h"
+#include "tomcrypt_cipher.h"
+#include "tomcrypt_hash.h"
+#include "tomcrypt_mac.h"
+#include "tomcrypt_prng.h"
+#include "tomcrypt_pk.h"
+#include "tomcrypt_math.h"
+#include "tomcrypt_misc.h"
+#include "tomcrypt_argchk.h"
+#include "tomcrypt_pkcs.h"
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TOMCRYPT_H_ */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */
+/* $Revision: 1.21 $ */
+/* $Date: 2006/12/16 19:34:05 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h
new file mode 100644
index 00000000000..cfc93ad7ea6
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h
@@ -0,0 +1,38 @@
+/* Defines the LTC_ARGCHK macro used within the library */
+/* ARGTYPE is defined in mycrypt_cfg.h */
+#if ARGTYPE == 0
+
+#include <signal.h>
+
+/* this is the default LibTomCrypt macro */
+void crypt_argchk(char *v, char *s, int d);
+#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 1
+
+/* fatal type of error */
+#define LTC_ARGCHK(x) assert((x))
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 2
+
+#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 3
+
+#define LTC_ARGCHK(x)
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 4
+
+#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
+#define LTC_ARGCHKVD(x) if (!(x)) return;
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/08/27 20:50:21 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h
new file mode 100644
index 00000000000..7feae6e8bdc
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h
@@ -0,0 +1,136 @@
+/* This is the build config file.
+ *
+ * With this you can setup what to inlcude/exclude automatically during any build. Just comment
+ * out the line that #define's the word for the thing you want to remove. phew!
+ */
+
+#ifndef TOMCRYPT_CFG_H
+#define TOMCRYPT_CFG_H
+
+#if defined(_WIN32) || defined(_MSC_VER)
+#define LTC_CALL __cdecl
+#else
+#ifndef LTC_CALL
+ #define LTC_CALL
+#endif
+#endif
+
+#ifndef LTC_EXPORT
+#define LTC_EXPORT
+#endif
+
+/* certain platforms use macros for these, making the prototypes broken */
+#ifndef LTC_NO_PROTOTYPES
+
+/* you can change how memory allocation works ... */
+LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
+LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
+LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
+LTC_EXPORT void LTC_CALL XFREE(void *p);
+
+LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
+
+
+/* change the clock function too */
+LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
+
+/* various other functions */
+LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
+LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
+LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
+
+LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
+
+#endif
+
+/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
+#ifndef ARGTYPE
+ #define ARGTYPE 0
+#endif
+
+/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
+ *
+ * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
+ * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
+ * use the portable [slower] macros.
+ */
+
+/* detect x86-32 machines somewhat */
+#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))))
+ #define ENDIAN_LITTLE
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detects MIPS R5900 processors (PS2) */
+#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
+ #define ENDIAN_LITTLE
+ #define ENDIAN_64BITWORD
+#endif
+
+/* detect amd64 */
+#if !defined(__STRICT_ANSI__) && defined(__x86_64__)
+ #define ENDIAN_LITTLE
+ #define ENDIAN_64BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detect PPC32 */
+#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
+ #define ENDIAN_BIG
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detect sparc and sparc64 */
+#if defined(__sparc__)
+ #define ENDIAN_BIG
+ #if defined(__arch64__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+
+#ifdef LTC_NO_FAST
+ #ifdef LTC_FAST
+ #undef LTC_FAST
+ #endif
+#endif
+
+/* No asm is a quick way to disable anything "not portable" */
+#ifdef LTC_NO_ASM
+ #undef ENDIAN_LITTLE
+ #undef ENDIAN_BIG
+ #undef ENDIAN_32BITWORD
+ #undef ENDIAN_64BITWORD
+ #undef LTC_FAST
+ #undef LTC_FAST_TYPE
+ #define LTC_NO_ROLC
+ #define LTC_NO_BSWAP
+#endif
+
+/* #define ENDIAN_LITTLE */
+/* #define ENDIAN_BIG */
+
+/* #define ENDIAN_32BITWORD */
+/* #define ENDIAN_64BITWORD */
+
+#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
+ #error You must specify a word size as well as endianess in tomcrypt_cfg.h
+#endif
+
+#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
+ #define ENDIAN_NEUTRAL
+#endif
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */
+/* $Revision: 1.19 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h
new file mode 100644
index 00000000000..bd740bf4a0c
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h
@@ -0,0 +1,891 @@
+/* ---- SYMMETRIC KEY STUFF -----
+ *
+ * We put each of the ciphers scheduled keys in their own structs then we put all of
+ * the key formats in one union. This makes the function prototypes easier to use.
+ */
+#ifdef LTC_BLOWFISH
+struct blowfish_key {
+ ulong32 S[4][256];
+ ulong32 K[18];
+};
+#endif
+
+#ifdef LTC_RC5
+struct rc5_key {
+ int rounds;
+ ulong32 K[50];
+};
+#endif
+
+#ifdef LTC_RC6
+struct rc6_key {
+ ulong32 K[44];
+};
+#endif
+
+#ifdef LTC_SAFERP
+struct saferp_key {
+ unsigned char K[33][16];
+ long rounds;
+};
+#endif
+
+#ifdef LTC_RIJNDAEL
+struct rijndael_key {
+ ulong32 eK[60], dK[60];
+ int Nr;
+};
+#endif
+
+#ifdef LTC_KSEED
+struct kseed_key {
+ ulong32 K[32], dK[32];
+};
+#endif
+
+#ifdef LTC_KASUMI
+struct kasumi_key {
+ ulong32 KLi1[8], KLi2[8],
+ KOi1[8], KOi2[8], KOi3[8],
+ KIi1[8], KIi2[8], KIi3[8];
+};
+#endif
+
+#ifdef LTC_XTEA
+struct xtea_key {
+ unsigned long A[32], B[32];
+};
+#endif
+
+#ifdef LTC_TWOFISH
+#ifndef LTC_TWOFISH_SMALL
+ struct twofish_key {
+ ulong32 S[4][256], K[40];
+ };
+#else
+ struct twofish_key {
+ ulong32 K[40];
+ unsigned char S[32], start;
+ };
+#endif
+#endif
+
+#ifdef LTC_SAFER
+#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6
+#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10
+#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8
+#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10
+#define LTC_SAFER_MAX_NOF_ROUNDS 13
+#define LTC_SAFER_BLOCK_LEN 8
+#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))
+typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN];
+typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN];
+struct safer_key { safer_key_t key; };
+#endif
+
+#ifdef LTC_RC2
+struct rc2_key { unsigned xkey[64]; };
+#endif
+
+#ifdef LTC_DES
+struct des_key {
+ ulong32 ek[32], dk[32];
+};
+
+struct des3_key {
+ ulong32 ek[3][32], dk[3][32];
+};
+#endif
+
+#ifdef LTC_CAST5
+struct cast5_key {
+ ulong32 K[32], keylen;
+};
+#endif
+
+#ifdef LTC_NOEKEON
+struct noekeon_key {
+ ulong32 K[4], dK[4];
+};
+#endif
+
+#ifdef LTC_SKIPJACK
+struct skipjack_key {
+ unsigned char key[10];
+};
+#endif
+
+#ifdef LTC_KHAZAD
+struct khazad_key {
+ ulong64 roundKeyEnc[8 + 1];
+ ulong64 roundKeyDec[8 + 1];
+};
+#endif
+
+#ifdef LTC_ANUBIS
+struct anubis_key {
+ int keyBits;
+ int R;
+ ulong32 roundKeyEnc[18 + 1][4];
+ ulong32 roundKeyDec[18 + 1][4];
+};
+#endif
+
+#ifdef LTC_MULTI2
+struct multi2_key {
+ int N;
+ ulong32 uk[8];
+};
+#endif
+
+typedef union Symmetric_key {
+#ifdef LTC_DES
+ struct des_key des;
+ struct des3_key des3;
+#endif
+#ifdef LTC_RC2
+ struct rc2_key rc2;
+#endif
+#ifdef LTC_SAFER
+ struct safer_key safer;
+#endif
+#ifdef LTC_TWOFISH
+ struct twofish_key twofish;
+#endif
+#ifdef LTC_BLOWFISH
+ struct blowfish_key blowfish;
+#endif
+#ifdef LTC_RC5
+ struct rc5_key rc5;
+#endif
+#ifdef LTC_RC6
+ struct rc6_key rc6;
+#endif
+#ifdef LTC_SAFERP
+ struct saferp_key saferp;
+#endif
+#ifdef LTC_RIJNDAEL
+ struct rijndael_key rijndael;
+#endif
+#ifdef LTC_XTEA
+ struct xtea_key xtea;
+#endif
+#ifdef LTC_CAST5
+ struct cast5_key cast5;
+#endif
+#ifdef LTC_NOEKEON
+ struct noekeon_key noekeon;
+#endif
+#ifdef LTC_SKIPJACK
+ struct skipjack_key skipjack;
+#endif
+#ifdef LTC_KHAZAD
+ struct khazad_key khazad;
+#endif
+#ifdef LTC_ANUBIS
+ struct anubis_key anubis;
+#endif
+#ifdef LTC_KSEED
+ struct kseed_key kseed;
+#endif
+#ifdef LTC_KASUMI
+ struct kasumi_key kasumi;
+#endif
+#ifdef LTC_MULTI2
+ struct multi2_key multi2;
+#endif
+ void *data;
+} symmetric_key;
+
+#ifdef LTC_ECB_MODE
+/** A block cipher ECB structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen;
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_ECB;
+#endif
+
+#ifdef LTC_CFB_MODE
+/** A block cipher CFB structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen;
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE],
+ /** The pad used to encrypt/decrypt */
+ pad[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_CFB;
+#endif
+
+#ifdef LTC_OFB_MODE
+/** A block cipher OFB structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen;
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_OFB;
+#endif
+
+#ifdef LTC_CBC_MODE
+/** A block cipher CBC structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen;
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_CBC;
+#endif
+
+
+#ifdef LTC_CTR_MODE
+/** A block cipher CTR structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen,
+ /** The mode (endianess) of the CTR, 0==little, 1==big */
+ mode,
+ /** counter width */
+ ctrlen;
+
+ /** The counter */
+ unsigned char ctr[MAXBLOCKSIZE],
+ /** The pad used to encrypt/decrypt */
+ pad[MAXBLOCKSIZE];
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_CTR;
+#endif
+
+
+#ifdef LTC_LRW_MODE
+/** A LRW structure */
+typedef struct {
+ /** The index of the cipher chosen (must be a 128-bit block cipher) */
+ int cipher;
+
+ /** The current IV */
+ unsigned char IV[16],
+
+ /** the tweak key */
+ tweak[16],
+
+ /** The current pad, it's the product of the first 15 bytes against the tweak key */
+ pad[16];
+
+ /** The scheduled symmetric key */
+ symmetric_key key;
+
+#ifdef LRW_TABLES
+ /** The pre-computed multiplication table */
+ unsigned char PC[16][256][16];
+#endif
+} symmetric_LRW;
+#endif
+
+#ifdef LTC_F8_MODE
+/** A block cipher F8 structure */
+typedef struct {
+ /** The index of the cipher chosen */
+ int cipher,
+ /** The block size of the given cipher */
+ blocklen,
+ /** The padding offset */
+ padlen;
+ /** The current IV */
+ unsigned char IV[MAXBLOCKSIZE],
+ MIV[MAXBLOCKSIZE];
+ /** Current block count */
+ ulong32 blockcnt;
+ /** The scheduled key */
+ symmetric_key key;
+} symmetric_F8;
+#endif
+
+
+/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */
+extern struct ltc_cipher_descriptor {
+ /** name of cipher */
+ char *name;
+ /** internal ID */
+ unsigned char ID;
+ /** min keysize (octets) */
+ int min_key_length,
+ /** max keysize (octets) */
+ max_key_length,
+ /** block size (octets) */
+ block_length,
+ /** default number of rounds */
+ default_rounds;
+ /** Setup the cipher
+ @param key The input symmetric key
+ @param keylen The length of the input key (octets)
+ @param num_rounds The requested number of rounds (0==default)
+ @param skey [out] The destination of the scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ /** Encrypt a block
+ @param pt The plaintext
+ @param ct [out] The ciphertext
+ @param skey The scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+ /** Decrypt a block
+ @param ct The ciphertext
+ @param pt [out] The plaintext
+ @param skey The scheduled key
+ @return CRYPT_OK if successful
+ */
+ int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+ /** Test the block cipher
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+
+ /** Terminate the context
+ @param skey The scheduled key
+ */
+ void (*done)(symmetric_key *skey);
+
+ /** Determine a key size
+ @param keysize [in/out] The size of the key desired and the suggested size
+ @return CRYPT_OK if successful
+ */
+ int (*keysize)(int *keysize);
+
+/** Accelerators **/
+ /** Accelerated ECB encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
+
+ /** Accelerated ECB decryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
+
+ /** Accelerated CBC encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
+
+ /** Accelerated CBC decryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
+
+ /** Accelerated CTR encryption
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param mode little or big endian counter (mode=0 or mode=1)
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
+
+ /** Accelerated LRW
+ @param pt Plaintext
+ @param ct Ciphertext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param tweak The LRW tweak
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
+
+ /** Accelerated LRW
+ @param ct Ciphertext
+ @param pt Plaintext
+ @param blocks The number of complete blocks to process
+ @param IV The initial value (input/output)
+ @param tweak The LRW tweak
+ @param skey The scheduled key context
+ @return CRYPT_OK if successful
+ */
+ int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
+
+ /** Accelerated CCM packet (one-shot)
+ @param key The secret key to use
+ @param keylen The length of the secret key (octets)
+ @param uskey A previously scheduled key [optional can be NULL]
+ @param nonce The session nonce [use once]
+ @param noncelen The length of the nonce
+ @param header The header for the session
+ @param headerlen The length of the header (octets)
+ @param pt [out] The plaintext
+ @param ptlen The length of the plaintext (octets)
+ @param ct [out] The ciphertext
+ @param tag [out] The destination tag
+ @param taglen [in/out] The max size and resulting size of the authentication tag
+ @param direction Encrypt or Decrypt direction (0 or 1)
+ @return CRYPT_OK if successful
+ */
+ int (*accel_ccm_memory)(
+ const unsigned char *key, unsigned long keylen,
+ symmetric_key *uskey,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+ /** Accelerated GCM packet (one shot)
+ @param key The secret key
+ @param keylen The length of the secret key
+ @param IV The initial vector
+ @param IVlen The length of the initial vector
+ @param adata The additional authentication data (header)
+ @param adatalen The length of the adata
+ @param pt The plaintext
+ @param ptlen The length of the plaintext (ciphertext length is the same)
+ @param ct The ciphertext
+ @param tag [out] The MAC tag
+ @param taglen [in/out] The MAC tag length
+ @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
+ @return CRYPT_OK on success
+ */
+ int (*accel_gcm_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *IV, unsigned long IVlen,
+ const unsigned char *adata, unsigned long adatalen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+ /** Accelerated one shot LTC_OMAC
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ */
+ int (*omac_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+ /** Accelerated one shot XCBC
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ */
+ int (*xcbc_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+ /** Accelerated one shot F9
+ @param key The secret key
+ @param keylen The key length (octets)
+ @param in The message
+ @param inlen Length of message (octets)
+ @param out [out] Destination for tag
+ @param outlen [in/out] Initial and final size of out
+ @return CRYPT_OK on success
+ @remark Requires manual padding
+ */
+ int (*f9_memory)(
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+} cipher_descriptor[];
+
+#ifdef LTC_BLOWFISH
+int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int blowfish_test(void);
+void blowfish_done(symmetric_key *skey);
+int blowfish_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor blowfish_desc;
+#endif
+
+#ifdef LTC_RC5
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int rc5_test(void);
+void rc5_done(symmetric_key *skey);
+int rc5_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc5_desc;
+#endif
+
+#ifdef LTC_RC6
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int rc6_test(void);
+void rc6_done(symmetric_key *skey);
+int rc6_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc6_desc;
+#endif
+
+#ifdef LTC_RC2
+int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int rc2_test(void);
+void rc2_done(symmetric_key *skey);
+int rc2_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rc2_desc;
+#endif
+
+#ifdef LTC_SAFERP
+int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int saferp_test(void);
+void saferp_done(symmetric_key *skey);
+int saferp_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor saferp_desc;
+#endif
+
+#ifdef LTC_SAFER
+int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+int safer_k64_test(void);
+int safer_sk64_test(void);
+int safer_sk128_test(void);
+void safer_done(symmetric_key *skey);
+int safer_64_keysize(int *keysize);
+int safer_128_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
+#endif
+
+#ifdef LTC_RIJNDAEL
+
+/* make aes an alias */
+#define aes_setup rijndael_setup
+#define aes_ecb_encrypt rijndael_ecb_encrypt
+#define aes_ecb_decrypt rijndael_ecb_decrypt
+#define aes_test rijndael_test
+#define aes_done rijndael_done
+#define aes_keysize rijndael_keysize
+
+#define aes_enc_setup rijndael_enc_setup
+#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt
+#define aes_enc_keysize rijndael_enc_keysize
+
+int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int rijndael_test(void);
+void rijndael_done(symmetric_key *skey);
+int rijndael_keysize(int *keysize);
+int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+void rijndael_enc_done(symmetric_key *skey);
+int rijndael_enc_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
+extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
+#endif
+
+#ifdef LTC_XTEA
+int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int xtea_test(void);
+void xtea_done(symmetric_key *skey);
+int xtea_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor xtea_desc;
+#endif
+
+#ifdef LTC_TWOFISH
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int twofish_test(void);
+void twofish_done(symmetric_key *skey);
+int twofish_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor twofish_desc;
+#endif
+
+#ifdef LTC_DES
+int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int des_test(void);
+void des_done(symmetric_key *skey);
+int des_keysize(int *keysize);
+int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int des3_test(void);
+void des3_done(symmetric_key *skey);
+int des3_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor des_desc, des3_desc;
+#endif
+
+#ifdef LTC_CAST5
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int cast5_test(void);
+void cast5_done(symmetric_key *skey);
+int cast5_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor cast5_desc;
+#endif
+
+#ifdef LTC_NOEKEON
+int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int noekeon_test(void);
+void noekeon_done(symmetric_key *skey);
+int noekeon_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor noekeon_desc;
+#endif
+
+#ifdef LTC_SKIPJACK
+int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int skipjack_test(void);
+void skipjack_done(symmetric_key *skey);
+int skipjack_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor skipjack_desc;
+#endif
+
+#ifdef LTC_KHAZAD
+int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int khazad_test(void);
+void khazad_done(symmetric_key *skey);
+int khazad_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor khazad_desc;
+#endif
+
+#ifdef LTC_ANUBIS
+int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int anubis_test(void);
+void anubis_done(symmetric_key *skey);
+int anubis_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor anubis_desc;
+#endif
+
+#ifdef LTC_KSEED
+int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int kseed_test(void);
+void kseed_done(symmetric_key *skey);
+int kseed_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor kseed_desc;
+#endif
+
+#ifdef LTC_KASUMI
+int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int kasumi_test(void);
+void kasumi_done(symmetric_key *skey);
+int kasumi_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor kasumi_desc;
+#endif
+
+
+#ifdef LTC_MULTI2
+int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
+int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
+int multi2_test(void);
+void multi2_done(symmetric_key *skey);
+int multi2_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor multi2_desc;
+#endif
+
+#ifdef LTC_ECB_MODE
+int ecb_start(int cipher, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_ECB *ecb);
+int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
+int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
+int ecb_done(symmetric_ECB *ecb);
+#endif
+
+#ifdef LTC_CFB_MODE
+int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CFB *cfb);
+int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
+int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
+int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
+int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
+int cfb_done(symmetric_CFB *cfb);
+#endif
+
+#ifdef LTC_OFB_MODE
+int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_OFB *ofb);
+int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
+int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
+int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
+int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
+int ofb_done(symmetric_OFB *ofb);
+#endif
+
+#ifdef LTC_CBC_MODE
+int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CBC *cbc);
+int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
+int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
+int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
+int cbc_done(symmetric_CBC *cbc);
+#endif
+
+#ifdef LTC_CTR_MODE
+
+#define CTR_COUNTER_LITTLE_ENDIAN 0x0000
+#define CTR_COUNTER_BIG_ENDIAN 0x1000
+#define LTC_CTR_RFC3686 0x2000
+
+int ctr_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ int num_rounds, int ctr_mode,
+ symmetric_CTR *ctr);
+int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
+int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
+int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
+int ctr_done(symmetric_CTR *ctr);
+int ctr_test(void);
+#endif
+
+#ifdef LTC_LRW_MODE
+
+#define LRW_ENCRYPT 0
+#define LRW_DECRYPT 1
+
+int lrw_start( int cipher,
+ const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *tweak,
+ int num_rounds,
+ symmetric_LRW *lrw);
+int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
+int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
+int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
+int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
+int lrw_done(symmetric_LRW *lrw);
+int lrw_test(void);
+
+/* don't call */
+int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
+#endif
+
+#ifdef LTC_F8_MODE
+int f8_start( int cipher, const unsigned char *IV,
+ const unsigned char *key, int keylen,
+ const unsigned char *salt_key, int skeylen,
+ int num_rounds, symmetric_F8 *f8);
+int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);
+int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);
+int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8);
+int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);
+int f8_done(symmetric_F8 *f8);
+int f8_test_mode(void);
+#endif
+
+#ifdef LTC_XTS_MODE
+typedef struct {
+ symmetric_key key1, key2;
+ int cipher;
+} symmetric_xts;
+
+int xts_start( int cipher,
+ const unsigned char *key1,
+ const unsigned char *key2,
+ unsigned long keylen,
+ int num_rounds,
+ symmetric_xts *xts);
+
+int xts_encrypt(
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ const unsigned char *tweak,
+ symmetric_xts *xts);
+int xts_decrypt(
+ const unsigned char *ct, unsigned long ptlen,
+ unsigned char *pt,
+ const unsigned char *tweak,
+ symmetric_xts *xts);
+
+void xts_done(symmetric_xts *xts);
+int xts_test(void);
+void xts_mult_x(unsigned char *I);
+#endif
+
+int find_cipher(const char *name);
+int find_cipher_any(const char *name, int blocklen, int keylen);
+int find_cipher_id(unsigned char ID);
+int register_cipher(const struct ltc_cipher_descriptor *cipher);
+int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
+int cipher_is_valid(int idx);
+
+LTC_MUTEX_PROTO(ltc_cipher_mutex)
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */
+/* $Revision: 1.54 $ */
+/* $Date: 2007/05/12 14:37:41 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h
new file mode 100644
index 00000000000..88ec8f984ab
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h
@@ -0,0 +1,424 @@
+#ifndef TOMCRYPT_CUSTOM_H_
+#define TOMCRYPT_CUSTOM_H_
+
+#define LTC_NO_CIPHERS
+#define LTC_NO_HASHES
+#define LTC_NO_MACS
+#define LTC_NO_PRNGS
+#define LTC_NO_CURVES
+#define LTC_NO_MODES
+#define LTC_NO_PKCS
+#define LTC_NO_ROLC
+
+#define LTC_SOURCE
+#define LTC_SHA1
+#define LTC_MD5
+#define LTC_DER
+#define LTC_RC4
+
+#define USE_LTM
+#define LTM_DESC
+
+/* macros for various libc functions you can change for embedded targets */
+#ifndef XMALLOC
+ #ifdef malloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMALLOC LibTomMalloc
+#endif
+#ifndef XREALLOC
+ #ifdef realloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XREALLOC LibTomRealloc
+#endif
+#ifndef XCALLOC
+ #ifdef calloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XCALLOC LibTomCalloc
+#endif
+#ifndef XFREE
+ #ifdef free
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XFREE LibTomFree
+#endif
+
+#ifndef XMEMSET
+ #ifdef memset
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMSET memset
+#endif
+#ifndef XMEMCPY
+ #ifdef memcpy
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMCPY memcpy
+#endif
+#ifndef XMEMCMP
+ #ifdef memcmp
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMCMP memcmp
+#endif
+#ifndef XSTRCMP
+ #ifdef strcmp
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XSTRCMP strcmp
+#endif
+
+#ifndef XCLOCK
+#define XCLOCK LibTomClock
+#endif
+#ifndef XCLOCKS_PER_SEC
+#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
+#endif
+
+#ifndef XQSORT
+ #ifdef qsort
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XQSORT LibTomQsort
+#endif
+
+/* Easy button? */
+#ifdef LTC_EASY
+ #define LTC_NO_CIPHERS
+ #define LTC_RIJNDAEL
+ #define LTC_BLOWFISH
+ #define LTC_DES
+ #define LTC_CAST5
+
+ #define LTC_NO_MODES
+ #define LTC_ECB_MODE
+ #define LTC_CBC_MODE
+ #define LTC_CTR_MODE
+
+ #define LTC_NO_HASHES
+ #define LTC_SHA1
+ #define LTC_SHA512
+ #define LTC_SHA384
+ #define LTC_SHA256
+ #define LTC_SHA224
+
+ #define LTC_NO_MACS
+ #define LTC_HMAC
+ #define LTC_OMAC
+ #define LTC_CCM_MODE
+
+ #define LTC_NO_PRNGS
+ #define LTC_SPRNG
+ #define LTC_YARROW
+ #define LTC_DEVRANDOM
+ #define TRY_URANDOM_FIRST
+
+ #define LTC_NO_PK
+ #define LTC_MRSA
+ #define LTC_MECC
+#endif
+
+/* Use small code where possible */
+/* #define LTC_SMALL_CODE */
+
+/* Enable self-test test vector checking */
+#ifndef LTC_NO_TEST
+ #define LTC_TEST
+#endif
+
+/* clean the stack of functions which put private information on stack */
+/* #define LTC_CLEAN_STACK */
+
+/* disable all file related functions */
+/* #define LTC_NO_FILE */
+
+/* disable all forms of ASM */
+/* #define LTC_NO_ASM */
+
+/* disable FAST mode */
+/* #define LTC_NO_FAST */
+
+/* disable BSWAP on x86 */
+/* #define LTC_NO_BSWAP */
+
+/* ---> Symmetric Block Ciphers <--- */
+#ifndef LTC_NO_CIPHERS
+
+#define LTC_BLOWFISH
+#define LTC_RC2
+#define LTC_RC5
+#define LTC_RC6
+#define LTC_SAFERP
+#define LTC_RIJNDAEL
+#define LTC_XTEA
+/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
+ * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
+#define LTC_TWOFISH
+#ifndef LTC_NO_TABLES
+ #define LTC_TWOFISH_TABLES
+ /* #define LTC_TWOFISH_ALL_TABLES */
+#else
+ #define LTC_TWOFISH_SMALL
+#endif
+/* #define LTC_TWOFISH_SMALL */
+/* LTC_DES includes EDE triple-LTC_DES */
+#define LTC_DES
+#define LTC_CAST5
+#define LTC_NOEKEON
+#define LTC_SKIPJACK
+#define LTC_SAFER
+#define LTC_KHAZAD
+#define LTC_ANUBIS
+#define LTC_ANUBIS_TWEAK
+#define LTC_KSEED
+#define LTC_KASUMI
+
+#endif /* LTC_NO_CIPHERS */
+
+
+/* ---> Block Cipher Modes of Operation <--- */
+#ifndef LTC_NO_MODES
+
+#define LTC_CFB_MODE
+#define LTC_OFB_MODE
+#define LTC_ECB_MODE
+#define LTC_CBC_MODE
+#define LTC_CTR_MODE
+
+/* F8 chaining mode */
+#define LTC_F8_MODE
+
+/* LRW mode */
+#define LTC_LRW_MODE
+#ifndef LTC_NO_TABLES
+ /* like GCM mode this will enable 16 8x128 tables [64KB] that make
+ * seeking very fast.
+ */
+ #define LRW_TABLES
+#endif
+
+/* XTS mode */
+#define LTC_XTS_MODE
+
+#endif /* LTC_NO_MODES */
+
+/* ---> One-Way Hash Functions <--- */
+#ifndef LTC_NO_HASHES
+
+#define LTC_CHC_HASH
+#define LTC_WHIRLPOOL
+#define LTC_SHA512
+#define LTC_SHA384
+#define LTC_SHA256
+#define LTC_SHA224
+#define LTC_TIGER
+#define LTC_SHA1
+#define LTC_MD5
+#define LTC_MD4
+#define LTC_MD2
+#define LTC_RIPEMD128
+#define LTC_RIPEMD160
+#define LTC_RIPEMD256
+#define LTC_RIPEMD320
+
+#endif /* LTC_NO_HASHES */
+
+/* ---> MAC functions <--- */
+#ifndef LTC_NO_MACS
+
+#define LTC_HMAC
+#define LTC_OMAC
+#define LTC_PMAC
+#define LTC_XCBC
+#define LTC_F9_MODE
+#define LTC_PELICAN
+
+#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
+ #error Pelican-MAC requires LTC_RIJNDAEL
+#endif
+
+/* ---> Encrypt + Authenticate Modes <--- */
+
+#define LTC_EAX_MODE
+#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
+ #error LTC_EAX_MODE requires CTR and LTC_OMAC mode
+#endif
+
+#define LTC_OCB_MODE
+#define LTC_CCM_MODE
+#define LTC_GCM_MODE
+
+/* Use 64KiB tables */
+#ifndef LTC_NO_TABLES
+ #define LTC_GCM_TABLES
+#endif
+
+/* USE SSE2? requires GCC works on x86_32 and x86_64*/
+#ifdef LTC_GCM_TABLES
+/* #define LTC_GCM_TABLES_SSE2 */
+#endif
+
+#endif /* LTC_NO_MACS */
+
+/* Various tidbits of modern neatoness */
+#define LTC_BASE64
+
+/* --> Pseudo Random Number Generators <--- */
+#ifndef LTC_NO_PRNGS
+
+/* Yarrow */
+#define LTC_YARROW
+/* which descriptor of AES to use? */
+/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
+#define LTC_YARROW_AES 0
+
+#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
+ #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
+#endif
+
+/* a PRNG that simply reads from an available system source */
+#define LTC_SPRNG
+
+/* The LTC_RC4 stream cipher */
+#define LTC_RC4
+
+/* Fortuna PRNG */
+#define LTC_FORTUNA
+/* reseed every N calls to the read function */
+#define LTC_FORTUNA_WD 10
+/* number of pools (4..32) can save a bit of ram by lowering the count */
+#define LTC_FORTUNA_POOLS 32
+
+/* Greg's LTC_SOBER128 PRNG ;-0 */
+#define LTC_SOBER128
+
+/* the *nix style /dev/random device */
+#define LTC_DEVRANDOM
+/* try /dev/urandom before trying /dev/random */
+#define TRY_URANDOM_FIRST
+
+#endif /* LTC_NO_PRNGS */
+
+/* ---> math provider? <--- */
+#ifndef LTC_NO_MATH
+
+/* LibTomMath */
+#define LTM_LTC_DESC
+
+/* TomsFastMath */
+//#define TFM_LTC_DESC
+
+#endif /* LTC_NO_MATH */
+
+/* ---> Public Key Crypto <--- */
+#ifndef LTC_NO_PK
+
+/* Include RSA support */
+#define LTC_MRSA
+
+/* Include Katja (a Rabin variant like RSA) */
+/* #define MKAT */
+
+/* Digital Signature Algorithm */
+#define LTC_MDSA
+
+/* ECC */
+#define LTC_MECC
+
+/* use Shamir's trick for point mul (speeds up signature verification) */
+#define LTC_ECC_SHAMIR
+
+#if defined(TFM_LTC_DESC) && defined(LTC_MECC)
+ #define LTC_MECC_ACCEL
+#endif
+
+/* do we want fixed point ECC */
+/* #define LTC_MECC_FP */
+
+/* Timing Resistant? */
+/* #define LTC_ECC_TIMING_RESISTANT */
+
+#endif /* LTC_NO_PK */
+
+/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */
+#ifndef LTC_NO_PKCS
+
+#define LTC_PKCS_1
+#define LTC_PKCS_5
+
+/* Include ASN.1 DER (required by DSA/RSA) */
+#define LTC_DER
+
+#endif /* LTC_NO_PKCS */
+
+/* cleanup */
+
+#ifdef LTC_MECC
+/* Supported ECC Key Sizes */
+#ifndef LTC_NO_CURVES
+ #define ECC112
+ #define ECC128
+ #define ECC160
+ #define ECC192
+ #define ECC224
+ #define ECC256
+ #define ECC384
+ #define ECC521
+#endif
+#endif
+
+#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA)
+ /* Include the MPI functionality? (required by the PK algorithms) */
+ #define MPI
+#endif
+
+#ifdef LTC_MRSA
+ #define LTC_PKCS_1
+#endif
+
+#if defined(LTC_DER) && !defined(MPI)
+ #error ASN.1 DER requires MPI functionality
+#endif
+
+#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER)
+ #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
+#endif
+
+/* THREAD management */
+#ifdef LTC_PTHREAD
+
+#include <pthread.h>
+
+#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
+#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
+#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL);
+#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x);
+#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x);
+
+#else
+
+/* default no functions */
+#define LTC_MUTEX_GLOBAL(x)
+#define LTC_MUTEX_PROTO(x)
+#define LTC_MUTEX_TYPE(x)
+#define LTC_MUTEX_INIT(x)
+#define LTC_MUTEX_LOCK(x)
+#define LTC_MUTEX_UNLOCK(x)
+
+#endif
+
+/* Debuggers */
+
+/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */
+/* #define LTC_VALGRIND */
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */
+/* $Revision: 1.73 $ */
+/* $Date: 2007/05/12 14:37:41 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h
new file mode 100644
index 00000000000..18553ebf9da
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h
@@ -0,0 +1,378 @@
+/* ---- HASH FUNCTIONS ---- */
+#ifdef LTC_SHA512
+struct sha512_state {
+ ulong64 length, state[8];
+ unsigned long curlen;
+ unsigned char buf[128];
+};
+#endif
+
+#ifdef LTC_SHA256
+struct sha256_state {
+ ulong64 length;
+ ulong32 state[8], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_SHA1
+struct sha1_state {
+ ulong64 length;
+ ulong32 state[5], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_MD5
+struct md5_state {
+ ulong64 length;
+ ulong32 state[4], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_MD4
+struct md4_state {
+ ulong64 length;
+ ulong32 state[4], curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_TIGER
+struct tiger_state {
+ ulong64 state[3], length;
+ unsigned long curlen;
+ unsigned char buf[64];
+};
+#endif
+
+#ifdef LTC_MD2
+struct md2_state {
+ unsigned char chksum[16], X[48], buf[16];
+ unsigned long curlen;
+};
+#endif
+
+#ifdef LTC_RIPEMD128
+struct rmd128_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[4];
+};
+#endif
+
+#ifdef LTC_RIPEMD160
+struct rmd160_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[5];
+};
+#endif
+
+#ifdef LTC_RIPEMD256
+struct rmd256_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[8];
+};
+#endif
+
+#ifdef LTC_RIPEMD320
+struct rmd320_state {
+ ulong64 length;
+ unsigned char buf[64];
+ ulong32 curlen, state[10];
+};
+#endif
+
+#ifdef LTC_WHIRLPOOL
+struct whirlpool_state {
+ ulong64 length, state[8];
+ unsigned char buf[64];
+ ulong32 curlen;
+};
+#endif
+
+#ifdef LTC_CHC_HASH
+struct chc_state {
+ ulong64 length;
+ unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
+ ulong32 curlen;
+};
+#endif
+
+typedef union Hash_state {
+#ifdef LTC_CHC_HASH
+ struct chc_state chc;
+#endif
+#ifdef LTC_WHIRLPOOL
+ struct whirlpool_state whirlpool;
+#endif
+#ifdef LTC_SHA512
+ struct sha512_state sha512;
+#endif
+#ifdef LTC_SHA256
+ struct sha256_state sha256;
+#endif
+#ifdef LTC_SHA1
+ struct sha1_state sha1;
+#endif
+#ifdef LTC_MD5
+ struct md5_state md5;
+#endif
+#ifdef LTC_MD4
+ struct md4_state md4;
+#endif
+#ifdef LTC_MD2
+ struct md2_state md2;
+#endif
+#ifdef LTC_TIGER
+ struct tiger_state tiger;
+#endif
+#ifdef LTC_RIPEMD128
+ struct rmd128_state rmd128;
+#endif
+#ifdef LTC_RIPEMD160
+ struct rmd160_state rmd160;
+#endif
+#ifdef LTC_RIPEMD256
+ struct rmd256_state rmd256;
+#endif
+#ifdef LTC_RIPEMD320
+ struct rmd320_state rmd320;
+#endif
+ void *data;
+} hash_state;
+
+/** hash descriptor */
+extern struct ltc_hash_descriptor {
+ /** name of hash */
+ char *name;
+ /** internal ID */
+ unsigned char ID;
+ /** Size of digest in octets */
+ unsigned long hashsize;
+ /** Input block size in octets */
+ unsigned long blocksize;
+ /** ASN.1 OID */
+ unsigned long OID[16];
+ /** Length of DER encoding */
+ unsigned long OIDlen;
+
+ /** Init a hash state
+ @param hash The hash to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*init)(hash_state *hash);
+ /** Process a block of data
+ @param hash The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+ */
+ int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
+ /** Produce the digest and store it
+ @param hash The hash state
+ @param out [out] The destination of the digest
+ @return CRYPT_OK if successful
+ */
+ int (*done)(hash_state *hash, unsigned char *out);
+ /** Self-test
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+ */
+ int (*test)(void);
+
+ /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
+ int (*hmac_block)(const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+} hash_descriptor[];
+
+#ifdef LTC_CHC_HASH
+int chc_register(int cipher);
+int chc_init(hash_state * md);
+int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int chc_done(hash_state * md, unsigned char *hash);
+int chc_test(void);
+extern const struct ltc_hash_descriptor chc_desc;
+#endif
+
+#ifdef LTC_WHIRLPOOL
+int whirlpool_init(hash_state * md);
+int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int whirlpool_done(hash_state * md, unsigned char *hash);
+int whirlpool_test(void);
+extern const struct ltc_hash_descriptor whirlpool_desc;
+#endif
+
+#ifdef LTC_SHA512
+int sha512_init(hash_state * md);
+int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha512_done(hash_state * md, unsigned char *hash);
+int sha512_test(void);
+extern const struct ltc_hash_descriptor sha512_desc;
+#endif
+
+#ifdef LTC_SHA384
+#ifndef LTC_SHA512
+ #error LTC_SHA512 is required for LTC_SHA384
+#endif
+int sha384_init(hash_state * md);
+#define sha384_process sha512_process
+int sha384_done(hash_state * md, unsigned char *hash);
+int sha384_test(void);
+extern const struct ltc_hash_descriptor sha384_desc;
+#endif
+
+#ifdef LTC_SHA256
+int sha256_init(hash_state * md);
+int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha256_done(hash_state * md, unsigned char *hash);
+int sha256_test(void);
+extern const struct ltc_hash_descriptor sha256_desc;
+
+#ifdef LTC_SHA224
+#ifndef LTC_SHA256
+ #error LTC_SHA256 is required for LTC_SHA224
+#endif
+int sha224_init(hash_state * md);
+#define sha224_process sha256_process
+int sha224_done(hash_state * md, unsigned char *hash);
+int sha224_test(void);
+extern const struct ltc_hash_descriptor sha224_desc;
+#endif
+#endif
+
+#ifdef LTC_SHA1
+int sha1_init(hash_state * md);
+int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha1_done(hash_state * md, unsigned char *hash);
+int sha1_test(void);
+extern const struct ltc_hash_descriptor sha1_desc;
+#endif
+
+#ifdef LTC_MD5
+int md5_init(hash_state * md);
+int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md5_done(hash_state * md, unsigned char *hash);
+int md5_test(void);
+extern const struct ltc_hash_descriptor md5_desc;
+#endif
+
+#ifdef LTC_MD4
+int md4_init(hash_state * md);
+int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md4_done(hash_state * md, unsigned char *hash);
+int md4_test(void);
+extern const struct ltc_hash_descriptor md4_desc;
+#endif
+
+#ifdef LTC_MD2
+int md2_init(hash_state * md);
+int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int md2_done(hash_state * md, unsigned char *hash);
+int md2_test(void);
+extern const struct ltc_hash_descriptor md2_desc;
+#endif
+
+#ifdef LTC_TIGER
+int tiger_init(hash_state * md);
+int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int tiger_done(hash_state * md, unsigned char *hash);
+int tiger_test(void);
+extern const struct ltc_hash_descriptor tiger_desc;
+#endif
+
+#ifdef LTC_RIPEMD128
+int rmd128_init(hash_state * md);
+int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd128_done(hash_state * md, unsigned char *hash);
+int rmd128_test(void);
+extern const struct ltc_hash_descriptor rmd128_desc;
+#endif
+
+#ifdef LTC_RIPEMD160
+int rmd160_init(hash_state * md);
+int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd160_done(hash_state * md, unsigned char *hash);
+int rmd160_test(void);
+extern const struct ltc_hash_descriptor rmd160_desc;
+#endif
+
+#ifdef LTC_RIPEMD256
+int rmd256_init(hash_state * md);
+int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd256_done(hash_state * md, unsigned char *hash);
+int rmd256_test(void);
+extern const struct ltc_hash_descriptor rmd256_desc;
+#endif
+
+#ifdef LTC_RIPEMD320
+int rmd320_init(hash_state * md);
+int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int rmd320_done(hash_state * md, unsigned char *hash);
+int rmd320_test(void);
+extern const struct ltc_hash_descriptor rmd320_desc;
+#endif
+
+
+int find_hash(const char *name);
+int find_hash_id(unsigned char ID);
+int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
+int find_hash_any(const char *name, int digestlen);
+int register_hash(const struct ltc_hash_descriptor *hash);
+int unregister_hash(const struct ltc_hash_descriptor *hash);
+int hash_is_valid(int idx);
+
+LTC_MUTEX_PROTO(ltc_hash_mutex)
+
+int hash_memory(int hash,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
+int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
+
+/* a simple macro for making hash "process" functions */
+#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
+int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \
+{ \
+ unsigned long n; \
+ int err; \
+ LTC_ARGCHK(md != NULL); \
+ LTC_ARGCHK(in != NULL); \
+ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
+ return CRYPT_INVALID_ARG; \
+ } \
+ while (inlen > 0) { \
+ if (md-> state_var .curlen == 0 && inlen >= block_size) { \
+ if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \
+ return err; \
+ } \
+ md-> state_var .length += block_size * 8; \
+ in += block_size; \
+ inlen -= block_size; \
+ } else { \
+ n = MIN(inlen, (block_size - md-> state_var .curlen)); \
+ memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \
+ md-> state_var .curlen += n; \
+ in += n; \
+ inlen -= n; \
+ if (md-> state_var .curlen == block_size) { \
+ if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \
+ return err; \
+ } \
+ md-> state_var .length += 8*block_size; \
+ md-> state_var .curlen = 0; \
+ } \
+ } \
+ } \
+ return CRYPT_OK; \
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_hash.h,v $ */
+/* $Revision: 1.22 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h
new file mode 100644
index 00000000000..7ad9516bd29
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h
@@ -0,0 +1,384 @@
+#ifdef LTC_HMAC
+typedef struct Hmac_state {
+ hash_state md;
+ int hash;
+ hash_state hashstate;
+ unsigned char *key;
+} hmac_state;
+
+int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
+int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen);
+int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen);
+int hmac_test(void);
+int hmac_memory(int hash,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int hmac_memory_multi(int hash,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+int hmac_file(int hash, const char *fname, const unsigned char *key,
+ unsigned long keylen,
+ unsigned char *dst, unsigned long *dstlen);
+#endif
+
+#ifdef LTC_OMAC
+
+typedef struct {
+ int cipher_idx,
+ buflen,
+ blklen;
+ unsigned char block[MAXBLOCKSIZE],
+ prev[MAXBLOCKSIZE],
+ Lu[2][MAXBLOCKSIZE];
+ symmetric_key key;
+} omac_state;
+
+int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
+int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
+int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
+int omac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int omac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+int omac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+int omac_test(void);
+#endif /* LTC_OMAC */
+
+#ifdef LTC_PMAC
+
+typedef struct {
+ unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
+ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
+ Lr[MAXBLOCKSIZE], /* L * x^-1 */
+ block[MAXBLOCKSIZE], /* currently accumulated block */
+ checksum[MAXBLOCKSIZE]; /* current checksum */
+
+ symmetric_key key; /* scheduled key for cipher */
+ unsigned long block_index; /* index # for current block */
+ int cipher_idx, /* cipher idx */
+ block_len, /* length of block */
+ buflen; /* number of bytes in the buffer */
+} pmac_state;
+
+int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
+int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen);
+int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen);
+
+int pmac_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *msg, unsigned long msglen,
+ unsigned char *out, unsigned long *outlen);
+
+int pmac_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+
+int pmac_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+
+int pmac_test(void);
+
+/* internal functions */
+int pmac_ntz(unsigned long x);
+void pmac_shift_xor(pmac_state *pmac);
+
+#endif /* PMAC */
+
+#ifdef LTC_EAX_MODE
+
+#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))
+ #error LTC_EAX_MODE requires LTC_OMAC and CTR
+#endif
+
+typedef struct {
+ unsigned char N[MAXBLOCKSIZE];
+ symmetric_CTR ctr;
+ omac_state headeromac, ctomac;
+} eax_state;
+
+int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen);
+
+int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
+int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
+int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
+int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
+
+int eax_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int eax_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ unsigned char *tag, unsigned long taglen,
+ int *stat);
+
+ int eax_test(void);
+#endif /* EAX MODE */
+
+#ifdef LTC_OCB_MODE
+typedef struct {
+ unsigned char L[MAXBLOCKSIZE], /* L value */
+ Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
+ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
+ Lr[MAXBLOCKSIZE], /* L * x^-1 */
+ R[MAXBLOCKSIZE], /* R value */
+ checksum[MAXBLOCKSIZE]; /* current checksum */
+
+ symmetric_key key; /* scheduled key for cipher */
+ unsigned long block_index; /* index # for current block */
+ int cipher, /* cipher idx */
+ block_len; /* length of block */
+} ocb_state;
+
+int ocb_init(ocb_state *ocb, int cipher,
+ const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
+
+int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
+int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
+
+int ocb_done_encrypt(ocb_state *ocb,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int ocb_done_decrypt(ocb_state *ocb,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen, int *stat);
+
+int ocb_encrypt_authenticate_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen);
+
+int ocb_decrypt_verify_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce,
+ const unsigned char *ct, unsigned long ctlen,
+ unsigned char *pt,
+ const unsigned char *tag, unsigned long taglen,
+ int *stat);
+
+int ocb_test(void);
+
+/* internal functions */
+void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
+int ocb_ntz(unsigned long x);
+int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
+
+#endif /* LTC_OCB_MODE */
+
+#ifdef LTC_CCM_MODE
+
+#define CCM_ENCRYPT 0
+#define CCM_DECRYPT 1
+
+int ccm_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ symmetric_key *uskey,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *header, unsigned long headerlen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+
+int ccm_test(void);
+
+#endif /* LTC_CCM_MODE */
+
+#if defined(LRW_MODE) || defined(LTC_GCM_MODE)
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);
+#endif
+
+
+/* table shared between GCM and LRW */
+#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))
+extern const unsigned char gcm_shift_table[];
+#endif
+
+#ifdef LTC_GCM_MODE
+
+#define GCM_ENCRYPT 0
+#define GCM_DECRYPT 1
+
+#define LTC_GCM_MODE_IV 0
+#define LTC_GCM_MODE_AAD 1
+#define LTC_GCM_MODE_TEXT 2
+
+typedef struct {
+ symmetric_key K;
+ unsigned char H[16], /* multiplier */
+ X[16], /* accumulator */
+ Y[16], /* counter */
+ Y_0[16], /* initial counter */
+ buf[16]; /* buffer for stuff */
+
+ int cipher, /* which cipher */
+ ivmode, /* Which mode is the IV in? */
+ mode, /* mode the GCM code is in */
+ buflen; /* length of data in buf */
+
+ ulong64 totlen, /* 64-bit counter used for IV and AAD */
+ pttotlen; /* 64-bit counter for the PT */
+
+#ifdef LTC_GCM_TABLES
+ unsigned char PC[16][256][16] /* 16 tables of 8x128 */
+#ifdef LTC_GCM_TABLES_SSE2
+__attribute__ ((aligned (16)))
+#endif
+;
+#endif
+} gcm_state;
+
+void gcm_mult_h(gcm_state *gcm, unsigned char *I);
+
+int gcm_init(gcm_state *gcm, int cipher,
+ const unsigned char *key, int keylen);
+
+int gcm_reset(gcm_state *gcm);
+
+int gcm_add_iv(gcm_state *gcm,
+ const unsigned char *IV, unsigned long IVlen);
+
+int gcm_add_aad(gcm_state *gcm,
+ const unsigned char *adata, unsigned long adatalen);
+
+int gcm_process(gcm_state *gcm,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ int direction);
+
+int gcm_done(gcm_state *gcm,
+ unsigned char *tag, unsigned long *taglen);
+
+int gcm_memory( int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *IV, unsigned long IVlen,
+ const unsigned char *adata, unsigned long adatalen,
+ unsigned char *pt, unsigned long ptlen,
+ unsigned char *ct,
+ unsigned char *tag, unsigned long *taglen,
+ int direction);
+int gcm_test(void);
+
+#endif /* LTC_GCM_MODE */
+
+#ifdef LTC_PELICAN
+
+typedef struct pelican_state
+{
+ symmetric_key K;
+ unsigned char state[16];
+ int buflen;
+} pelican_state;
+
+int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen);
+int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen);
+int pelican_done(pelican_state *pelmac, unsigned char *out);
+int pelican_test(void);
+
+int pelican_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out);
+
+#endif
+
+#ifdef LTC_XCBC
+
+/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */
+#define LTC_XCBC_PURE 0x8000UL
+
+typedef struct {
+ unsigned char K[3][MAXBLOCKSIZE],
+ IV[MAXBLOCKSIZE];
+
+ symmetric_key key;
+
+ int cipher,
+ buflen,
+ blocksize;
+} xcbc_state;
+
+int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen);
+int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen);
+int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen);
+int xcbc_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int xcbc_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+int xcbc_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+int xcbc_test(void);
+
+#endif
+
+#ifdef LTC_F9_MODE
+
+typedef struct {
+ unsigned char akey[MAXBLOCKSIZE],
+ ACC[MAXBLOCKSIZE],
+ IV[MAXBLOCKSIZE];
+
+ symmetric_key key;
+
+ int cipher,
+ buflen,
+ keylen,
+ blocksize;
+} f9_state;
+
+int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen);
+int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen);
+int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen);
+int f9_memory(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int f9_memory_multi(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+int f9_file(int cipher,
+ const unsigned char *key, unsigned long keylen,
+ const char *filename,
+ unsigned char *out, unsigned long *outlen);
+int f9_test(void);
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_mac.h,v $ */
+/* $Revision: 1.23 $ */
+/* $Date: 2007/05/12 14:37:41 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h
new file mode 100644
index 00000000000..53bda9bb4ba
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h
@@ -0,0 +1,424 @@
+/* fix for MSVC ...evil! */
+#ifdef _MSC_VER
+ #define CONST64(n) n ## ui64
+ typedef unsigned __int64 ulong64;
+#else
+ #define CONST64(n) n ## ULL
+ typedef unsigned long long ulong64;
+#endif
+
+/* this is the "32-bit at least" data type
+ * Re-define it to suit your platform but it must be at least 32-bits
+ */
+#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__))
+ typedef unsigned ulong32;
+#else
+ typedef unsigned long ulong32;
+#endif
+
+/* ---- HELPER MACROS ---- */
+#ifdef ENDIAN_NEUTRAL
+
+#define STORE32L(x, y) \
+ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y) \
+ { x = ((unsigned long)((y)[3] & 255)<<24) | \
+ ((unsigned long)((y)[2] & 255)<<16) | \
+ ((unsigned long)((y)[1] & 255)<<8) | \
+ ((unsigned long)((y)[0] & 255)); }
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#define STORE32H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((unsigned long)((y)[0] & 255)<<24) | \
+ ((unsigned long)((y)[1] & 255)<<16) | \
+ ((unsigned long)((y)[2] & 255)<<8) | \
+ ((unsigned long)((y)[3] & 255)); }
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#endif /* ENDIAN_NEUTRAL */
+
+#ifdef ENDIAN_LITTLE
+
+#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
+
+#define STORE32H(x, y) \
+asm __volatile__ ( \
+ "bswapl %0 \n\t" \
+ "movl %0,(%1)\n\t" \
+ "bswapl %0 \n\t" \
+ ::"r"(x), "r"(y));
+
+#define LOAD32H(x, y) \
+asm __volatile__ ( \
+ "movl (%1),%0\n\t" \
+ "bswapl %0\n\t" \
+ :"=r"(x): "r"(y));
+
+#else
+
+#define STORE32H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((unsigned long)((y)[0] & 255)<<24) | \
+ ((unsigned long)((y)[1] & 255)<<16) | \
+ ((unsigned long)((y)[2] & 255)<<8) | \
+ ((unsigned long)((y)[3] & 255)); }
+
+#endif
+
+
+/* x86_64 processor */
+#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
+
+#define STORE64H(x, y) \
+asm __volatile__ ( \
+ "bswapq %0 \n\t" \
+ "movq %0,(%1)\n\t" \
+ "bswapq %0 \n\t" \
+ ::"r"(x), "r"(y));
+
+#define LOAD64H(x, y) \
+asm __volatile__ ( \
+ "movq (%1),%0\n\t" \
+ "bswapq %0\n\t" \
+ :"=r"(x): "r"(y));
+
+#else
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#endif
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32L(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32L(x, y) \
+ XMEMCPY(&(x), y, 4);
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#else /* 64-bit words then */
+
+#define STORE32L(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32L(x, y) \
+ { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64L(x, y) \
+ { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
+
+#define LOAD64L(x, y) \
+ { XMEMCPY(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+
+#endif /* ENDIAN_LITTLE */
+
+#ifdef ENDIAN_BIG
+#define STORE32L(x, y) \
+ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y) \
+ { x = ((unsigned long)((y)[3] & 255)<<24) | \
+ ((unsigned long)((y)[2] & 255)<<16) | \
+ ((unsigned long)((y)[1] & 255)<<8) | \
+ ((unsigned long)((y)[0] & 255)); }
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32H(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32H(x, y) \
+ XMEMCPY(&(x), y, 4);
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
+ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
+
+#else /* 64-bit words then */
+
+#define STORE32H(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32H(x, y) \
+ { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64H(x, y) \
+ { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
+
+#define LOAD64H(x, y) \
+ { XMEMCPY(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+#endif /* ENDIAN_BIG */
+
+#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
+ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
+
+
+/* 32-bit Rotates */
+#if defined(_MSC_VER)
+
+/* instrinsic rotate */
+#include <stdlib.h>
+#pragma intrinsic(_lrotr,_lrotl)
+#define ROR(x,n) _lrotr(x,n)
+#define ROL(x,n) _lrotl(x,n)
+#define RORc(x,n) _lrotr(x,n)
+#define ROLc(x,n) _lrotl(x,n)
+
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
+
+static inline unsigned ROL(unsigned word, int i)
+{
+ asm ("roll %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline unsigned ROR(unsigned word, int i)
+{
+ asm ("rorl %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned ROLc(unsigned word, const int i)
+{
+ asm ("roll %2,%0"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+static inline unsigned RORc(unsigned word, const int i)
+{
+ asm ("rorl %2,%0"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
+
+static inline unsigned ROL(unsigned word, int i)
+{
+ asm ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (i));
+ return word;
+}
+
+static inline unsigned ROR(unsigned word, int i)
+{
+ asm ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (32-i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned ROLc(unsigned word, const int i)
+{
+ asm ("rotlwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+static inline unsigned RORc(unsigned word, const int i)
+{
+ asm ("rotrwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+
+#else
+
+/* rotates the hard way */
+#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+
+#endif
+
+
+/* 64-bit Rotates */
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM)
+
+static inline unsigned long ROL64(unsigned long word, int i)
+{
+ asm("rolq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline unsigned long ROR64(unsigned long word, int i)
+{
+ asm("rorq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned long ROL64c(unsigned long word, const int i)
+{
+ asm("rolq %2,%0"
+ :"=r" (word)
+ :"0" (word),"J" (i));
+ return word;
+}
+
+static inline unsigned long ROR64c(unsigned long word, const int i)
+{
+ asm("rorq %2,%0"
+ :"=r" (word)
+ :"0" (word),"J" (i));
+ return word;
+}
+
+#else /* LTC_NO_ROLC */
+
+#define ROL64c ROL64
+#define ROR64c ROR64
+
+#endif
+
+#else /* Not x86_64 */
+
+#define ROL64(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROL64c(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64c(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#endif
+
+#ifndef MAX
+ #define MAX(x, y) ( ((x)>(y))?(x):(y) )
+#endif
+
+#ifndef MIN
+ #define MIN(x, y) ( ((x)<(y))?(x):(y) )
+#endif
+
+/* extract a byte portably */
+#ifdef _MSC_VER
+ #define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
+#else
+ #define byte(x, n) (((x) >> (8 * (n))) & 255)
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */
+/* $Revision: 1.15 $ */
+/* $Date: 2006/11/29 23:43:57 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h
new file mode 100644
index 00000000000..a05d7fff942
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h
@@ -0,0 +1,500 @@
+/** math functions **/
+
+#define LTC_MP_LT -1
+#define LTC_MP_EQ 0
+#define LTC_MP_GT 1
+
+#define LTC_MP_NO 0
+#define LTC_MP_YES 1
+
+#ifndef LTC_MECC
+ typedef void ecc_point;
+#endif
+
+#ifndef LTC_MRSA
+ typedef void rsa_key;
+#endif
+
+/** math descriptor */
+typedef struct {
+ /** Name of the math provider */
+ char *name;
+
+ /** Bits per digit, amount of bits must fit in an unsigned long */
+ int bits_per_digit;
+
+/* ---- init/deinit functions ---- */
+
+ /** initialize a bignum
+ @param a The number to initialize
+ @return CRYPT_OK on success
+ */
+ int (*init)(void **a);
+
+ /** init copy
+ @param dst The number to initialize and write to
+ @param src The number to copy from
+ @return CRYPT_OK on success
+ */
+ int (*init_copy)(void **dst, void *src);
+
+ /** deinit
+ @param a The number to free
+ @return CRYPT_OK on success
+ */
+ void (*deinit)(void *a);
+
+/* ---- data movement ---- */
+
+ /** negate
+ @param src The number to negate
+ @param dst The destination
+ @return CRYPT_OK on success
+ */
+ int (*neg)(void *src, void *dst);
+
+ /** copy
+ @param src The number to copy from
+ @param dst The number to write to
+ @return CRYPT_OK on success
+ */
+ int (*copy)(void *src, void *dst);
+
+/* ---- trivial low level functions ---- */
+
+ /** set small constant
+ @param a Number to write to
+ @param n Source upto bits_per_digit (actually meant for very small constants)
+ @return CRYPT_OK on succcess
+ */
+ int (*set_int)(void *a, unsigned long n);
+
+ /** get small constant
+ @param a Number to read, only fetches upto bits_per_digit from the number
+ @return The lower bits_per_digit of the integer (unsigned)
+ */
+ unsigned long (*get_int)(void *a);
+
+ /** get digit n
+ @param a The number to read from
+ @param n The number of the digit to fetch
+ @return The bits_per_digit sized n'th digit of a
+ */
+ unsigned long (*get_digit)(void *a, int n);
+
+ /** Get the number of digits that represent the number
+ @param a The number to count
+ @return The number of digits used to represent the number
+ */
+ int (*get_digit_count)(void *a);
+
+ /** compare two integers
+ @param a The left side integer
+ @param b The right side integer
+ @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
+ */
+ int (*compare)(void *a, void *b);
+
+ /** compare against int
+ @param a The left side integer
+ @param b The right side integer (upto bits_per_digit)
+ @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
+ */
+ int (*compare_d)(void *a, unsigned long n);
+
+ /** Count the number of bits used to represent the integer
+ @param a The integer to count
+ @return The number of bits required to represent the integer
+ */
+ int (*count_bits)(void * a);
+
+ /** Count the number of LSB bits which are zero
+ @param a The integer to count
+ @return The number of contiguous zero LSB bits
+ */
+ int (*count_lsb_bits)(void *a);
+
+ /** Compute a power of two
+ @param a The integer to store the power in
+ @param n The power of two you want to store (a = 2^n)
+ @return CRYPT_OK on success
+ */
+ int (*twoexpt)(void *a , int n);
+
+/* ---- radix conversions ---- */
+
+ /** read ascii string
+ @param a The integer to store into
+ @param str The string to read
+ @param radix The radix the integer has been represented in (2-64)
+ @return CRYPT_OK on success
+ */
+ int (*read_radix)(void *a, const char *str, int radix);
+
+ /** write number to string
+ @param a The integer to store
+ @param str The destination for the string
+ @param radix The radix the integer is to be represented in (2-64)
+ @return CRYPT_OK on success
+ */
+ int (*write_radix)(void *a, char *str, int radix);
+
+ /** get size as unsigned char string
+ @param a The integer to get the size (when stored in array of octets)
+ @return The length of the integer
+ */
+ unsigned long (*unsigned_size)(void *a);
+
+ /** store an integer as an array of octets
+ @param src The integer to store
+ @param dst The buffer to store the integer in
+ @return CRYPT_OK on success
+ */
+ int (*unsigned_write)(void *src, unsigned char *dst);
+
+ /** read an array of octets and store as integer
+ @param dst The integer to load
+ @param src The array of octets
+ @param len The number of octets
+ @return CRYPT_OK on success
+ */
+ int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len);
+
+/* ---- basic math ---- */
+
+ /** add two integers
+ @param a The first source integer
+ @param b The second source integer
+ @param c The destination of "a + b"
+ @return CRYPT_OK on success
+ */
+ int (*add)(void *a, void *b, void *c);
+
+
+ /** add two integers
+ @param a The first source integer
+ @param b The second source integer (single digit of upto bits_per_digit in length)
+ @param c The destination of "a + b"
+ @return CRYPT_OK on success
+ */
+ int (*addi)(void *a, unsigned long b, void *c);
+
+ /** subtract two integers
+ @param a The first source integer
+ @param b The second source integer
+ @param c The destination of "a - b"
+ @return CRYPT_OK on success
+ */
+ int (*sub)(void *a, void *b, void *c);
+
+ /** subtract two integers
+ @param a The first source integer
+ @param b The second source integer (single digit of upto bits_per_digit in length)
+ @param c The destination of "a - b"
+ @return CRYPT_OK on success
+ */
+ int (*subi)(void *a, unsigned long b, void *c);
+
+ /** multiply two integers
+ @param a The first source integer
+ @param b The second source integer (single digit of upto bits_per_digit in length)
+ @param c The destination of "a * b"
+ @return CRYPT_OK on success
+ */
+ int (*mul)(void *a, void *b, void *c);
+
+ /** multiply two integers
+ @param a The first source integer
+ @param b The second source integer (single digit of upto bits_per_digit in length)
+ @param c The destination of "a * b"
+ @return CRYPT_OK on success
+ */
+ int (*muli)(void *a, unsigned long b, void *c);
+
+ /** Square an integer
+ @param a The integer to square
+ @param b The destination
+ @return CRYPT_OK on success
+ */
+ int (*sqr)(void *a, void *b);
+
+ /** Divide an integer
+ @param a The dividend
+ @param b The divisor
+ @param c The quotient (can be NULL to signify don't care)
+ @param d The remainder (can be NULL to signify don't care)
+ @return CRYPT_OK on success
+ */
+ int (*mpdiv)(void *a, void *b, void *c, void *d);
+
+ /** divide by two
+ @param a The integer to divide (shift right)
+ @param b The destination
+ @return CRYPT_OK on success
+ */
+ int (*div_2)(void *a, void *b);
+
+ /** Get remainder (small value)
+ @param a The integer to reduce
+ @param b The modulus (upto bits_per_digit in length)
+ @param c The destination for the residue
+ @return CRYPT_OK on success
+ */
+ int (*modi)(void *a, unsigned long b, unsigned long *c);
+
+ /** gcd
+ @param a The first integer
+ @param b The second integer
+ @param c The destination for (a, b)
+ @return CRYPT_OK on success
+ */
+ int (*gcd)(void *a, void *b, void *c);
+
+ /** lcm
+ @param a The first integer
+ @param b The second integer
+ @param c The destination for [a, b]
+ @return CRYPT_OK on success
+ */
+ int (*lcm)(void *a, void *b, void *c);
+
+ /** Modular multiplication
+ @param a The first source
+ @param b The second source
+ @param c The modulus
+ @param d The destination (a*b mod c)
+ @return CRYPT_OK on success
+ */
+ int (*mulmod)(void *a, void *b, void *c, void *d);
+
+ /** Modular squaring
+ @param a The first source
+ @param b The modulus
+ @param c The destination (a*a mod b)
+ @return CRYPT_OK on success
+ */
+ int (*sqrmod)(void *a, void *b, void *c);
+
+ /** Modular inversion
+ @param a The value to invert
+ @param b The modulus
+ @param c The destination (1/a mod b)
+ @return CRYPT_OK on success
+ */
+ int (*invmod)(void *, void *, void *);
+
+/* ---- reduction ---- */
+
+ /** setup montgomery
+ @param a The modulus
+ @param b The destination for the reduction digit
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_setup)(void *a, void **b);
+
+ /** get normalization value
+ @param a The destination for the normalization value
+ @param b The modulus
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_normalization)(void *a, void *b);
+
+ /** reduce a number
+ @param a The number [and dest] to reduce
+ @param b The modulus
+ @param c The value "b" from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*montgomery_reduce)(void *a, void *b, void *c);
+
+ /** clean up (frees memory)
+ @param a The value "b" from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ void (*montgomery_deinit)(void *a);
+
+/* ---- exponentiation ---- */
+
+ /** Modular exponentiation
+ @param a The base integer
+ @param b The power (can be negative) integer
+ @param c The modulus integer
+ @param d The destination
+ @return CRYPT_OK on success
+ */
+ int (*exptmod)(void *a, void *b, void *c, void *d);
+
+ /** Primality testing
+ @param a The integer to test
+ @param b The destination of the result (FP_YES if prime)
+ @return CRYPT_OK on success
+ */
+ int (*isprime)(void *a, int *b);
+
+/* ---- (optional) ecc point math ---- */
+
+ /** ECC GF(p) point multiplication (from the NIST curves)
+ @param k The integer to multiply the point by
+ @param G The point to multiply
+ @param R The destination for kG
+ @param modulus The modulus for the field
+ @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
+
+ /** ECC GF(p) point addition
+ @param P The first point
+ @param Q The second point
+ @param R The destination of P + Q
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
+
+ /** ECC GF(p) point double
+ @param P The first point
+ @param R The destination of 2P
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ */
+ int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);
+
+ /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)
+ @param P The point to map
+ @param modulus The modulus
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+ @remark The mapping can be different but keep in mind a ecc_point only has three
+ integers (x,y,z) so if you use a different mapping you have to make it fit.
+ */
+ int (*ecc_map)(ecc_point *P, void *modulus, void *mp);
+
+ /** Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+ */
+ int (*ecc_mul2add)(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C,
+ void *modulus);
+
+/* ---- (optional) rsa optimized math (for internal CRT) ---- */
+
+ /** RSA Key Generation
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+ */
+ int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key);
+
+
+ /** RSA exponentiation
+ @param in The octet array representing the base
+ @param inlen The length of the input
+ @param out The destination (to be stored in an octet array format)
+ @param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus)
+ @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
+ @param key The RSA key to use
+ @return CRYPT_OK on success
+ */
+ int (*rsa_me)(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key);
+} ltc_math_descriptor;
+
+extern ltc_math_descriptor ltc_mp;
+
+int ltc_init_multi(void **a, ...);
+void ltc_deinit_multi(void *a, ...);
+
+#ifdef LTM_DESC
+extern const ltc_math_descriptor ltm_desc;
+#endif
+
+#ifdef TFM_DESC
+extern const ltc_math_descriptor tfm_desc;
+#endif
+
+#ifdef GMP_DESC
+extern const ltc_math_descriptor gmp_desc;
+#endif
+
+#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE)
+
+#define MP_DIGIT_BIT ltc_mp.bits_per_digit
+
+/* some handy macros */
+#define mp_init(a) ltc_mp.init(a)
+#define mp_init_multi ltc_init_multi
+#define mp_clear(a) ltc_mp.deinit(a)
+#define mp_clear_multi ltc_deinit_multi
+#define mp_init_copy(a, b) ltc_mp.init_copy(a, b)
+
+#define mp_neg(a, b) ltc_mp.neg(a, b)
+#define mp_copy(a, b) ltc_mp.copy(a, b)
+
+#define mp_set(a, b) ltc_mp.set_int(a, b)
+#define mp_set_int(a, b) ltc_mp.set_int(a, b)
+#define mp_get_int(a) ltc_mp.get_int(a)
+#define mp_get_digit(a, n) ltc_mp.get_digit(a, n)
+#define mp_get_digit_count(a) ltc_mp.get_digit_count(a)
+#define mp_cmp(a, b) ltc_mp.compare(a, b)
+#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b)
+#define mp_count_bits(a) ltc_mp.count_bits(a)
+#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a)
+#define mp_2expt(a, b) ltc_mp.twoexpt(a, b)
+
+#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c)
+#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c)
+#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
+#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
+#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
+
+#define mp_add(a, b, c) ltc_mp.add(a, b, c)
+#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c)
+#define mp_sub(a, b, c) ltc_mp.sub(a, b, c)
+#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c)
+#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
+#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
+#define mp_sqr(a, b) ltc_mp.sqr(a, b)
+#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
+#define mp_div_2(a, b) ltc_mp.div_2(a, b)
+#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
+#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c)
+#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c)
+#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c)
+
+#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d)
+#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c)
+#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c)
+
+#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b)
+#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b)
+#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c)
+#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a)
+
+#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
+#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c)
+
+#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)
+#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)
+#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0);
+
+#define mp_tohex(a, b) mp_toradix(a, b, 16)
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_math.h,v $ */
+/* $Revision: 1.44 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h
new file mode 100644
index 00000000000..f5384cacc51
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h
@@ -0,0 +1,23 @@
+/* ---- LTC_BASE64 Routines ---- */
+#ifdef LTC_BASE64
+int base64_encode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen);
+
+int base64_decode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+/* ---- MEM routines ---- */
+void zeromem(void *dst, size_t len);
+void burn_stack(unsigned long len);
+
+const char *error_to_string(int err);
+
+extern const char *crypt_build_settings;
+
+/* ---- HMM ---- */
+int crypt_fsa(void *mp, ...);
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h
new file mode 100644
index 00000000000..b5f277a8848
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h
@@ -0,0 +1,558 @@
+/* ---- NUMBER THEORY ---- */
+
+enum {
+ PK_PUBLIC=0,
+ PK_PRIVATE=1
+};
+
+int rand_prime(void *N, long len, prng_state *prng, int wprng);
+
+/* ---- RSA ---- */
+#ifdef LTC_MRSA
+
+/* Min and Max RSA key sizes (in bits) */
+#define MIN_RSA_SIZE 1024
+#define MAX_RSA_SIZE 4096
+
+/** RSA LTC_PKCS style key */
+typedef struct Rsa_key {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+ /** The public exponent */
+ void *e;
+ /** The private exponent */
+ void *d;
+ /** The modulus */
+ void *N;
+ /** The p factor of N */
+ void *p;
+ /** The q factor of N */
+ void *q;
+ /** The 1/q mod p CRT param */
+ void *qP;
+ /** The d mod (p - 1) CRT param */
+ void *dP;
+ /** The d mod (q - 1) CRT param */
+ void *dQ;
+} rsa_key;
+
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
+
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key);
+
+void rsa_free(rsa_key *key);
+
+/* These use LTC_PKCS #1 v2.0 padding */
+#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \
+ rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key)
+
+#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \
+ rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key)
+
+#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \
+ rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key)
+
+#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \
+ rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key)
+
+/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key);
+
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ int hash_idx, int padding,
+ int *stat, rsa_key *key);
+
+int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int padding,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ rsa_key *key);
+
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ int hash_idx, unsigned long saltlen,
+ int *stat, rsa_key *key);
+
+/* LTC_PKCS #1 import/export */
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
+
+/* Ladik: Added for verifying Blizzard strong signature verification */
+int rsa_verify_simple(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat,
+ rsa_key *key);
+
+#endif
+
+/* ---- Katja ---- */
+#ifdef MKAT
+
+/* Min and Max KAT key sizes (in bits) */
+#define MIN_KAT_SIZE 1024
+#define MAX_KAT_SIZE 4096
+
+/** Katja LTC_PKCS style key */
+typedef struct KAT_key {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+ /** The private exponent */
+ void *d;
+ /** The modulus */
+ void *N;
+ /** The p factor of N */
+ void *p;
+ /** The q factor of N */
+ void *q;
+ /** The 1/q mod p CRT param */
+ void *qP;
+ /** The d mod (p - 1) CRT param */
+ void *dP;
+ /** The d mod (q - 1) CRT param */
+ void *dQ;
+ /** The pq param */
+ void *pq;
+} katja_key;
+
+int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key);
+
+int katja_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ katja_key *key);
+
+void katja_free(katja_key *key);
+
+/* These use LTC_PKCS #1 v2.0 padding */
+int katja_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx, int hash_idx, katja_key *key);
+
+int katja_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ int hash_idx, int *stat,
+ katja_key *key);
+
+/* LTC_PKCS #1 import/export */
+int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key);
+int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);
+
+#endif
+
+/* ---- ECC Routines ---- */
+#ifdef LTC_MECC
+
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 256
+
+/* max private key size */
+#define ECC_MAXSIZE 66
+
+/** Structure defines a NIST GF(p) curve */
+typedef struct {
+ /** The size of the curve in octets */
+ int size;
+
+ /** name of curve */
+ char *name;
+
+ /** The prime that defines the field the curve is in (encoded in hex) */
+ char *prime;
+
+ /** The fields B param (hex) */
+ char *B;
+
+ /** The order of the curve (hex) */
+ char *order;
+
+ /** The x co-ordinate of the base point on the curve (hex) */
+ char *Gx;
+
+ /** The y co-ordinate of the base point on the curve (hex) */
+ char *Gy;
+} ltc_ecc_set_type;
+
+/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
+typedef struct {
+ /** The x co-ordinate */
+ void *x;
+
+ /** The y co-ordinate */
+ void *y;
+
+ /** The z co-ordinate */
+ void *z;
+} ecc_point;
+
+/** An ECC key */
+typedef struct {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */
+ int idx;
+
+ /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */
+ const ltc_ecc_set_type *dp;
+
+ /** The public key */
+ ecc_point pubkey;
+
+ /** The private key */
+ void *k;
+} ecc_key;
+
+/** the ECC params provided */
+extern const ltc_ecc_set_type ltc_ecc_sets[];
+
+int ecc_test(void);
+void ecc_sizes(int *low, int *high);
+int ecc_get_size(ecc_key *key);
+
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
+int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
+void ecc_free(ecc_key *key);
+
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
+
+int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
+int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
+
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ ecc_key *key);
+
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ ecc_key *key);
+
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key);
+
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key);
+
+/* low level functions */
+ecc_point *ltc_ecc_new_point(void);
+void ltc_ecc_del_point(ecc_point *p);
+int ltc_ecc_is_valid_idx(int n);
+
+/* point ops (mp == montgomery digit) */
+#if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC)
+/* R = 2P */
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);
+
+/* R = P + Q */
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
+#endif
+
+#if defined(LTC_MECC_FP)
+/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
+int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
+
+/* functions for saving/loading/freeing/adding to fixed point cache */
+int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
+int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen);
+void ltc_ecc_fp_free(void);
+int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock);
+
+/* lock/unlock all points currently in fixed point cache */
+void ltc_ecc_fp_tablelock(int lock);
+#endif
+
+/* R = kG */
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
+
+#ifdef LTC_ECC_SHAMIR
+/* kA*A + kB*B = C */
+int ltc_ecc_mul2add(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C,
+ void *modulus);
+
+#ifdef LTC_MECC_FP
+/* Shamir's trick with optimized point multiplication using fixed point cache */
+int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C, void *modulus);
+#endif
+
+#endif
+
+
+/* map P to affine from projective */
+int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
+
+#endif
+
+#ifdef LTC_MDSA
+
+/* Max diff between group and modulus size in bytes */
+#define LTC_MDSA_DELTA 512
+
+/* Max DSA group size in bytes (default allows 4k-bit groups) */
+#define LTC_MDSA_MAX_GROUP 512
+
+/** DSA key structure */
+typedef struct {
+ /** The key type, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ /** The order of the sub-group used in octets */
+ int qord;
+
+ /** The generator */
+ void *g;
+
+ /** The prime used to generate the sub-group */
+ void *q;
+
+ /** The large prime that generats the field the contains the sub-group */
+ void *p;
+
+ /** The private key */
+ void *x;
+
+ /** The public key */
+ void *y;
+} dsa_key;
+
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
+void dsa_free(dsa_key *key);
+
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ void *r, void *s,
+ prng_state *prng, int wprng, dsa_key *key);
+
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, dsa_key *key);
+
+int dsa_verify_hash_raw( void *r, void *s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key);
+
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key);
+
+int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ dsa_key *key);
+
+int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dsa_key *key);
+
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
+int dsa_verify_key(dsa_key *key, int *stat);
+
+int dsa_shared_secret(void *private_key, void *base,
+ dsa_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+#ifdef LTC_DER
+/* DER handling */
+
+enum {
+ LTC_ASN1_EOL,
+ LTC_ASN1_BOOLEAN,
+ LTC_ASN1_INTEGER,
+ LTC_ASN1_SHORT_INTEGER,
+ LTC_ASN1_BIT_STRING,
+ LTC_ASN1_OCTET_STRING,
+ LTC_ASN1_NULL,
+ LTC_ASN1_OBJECT_IDENTIFIER,
+ LTC_ASN1_IA5_STRING,
+ LTC_ASN1_PRINTABLE_STRING,
+ LTC_ASN1_UTF8_STRING,
+ LTC_ASN1_UTCTIME,
+ LTC_ASN1_CHOICE,
+ LTC_ASN1_SEQUENCE,
+ LTC_ASN1_SET,
+ LTC_ASN1_SETOF
+};
+
+/** A LTC ASN.1 list type */
+typedef struct ltc_asn1_list_ {
+ /** The LTC ASN.1 enumerated type identifier */
+ int type;
+ /** The data to encode or place for decoding */
+ void *data;
+ /** The size of the input or resulting output */
+ unsigned long size;
+ /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
+ int used;
+ /** prev/next entry in the list */
+ struct ltc_asn1_list_ *prev, *next, *child, *parent;
+} ltc_asn1_list;
+
+#define LTC_SET_ASN1(list, index, Type, Data, Size) \
+ do { \
+ int LTC_MACRO_temp = (index); \
+ ltc_asn1_list *LTC_MACRO_list = (list); \
+ LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \
+ LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
+ LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
+ LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
+ } while (0);
+
+/* SEQUENCE */
+int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of);
+
+#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
+
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, int ordered);
+
+#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
+
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen);
+
+/* SET */
+#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
+#define der_length_set der_length_sequence
+int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+/* VA list handy helpers with triplets of <type, size, data> */
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
+
+/* FLEXI DECODER handle unknown list decoder */
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
+void der_free_sequence_flexi(ltc_asn1_list *list);
+void der_sequence_free(ltc_asn1_list *in);
+
+/* BOOLEAN */
+int der_length_boolean(unsigned long *outlen);
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out);
+/* INTEGER */
+int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen);
+int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num);
+int der_length_integer(void *num, unsigned long *len);
+
+/* INTEGER -- handy for 0..2^32-1 values */
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);
+int der_length_short_integer(unsigned long num, unsigned long *outlen);
+
+/* BIT STRING */
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
+
+/* OCTET STRING */
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
+
+/* OBJECT IDENTIFIER */
+int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen);
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen);
+unsigned long der_object_identifier_bits(unsigned long x);
+
+/* IA5 STRING */
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_ia5_char_encode(int c);
+int der_ia5_value_decode(int v);
+
+/* Printable STRING */
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_printable_char_encode(int c);
+int der_printable_value_decode(int v);
+
+/* UTF-8 */
+#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR)
+#include <wchar.h>
+#else
+typedef ulong32 wchar_t;
+#endif
+
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen);
+unsigned long der_utf8_charsize(const wchar_t c);
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);
+
+
+/* CHOICE */
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen);
+
+/* UTCTime */
+typedef struct {
+ unsigned YY, /* year */
+ MM, /* month */
+ DD, /* day */
+ hh, /* hour */
+ mm, /* minute */
+ ss, /* second */
+ off_dir, /* timezone offset direction 0 == +, 1 == - */
+ off_hh, /* timezone offset hours */
+ off_mm; /* timezone offset minutes */
+} ltc_utctime;
+
+int der_encode_utctime(ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out);
+
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */
+/* $Revision: 1.81 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h
new file mode 100644
index 00000000000..84fb82a6229
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h
@@ -0,0 +1,89 @@
+/* LTC_PKCS Header Info */
+
+/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */
+#ifdef LTC_PKCS_1
+
+enum ltc_pkcs_1_v1_5_blocks
+{
+ LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */
+ LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */
+};
+
+enum ltc_pkcs_1_paddings
+{
+ LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
+ LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */
+ LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */
+};
+
+int pkcs_1_mgf1( int hash_idx,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen);
+
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
+
+/* *** v1.5 padding */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ prng_state *prng,
+ int prng_idx,
+ unsigned char *out,
+ unsigned long *outlen);
+
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid);
+
+/* *** v2.1 padding */
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, int hash_idx,
+ unsigned char *out, unsigned long *outlen,
+ int *res);
+
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, prng_state *prng,
+ int prng_idx, int hash_idx,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, int hash_idx,
+ unsigned long modulus_bitlen, int *res);
+
+#endif /* LTC_PKCS_1 */
+
+/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */
+#ifdef LTC_PKCS_5
+
+/* Algorithm #1 (old) */
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+/* Algorithm #2 (new) */
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
+ const unsigned char *salt, unsigned long salt_len,
+ int iteration_count, int hash_idx,
+ unsigned char *out, unsigned long *outlen);
+
+#endif /* LTC_PKCS_5 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pkcs.h,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h
new file mode 100644
index 00000000000..f3e3e550e88
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h
@@ -0,0 +1,199 @@
+/* ---- PRNG Stuff ---- */
+#ifdef LTC_YARROW
+struct yarrow_prng {
+ int cipher, hash;
+ unsigned char pool[MAXBLOCKSIZE];
+ symmetric_CTR ctr;
+ LTC_MUTEX_TYPE(prng_lock)
+};
+#endif
+
+#ifdef LTC_RC4
+struct rc4_prng {
+ int x, y;
+ unsigned char buf[256];
+};
+#endif
+
+#ifdef LTC_FORTUNA
+struct fortuna_prng {
+ hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */
+
+ symmetric_key skey;
+
+ unsigned char K[32], /* the current key */
+ IV[16]; /* IV for CTR mode */
+
+ unsigned long pool_idx, /* current pool we will add to */
+ pool0_len, /* length of 0'th pool */
+ wd;
+
+ ulong64 reset_cnt; /* number of times we have reset */
+ LTC_MUTEX_TYPE(prng_lock)
+};
+#endif
+
+#ifdef LTC_SOBER128
+struct sober128_prng {
+ ulong32 R[17], /* Working storage for the shift register */
+ initR[17], /* saved register contents */
+ konst, /* key dependent constant */
+ sbuf; /* partial word encryption buffer */
+
+ int nbuf, /* number of part-word stream bits buffered */
+ flag, /* first add_entropy call or not? */
+ set; /* did we call add_entropy to set key? */
+
+};
+#endif
+
+typedef union Prng_state {
+ char dummy[1];
+#ifdef LTC_YARROW
+ struct yarrow_prng yarrow;
+#endif
+#ifdef LTC_RC4
+ struct rc4_prng rc4;
+#endif
+#ifdef LTC_FORTUNA
+ struct fortuna_prng fortuna;
+#endif
+#ifdef LTC_SOBER128
+ struct sober128_prng sober128;
+#endif
+} prng_state;
+
+/** PRNG descriptor */
+extern struct ltc_prng_descriptor {
+ /** Name of the PRNG */
+ char *name;
+ /** size in bytes of exported state */
+ int export_size;
+ /** Start a PRNG state
+ @param prng [out] The state to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*start)(prng_state *prng);
+ /** Add entropy to the PRNG
+ @param in The entropy
+ @param inlen Length of the entropy (octets)\
+ @param prng The PRNG state
+ @return CRYPT_OK if successful
+ */
+ int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Ready a PRNG state to read from
+ @param prng The PRNG state to ready
+ @return CRYPT_OK if successful
+ */
+ int (*ready)(prng_state *prng);
+ /** Read from the PRNG
+ @param out [out] Where to store the data
+ @param outlen Length of data desired (octets)
+ @param prng The PRNG state to read from
+ @return Number of octets read
+ */
+ unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
+ /** Terminate a PRNG state
+ @param prng The PRNG state to terminate
+ @return CRYPT_OK if successful
+ */
+ int (*done)(prng_state *prng);
+ /** Export a PRNG state
+ @param out [out] The destination for the state
+ @param outlen [in/out] The max size and resulting size of the PRNG state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+ */
+ int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ /** Import a PRNG state
+ @param in The data to import
+ @param inlen The length of the data to import (octets)
+ @param prng The PRNG to initialize/import
+ @return CRYPT_OK if successful
+ */
+ int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Self-test the PRNG
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+} prng_descriptor[];
+
+#ifdef LTC_YARROW
+int yarrow_start(prng_state *prng);
+int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int yarrow_ready(prng_state *prng);
+unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int yarrow_done(prng_state *prng);
+int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int yarrow_test(void);
+extern const struct ltc_prng_descriptor yarrow_desc;
+#endif
+
+#ifdef LTC_FORTUNA
+int fortuna_start(prng_state *prng);
+int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_ready(prng_state *prng);
+unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int fortuna_done(prng_state *prng);
+int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_test(void);
+extern const struct ltc_prng_descriptor fortuna_desc;
+#endif
+
+#ifdef LTC_RC4
+int rc4_start(prng_state *prng);
+int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int rc4_ready(prng_state *prng);
+unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int rc4_done(prng_state *prng);
+int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int rc4_test(void);
+extern const struct ltc_prng_descriptor rc4_desc;
+#endif
+
+#ifdef LTC_SPRNG
+int sprng_start(prng_state *prng);
+int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sprng_ready(prng_state *prng);
+unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int sprng_done(prng_state *prng);
+int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sprng_test(void);
+extern const struct ltc_prng_descriptor sprng_desc;
+#endif
+
+#ifdef LTC_SOBER128
+int sober128_start(prng_state *prng);
+int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sober128_ready(prng_state *prng);
+unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int sober128_done(prng_state *prng);
+int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int sober128_test(void);
+extern const struct ltc_prng_descriptor sober128_desc;
+#endif
+
+int find_prng(const char *name);
+int register_prng(const struct ltc_prng_descriptor *prng);
+int unregister_prng(const struct ltc_prng_descriptor *prng);
+int prng_is_valid(int idx);
+LTC_MUTEX_PROTO(ltc_prng_mutex)
+
+/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
+ * might not work on all platforms as planned
+ */
+unsigned long rng_get_bytes(unsigned char *out,
+ unsigned long outlen,
+ void (*callback)(void));
+
+int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/math/ltm_desc.c b/dep/StormLib/src/libtomcrypt/src/math/ltm_desc.c
new file mode 100644
index 00000000000..25dc0b32279
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/math/ltm_desc.c
@@ -0,0 +1,483 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+#define DESC_DEF_ONLY
+#include "../headers/tomcrypt.h"
+
+#ifdef LTM_DESC
+
+#include "../../../libtommath/tommath.h"
+
+static const struct {
+ int mpi_code, ltc_code;
+} mpi_to_ltc_codes[] = {
+ { MP_OKAY , CRYPT_OK},
+ { MP_MEM , CRYPT_MEM},
+ { MP_VAL , CRYPT_INVALID_ARG},
+};
+
+/**
+ Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
+ @param err The error to convert
+ @return The equivalent LTC error code or CRYPT_ERROR if none found
+*/
+static int mpi_to_ltc_error(int err)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
+ if (err == mpi_to_ltc_codes[x].mpi_code) {
+ return mpi_to_ltc_codes[x].ltc_code;
+ }
+ }
+ return CRYPT_ERROR;
+}
+
+static int init(void **a)
+{
+ int err;
+
+ LTC_ARGCHK(a != NULL);
+
+ *a = XCALLOC(1, sizeof(mp_int));
+ if (*a == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {
+ XFREE(*a);
+ }
+ return err;
+}
+
+static void deinit(void *a)
+{
+ LTC_ARGCHKVD(a != NULL);
+ mp_clear(a);
+ XFREE(a);
+}
+
+static int neg(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_neg(a, b));
+}
+
+static int copy(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_copy(a, b));
+}
+
+static int init_copy(void **a, void *b)
+{
+ if (init(a) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+ return copy(b, *a);
+}
+
+/* ---- trivial ---- */
+static int set_int(void *a, unsigned long b)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpi_to_ltc_error(mp_set_int(a, b));
+}
+
+static unsigned long get_int(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_get_int(a);
+}
+
+static unsigned long get_digit(void *a, int n)
+{
+ mp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return (n >= A->used || n < 0) ? 0 : A->dp[n];
+}
+
+static int get_digit_count(void *a)
+{
+ mp_int *A;
+ LTC_ARGCHK(a != NULL);
+ A = a;
+ return A->used;
+}
+
+static int compare(void *a, void *b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ ret = mp_cmp(a, b);
+ switch (ret) {
+ case MP_LT: return LTC_MP_LT;
+ case MP_EQ: return LTC_MP_EQ;
+ case MP_GT: return LTC_MP_GT;
+ }
+ return 0;
+}
+
+static int compare_d(void *a, unsigned long b)
+{
+ int ret;
+ LTC_ARGCHK(a != NULL);
+ ret = mp_cmp_d(a, b);
+ switch (ret) {
+ case MP_LT: return LTC_MP_LT;
+ case MP_EQ: return LTC_MP_EQ;
+ case MP_GT: return LTC_MP_GT;
+ }
+ return 0;
+}
+
+static int count_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_count_bits(a);
+}
+
+static int count_lsb_bits(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_cnt_lsb(a);
+}
+
+
+static int twoexpt(void *a, int n)
+{
+ LTC_ARGCHK(a != NULL);
+ return mpi_to_ltc_error(mp_2expt(a, n));
+}
+
+/* ---- conversions ---- */
+
+/* read ascii string */
+static int read_radix(void *a, const char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_read_radix(a, b, radix));
+}
+
+/* write one */
+static int write_radix(void *a, char *b, int radix)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_toradix(a, b, radix));
+}
+
+/* get size as unsigned char string */
+static unsigned long unsigned_size(void *a)
+{
+ LTC_ARGCHK(a != NULL);
+ return mp_unsigned_bin_size(a);
+}
+
+/* store */
+static int unsigned_write(void *a, unsigned char *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
+}
+
+/* read */
+static int unsigned_read(void *a, unsigned char *b, unsigned long len)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));
+}
+
+/* add */
+static int add(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_add(a, b, c));
+}
+
+static int addi(void *a, unsigned long b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_add_d(a, b, c));
+}
+
+/* sub */
+static int sub(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sub(a, b, c));
+}
+
+static int subi(void *a, unsigned long b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sub_d(a, b, c));
+}
+
+/* mul */
+static int mul(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_mul(a, b, c));
+}
+
+static int muli(void *a, unsigned long b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_mul_d(a, b, c));
+}
+
+/* sqr */
+static int sqr(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_sqr(a, b));
+}
+
+/* div */
+static int divide(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_div(a, b, c, d));
+}
+
+static int div_2(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_div_2(a, b));
+}
+
+/* modi */
+static int modi(void *a, unsigned long b, unsigned long *c)
+{
+ mp_digit tmp;
+ int err;
+
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(c != NULL);
+
+ if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {
+ return err;
+ }
+ *c = tmp;
+ return CRYPT_OK;
+}
+
+/* gcd */
+static int gcd(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_gcd(a, b, c));
+}
+
+/* lcm */
+static int lcm(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_lcm(a, b, c));
+}
+
+static int mulmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
+}
+
+static int sqrmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_sqrmod(a,b,c));
+}
+
+/* invmod */
+static int invmod(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_invmod(a, b, c));
+}
+
+/* setup */
+static int montgomery_setup(void *a, void **b)
+{
+ int err;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ *b = XCALLOC(1, sizeof(mp_digit));
+ if (*b == NULL) {
+ return CRYPT_MEM;
+ }
+ if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {
+ XFREE(*b);
+ }
+ return err;
+}
+
+/* get normalization value */
+static int montgomery_normalization(void *a, void *b)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));
+}
+
+/* reduce */
+static int montgomery_reduce(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));
+}
+
+/* clean up */
+static void montgomery_deinit(void *a)
+{
+ XFREE(a);
+}
+
+static int exptmod(void *a, void *b, void *c, void *d)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(d != NULL);
+ return mpi_to_ltc_error(mp_exptmod(a,b,c,d));
+}
+
+static int isprime(void *a, int *b)
+{
+ int err;
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ err = mpi_to_ltc_error(mp_prime_is_prime(a, 8, b));
+ *b = (*b == MP_YES) ? LTC_MP_YES : LTC_MP_NO;
+ return err;
+}
+
+const ltc_math_descriptor ltm_desc = {
+
+ "LibTomMath",
+ (int)DIGIT_BIT,
+
+ &init,
+ &init_copy,
+ &deinit,
+
+ &neg,
+ &copy,
+
+ &set_int,
+ &get_int,
+ &get_digit,
+ &get_digit_count,
+ &compare,
+ &compare_d,
+ &count_bits,
+ &count_lsb_bits,
+ &twoexpt,
+
+ &read_radix,
+ &write_radix,
+ &unsigned_size,
+ &unsigned_write,
+ &unsigned_read,
+
+ &add,
+ &addi,
+ &sub,
+ &subi,
+ &mul,
+ &muli,
+ &sqr,
+ &divide,
+ &div_2,
+ &modi,
+ &gcd,
+ &lcm,
+
+ &mulmod,
+ &sqrmod,
+ &invmod,
+
+ &montgomery_setup,
+ &montgomery_normalization,
+ &montgomery_reduce,
+ &montgomery_deinit,
+
+ &exptmod,
+ &isprime,
+
+#ifdef LTC_MECC
+#ifdef LTC_MECC_FP
+ &ltc_ecc_fp_mulmod,
+#else
+ &ltc_ecc_mulmod,
+#endif
+ &ltc_ecc_projective_add_point,
+ &ltc_ecc_projective_dbl_point,
+ &ltc_ecc_map,
+#ifdef LTC_ECC_SHAMIR
+#ifdef LTC_MECC_FP
+ &ltc_ecc_fp_mul2add,
+#else
+ &ltc_ecc_mul2add,
+#endif /* LTC_MECC_FP */
+#else
+ NULL,
+#endif /* LTC_ECC_SHAMIR */
+#else
+ NULL, NULL, NULL, NULL, NULL,
+#endif /* LTC_MECC */
+
+#ifdef LTC_MRSA
+ &rsa_make_key,
+ &rsa_exptmod,
+#else
+ NULL, NULL
+#endif
+};
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/math/ltm_desc.c,v $ */
+/* $Revision: 1.31 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/math/multi.c b/dep/StormLib/src/libtomcrypt/src/math/multi.c
new file mode 100644
index 00000000000..7d40040a1de
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/math/multi.c
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+#ifdef MPI
+#include <stdarg.h>
+
+int ltc_init_multi(void **a, ...)
+{
+ void **cur = a;
+ int np = 0;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ if (mp_init(cur) != CRYPT_OK) {
+ /* failed */
+ va_list clean_list;
+
+ va_start(clean_list, a);
+ cur = a;
+ while (np--) {
+ mp_clear(*cur);
+ cur = va_arg(clean_list, void**);
+ }
+ va_end(clean_list);
+ return CRYPT_MEM;
+ }
+ ++np;
+ cur = va_arg(args, void**);
+ }
+ va_end(args);
+ return CRYPT_OK;
+}
+
+void ltc_deinit_multi(void *a, ...)
+{
+ void *cur = a;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mp_clear(cur);
+ cur = va_arg(args, void *);
+ }
+ va_end(args);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/math/multi.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:23 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/math/rand_prime.c b/dep/StormLib/src/libtomcrypt/src/math/rand_prime.c
new file mode 100644
index 00000000000..913fa95a4a3
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/math/rand_prime.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file rand_prime.c
+ Generate a random prime, Tom St Denis
+*/
+
+#define USE_BBS 1
+
+int rand_prime(void *N, long len, prng_state *prng, int wprng)
+{
+ int err, res, type;
+ unsigned char *buf;
+
+ LTC_ARGCHK(N != NULL);
+
+ /* get type */
+ if (len < 0) {
+ type = USE_BBS;
+ len = -len;
+ } else {
+ type = 0;
+ }
+
+ /* allow sizes between 2 and 512 bytes for a prime size */
+ if (len < 2 || len > 512) {
+ return CRYPT_INVALID_PRIME_SIZE;
+ }
+
+ /* valid PRNG? Better be! */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* allocate buffer to work with */
+ buf = XCALLOC(1, len);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ do {
+ /* generate value */
+ if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) {
+ XFREE(buf);
+ return CRYPT_ERROR_READPRNG;
+ }
+
+ /* munge bits */
+ buf[0] |= 0x80 | 0x40;
+ buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+ /* load value */
+ if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* test */
+ if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+ } while (res == LTC_MP_NO);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, len);
+#endif
+
+ XFREE(buf);
+ return CRYPT_OK;
+}
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:23 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/base64_decode.c b/dep/StormLib/src/libtomcrypt/src/misc/base64_decode.c
new file mode 100644
index 00000000000..3d13393a1dc
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/base64_decode.c
@@ -0,0 +1,104 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file base64_decode.c
+ Compliant base64 code donated by Wayne Scott (wscott@bitmover.com)
+*/
+
+
+#ifdef LTC_BASE64
+
+static const unsigned char map[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+
+/**
+ base64 decode a block of memory
+ @param in The base64 data to decode
+ @param inlen The length of the base64 data
+ @param out [out] The destination of the binary decoded data
+ @param outlen [in/out] The max size and resulting size of the decoded data
+ @return CRYPT_OK if successful
+*/
+int base64_decode(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long t, x, y, z;
+ unsigned char c;
+ int g;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ g = 3;
+ for (x = y = z = t = 0; x < inlen; x++) {
+ c = map[in[x]&0xFF];
+ if (c == 255) continue;
+ /* the final = symbols are read and used to trim the remaining bytes */
+ if (c == 254) {
+ c = 0;
+ /* prevent g < 0 which would potentially allow an overflow later */
+ if (--g < 0) {
+ return CRYPT_INVALID_PACKET;
+ }
+ } else if (g != 3) {
+ /* we only allow = to be at the end */
+ return CRYPT_INVALID_PACKET;
+ }
+
+ t = (t<<6)|c;
+
+ if (++y == 4) {
+ if (z + g > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[z++] = (unsigned char)((t>>16)&255);
+ if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
+ if (g > 2) out[z++] = (unsigned char)(t&255);
+ y = t = 0;
+ }
+ }
+ if (y != 0) {
+ return CRYPT_INVALID_PACKET;
+ }
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/base64/base64_decode.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c
new file mode 100644
index 00000000000..537516d80d9
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+#include <signal.h>
+
+/**
+ @file crypt_argchk.c
+ Perform argument checking, Tom St Denis
+*/
+
+#if (ARGTYPE == 0)
+void crypt_argchk(char *v, char *s, int d)
+{
+ fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
+ v, d, s);
+ (void)raise(SIGABRT);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c
new file mode 100644
index 00000000000..fef2d8cca32
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_find_hash.c
+ Find a hash, Tom St Denis
+*/
+
+/**
+ Find a registered hash by name
+ @param name The name of the hash to look for
+ @return >= 0 if found, -1 if not present
+*/
+int find_hash(const char *name)
+{
+ int x;
+ LTC_ARGCHK(name != NULL);
+ LTC_MUTEX_LOCK(&ltc_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) {
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return -1;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c
new file mode 100644
index 00000000000..fafbb0e226f
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c
@@ -0,0 +1,41 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_find_prng.c
+ Find a PRNG, Tom St Denis
+*/
+
+/**
+ Find a registered PRNG by name
+ @param name The name of the PRNG to look for
+ @return >= 0 if found, -1 if not present
+*/
+int find_prng(const char *name)
+{
+ int x;
+ LTC_ARGCHK(name != NULL);
+ LTC_MUTEX_LOCK(&ltc_prng_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) {
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return x;
+ }
+ }
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return -1;
+}
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_prng.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c
new file mode 100644
index 00000000000..5925fd27302
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c
@@ -0,0 +1,27 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_hash_descriptor.c
+ Stores the hash descriptor table, Tom St Denis
+*/
+
+struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {
+{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }
+};
+
+LTC_MUTEX_GLOBAL(ltc_hash_mutex)
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c
new file mode 100644
index 00000000000..8ed5105b56c
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_hash_is_valid.c
+ Determine if hash is valid, Tom St Denis
+*/
+
+/*
+ Test if a hash index is valid
+ @param idx The index of the hash to search for
+ @return CRYPT_OK if valid
+*/
+int hash_is_valid(int idx)
+{
+ LTC_MUTEX_LOCK(&ltc_hash_mutex);
+ if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return CRYPT_INVALID_HASH;
+ }
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_libc.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_libc.c
new file mode 100644
index 00000000000..bcc89f4f94d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_libc.c
@@ -0,0 +1,43 @@
+/*****************************************************************************/
+/* crypt_libc.c Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* Description: */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 05.05.10 1.00 Lad The first version of crypt_libc.c */
+/*****************************************************************************/
+
+// LibTomCrypt header
+#include <stdlib.h>
+#include "../headers/tomcrypt.h"
+
+void * LibTomMalloc(size_t n)
+{
+ return malloc(n);
+}
+
+void * LibTomCalloc(size_t n, size_t s)
+{
+ return calloc(n, s);
+}
+
+void * LibTomRealloc(void *p, size_t n)
+{
+ return realloc(p, n);
+}
+
+void LibTomFree(void * p)
+{
+ free(p);
+}
+
+clock_t LibTomClock(void)
+{
+ return clock();
+}
+
+void LibTomQsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
+{
+ qsort(base, nmemb, size, compar);
+}
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
new file mode 100644
index 00000000000..91ba9d162d2
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
@@ -0,0 +1,13 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+ltc_math_descriptor ltc_mp;
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c
new file mode 100644
index 00000000000..c5b39e0c26f
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c
@@ -0,0 +1,26 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_prng_descriptor.c
+ Stores the PRNG descriptors, Tom St Denis
+*/
+struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {
+{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+LTC_MUTEX_GLOBAL(ltc_prng_mutex)
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c
new file mode 100644
index 00000000000..d38fd3a3c9d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_prng_is_valid.c
+ Determine if PRNG is valid, Tom St Denis
+*/
+
+/*
+ Test if a PRNG index is valid
+ @param idx The index of the PRNG to search for
+ @return CRYPT_OK if valid
+*/
+int prng_is_valid(int idx)
+{
+ LTC_MUTEX_LOCK(&ltc_prng_mutex);
+ if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return CRYPT_INVALID_PRNG;
+ }
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c
new file mode 100644
index 00000000000..17300915487
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_register_hash.c
+ Register a HASH, Tom St Denis
+*/
+
+/**
+ Register a hash with the descriptor table
+ @param hash The hash you wish to register
+ @return value >= 0 if successfully added (or already present), -1 if unsuccessful
+*/
+int register_hash(const struct ltc_hash_descriptor *hash)
+{
+ int x;
+
+ LTC_ARGCHK(hash != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(&ltc_hash_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return x;
+ }
+ }
+
+ /* find a blank spot */
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (hash_descriptor[x].name == NULL) {
+ XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return x;
+ }
+ }
+
+ /* no spot */
+ LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
+ return -1;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_hash.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c b/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c
new file mode 100644
index 00000000000..29fc9bdf63d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file crypt_register_prng.c
+ Register a PRNG, Tom St Denis
+*/
+
+/**
+ Register a PRNG with the descriptor table
+ @param prng The PRNG you wish to register
+ @return value >= 0 if successfully added (or already present), -1 if unsuccessful
+*/
+int register_prng(const struct ltc_prng_descriptor *prng)
+{
+ int x;
+
+ LTC_ARGCHK(prng != NULL);
+
+ /* is it already registered? */
+ LTC_MUTEX_LOCK(&ltc_prng_mutex);
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return x;
+ }
+ }
+
+ /* find a blank spot */
+ for (x = 0; x < TAB_SIZE; x++) {
+ if (prng_descriptor[x].name == NULL) {
+ XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return x;
+ }
+ }
+
+ /* no spot */
+ LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
+ return -1;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_prng.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/misc/zeromem.c b/dep/StormLib/src/libtomcrypt/src/misc/zeromem.c
new file mode 100644
index 00000000000..faa0efa7842
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/misc/zeromem.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../headers/tomcrypt.h"
+
+/**
+ @file zeromem.c
+ Zero a block of memory, Tom St Denis
+*/
+
+/**
+ Zero a block of memory
+ @param out The destination of the area to zero
+ @param outlen The length of the area to zero (octets)
+*/
+void zeromem(void *out, size_t outlen)
+{
+ unsigned char *mem = out;
+ LTC_ARGCHKVD(out != NULL);
+ while (outlen-- > 0) {
+ *mem++ = 0;
+ }
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
new file mode 100644
index 00000000000..e53686750fd
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
@@ -0,0 +1,102 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (one per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ if (in[x] & 0x80) {
+ /* long format get number of length bytes */
+ y = in[x++] & 0x7F;
+
+ /* invalid if 0 or > 2 */
+ if (y == 0 || y > 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data len */
+ dlen = 0;
+ while (y--) {
+ dlen = (dlen << 8) | (unsigned long)in[x++];
+ }
+ } else {
+ /* short format */
+ dlen = in[x++] & 0x7F;
+ }
+
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen + x > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ *outlen = blen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
new file mode 100644
index 00000000000..617d4e8611d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_boolean.c
+ ASN.1 DER, decode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a BOOLEAN
+ @param in The destination for the DER encoded BOOLEAN
+ @param inlen The size of the DER BOOLEAN
+ @param out [out] The boolean to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *out = (in[2]==0xFF) ? 1 : 0;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c
new file mode 100644
index 00000000000..44a0891bead
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c
@@ -0,0 +1,182 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_choice.c
+ ASN.1 DER, decode a CHOICE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a CHOICE
+ @param in The DER encoded input
+ @param inlen [in/out] The size of the input and resulting size of read type
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @return CRYPT_OK on success
+*/
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen)
+{
+ unsigned long size, x, z;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (*inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* set all of the "used" flags to zero */
+ for (x = 0; x < outlen; x++) {
+ list[x].used = 0;
+ }
+
+ /* now scan until we have a winner */
+ for (x = 0; x < outlen; x++) {
+ size = list[x].size;
+ data = list[x].data;
+
+ switch (list[x].type) {
+ case LTC_ASN1_INTEGER:
+ if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_integer(data, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_short_integer(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_bit_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_octet_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
+ *inlen = 2;
+ list[x].used = 1;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *inlen;
+ if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
+ if (der_length_sequence(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
new file mode 100644
index 00000000000..f2e073b8d84
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a IA5 STRING
+ @param in The DER encoded IA5 STRING
+ @param inlen The size of the DER IA5 STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x16 */
+ if ((in[0] & 0x1F) != 0x16) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_ia5_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c
new file mode 100644
index 00000000000..cca27451963
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of DER encoded data
+ @param num The first mp_int to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
+{
+ unsigned long x, y, z;
+ int err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* min DER INTEGER is 0x02 01 00 == 0 */
+ if (inlen < (1 + 1 + 1)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok expect 0x02 when we AND with 0001 1111 [1F] */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now decode the len stuff */
+ z = in[x++];
+
+ if ((z & 0x80) == 0x00) {
+ /* short form */
+
+ /* will it overflow? */
+ if (x + z > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* long form */
+ z &= 0x7F;
+
+ /* will number of length bytes overflow? (or > 4) */
+ if (((x + z) > inlen) || (z > 4) || (z == 0)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now read it in */
+ y = 0;
+ while (z--) {
+ y = ((unsigned long)(in[x++])) | (y << 8);
+ }
+
+ /* now will reading y bytes overrun? */
+ if ((x + y) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* see if it's negative */
+ if (in[x] & 0x80) {
+ void *tmp;
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
+ mp_clear(tmp);
+ return CRYPT_MEM;
+ }
+ mp_clear(tmp);
+ }
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
new file mode 100644
index 00000000000..e7baae88e0c
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_object_identifier.c
+ ASN.1 DER, Decode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Decode OID data and store the array of integers in words
+ @param in The OID DER encoded data
+ @param inlen The length of the OID data
+ @param words [out] The destination of the OID words
+ @param outlen [in/out] The number of OID words
+ @return CRYPT_OK if successful
+*/
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen)
+{
+ unsigned long x, y, t, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* header is at least 3 bytes */
+ if (inlen < 3) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* must be room for at least two words */
+ if (*outlen < 2) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode the packet header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x06) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length */
+ if (in[x] < 128) {
+ len = in[x++];
+ } else {
+ if (in[x] < 0x81 || in[x] > 0x82) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+ len = 0;
+ while (y--) {
+ len = (len << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ if (len < 1 || (len + x) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode words */
+ y = 0;
+ t = 0;
+ while (len--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x++] & 0x80)) {
+ /* store t */
+ if (y >= *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ if (y == 0) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
+ t = 0;
+ }
+ }
+
+ *outlen = y;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c
new file mode 100644
index 00000000000..523d0baa057
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a OCTET STRING
+ @param in The DER encoded OCTET STRING
+ @param inlen The size of the DER OCTET STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x04 */
+ if ((in[0] & 0x1F) != 0x04) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ out[y] = in[x++];
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c
new file mode 100644
index 00000000000..f8325934395
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a printable STRING
+ @param in The DER encoded printable STRING
+ @param inlen The size of the DER printable STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x13 */
+ if ((in[0] & 0x1F) != 0x13) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_printable_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c
new file mode 100644
index 00000000000..9b00f61b09a
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c
@@ -0,0 +1,287 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence_ex.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param ordered Search an unordeded or ordered list
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, int ordered)
+{
+ int err, type;
+ unsigned long size, x, y, z, i, blksize;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ x = 0;
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+
+ if (in[x] < 128) {
+ blksize = in[x++];
+ } else if (in[x] & 0x80) {
+ if (in[x] < 0x81 || in[x] > 0x83) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+
+ /* would reading the len bytes overrun? */
+ if (x + y > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read len */
+ blksize = 0;
+ while (y--) {
+ blksize = (blksize << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ /* would this blksize overflow? */
+ if (x + blksize > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < outlen; i++) {
+ list[i].used = 0;
+ }
+
+ /* ok read data */
+ inlen = blksize;
+ for (i = 0; i < outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < outlen; i++) {
+ if (list[i].used == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c
new file mode 100644
index 00000000000..9c648bc89c6
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c
@@ -0,0 +1,386 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_sequence_flexi.c
+ ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static unsigned long fetch_length(const unsigned char *in, unsigned long inlen)
+{
+ unsigned long x, y, z;
+
+ y = 0;
+
+ /* skip type and read len */
+ if (inlen < 2) {
+ return 0xFFFFFFFF;
+ }
+ ++in; ++y;
+
+ /* read len */
+ x = *in++; ++y;
+
+ /* <128 means literal */
+ if (x < 128) {
+ return x+y;
+ }
+ x &= 0x7F; /* the lower 7 bits are the length of the length */
+ inlen -= 2;
+
+ /* len means len of len! */
+ if (x == 0 || x > 4 || x > inlen) {
+ return 0xFFFFFFFF;
+ }
+
+ y += x;
+ z = 0;
+ while (x--) {
+ z = (z<<8) | ((unsigned long)*in);
+ ++in;
+ }
+ return z+y;
+}
+
+/**
+ ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @param out [out] A pointer to the linked list
+ @return CRYPT_OK on success.
+*/
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
+{
+ ltc_asn1_list *l;
+ unsigned long err, type, len, totlen, x, y;
+ void *realloc_tmp;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ l = NULL;
+ totlen = 0;
+
+ /* scan the input and and get lengths and what not */
+ while (*inlen) {
+ /* read the type byte */
+ type = *in;
+
+ /* fetch length */
+ len = fetch_length(in, *inlen);
+ if (len > *inlen) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* alloc new link */
+ if (l == NULL) {
+ l = XCALLOC(1, sizeof(*l));
+ if (l == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ } else {
+ l->next = XCALLOC(1, sizeof(*l));
+ if (l->next == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ l->next->prev = l;
+ l = l->next;
+ }
+
+ /* now switch on type */
+ switch (type) {
+ case 0x01: /* BOOLEAN */
+ l->type = LTC_ASN1_BOOLEAN;
+ l->size = 1;
+ l->data = XCALLOC(1, sizeof(int));
+
+ if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_boolean(&len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x02: /* INTEGER */
+ /* init field */
+ l->type = LTC_ASN1_INTEGER;
+ l->size = 1;
+ if ((err = mp_init(&l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* decode field */
+ if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* calc length of object */
+ if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x03: /* BIT */
+ /* init field */
+ l->type = LTC_ASN1_BIT_STRING;
+ l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x04: /* OCTET */
+
+ /* init field */
+ l->type = LTC_ASN1_OCTET_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x05: /* NULL */
+
+ /* valid NULL is 0x05 0x00 */
+ if (in[0] != 0x05 || in[1] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* simple to store ;-) */
+ l->type = LTC_ASN1_NULL;
+ l->data = NULL;
+ l->size = 0;
+ len = 2;
+
+ break;
+
+ case 0x06: /* OID */
+
+ /* init field */
+ l->type = LTC_ASN1_OBJECT_IDENTIFIER;
+ l->size = len;
+
+ if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* resize it to save a bunch of mem */
+ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
+ /* out of heap but this is not an error */
+ break;
+ }
+ l->data = realloc_tmp;
+ break;
+
+ case 0x0C: /* UTF8 */
+
+ /* init field */
+ l->type = LTC_ASN1_UTF8_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x13: /* PRINTABLE */
+
+ /* init field */
+ l->type = LTC_ASN1_PRINTABLE_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x16: /* IA5 */
+
+ /* init field */
+ l->type = LTC_ASN1_IA5_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x17: /* UTC TIME */
+
+ /* init field */
+ l->type = LTC_ASN1_UTCTIME;
+ l->size = 1;
+
+ if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ len = *inlen;
+ if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x30: /* SEQUENCE */
+ case 0x31: /* SET */
+
+ /* init field */
+ l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET;
+
+ /* we have to decode the SEQUENCE header and get it's length */
+
+ /* move past type */
+ ++in; --(*inlen);
+
+ /* read length byte */
+ x = *in++; --(*inlen);
+
+ /* smallest SEQUENCE/SET header */
+ y = 2;
+
+ /* now if it's > 127 the next bytes are the length of the length */
+ if (x > 128) {
+ x &= 0x7F;
+ in += x;
+ *inlen -= x;
+
+ /* update sequence header len */
+ y += x;
+ }
+
+ /* Sequence elements go as child */
+ len = len - y;
+ if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* len update */
+ totlen += y;
+
+ /* link them up y0 */
+ l->child->parent = l;
+
+ break;
+ default:
+ /* invalid byte ... this is a soft error */
+ /* remove link */
+ l = l->prev;
+ XFREE(l->next);
+ l->next = NULL;
+ goto outside;
+ }
+
+ /* advance pointers */
+ totlen += len;
+ in += len;
+ *inlen -= len;
+ }
+
+outside:
+
+ /* rewind l please */
+ while (l->prev != NULL || l->parent != NULL) {
+ if (l->parent != NULL) {
+ l = l->parent;
+ } else {
+ l = l->prev;
+ }
+ }
+
+ /* return */
+ *out = l;
+ *inlen = totlen;
+ return CRYPT_OK;
+
+error:
+ /* free list */
+ der_sequence_free(l);
+
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */
+/* $Revision: 1.26 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c
new file mode 100644
index 00000000000..ff633df3511
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c
@@ -0,0 +1,139 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence_multi.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_CHOICE:
+ ++x;
+ break;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_CHOICE:
+ list[x].type = type;
+ list[x].size = size;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_decode_sequence(in, inlen, list, x);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c
new file mode 100644
index 00000000000..907e4e1c3bb
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_short_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a short integer
+ @param in The DER encoded data
+ @param inlen Size of data
+ @param num [out] The integer to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num)
+{
+ unsigned long len, x, y;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check length */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the packet len */
+ len = in[x++];
+
+ if (x + len > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read number */
+ y = 0;
+ while (len--) {
+ y = (y<<8) | (unsigned long)in[x++];
+ }
+ *num = y;
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c
new file mode 100644
index 00000000000..7f3f0d76683
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_utctime.c
+ ASN.1 DER, decode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int char_to_int(unsigned char x)
+{
+ switch (x) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ }
+ return 100;
+}
+
+#define DECODE_V(y, max) \
+ y = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 2;
+
+/**
+ Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)
+ @param in Input buffer
+ @param inlen Length of input buffer in octets
+ @param out [out] Destination of UTC time structure
+ @return CRYPT_OK if successful
+*/
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out)
+{
+ unsigned char buf[32];
+ unsigned long x;
+ int y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check header */
+ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode the string */
+ for (x = 0; x < in[1]; x++) {
+ y = der_ia5_value_decode(in[x+2]);
+ if (y == -1) {
+ return CRYPT_INVALID_PACKET;
+ }
+ buf[x] = y;
+ }
+ *inlen = 2 + x;
+
+
+ /* possible encodings are
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+ So let's do a trivial decode upto [including] mm
+ */
+
+ x = 0;
+ DECODE_V(out->YY, 100);
+ DECODE_V(out->MM, 13);
+ DECODE_V(out->DD, 32);
+ DECODE_V(out->hh, 24);
+ DECODE_V(out->mm, 60);
+
+ /* clear timezone and seconds info */
+ out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
+
+ /* now is it Z, +, - or 0-9 */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+
+ /* decode seconds */
+ DECODE_V(out->ss, 60);
+
+ /* now is it Z, +, - */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ } else {
+ return CRYPT_INVALID_PACKET;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c
new file mode 100644
index 00000000000..898d6cd2a76
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_decode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a UTF8 STRING
+ @param in The DER encoded UTF8 STRING
+ @param inlen The size of the DER UTF8 STRING
+ @param out [out] The array of utf8s stored (one per char)
+ @param outlen [in/out] The number of utf8s stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen)
+{
+ wchar_t tmp;
+ unsigned long x, y, z, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x0C */
+ if ((in[0] & 0x1F) != 0x0C) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* proceed to decode */
+ for (y = 0; x < inlen; ) {
+ /* get first byte */
+ tmp = in[x++];
+
+ /* count number of bytes */
+ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);
+
+ if (z > 4 || (x + (z - 1) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode, grab upper bits */
+ tmp >>= z;
+
+ /* grab remaining bytes */
+ if (z > 1) { --z; }
+ while (z-- != 0) {
+ if ((in[x] & 0xC0) != 0x80) {
+ return CRYPT_INVALID_PACKET;
+ }
+ tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
+ }
+
+ if (y > *outlen) {
+ *outlen = y;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[y++] = tmp;
+ }
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c
new file mode 100644
index 00000000000..2bffa3b6341
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_bit_string.c
+ ASN.1 DER, get length of BIT STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of BIT STRING
+ @param nbits The number of bits in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
+{
+ unsigned long nbytes;
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the number of the bytes */
+ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
+
+ if (nbytes < 128) {
+ /* 03 LL PP DD DD DD ... */
+ *outlen = 2 + nbytes;
+ } else if (nbytes < 256) {
+ /* 03 81 LL PP DD DD DD ... */
+ *outlen = 3 + nbytes;
+ } else if (nbytes < 65536) {
+ /* 03 82 LL LL PP DD DD DD ... */
+ *outlen = 4 + nbytes;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c
new file mode 100644
index 00000000000..e34ce5c65d8
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_boolean.c
+ ASN.1 DER, get length of a BOOLEAN, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of a BOOLEAN
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_boolean(unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ *outlen = 3;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c
new file mode 100644
index 00000000000..473bc793257
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c
@@ -0,0 +1,194 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_ia5_string.c
+ ASN.1 DER, get length of IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} ia5_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '#', 35 },
+{ '$', 36 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '*', 42 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ '\\', 92 },
+{ ']', 93 },
+{ '^', 94 },
+{ '_', 95 },
+{ '`', 96 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '{', 123 },
+{ '|', 124 },
+{ '}', 125 },
+{ '~', 126 }
+};
+
+int der_ia5_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].code == c) {
+ return ia5_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_ia5_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].value == v) {
+ return ia5_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of IA5 STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_ia5_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c
new file mode 100644
index 00000000000..540d205f028
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The int to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_integer(void *num, unsigned long *outlen)
+{
+ unsigned long z, len;
+ int leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* positive */
+
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* size for bignum */
+ z = len = leading_zero + mp_unsigned_bin_size(num);
+ } else {
+ /* it's negative */
+ /* find power of 2 that is a multiple of eight and greater than count bits */
+ leading_zero = 0;
+ z = mp_count_bits(num);
+ z = z + (8 - (z & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
+ len = z = z >> 3;
+ }
+
+ /* now we need a length */
+ if (z < 128) {
+ /* short form */
+ ++len;
+ } else {
+ /* long form (relies on z != 0), assumes length bytes < 128 */
+ ++len;
+
+ while (z) {
+ ++len;
+ z >>= 8;
+ }
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ ++len;
+
+ /* return length */
+ *outlen = len;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c
new file mode 100644
index 00000000000..94c326f7cac
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_object_identifier.c
+ ASN.1 DER, get length of Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+unsigned long der_object_identifier_bits(unsigned long x)
+{
+ unsigned long c;
+ x &= 0xFFFFFFFF;
+ c = 0;
+ while (x) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+
+/**
+ Gets length of DER encoding of Object Identifier
+ @param nwords The number of OID words
+ @param words The actual OID words to get the size of
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen)
+{
+ unsigned long y, z, t, wordbuf;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+
+ /* must be >= 2 words */
+ if (nwords < 2) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* word1 = 0,1,2,3 and word2 0..39 */
+ if (words[0] > 3 || (words[0] < 2 && words[1] > 39)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* leading word is the first two */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ /* grab next word */
+ wordbuf = words[y+1];
+ }
+ }
+
+ /* now depending on the length our length encoding changes */
+ if (z < 128) {
+ z += 2;
+ } else if (z < 256) {
+ z += 3;
+ } else if (z < 65536UL) {
+ z += 4;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c
new file mode 100644
index 00000000000..acd4053c16a
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_octet_string.c
+ ASN.1 DER, get length of OCTET STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of OCTET STRING
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+
+ if (noctets < 128) {
+ /* 04 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 04 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 04 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 04 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c
new file mode 100644
index 00000000000..ef1ed0ede37
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c
@@ -0,0 +1,166 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_printable_string.c
+ ASN.1 DER, get length of Printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} printable_table[] = {
+{ ' ', 32 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ '=', 61 },
+{ '?', 63 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+};
+
+int der_printable_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].code == c) {
+ return printable_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_printable_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].value == v) {
+ return printable_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of Printable STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_printable_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c
new file mode 100644
index 00000000000..e75ed7e7eeb
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c
@@ -0,0 +1,169 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* store size */
+ *outlen = y;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c
new file mode 100644
index 00000000000..afa6dd0ee61
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_short_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The integer to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_short_integer(unsigned long num, unsigned long *outlen)
+{
+ unsigned long z, y, len;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* get the number of bytes */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ len = 1;
+
+ /* length byte */
+ ++len;
+
+ /* bytes in value */
+ len += z;
+
+ /* see if msb is set */
+ len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* return length */
+ *outlen = len;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c
new file mode 100644
index 00000000000..1296babbadf
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_utctime.c
+ ASN.1 DER, get length of UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Gets length of DER encoding of UTCTIME
+ @param utctime The UTC time structure to get the size of
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(utctime != NULL);
+
+ if (utctime->off_hh == 0 && utctime->off_mm == 0) {
+ /* we encode as YYMMDDhhmmssZ */
+ *outlen = 2 + 13;
+ } else {
+ /* we encode as YYMMDDhhmmss{+|-}hh'mm' */
+ *outlen = 2 + 17;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c
new file mode 100644
index 00000000000..514db8450ef
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_length_utf8_string.c
+ ASN.1 DER, get length of UTF8 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/** Return the size in bytes of a UTF-8 character
+ @param c The UTF-8 character to measure
+ @return The size in bytes
+*/
+unsigned long der_utf8_charsize(const wchar_t c)
+{
+ if (c <= 0x7F) {
+ return 1;
+ } else if (c <= 0x7FF) {
+ return 2;
+ } else if (c <= 0xFFFF) {
+ return 3;
+ } else {
+ return 4;
+ }
+}
+
+/**
+ Gets length of DER encoding of UTF8 STRING
+ @param in The characters to measure the length of
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ len = 0;
+ for (x = 0; x < noctets; x++) {
+ if (in[x] < 0 || in[x] > 0x10FFFF) {
+ return CRYPT_INVALID_ARG;
+ }
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if (len < 128) {
+ /* 0C LL DD DD DD ... */
+ *outlen = 2 + len;
+ } else if (len < 256) {
+ /* 0C 81 LL DD DD DD ... */
+ *outlen = 3 + len;
+ } else if (len < 65536UL) {
+ /* 0C 82 LL LL DD DD DD ... */
+ *outlen = 4 + len;
+ } else if (len < 16777216UL) {
+ /* 0C 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + len;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c
new file mode 100644
index 00000000000..4887215397f
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c
@@ -0,0 +1,65 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file der_sequence_free.c
+ ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Free memory allocated by der_decode_sequence_flexi()
+ @param in The list to free
+*/
+void der_sequence_free(ltc_asn1_list *in)
+{
+ ltc_asn1_list *l;
+
+ /* walk to the start of the chain */
+ while (in->prev != NULL || in->parent != NULL) {
+ if (in->parent != NULL) {
+ in = in->parent;
+ } else {
+ in = in->prev;
+ }
+ }
+
+ /* now walk the list and free stuff */
+ while (in != NULL) {
+ /* is there a child? */
+ if (in->child) {
+ /* disconnect */
+ in->child->parent = NULL;
+ der_sequence_free(in->child);
+ }
+
+ switch (in->type) {
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE: break;
+ case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break;
+ default : if (in->data != NULL) { XFREE(in->data); }
+ }
+
+ /* move to next and free current */
+ l = in->next;
+ free(in);
+ in = l;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
new file mode 100644
index 00000000000..5a1324c4986
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_map.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Map a projective jacbobian point back to affine space
+ @param P [in/out] The point to map
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* first map z back to normal */
+ if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z */
+ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z^2 and 1/z^3 */
+ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* multiply against x/y */
+ if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
new file mode 100644
index 00000000000..2c468eaafa1
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
@@ -0,0 +1,207 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_mul2add.c
+ ECC Crypto, Shamir's Trick, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+#ifdef LTC_ECC_SHAMIR
+
+/** Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mul2add(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C,
+ void *modulus)
+{
+ ecc_point *precomp[16];
+ unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
+ unsigned char *tA, *tB;
+ int err, first;
+ void *mp, *mu;
+
+ /* argchks */
+ LTC_ARGCHK(A != NULL);
+ LTC_ARGCHK(B != NULL);
+ LTC_ARGCHK(C != NULL);
+ LTC_ARGCHK(kA != NULL);
+ LTC_ARGCHK(kB != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* allocate memory */
+ tA = XCALLOC(1, ECC_BUF_SIZE);
+ if (tA == NULL) {
+ return CRYPT_MEM;
+ }
+ tB = XCALLOC(1, ECC_BUF_SIZE);
+ if (tB == NULL) {
+ XFREE(tA);
+ return CRYPT_MEM;
+ }
+
+ /* get sizes */
+ lenA = mp_unsigned_bin_size(kA);
+ lenB = mp_unsigned_bin_size(kB);
+ len = MAX(lenA, lenB);
+
+ /* sanity check */
+ if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) {
+ err = CRYPT_INVALID_ARG;
+ goto ERR_T;
+ }
+
+ /* extract and justify kA */
+ mp_to_unsigned_bin(kA, (len - lenA) + tA);
+
+ /* extract and justify kB */
+ mp_to_unsigned_bin(kB, (len - lenB) + tB);
+
+ /* allocate the table */
+ for (x = 0; x < 16; x++) {
+ precomp[x] = ltc_ecc_new_point();
+ if (precomp[x] == NULL) {
+ for (y = 0; y < x; ++y) {
+ ltc_ecc_del_point(precomp[y]);
+ }
+ err = CRYPT_MEM;
+ goto ERR_T;
+ }
+ }
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ goto ERR_P;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto ERR_MP;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto ERR_MU;
+ }
+
+ /* copy ones ... */
+ if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,0](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [0,i](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,j](A + B) table (i != 0, j != 0) */
+ for (x = 1; x < 4; x++) {
+ for (y = 1; y < 4; y++) {
+ if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+
+ nibble = 3;
+ first = 1;
+ bitbufA = tA[0];
+ bitbufB = tB[0];
+
+ /* for every byte of the multiplicands */
+ for (x = -1;; ) {
+ /* grab a nibble */
+ if (++nibble == 4) {
+ ++x; if (x == len) break;
+ bitbufA = tA[x];
+ bitbufB = tB[x];
+ nibble = 0;
+ }
+
+ /* extract two bits from both, shift/update */
+ nA = (bitbufA >> 6) & 0x03;
+ nB = (bitbufB >> 6) & 0x03;
+ bitbufA = (bitbufA << 2) & 0xFF;
+ bitbufB = (bitbufB << 2) & 0xFF;
+
+ /* if both zero, if first, continue */
+ if ((nA == 0) && (nB == 0) && (first == 1)) {
+ continue;
+ }
+
+ /* double twice, only if this isn't the first */
+ if (first == 0) {
+ /* double twice */
+ if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+
+ /* if not both zero */
+ if ((nA != 0) || (nB != 0)) {
+ if (first == 1) {
+ /* if first, copy from table */
+ first = 0;
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->x, C->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->y, C->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK) { goto ERR_MU; }
+ } else {
+ /* if not first, add from table */
+ if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+ }
+
+ /* reduce to affine */
+ err = ltc_ecc_map(C, modulus, mp);
+
+ /* clean up */
+ERR_MU:
+ mp_clear(mu);
+ERR_MP:
+ mp_montgomery_free(mp);
+ERR_P:
+ for (x = 0; x < 16; x++) {
+ ltc_ecc_del_point(precomp[x]);
+ }
+ERR_T:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tA, ECC_BUF_SIZE);
+ zeromem(tB, ECC_BUF_SIZE);
+#endif
+ XFREE(tA);
+ XFREE(tB);
+
+ return err;
+}
+
+#endif
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
new file mode 100644
index 00000000000..f9d0cad832d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
@@ -0,0 +1,222 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_mulmod.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+#ifndef LTC_ECC_TIMING_RESISTANT
+
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
+
+/**
+ Perform a point multiplication
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
+{
+ ecc_point *tG, *M[8];
+ int i, j, err;
+ void *mu, *mp;
+ unsigned long buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ LTC_ARGCHK(k != NULL);
+ LTC_ARGCHK(G != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ mp_montgomery_free(mp);
+ return err;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ mp_montgomery_free(mp);
+ mp_clear(mu);
+ return err;
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 8; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ mp_montgomery_free(mp);
+ mp_clear(mu);
+ return CRYPT_MEM;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
+ if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; }
+ }
+ mp_clear(mu);
+ mu = NULL;
+
+ /* calc the M tab, which holds kG for k==8..15 */
+ /* M[0] == 8G */
+ if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* now find (8+k)G for k=1..7 */
+ for (j = 9; j < 16; j++) {
+ if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mp_get_digit_count(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mp_get_digit(k, digidx);
+ bitcnt = (int) ltc_mp.bits_per_digit;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1;
+ buf <<= 1;
+
+ /* skip leading zero bits */
+ if (mode == 0 && i == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we double */
+ if (mode == 1 && i == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (i << (WINSIZE - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == WINSIZE) {
+ /* if this is the first window we do a simple copy */
+ if (first == 1) {
+ /* R = kG [k = first window] */
+ if ((err = mp_copy(M[bitbuf-8]->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[bitbuf-8]->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[bitbuf-8]->z, R->z)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* normal window */
+ /* ok window is filled so double as required and add */
+ /* double first */
+ for (j = 0; j < WINSIZE; j++) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+ if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ /* empty window and reset */
+ bitcpy = bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then double/add */
+ if (mode == 2 && bitcpy > 0) {
+ /* double then add */
+ for (j = 0; j < bitcpy; j++) {
+ /* only double if we have had at least one add first */
+ if (first == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << WINSIZE)) != 0) {
+ if (first == 1){
+ /* first add, so copy */
+ if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* then add */
+ if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ }
+ }
+ }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+done:
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ mp_montgomery_free(mp);
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 8; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+ return err;
+}
+
+#endif
+
+#undef WINSIZE
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c,v $ */
+/* $Revision: 1.26 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
new file mode 100644
index 00000000000..f5a4acb4c5a
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_points.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Allocate a new ECC point
+ @return A newly allocated point or NULL on error
+*/
+ecc_point *ltc_ecc_new_point(void)
+{
+ ecc_point *p;
+ p = XCALLOC(1, sizeof(*p));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) {
+ XFREE(p);
+ return NULL;
+ }
+ return p;
+}
+
+/** Free an ECC point from memory
+ @param p The point to free
+*/
+void ltc_ecc_del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(p->x, p->y, p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */
+ XFREE(p);
+ }
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
new file mode 100644
index 00000000000..b4416fc77de
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
@@ -0,0 +1,196 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_projective_add_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
+{
+ void *t1, *t2, *x, *y, *z;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(Q != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* should we dbl instead? */
+ if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
+
+ if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) &&
+ (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
+ (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
+ mp_clear_multi(t1, t2, x, y, z, NULL);
+ return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
+ }
+
+ if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; }
+
+ /* if Z is one then these are no-operations */
+ if (Q->z != NULL) {
+ /* T1 = Z' * Z' */
+ if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * T1 */
+ if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z' * T1 */
+ if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T1 = Z*Z */
+ if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = X' * T1 */
+ if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z * T1 */
+ if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Y' * T1 */
+ if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* Y = Y - T1 */
+ if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = 2T1 */
+ if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = Y + T1 */
+ if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = 2T2 */
+ if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = X + T2 */
+ if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+
+ /* if Z' != 1 */
+ if (Q->z != NULL) {
+ /* Z = Z * Z' */
+ if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Z = Z * X */
+ if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * X */
+ if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2 * x */
+ if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = Y*Y */
+ if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 * Y */
+ if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = T2 - T1 */
+ if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(y)) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; }
+
+ if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, x, y, z, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
new file mode 100644
index 00000000000..b990e0a14aa
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file ltc_ecc_projective_dbl_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Double an ECC point
+ @param P The point to double
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (P != R) {
+ if ((err = mp_copy(P->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->z, R->z)) != CRYPT_OK) { goto done; }
+ }
+
+ /* t1 = Z * Z */
+ if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = Y * Z */
+ if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = 2Z */
+ if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->z, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T2 = X - T1 */
+ if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = X + T1 */
+ if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T1 * T2 */
+ if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = 2T2 */
+ if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = T1 + T2 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Y = 2Y */
+ if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->y, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * Y */
+ if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = Y * Y */
+ if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2/2 */
+ if (mp_isodd(t2)) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; }
+ /* Y = Y * X */
+ if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = T1 * T1 */
+ if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Y = Y - X */
+ if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y - T2 */
+ if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, NULL);
+ return err;
+}
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
new file mode 100644
index 00000000000..e8f6418067c
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
@@ -0,0 +1,108 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file pkcs_1_mgf1.c
+ The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ Perform LTC_PKCS #1 MGF1 (internal)
+ @param seed The seed for MGF1
+ @param seedlen The length of the seed
+ @param hash_idx The index of the hash desired
+ @param mask [out] The destination
+ @param masklen The length of the mask desired
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_mgf1(int hash_idx,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen)
+{
+ unsigned long hLen, x;
+ ulong32 counter;
+ int err;
+ hash_state *md;
+ unsigned char *buf;
+
+ LTC_ARGCHK(seed != NULL);
+ LTC_ARGCHK(mask != NULL);
+
+ /* ensure valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash output size */
+ hLen = hash_descriptor[hash_idx].hashsize;
+
+ /* allocate memory */
+ md = XMALLOC(sizeof(hash_state));
+ buf = XMALLOC(hLen);
+ if (md == NULL || buf == NULL) {
+ if (md != NULL) {
+ XFREE(md);
+ }
+ if (buf != NULL) {
+ XFREE(buf);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* start counter */
+ counter = 0;
+
+ while (masklen > 0) {
+ /* handle counter */
+ STORE32H(counter, buf);
+ ++counter;
+
+ /* get hash of seed || counter */
+ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store it */
+ for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+ *mask++ = buf[x];
+ }
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, hLen);
+ zeromem(md, sizeof(hash_state));
+#endif
+
+ XFREE(buf);
+ XFREE(md);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
new file mode 100644
index 00000000000..709ab8a8cd2
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -0,0 +1,189 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file pkcs_1_oaep_decode.c
+ OAEP Padding for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 OAEP decode
+ @param msg The encoded data to decode
+ @param msglen The length of the encoded data (octets)
+ @param lparam The session or system data (can be NULL)
+ @param lparamlen The length of the lparam
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash_idx The index of the hash desired
+ @param out [out] Destination of decoding
+ @param outlen [in/out] The max size and resulting size of the decoding
+ @param res [out] Result of decoding, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if invalid)
+*/
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, int hash_idx,
+ unsigned char *out, unsigned long *outlen,
+ int *res)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid packet */
+ *res = 0;
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test hash/message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ok so it's now in the form
+
+ 0x00 || maskedseed || maskedDB
+
+ 1 || hLen || modulus_len - hLen - 1
+
+ */
+
+ /* must have leading 0x00 byte */
+ if (msg[0] != 0x00) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now read the masked seed */
+ x = 1;
+ XMEMCPY(seed, msg + x, hLen);
+ x += hLen;
+
+ /* now read the masked DB */
+ XMEMCPY(DB, msg + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+ /* compute lhash and store it in seed [reuse temps!] */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* compare the lhash'es */
+ if (XMEMCMP(seed, DB, hLen) != 0) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now zeroes before a 0x01 */
+ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+ /* step... */
+ }
+
+ /* error out if wasn't 0x01 */
+ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* rest is the message (and skip 0x01) */
+ if ((modulus_len - hLen - 1 - ++x) > *outlen) {
+ *outlen = modulus_len - hLen - 1 - x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* copy message */
+ *outlen = modulus_len - hLen - 1 - x;
+ XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
+ x += modulus_len - hLen - 1;
+
+ /* valid packet */
+ *res = 1;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
new file mode 100644
index 00000000000..c3a7211ef9c
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
@@ -0,0 +1,177 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file pkcs_1_pss_decode.c
+ LTC_PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 PSS decode
+ @param msghash The hash to verify
+ @param msghashlen The length of the hash (octets)
+ @param sig The signature data (encoded data)
+ @param siglen The length of the signature data (octets)
+ @param saltlen The length of the salt used (octets)
+ @param hash_idx The index of the hash desired
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param res [out] The result of the comparison, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if the comparison failed)
+*/
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, int hash_idx,
+ unsigned long modulus_bitlen, int *res)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+ hash_state md;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* ensure hash is valid */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_descriptor[hash_idx].hashsize;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) ||
+ (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ensure the 0xBC byte */
+ if (sig[siglen-1] != 0xBC) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* copy out the DB */
+ x = 0;
+ XMEMCPY(DB, sig + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* copy out the hash */
+ XMEMCPY(hash, sig + x, hLen);
+ x += hLen;
+
+ /* check the MSB */
+ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now clear the first byte [make sure smaller than modulus] */
+ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+ /* check for zeroes and 0x01 */
+ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+ if (DB[x] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ /* check for the 0x01 */
+ if (DB[x++] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+ if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ zeromem(mask, 8);
+ if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* mask == hash means valid signature */
+ if (XMEMCMP(mask, hash, hLen) == 0) {
+ *res = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c
new file mode 100644
index 00000000000..7c3711c17c9
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/** @file pkcs_1_v1_5_decode.c
+ *
+ * LTC_PKCS #1 v1.5 Padding. (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/** @brief LTC_PKCS #1 v1.5 decode.
+ *
+ * @param msg The encoded data to decode
+ * @param msglen The length of the encoded data (octets)
+ * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * @param modulus_bitlen The bit length of the RSA modulus
+ * @param out [out] Destination of decoding
+ * @param outlen [in/out] The max size and resulting size of the decoding
+ * @param is_valid [out] Boolean whether the padding was valid
+ *
+ * @return CRYPT_OK if successful (even if invalid)
+ */
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid)
+{
+ unsigned long modulus_len, ps_len, i;
+ int result;
+
+ /* default to invalid packet */
+ *is_valid = 0;
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+
+ if ((msglen > modulus_len) || (modulus_len < 11)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* separate encoded message */
+
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ if (block_type == LTC_LTC_PKCS_1_EME) {
+ for (i = 2; i < modulus_len; i++) {
+ /* separator */
+ if (msg[i] == 0x00) { break; }
+ }
+ ps_len = i++ - 2;
+
+ if ((i >= modulus_len) || (ps_len < 8)) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m,
+ * or the length of ps is less than 8 octets.
+ */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+ } else {
+ for (i = 2; i < modulus_len - 1; i++) {
+ if (msg[i] != 0xFF) { break; }
+ }
+
+ /* separator check */
+ if (msg[i] != 0) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ ps_len = i - 2;
+ }
+
+ if (*outlen < (msglen - (2 + ps_len + 1))) {
+ *outlen = msglen - (2 + ps_len + 1);
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ *outlen = (msglen - (2 + ps_len + 1));
+ XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
+
+ /* valid packet */
+ *is_valid = 1;
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_decode */
+
+#endif /* #ifdef LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c
new file mode 100644
index 00000000000..ba44106f2b7
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c
@@ -0,0 +1,113 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_exptmod.c
+ RSA LTC_PKCS exptmod, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Compute an RSA modular exponentiation
+ @param in The input data to send into RSA
+ @param inlen The length of the input (octets)
+ @param out [out] The destination
+ @param outlen [in/out] The max size and resulting size of the output
+ @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
+ @param key The RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key)
+{
+ void *tmp, *tmpa, *tmpb;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is the key of the right type for the operation? */
+ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* must be a private or public operation */
+ if (which != PK_PRIVATE && which != PK_PUBLIC) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* init and copy into tmp */
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK) { return err; }
+ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }
+
+ /* sanity check on the input */
+ if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
+ err = CRYPT_PK_INVALID_SIZE;
+ goto error;
+ }
+
+ /* are we using the private exponent and is the key optimized? */
+ if (which == PK_PRIVATE) {
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; }
+ } else {
+ /* exptmod it */
+ if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ /* read it back */
+ x = (unsigned long)mp_unsigned_bin_size(key->N);
+ if (x > *outlen) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ /* this should never happen ... */
+ if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
+ err = CRYPT_ERROR;
+ goto error;
+ }
+ *outlen = x;
+
+ /* convert it */
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; }
+
+ /* clean up and return */
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(tmp, tmpa, tmpb, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */
+/* $Revision: 1.18 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c
new file mode 100644
index 00000000000..a10ed5928ce
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_free.c
+ Free an RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(key->e, key->d, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c
new file mode 100644
index 00000000000..6254fd7ff86
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c
@@ -0,0 +1,143 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_import.c
+ Import a LTC_PKCS RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ void *zero;
+ unsigned char *tmpbuf;
+ unsigned long t, x, y, z, tmpoid[16];
+ ltc_asn1_list ssl_pubkey_hashoid[2];
+ ltc_asn1_list ssl_pubkey[2];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
+ &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ /* this includes the internal hash ID and optional params (NULL in this case) */
+ LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
+ LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0);
+
+ /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
+ then proceed to convert bit to octet
+ */
+ LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2);
+ LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
+
+ if (der_decode_sequence(in, inlen,
+ ssl_pubkey, 2UL) == CRYPT_OK) {
+
+ /* ok now we have to reassemble the BIT STRING to an OCTET STRING. Thanks OpenSSL... */
+ for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) {
+ y = (y << 1) | tmpbuf[x];
+ if (++z == 8) {
+ tmpbuf[t++] = (unsigned char)y;
+ y = 0;
+ z = 0;
+ }
+ }
+
+ /* now it should be SEQUENCE { INTEGER, INTEGER } */
+ if ((err = der_decode_sequence_multi(tmpbuf, t,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ goto LBL_ERR;
+ }
+ XFREE(tmpbuf);
+ key->type = PK_PUBLIC;
+ return CRYPT_OK;
+ }
+ XFREE(tmpbuf);
+
+ /* not SSL public key, try to match against LTC_PKCS #1 standards */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
+ if ((err = mp_init(&zero)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* it's a private key */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, zero,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_INTEGER, 1UL, key->d,
+ LTC_ASN1_INTEGER, 1UL, key->p,
+ LTC_ASN1_INTEGER, 1UL, key->q,
+ LTC_ASN1_INTEGER, 1UL, key->dP,
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
+ LTC_ASN1_INTEGER, 1UL, key->qP,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ mp_clear(zero);
+ goto LBL_ERR;
+ }
+ mp_clear(zero);
+ key->type = PK_PRIVATE;
+ } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
+ /* we don't support multi-prime RSA */
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_ERR;
+ } else {
+ /* it's a public key and we lack e */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, key->N,
+ LTC_ASN1_INTEGER, 1UL, key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PUBLIC;
+ }
+ return CRYPT_OK;
+LBL_ERR:
+ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_import.c,v $ */
+/* $Revision: 1.23 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c
new file mode 100644
index 00000000000..bd37b4ae1cb
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c
@@ -0,0 +1,112 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_make_key.c
+ RSA key generation, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Create an RSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
+{
+ void *p, *q, *tmp1, *tmp2, *tmp3;
+ int err;
+
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if ((e < 3) || ((e & 1) == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* make primes p and q (optimization provided by Wayne Scott) */
+ if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto errkey; } /* tmp3 = e */
+
+ /* make prime "p" */
+ do {
+ if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(p-1, e) */
+ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */
+
+ /* make prime "q" */
+ do {
+ if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(q-1, e) */
+ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */
+
+ /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */
+ /* tmp1 = q-1 (previous do/while loop) */
+ if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = lcm(p-1, q-1) */
+
+ /* make key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ if ((err = mp_set_int( key->e, e)) != CRYPT_OK) { goto errkey; } /* key->e = e */
+ if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */
+ if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */
+
+ /* optimize for CRT now */
+ /* find d mod q-1 and d mod p-1 */
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */
+ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */
+ if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */
+ if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */
+ if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */
+
+ if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; }
+
+ /* set key type (in this case it's CRT optimized) */
+ key->type = PK_PRIVATE;
+
+ /* return ok and free temps */
+ err = CRYPT_OK;
+ goto cleanup;
+errkey:
+ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+cleanup:
+ mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_make_key.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
new file mode 100644
index 00000000000..103ae2f5303
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_verify_hash.c
+ RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ LTC_PKCS #1 de-sign then v1.5 or PSS depad
+ @param sig The signature data
+ @param siglen The length of the signature data (octets)
+ @param hash The hash of the message that was signed
+ @param hashlen The length of the hash of the message that was signed (octets)
+ @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)
+ @param hash_idx The index of the desired hash
+ @param saltlen The length of the salt used during signature
+ @param stat [out] The result of the signature comparison, 1==valid, 0==invalid
+ @param key The public RSA key corresponding to the key that performed the signature
+ @return CRYPT_OK on success (even if the signature is invalid)
+*/
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ int hash_idx, unsigned long saltlen,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmpbuf;
+
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_PSS)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XMALLOC(siglen);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* make sure the output is the right size */
+ if (x != siglen) {
+ XFREE(tmpbuf);
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ /* PSS decode and verify it */
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+ } else {
+ /* LTC_PKCS #1 v1.5 decode it */
+ unsigned char *out;
+ unsigned long outlen, loid[16];
+ int decoded;
+ ltc_asn1_list digestinfo[2], siginfo[2];
+
+ /* not all hashes have OIDs... so sad */
+ if (hash_descriptor[hash_idx].OIDlen == 0) {
+ err = CRYPT_INVALID_ARG;
+ goto bail_2;
+ }
+
+ /* allocate temp buffer for decoded hash */
+ outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;
+ out = XMALLOC(outlen);
+ if (out == NULL) {
+ err = CRYPT_MEM;
+ goto bail_2;
+ }
+
+ if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
+
+ if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* test OID */
+ if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&
+ (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&
+ (siginfo[1].size == hashlen) &&
+ (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {
+ *stat = 1;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(out, outlen);
+#endif
+ XFREE(out);
+ }
+
+bail_2:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmpbuf, siglen);
+#endif
+ XFREE(tmpbuf);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c
new file mode 100644
index 00000000000..6d8888c858d
--- /dev/null
+++ b/dep/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include "../../headers/tomcrypt.h"
+
+/**
+ @file rsa_verify_simple.c
+ Created by Ladislav Zezula (zezula@volny.cz) as modification
+ for Blizzard strong signature verification
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Simple RSA decryption
+ @param sig The signature data
+ @param siglen The length of the signature data (octets)
+ @param hash The hash of the message that was signed
+ @param hashlen The length of the hash of the message that was signed (octets)
+ @param stat [out] The result of the signature comparison, 1==valid, 0==invalid
+ @param key The public RSA key corresponding
+ @return Error code
+*/
+int rsa_verify_simple(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ unsigned char *tmpbuf;
+ int err;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XMALLOC(siglen);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* make sure the output is the right size */
+ if (x != siglen) {
+ XFREE(tmpbuf);
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* compare the decrypted signature with the given hash */
+ if(x == hashlen && XMEMCMP(tmpbuf, hash, hashlen) == 0)
+ *stat = 1;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmpbuf, siglen);
+#endif
+ XFREE(tmpbuf);
+ return CRYPT_OK;
+}
+
+#endif /* LTC_MRSA */
diff --git a/dep/StormLib/src/libtommath/bn_fast_mp_invmod.c b/dep/StormLib/src/libtommath/bn_fast_mp_invmod.c
new file mode 100644
index 00000000000..597d7a9b5fa
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_fast_mp_invmod.c
@@ -0,0 +1,148 @@
+#include "tommath.h"
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, B, D;
+ int res, neg;
+
+ /* 2. [modified] b must be odd */
+ if (mp_iseven (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init all our temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x == modulus, y == value to invert */
+ if ((res = mp_copy (b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* we need y = |a| */
+ if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if B is odd then */
+ if (mp_isodd (&B) == 1) {
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* B = B/2 */
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if D is odd then */
+ if (mp_isodd (&D) == 1) {
+ /* D = (D-x)/2 */
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* D = D/2 */
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0) {
+ goto top;
+ }
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* b is now the inverse */
+ neg = a->sign;
+ while (D.sign == MP_NEG) {
+ if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ mp_exch (&D, c);
+ c->sign = neg;
+ res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c b/dep/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c
new file mode 100644
index 00000000000..65eed7da1fe
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c
@@ -0,0 +1,172 @@
+#include "tommath.h"
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, olduse;
+ mp_word W[MP_WARRAY];
+
+ /* get old used count */
+ olduse = x->used;
+
+ /* grow a as required */
+ if (x->alloc < n->used + 1) {
+ if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* first we have to get the digits of the input into
+ * an array of double precision words W[...]
+ */
+ {
+ register mp_word *_W;
+ register mp_digit *tmpx;
+
+ /* alias for the W[] array */
+ _W = W;
+
+ /* alias for the digits of x*/
+ tmpx = x->dp;
+
+ /* copy the digits of a into W[0..a->used-1] */
+ for (ix = 0; ix < x->used; ix++) {
+ *_W++ = *tmpx++;
+ }
+
+ /* zero the high words of W[a->used..m->used*2] */
+ for (; ix < n->used * 2 + 1; ix++) {
+ *_W++ = 0;
+ }
+ }
+
+ /* now we proceed to zero successive digits
+ * from the least significant upwards
+ */
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * m' mod b
+ *
+ * We avoid a double precision multiplication (which isn't required)
+ * by casting the value down to a mp_digit. Note this requires
+ * that W[ix-1] have the carry cleared (see after the inner loop)
+ */
+ register mp_digit mu;
+ mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i
+ *
+ * This is computed in place and on the fly. The multiplication
+ * by b**i is handled by offseting which columns the results
+ * are added to.
+ *
+ * Note the comba method normally doesn't handle carries in the
+ * inner loop In this case we fix the carry from the previous
+ * column since the Montgomery reduction requires digits of the
+ * result (so far) [see above] to work. This is
+ * handled by fixing up one carry after the inner loop. The
+ * carry fixups are done in order so after these loops the
+ * first m->used words of W[] have the carries fixed
+ */
+ {
+ register int iy;
+ register mp_digit *tmpn;
+ register mp_word *_W;
+
+ /* alias for the digits of the modulus */
+ tmpn = n->dp;
+
+ /* Alias for the columns set by an offset of ix */
+ _W = W + ix;
+
+ /* inner loop */
+ for (iy = 0; iy < n->used; iy++) {
+ *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+ }
+ }
+
+ /* now fix carry for next digit, W[ix+1] */
+ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* now we have to propagate the carries and
+ * shift the words downward [all those least
+ * significant digits we zeroed].
+ */
+ {
+ register mp_digit *tmpx;
+ register mp_word *_W, *_W1;
+
+ /* nox fix rest of carries */
+
+ /* alias for current word */
+ _W1 = W + ix;
+
+ /* alias for next word, where the carry goes */
+ _W = W + ++ix;
+
+ for (; ix <= n->used * 2 + 1; ix++) {
+ *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* copy out, A = A/b**n
+ *
+ * The result is A/b**n but instead of converting from an
+ * array of mp_word to mp_digit than calling mp_rshd
+ * we just copy them in the right order
+ */
+
+ /* alias for destination word */
+ tmpx = x->dp;
+
+ /* alias for shifted double precision result */
+ _W = W + n->used;
+
+ for (ix = 0; ix < n->used + 1; ix++) {
+ *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+ }
+
+ /* zero oldused digits, if the input a was larger than
+ * m->used+1 we'll have to clear the digits
+ */
+ for (; ix < olduse; ix++) {
+ *tmpx++ = 0;
+ }
+ }
+
+ /* set the max used and clamp */
+ x->used = n->used + 1;
+ mp_clamp (x);
+
+ /* if A >= m then A = A - m */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c b/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c
new file mode 100644
index 00000000000..df83f89ecab
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c
@@ -0,0 +1,107 @@
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier. It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards. This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ register mp_word _W;
+
+ /* grow the destination as required */
+ if (c->alloc < digs) {
+ if ((res = mp_grow (c, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = MIN(digs, a->used + b->used);
+
+ /* clear the carry */
+ _W = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty;
+ int iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; ++iz) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+ tmpc = c->dp;
+ for (ix = 0; ix < pa+1; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c b/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c
new file mode 100644
index 00000000000..6866aab7529
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c
@@ -0,0 +1,98 @@
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs. See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed. This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ pa = a->used + b->used;
+ if (c->alloc < pa) {
+ if ((res = mp_grow (c, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = a->used + b->used;
+ _W = 0;
+ for (ix = digs; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially its
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+
+ tmpc = c->dp + digs;
+ for (ix = digs; ix < pa; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_fast_s_mp_sqr.c b/dep/StormLib/src/libtommath/bn_fast_s_mp_sqr.c
new file mode 100644
index 00000000000..5f9d58cac62
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_fast_s_mp_sqr.c
@@ -0,0 +1,114 @@
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens. You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY], *tmpx;
+ mp_word W1;
+
+ /* grow the destination as required */
+ pa = a->used + a->used;
+ if (b->alloc < pa) {
+ if ((res = mp_grow (b, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ W1 = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_word _W;
+ mp_digit *tmpy;
+
+ /* clear counter */
+ _W = 0;
+
+ /* get offsets into the two bignums */
+ ty = MIN(a->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = a->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* now for squaring tx can never equal ty
+ * we halve the distance since they approach at a rate of 2x
+ * and we have to round because odd cases need to be executed
+ */
+ iy = MIN(iy, (ty-tx+1)>>1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* double the inner product and add carry */
+ _W = _W + _W + W1;
+
+ /* even columns have the square term in them */
+ if ((ix&1) == 0) {
+ _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+ }
+
+ /* store it */
+ W[ix] = (mp_digit)(_W & MP_MASK);
+
+ /* make next carry */
+ W1 = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = b->used;
+ b->used = a->used+a->used;
+
+ {
+ mp_digit *tmpb;
+ tmpb = b->dp;
+ for (ix = 0; ix < pa; ix++) {
+ *tmpb++ = W[ix] & MP_MASK;
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpb++ = 0;
+ }
+ }
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_2expt.c b/dep/StormLib/src/libtommath/bn_mp_2expt.c
new file mode 100644
index 00000000000..f899eaee43e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_2expt.c
@@ -0,0 +1,48 @@
+#include "tommath.h"
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+ int res;
+
+ /* zero a as per default */
+ mp_zero (a);
+
+ /* grow a to accomodate the single bit */
+ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set the used count of where the bit will go */
+ a->used = b / DIGIT_BIT + 1;
+
+ /* put the single bit in its place */
+ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_abs.c b/dep/StormLib/src/libtommath/bn_mp_abs.c
new file mode 100644
index 00000000000..14f3a7e074d
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_abs.c
@@ -0,0 +1,43 @@
+#include "tommath.h"
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* copy a to b */
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* force the sign of b to positive */
+ b->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_add.c b/dep/StormLib/src/libtommath/bn_mp_add.c
new file mode 100644
index 00000000000..b368b21c7cb
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_add.c
@@ -0,0 +1,53 @@
+#include "tommath.h"
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ /* get sign of both inputs */
+ sa = a->sign;
+ sb = b->sign;
+
+ /* handle two cases, not four */
+ if (sa == sb) {
+ /* both positive or both negative */
+ /* add their magnitudes, copy the sign */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* one positive, the other negative */
+ /* subtract the one with the greater magnitude from */
+ /* the one of the lesser magnitude. The result gets */
+ /* the sign of the one with the greater magnitude. */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ c->sign = sb;
+ res = s_mp_sub (b, a, c);
+ } else {
+ c->sign = sa;
+ res = s_mp_sub (a, b, c);
+ }
+ }
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_add_d.c b/dep/StormLib/src/libtommath/bn_mp_add_d.c
new file mode 100644
index 00000000000..c147554bdb8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_add_d.c
@@ -0,0 +1,112 @@
+#include "tommath.h"
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, ix, oldused;
+ mp_digit *tmpa, *tmpc, mu;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative and |a| >= b, call c = |a| - b */
+ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+ /* temporarily fix sign of a */
+ a->sign = MP_ZPOS;
+
+ /* c = |a| - b */
+ res = mp_sub_d(a, b, c);
+
+ /* fix sign */
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* old number of used digits in c */
+ oldused = c->used;
+
+ /* sign always positive */
+ c->sign = MP_ZPOS;
+
+ /* source alias */
+ tmpa = a->dp;
+
+ /* destination alias */
+ tmpc = c->dp;
+
+ /* if a is positive */
+ if (a->sign == MP_ZPOS) {
+ /* add digit, after this we're propagating
+ * the carry.
+ */
+ *tmpc = *tmpa++ + b;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+
+ /* now handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ + mu;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+ }
+ /* set final carry */
+ ix++;
+ *tmpc++ = mu;
+
+ /* setup size */
+ c->used = a->used + 1;
+ } else {
+ /* a was negative and |a| < b */
+ c->used = 1;
+
+ /* the result is a single digit */
+ if (a->used == 1) {
+ *tmpc++ = b - a->dp[0];
+ } else {
+ *tmpc++ = b;
+ }
+
+ /* setup count so the clearing of oldused
+ * can fall through correctly
+ */
+ ix = 1;
+ }
+
+ /* now zero to oldused */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_addmod.c b/dep/StormLib/src/libtommath/bn_mp_addmod.c
new file mode 100644
index 00000000000..0a21f62e9a6
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_addmod.c
@@ -0,0 +1,41 @@
+#include "tommath.h"
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_and.c b/dep/StormLib/src/libtommath/bn_mp_and.c
new file mode 100644
index 00000000000..6b7afc104a8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_and.c
@@ -0,0 +1,57 @@
+#include "tommath.h"
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] &= x->dp[ix];
+ }
+
+ /* zero digits above the last from the smallest mp_int */
+ for (; ix < t.used; ix++) {
+ t.dp[ix] = 0;
+ }
+
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_clamp.c b/dep/StormLib/src/libtommath/bn_mp_clamp.c
new file mode 100644
index 00000000000..d3cc21c3eff
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_clamp.c
@@ -0,0 +1,44 @@
+#include "tommath.h"
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast. Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+ /* decrease used while the most significant digit is
+ * zero.
+ */
+ while (a->used > 0 && a->dp[a->used - 1] == 0) {
+ --(a->used);
+ }
+
+ /* reset the sign flag if used == 0 */
+ if (a->used == 0) {
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_clear.c b/dep/StormLib/src/libtommath/bn_mp_clear.c
new file mode 100644
index 00000000000..7644c382512
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_clear.c
@@ -0,0 +1,44 @@
+#include "tommath.h"
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* clear one (frees) */
+void
+mp_clear (mp_int * a)
+{
+ int i;
+
+ /* only do anything if a hasn't been freed previously */
+ if (a->dp != NULL) {
+ /* first zero the digits */
+ for (i = 0; i < a->used; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* free ram */
+ XFREE(a->dp);
+
+ /* reset members to make debugging easier */
+ a->dp = NULL;
+ a->alloc = a->used = 0;
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_clear_multi.c b/dep/StormLib/src/libtommath/bn_mp_clear_multi.c
new file mode 100644
index 00000000000..a1076243675
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_clear_multi.c
@@ -0,0 +1,34 @@
+#include "tommath.h"
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...)
+{
+ mp_int* next_mp = mp;
+ va_list args;
+ va_start(args, mp);
+ while (next_mp != NULL) {
+ mp_clear(next_mp);
+ next_mp = va_arg(args, mp_int*);
+ }
+ va_end(args);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_cmp.c b/dep/StormLib/src/libtommath/bn_mp_cmp.c
new file mode 100644
index 00000000000..761d2b0dc75
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_cmp.c
@@ -0,0 +1,43 @@
+#include "tommath.h"
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+ /* compare based on sign */
+ if (a->sign != b->sign) {
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ } else {
+ return MP_GT;
+ }
+ }
+
+ /* compare digits */
+ if (a->sign == MP_NEG) {
+ /* if negative compare opposite direction */
+ return mp_cmp_mag(b, a);
+ } else {
+ return mp_cmp_mag(a, b);
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_cmp_d.c b/dep/StormLib/src/libtommath/bn_mp_cmp_d.c
new file mode 100644
index 00000000000..420dfd31aa1
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_cmp_d.c
@@ -0,0 +1,44 @@
+#include "tommath.h"
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+ /* compare based on sign */
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ }
+
+ /* compare based on magnitude */
+ if (a->used > 1) {
+ return MP_GT;
+ }
+
+ /* compare the only digit of a to b */
+ if (a->dp[0] > b) {
+ return MP_GT;
+ } else if (a->dp[0] < b) {
+ return MP_LT;
+ } else {
+ return MP_EQ;
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_cmp_mag.c b/dep/StormLib/src/libtommath/bn_mp_cmp_mag.c
new file mode 100644
index 00000000000..92565a3b896
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_cmp_mag.c
@@ -0,0 +1,55 @@
+#include "tommath.h"
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+ int n;
+ mp_digit *tmpa, *tmpb;
+
+ /* compare based on # of non-zero digits */
+ if (a->used > b->used) {
+ return MP_GT;
+ }
+
+ if (a->used < b->used) {
+ return MP_LT;
+ }
+
+ /* alias for a */
+ tmpa = a->dp + (a->used - 1);
+
+ /* alias for b */
+ tmpb = b->dp + (a->used - 1);
+
+ /* compare based on digits */
+ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+ if (*tmpa > *tmpb) {
+ return MP_GT;
+ }
+
+ if (*tmpa < *tmpb) {
+ return MP_LT;
+ }
+ }
+ return MP_EQ;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_cnt_lsb.c b/dep/StormLib/src/libtommath/bn_mp_cnt_lsb.c
new file mode 100644
index 00000000000..60406610ed6
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_cnt_lsb.c
@@ -0,0 +1,53 @@
+#include "tommath.h"
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+static const int lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+ int x;
+ mp_digit q, qq;
+
+ /* easy out */
+ if (mp_iszero(a) == 1) {
+ return 0;
+ }
+
+ /* scan lower digits until non-zero */
+ for (x = 0; x < a->used && a->dp[x] == 0; x++);
+ q = a->dp[x];
+ x *= DIGIT_BIT;
+
+ /* now scan this digit until a 1 is found */
+ if ((q & 1) == 0) {
+ do {
+ qq = q & 15;
+ x += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+ return x;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_copy.c b/dep/StormLib/src/libtommath/bn_mp_copy.c
new file mode 100644
index 00000000000..7828592da5d
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_copy.c
@@ -0,0 +1,68 @@
+#include "tommath.h"
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+ int res, n;
+
+ /* if dst == src do nothing */
+ if (a == b) {
+ return MP_OKAY;
+ }
+
+ /* grow dest */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero b and copy the parameters over */
+ {
+ register mp_digit *tmpa, *tmpb;
+
+ /* pointer aliases */
+
+ /* source */
+ tmpa = a->dp;
+
+ /* destination */
+ tmpb = b->dp;
+
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) {
+ *tmpb++ = *tmpa++;
+ }
+
+ /* clear high digits */
+ for (; n < b->used; n++) {
+ *tmpb++ = 0;
+ }
+ }
+
+ /* copy used count and sign */
+ b->used = a->used;
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_count_bits.c b/dep/StormLib/src/libtommath/bn_mp_count_bits.c
new file mode 100644
index 00000000000..9d8640fdfce
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_count_bits.c
@@ -0,0 +1,45 @@
+#include "tommath.h"
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+ int r;
+ mp_digit q;
+
+ /* shortcut */
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits and add that */
+ r = (a->used - 1) * DIGIT_BIT;
+
+ /* take the last digit and count the bits in it */
+ q = a->dp[a->used - 1];
+ while (q > ((mp_digit) 0)) {
+ ++r;
+ q >>= ((mp_digit) 1);
+ }
+ return r;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_div.c b/dep/StormLib/src/libtommath/bn_mp_div.c
new file mode 100644
index 00000000000..3004a3ea016
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_div.c
@@ -0,0 +1,292 @@
+#include "tommath.h"
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int ta, tb, tq, q;
+ int res, n, n2;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ /* init our temps */
+ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+ return res;
+ }
+
+
+ mp_set(&tq, 1);
+ n = mp_count_bits(a) - mp_count_bits(b);
+ if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+ ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+
+ while (n-- >= 0) {
+ if (mp_cmp(&tb, &ta) != MP_GT) {
+ if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+ ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+ if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+ ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* now q == quotient and ta == remainder */
+ n = a->sign;
+ n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+ if (c != NULL) {
+ mp_exch(c, &q);
+ c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+ }
+ if (d != NULL) {
+ mp_exch(d, &ta);
+ d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+ }
+LBL_ERR:
+ mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+ return res;
+}
+
+#else
+
+/* integer signed division.
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly
+ * incomplete. For example, it doesn't consider
+ * the case where digits are removed from 'x' in
+ * the inner loop. It also doesn't consider the
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int q, x, y, t1, t2;
+ int res, n, t, i, norm, neg;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+ return res;
+ }
+ q.used = a->used + 2;
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ goto LBL_Q;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+ goto LBL_X;
+ }
+
+ /* fix the sign */
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+ x.sign = y.sign = MP_ZPOS;
+
+ /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+ norm = mp_count_bits(&y) % DIGIT_BIT;
+ if (norm < (int)(DIGIT_BIT-1)) {
+ norm = (DIGIT_BIT-1) - norm;
+ if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ } else {
+ norm = 0;
+ }
+
+ /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+ n = x.used - 1;
+ t = y.used - 1;
+
+ /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+ goto LBL_Y;
+ }
+
+ while (mp_cmp (&x, &y) != MP_LT) {
+ ++(q.dp[n - t]);
+ if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ }
+
+ /* reset y by shifting it back down */
+ mp_rshd (&y, n - t);
+
+ /* step 3. for i from n down to (t + 1) */
+ for (i = n; i >= (t + 1); i--) {
+ if (i > x.used) {
+ continue;
+ }
+
+ /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+ * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+ if (x.dp[i] == y.dp[t]) {
+ q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+ } else {
+ mp_word tmp;
+ tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+ tmp |= ((mp_word) x.dp[i - 1]);
+ tmp /= ((mp_word) y.dp[t]);
+ if (tmp > (mp_word) MP_MASK)
+ tmp = MP_MASK;
+ q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+ }
+
+ /* while (q{i-t-1} * (yt * b + y{t-1})) >
+ xi * b**2 + xi-1 * b + xi-2
+
+ do q{i-t-1} -= 1;
+ */
+ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+ do {
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+ /* find left hand */
+ mp_zero (&t1);
+ t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+ t1.dp[1] = y.dp[t];
+ t1.used = 2;
+ if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* find right hand */
+ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+ t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+ t2.dp[2] = x.dp[i];
+ t2.used = 3;
+ } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+ /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+ if (x.sign == MP_NEG) {
+ if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+ }
+ }
+
+ /* now q is the quotient and x is the remainder
+ * [which we have to normalize]
+ */
+
+ /* get sign before writing to c */
+ x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+ if (c != NULL) {
+ mp_clamp (&q);
+ mp_exch (&q, c);
+ c->sign = neg;
+ }
+
+ if (d != NULL) {
+ mp_div_2d (&x, norm, &x, NULL);
+ mp_exch (&x, d);
+ }
+
+ res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+ return res;
+}
+
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_div_2.c b/dep/StormLib/src/libtommath/bn_mp_div_2.c
new file mode 100644
index 00000000000..f3b9d16fa37
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_div_2.c
@@ -0,0 +1,68 @@
+#include "tommath.h"
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* copy */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* source alias */
+ tmpa = a->dp + b->used - 1;
+
+ /* dest alias */
+ tmpb = b->dp + b->used - 1;
+
+ /* carry */
+ r = 0;
+ for (x = b->used - 1; x >= 0; x--) {
+ /* get the carry for the next iteration */
+ rr = *tmpa & 1;
+
+ /* shift the current digit, add in carry and store */
+ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+ /* forward carry to next iteration */
+ r = rr;
+ }
+
+ /* zero excess digits */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_div_2d.c b/dep/StormLib/src/libtommath/bn_mp_div_2d.c
new file mode 100644
index 00000000000..861ea23a31a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_div_2d.c
@@ -0,0 +1,97 @@
+#include "tommath.h"
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+ mp_digit D, r, rr;
+ int x, res;
+ mp_int t;
+
+
+ /* if the shift count is <= 0 then we do no work */
+ if (b <= 0) {
+ res = mp_copy (a, c);
+ if (d != NULL) {
+ mp_zero (d);
+ }
+ return res;
+ }
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ /* get the remainder */
+ if (d != NULL) {
+ if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ mp_rshd (c, b / DIGIT_BIT);
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ D = (mp_digit) (b % DIGIT_BIT);
+ if (D != 0) {
+ register mp_digit *tmpc, mask, shift;
+
+ /* mask */
+ mask = (((mp_digit)1) << D) - 1;
+
+ /* shift for lsb */
+ shift = DIGIT_BIT - D;
+
+ /* alias */
+ tmpc = c->dp + (c->used - 1);
+
+ /* carry */
+ r = 0;
+ for (x = c->used - 1; x >= 0; x--) {
+ /* get the lower bits of this word in a temp */
+ rr = *tmpc & mask;
+
+ /* shift the current word and mix in the carry bits from the previous word */
+ *tmpc = (*tmpc >> D) | (r << shift);
+ --tmpc;
+
+ /* set the carry to the carry bits of the current word found above */
+ r = rr;
+ }
+ }
+ mp_clamp (c);
+ if (d != NULL) {
+ mp_exch (&t, d);
+ }
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_div_3.c b/dep/StormLib/src/libtommath/bn_mp_div_3.c
new file mode 100644
index 00000000000..4fc08fc4da4
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_div_3.c
@@ -0,0 +1,79 @@
+#include "tommath.h"
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w, t;
+ mp_digit b;
+ int res, ix;
+
+ /* b = 2**DIGIT_BIT / 3 */
+ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= 3) {
+ /* multiply w by [1/3] */
+ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+ /* now subtract 3 * [w/3] from w, to get the remainder */
+ w -= t+t+t;
+
+ /* fixup the remainder as required since
+ * the optimization is not exact.
+ */
+ while (w >= 3) {
+ t += 1;
+ w -= 3;
+ }
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ /* [optional] store the remainder */
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ /* [optional] store the quotient */
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_div_d.c b/dep/StormLib/src/libtommath/bn_mp_div_d.c
new file mode 100644
index 00000000000..c0318a4a1be
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_div_d.c
@@ -0,0 +1,115 @@
+#include "tommath.h"
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+ int x;
+
+ /* fast return if no power of two */
+ if ((b==0) || (b & (b-1))) {
+ return 0;
+ }
+
+ for (x = 0; x < DIGIT_BIT; x++) {
+ if (b == (((mp_digit)1)<<x)) {
+ *p = x;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ int res, ix;
+
+ /* cannot divide by zero */
+ if (b == 0) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if (b == 1 || mp_iszero(a) == 1) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if (s_is_power_of_two(b, &ix) == 1) {
+ if (d != NULL) {
+ *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+#ifdef BN_MP_DIV_3_C
+ /* three? */
+ if (b == 3) {
+ return mp_div_3(a, c, d);
+ }
+#endif
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= ((mp_word)t) * ((mp_word)b);
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2007/01/09 04:44:32 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_dr_is_modulus.c b/dep/StormLib/src/libtommath/bn_mp_dr_is_modulus.c
new file mode 100644
index 00000000000..22ba5df3d0a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_dr_is_modulus.c
@@ -0,0 +1,43 @@
+#include "tommath.h"
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+ int ix;
+
+ /* must be at least two digits */
+ if (a->used < 2) {
+ return 0;
+ }
+
+ /* must be of the form b**k - a [a <= b] so all
+ * but the first digit must be equal to -1 (mod b).
+ */
+ for (ix = 1; ix < a->used; ix++) {
+ if (a->dp[ix] != MP_MASK) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_dr_reduce.c b/dep/StormLib/src/libtommath/bn_mp_dr_reduce.c
new file mode 100644
index 00000000000..0afac941fca
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_dr_reduce.c
@@ -0,0 +1,94 @@
+#include "tommath.h"
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ * Chae Hoon Lim, Pil Joong Lee,
+ * POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+ int err, i, m;
+ mp_word r;
+ mp_digit mu, *tmpx1, *tmpx2;
+
+ /* m = digits in modulus */
+ m = n->used;
+
+ /* ensure that "x" has at least 2m digits */
+ if (x->alloc < m + m) {
+ if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+ /* aliases for digits */
+ /* alias for lower half of x */
+ tmpx1 = x->dp;
+
+ /* alias for upper half of x, or x/B**m */
+ tmpx2 = x->dp + m;
+
+ /* set carry to zero */
+ mu = 0;
+
+ /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+ for (i = 0; i < m; i++) {
+ r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+ *tmpx1++ = (mp_digit)(r & MP_MASK);
+ mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+ }
+
+ /* set final carry */
+ *tmpx1++ = mu;
+
+ /* zero words above m */
+ for (i = m + 1; i < x->used; i++) {
+ *tmpx1++ = 0;
+ }
+
+ /* clamp, sub and return */
+ mp_clamp (x);
+
+ /* if x >= n then subtract and reduce again
+ * Each successive "recursion" makes the input smaller and smaller.
+ */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ s_mp_sub(x, n, x);
+ goto top;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_dr_setup.c b/dep/StormLib/src/libtommath/bn_mp_dr_setup.c
new file mode 100644
index 00000000000..a5152f713bd
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_dr_setup.c
@@ -0,0 +1,32 @@
+#include "tommath.h"
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+ /* the casts are required if DIGIT_BIT is one less than
+ * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+ */
+ *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+ ((mp_word)a->dp[0]));
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_exch.c b/dep/StormLib/src/libtommath/bn_mp_exch.c
new file mode 100644
index 00000000000..e5ec7f57730
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_exch.c
@@ -0,0 +1,34 @@
+#include "tommath.h"
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+ mp_int t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_expt_d.c b/dep/StormLib/src/libtommath/bn_mp_expt_d.c
new file mode 100644
index 00000000000..7bf371ce6ae
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_expt_d.c
@@ -0,0 +1,57 @@
+#include "tommath.h"
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* calculate c = a**b using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, x;
+ mp_int g;
+
+ if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set initial result */
+ mp_set (c, 1);
+
+ for (x = 0; x < (int) DIGIT_BIT; x++) {
+ /* square */
+ if ((res = mp_sqr (c, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+
+ /* if the bit is set multiply */
+ if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+ if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+ }
+
+ /* shift to next bit */
+ b <<= 1;
+ }
+
+ mp_clear (&g);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_exptmod.c b/dep/StormLib/src/libtommath/bn_mp_exptmod.c
new file mode 100644
index 00000000000..27c46ea0ab2
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_exptmod.c
@@ -0,0 +1,112 @@
+#include "tommath.h"
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions. Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+ int dr;
+
+ /* modulus P must be positive */
+ if (P->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* if exponent X is negative we have to recurse */
+ if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+ mp_int tmpG, tmpX;
+ int err;
+
+ /* first compute 1/G mod P */
+ if ((err = mp_init(&tmpG)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+
+ /* now get |X| */
+ if ((err = mp_init(&tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+ if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+ }
+
+ /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+ err = mp_exptmod(&tmpG, &tmpX, P, Y);
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+#else
+ /* no invmod */
+ return MP_VAL;
+#endif
+ }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+ if (mp_reduce_is_2k_l(P) == MP_YES) {
+ return s_mp_exptmod(G, X, P, Y, 1);
+ }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+ /* is it a DR modulus? */
+ dr = mp_dr_is_modulus(P);
+#else
+ /* default to no */
+ dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+ /* if not, is it a unrestricted DR modulus? */
+ if (dr == 0) {
+ dr = mp_reduce_is_2k(P) << 1;
+ }
+#endif
+
+ /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+ if (mp_isodd (P) == 1 || dr != 0) {
+ return mp_exptmod_fast (G, X, P, Y, dr);
+ } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+ /* otherwise use the generic Barrett reduction technique */
+ return s_mp_exptmod (G, X, P, Y, 0);
+#else
+ /* no exptmod for evens */
+ return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+ }
+#endif
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_exptmod_fast.c b/dep/StormLib/src/libtommath/bn_mp_exptmod_fast.c
new file mode 100644
index 00000000000..31205d4e20c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_exptmod_fast.c
@@ -0,0 +1,321 @@
+#include "tommath.h"
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res;
+ mp_digit buf, mp;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+ /* use a pointer to the reduction algorithm. This allows us to use
+ * one of many reduction algorithms without modding the guts of
+ * the code with if statements everywhere.
+ */
+ int (*redux)(mp_int*,mp_int*,mp_digit);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* determine and setup reduction code */
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+ /* now setup montgomery */
+ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+
+ /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+ if (((P->used * 2 + 1) < MP_WARRAY) &&
+ P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ redux = fast_mp_montgomery_reduce;
+ } else
+#endif
+ {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+ /* use slower baseline Montgomery method */
+ redux = mp_montgomery_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+ } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+ /* setup DR reduction for moduli of the form B**k - b */
+ mp_dr_setup(P, &mp);
+ redux = mp_dr_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+ /* setup DR reduction for moduli of the form 2**k - b */
+ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+ redux = mp_reduce_2k;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* create M table
+ *
+
+ *
+ * The first half of the table is not computed though accept for M[0] and M[1]
+ */
+
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ /* now we need R mod m */
+ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_RES;
+#endif
+
+ /* now set M[1] to G * R mod m */
+ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ } else {
+ mp_set(&res, 1);
+ if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* create upper table */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits so break */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int)DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* get next bit of the window */
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ if (redmode == 0) {
+ /* fixup result if Montgomery reduction is used
+ * recall that any value in a Montgomery system is
+ * actually multiplied by R mod n. So we have
+ * to reduce one more time to cancel out the factor
+ * of R.
+ */
+ if ((err = redux(&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* swap res with Y */
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
+
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_exteuclid.c b/dep/StormLib/src/libtommath/bn_mp_exteuclid.c
new file mode 100644
index 00000000000..9881d6edc80
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_exteuclid.c
@@ -0,0 +1,82 @@
+#include "tommath.h"
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Extended euclidean algorithm of (a, b) produces
+ a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+ mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+ int err;
+
+ if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+ return err;
+ }
+
+ /* initialize, (u1,u2,u3) = (1,0,a) */
+ mp_set(&u1, 1);
+ if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* initialize, (v1,v2,v3) = (0,1,b) */
+ mp_set(&v2, 1);
+ if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
+
+ /* loop while v3 != 0 */
+ while (mp_iszero(&v3) == MP_NO) {
+ /* q = u3/v3 */
+ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
+
+ /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
+
+ /* (u1,u2,u3) = (v1,v2,v3) */
+ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* (v1,v2,v3) = (t1,t2,t3) */
+ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
+ }
+
+ /* make sure U3 >= 0 */
+ if (u3.sign == MP_NEG) {
+ mp_neg(&u1, &u1);
+ mp_neg(&u2, &u2);
+ mp_neg(&u3, &u3);
+ }
+
+ /* copy result out */
+ if (U1 != NULL) { mp_exch(U1, &u1); }
+ if (U2 != NULL) { mp_exch(U2, &u2); }
+ if (U3 != NULL) { mp_exch(U3, &u3); }
+
+ err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_fread.c b/dep/StormLib/src/libtommath/bn_mp_fread.c
new file mode 100644
index 00000000000..2976b30aa68
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_fread.c
@@ -0,0 +1,67 @@
+#include "tommath.h"
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+ int err, ch, neg, y;
+
+ /* clear a */
+ mp_zero(a);
+
+ /* if first digit is - then set negative */
+ ch = fgetc(stream);
+ if (ch == '-') {
+ neg = MP_NEG;
+ ch = fgetc(stream);
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ for (;;) {
+ /* find y in the radix map */
+ for (y = 0; y < radix; y++) {
+ if (mp_s_rmap[y] == ch) {
+ break;
+ }
+ }
+ if (y == radix) {
+ break;
+ }
+
+ /* shift up and add */
+ if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+ return err;
+ }
+
+ ch = fgetc(stream);
+ }
+ if (mp_cmp_d(a, 0) != MP_EQ) {
+ a->sign = neg;
+ }
+
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_fwrite.c b/dep/StormLib/src/libtommath/bn_mp_fwrite.c
new file mode 100644
index 00000000000..6782b2e19f7
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_fwrite.c
@@ -0,0 +1,52 @@
+#include "tommath.h"
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+ char *buf;
+ int err, len, x;
+
+ if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+ return err;
+ }
+
+ buf = OPT_CAST(char) XMALLOC (len);
+ if (buf == NULL) {
+ return MP_MEM;
+ }
+
+ if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+ XFREE (buf);
+ return err;
+ }
+
+ for (x = 0; x < len; x++) {
+ if (fputc(buf[x], stream) == EOF) {
+ XFREE (buf);
+ return MP_VAL;
+ }
+ }
+
+ XFREE (buf);
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_gcd.c b/dep/StormLib/src/libtommath/bn_mp_gcd.c
new file mode 100644
index 00000000000..ce980eb6bb0
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_gcd.c
@@ -0,0 +1,105 @@
+#include "tommath.h"
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int u, v;
+ int k, u_lsb, v_lsb, res;
+
+ /* either zero than gcd is the largest */
+ if (mp_iszero (a) == MP_YES) {
+ return mp_abs (b, c);
+ }
+ if (mp_iszero (b) == MP_YES) {
+ return mp_abs (a, c);
+ }
+
+ /* get copies of a and b we can modify */
+ if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+ goto LBL_U;
+ }
+
+ /* must be positive for the remainder of the algorithm */
+ u.sign = v.sign = MP_ZPOS;
+
+ /* B1. Find the common power of two for u and v */
+ u_lsb = mp_cnt_lsb(&u);
+ v_lsb = mp_cnt_lsb(&v);
+ k = MIN(u_lsb, v_lsb);
+
+ if (k > 0) {
+ /* divide the power of two out */
+ if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* divide any remaining factors of two out */
+ if (u_lsb != k) {
+ if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ if (v_lsb != k) {
+ if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ while (mp_iszero(&v) == 0) {
+ /* make sure v is the largest */
+ if (mp_cmp_mag(&u, &v) == MP_GT) {
+ /* swap u and v to make sure v is >= u */
+ mp_exch(&u, &v);
+ }
+
+ /* subtract smallest from largest */
+ if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ /* Divide out all factors of two */
+ if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* multiply by 2**k which we divided out at the beginning */
+ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ c->sign = MP_ZPOS;
+ res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_get_int.c b/dep/StormLib/src/libtommath/bn_mp_get_int.c
new file mode 100644
index 00000000000..d9c76d0d15c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_get_int.c
@@ -0,0 +1,45 @@
+#include "tommath.h"
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a)
+{
+ int i;
+ unsigned long res;
+
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits of the lsb we have to read */
+ i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+ /* get most significant digit of result */
+ res = DIGIT(a,i);
+
+ while (--i >= 0) {
+ res = (res << DIGIT_BIT) | DIGIT(a,i);
+ }
+
+ /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+ return res & 0xFFFFFFFFUL;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_grow.c b/dep/StormLib/src/libtommath/bn_mp_grow.c
new file mode 100644
index 00000000000..a05dad73bc1
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_grow.c
@@ -0,0 +1,57 @@
+#include "tommath.h"
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+ int i;
+ mp_digit *tmp;
+
+ /* if the alloc size is smaller alloc more ram */
+ if (a->alloc < size) {
+ /* ensure there are always at least MP_PREC digits extra on top */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* reallocate the array a->dp
+ *
+ * We store the return in a temporary variable
+ * in case the operation failed we don't want
+ * to overwrite the dp member of a.
+ */
+ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+ if (tmp == NULL) {
+ /* reallocation failed but "a" is still valid [can be freed] */
+ return MP_MEM;
+ }
+
+ /* reallocation succeeded so set a->dp */
+ a->dp = tmp;
+
+ /* zero excess digits */
+ i = a->alloc;
+ a->alloc = size;
+ for (; i < a->alloc; i++) {
+ a->dp[i] = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init.c b/dep/StormLib/src/libtommath/bn_mp_init.c
new file mode 100644
index 00000000000..107d98be6e8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init.c
@@ -0,0 +1,46 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+ int i;
+
+ /* allocate memory required and clear it */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the digits to zero */
+ for (i = 0; i < MP_PREC; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* set the used to zero, allocated digits to the default precision
+ * and sign to positive */
+ a->used = 0;
+ a->alloc = MP_PREC;
+ a->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init_copy.c b/dep/StormLib/src/libtommath/bn_mp_init_copy.c
new file mode 100644
index 00000000000..3ca1186ce1d
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init_copy.c
@@ -0,0 +1,32 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_init (a)) != MP_OKAY) {
+ return res;
+ }
+ return mp_copy (b, a);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init_multi.c b/dep/StormLib/src/libtommath/bn_mp_init_multi.c
new file mode 100644
index 00000000000..4f6f367ffd5
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init_multi.c
@@ -0,0 +1,59 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...)
+{
+ mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
+ int n = 0; /* Number of ok inits */
+ mp_int* cur_arg = mp;
+ va_list args;
+
+ va_start(args, mp); /* init args to next argument from caller */
+ while (cur_arg != NULL) {
+ if (mp_init(cur_arg) != MP_OKAY) {
+ /* Oops - error! Back-track and mp_clear what we already
+ succeeded in init-ing, then return error.
+ */
+ va_list clean_args;
+
+ /* end the current list */
+ va_end(args);
+
+ /* now start cleaning up */
+ cur_arg = mp;
+ va_start(clean_args, mp);
+ while (n--) {
+ mp_clear(cur_arg);
+ cur_arg = va_arg(clean_args, mp_int*);
+ }
+ va_end(clean_args);
+ res = MP_MEM;
+ break;
+ }
+ n++;
+ cur_arg = va_arg(args, mp_int*);
+ }
+ va_end(args);
+ return res; /* Assumed ok, if error flagged above. */
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init_set.c b/dep/StormLib/src/libtommath/bn_mp_init_set.c
new file mode 100644
index 00000000000..853323f3aaa
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init_set.c
@@ -0,0 +1,32 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ mp_set(a, b);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init_set_int.c b/dep/StormLib/src/libtommath/bn_mp_init_set_int.c
new file mode 100644
index 00000000000..b2f8727e336
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init_set_int.c
@@ -0,0 +1,31 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ return mp_set_int(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_init_size.c b/dep/StormLib/src/libtommath/bn_mp_init_size.c
new file mode 100644
index 00000000000..17b8d9fceb0
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_init_size.c
@@ -0,0 +1,48 @@
+#include "tommath.h"
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+ int x;
+
+ /* pad size so there are always extra digits */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* alloc mem */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the members */
+ a->used = 0;
+ a->alloc = size;
+ a->sign = MP_ZPOS;
+
+ /* zero the digits */
+ for (x = 0; x < size; x++) {
+ a->dp[x] = 0;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_invmod.c b/dep/StormLib/src/libtommath/bn_mp_invmod.c
new file mode 100644
index 00000000000..038e584a25c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_invmod.c
@@ -0,0 +1,43 @@
+#include "tommath.h"
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+#ifdef BN_FAST_MP_INVMOD_C
+ /* if the modulus is odd we can use a faster routine instead */
+ if (mp_isodd (b) == 1) {
+ return fast_mp_invmod (a, b, c);
+ }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+ return mp_invmod_slow(a, b, c);
+#endif
+
+ return MP_VAL;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_invmod_slow.c b/dep/StormLib/src/libtommath/bn_mp_invmod_slow.c
new file mode 100644
index 00000000000..3792a4c2333
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_invmod_slow.c
@@ -0,0 +1,175 @@
+#include "tommath.h"
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, A, B, C, D;
+ int res;
+
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v,
+ &A, &B, &C, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x = a, y = b */
+ if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 2. [modified] if x,y are both even then return an error! */
+ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&A, 1);
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if A or B is odd then */
+ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+ /* A = (A+y)/2, B = (B-x)/2 */
+ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* A = A/2, B = B/2 */
+ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if C or D is odd then */
+ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+ /* C = (C+y)/2, D = (D-x)/2 */
+ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* C = C/2, D = D/2 */
+ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, A = A - C, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, C = C - A, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0)
+ goto top;
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* if its too low */
+ while (mp_cmp_d(&C, 0) == MP_LT) {
+ if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* too big */
+ while (mp_cmp_mag(&C, b) != MP_LT) {
+ if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* C is now the inverse */
+ mp_exch (&C, c);
+ res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_is_square.c b/dep/StormLib/src/libtommath/bn_mp_is_square.c
new file mode 100644
index 00000000000..5d2fa072ce9
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_is_square.c
@@ -0,0 +1,109 @@
+#include "tommath.h"
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret)
+{
+ int res;
+ mp_digit c;
+ mp_int t;
+ unsigned long r;
+
+ /* Default to Non-square :) */
+ *ret = MP_NO;
+
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* digits used? (TSD) */
+ if (arg->used == 0) {
+ return MP_OKAY;
+ }
+
+ /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+ if (rem_128[127 & DIGIT(arg,0)] == 1) {
+ return MP_OKAY;
+ }
+
+ /* Next check mod 105 (3*5*7) */
+ if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+ return res;
+ }
+ if (rem_105[c] == 1) {
+ return MP_OKAY;
+ }
+
+
+ if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ r = mp_get_int(&t);
+ /* Check for other prime modules, note it's not an ERROR but we must
+ * free "t" so the easiest way is to goto ERR. We know that res
+ * is already equal to MP_OKAY from the mp_mod call
+ */
+ if ( (1L<<(r%11)) & 0x5C4L ) goto ERR;
+ if ( (1L<<(r%13)) & 0x9E4L ) goto ERR;
+ if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR;
+ if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR;
+ if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR;
+ if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR;
+ if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR;
+
+ /* Final check - is sqr(sqrt(arg)) == arg ? */
+ if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_jacobi.c b/dep/StormLib/src/libtommath/bn_mp_jacobi.c
new file mode 100644
index 00000000000..c70b946f316
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_jacobi.c
@@ -0,0 +1,105 @@
+#include "tommath.h"
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+ mp_int a1, p1;
+ int k, s, r, res;
+ mp_digit residue;
+
+ /* if p <= 0 return MP_VAL */
+ if (mp_cmp_d(p, 0) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* step 1. if a == 0, return 0 */
+ if (mp_iszero (a) == 1) {
+ *c = 0;
+ return MP_OKAY;
+ }
+
+ /* step 2. if a == 1, return 1 */
+ if (mp_cmp_d (a, 1) == MP_EQ) {
+ *c = 1;
+ return MP_OKAY;
+ }
+
+ /* default */
+ s = 0;
+
+ /* step 3. write a = a1 * 2**k */
+ if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&p1)) != MP_OKAY) {
+ goto LBL_A1;
+ }
+
+ /* divide out larger power of two */
+ k = mp_cnt_lsb(&a1);
+ if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+
+ /* step 4. if e is even set s=1 */
+ if ((k & 1) == 0) {
+ s = 1;
+ } else {
+ /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+ residue = p->dp[0] & 7;
+
+ if (residue == 1 || residue == 7) {
+ s = 1;
+ } else if (residue == 3 || residue == 5) {
+ s = -1;
+ }
+ }
+
+ /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+ if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+ s = -s;
+ }
+
+ /* if a1 == 1 we're done */
+ if (mp_cmp_d (&a1, 1) == MP_EQ) {
+ *c = s;
+ } else {
+ /* n1 = n mod a1 */
+ if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ *c = s * r;
+ }
+
+ /* done */
+ res = MP_OKAY;
+LBL_P1:mp_clear (&p1);
+LBL_A1:mp_clear (&a1);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_karatsuba_mul.c b/dep/StormLib/src/libtommath/bn_mp_karatsuba_mul.c
new file mode 100644
index 00000000000..b15ec24966b
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_karatsuba_mul.c
@@ -0,0 +1,167 @@
+#include "tommath.h"
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* c = |a| * |b| using Karatsuba Multiplication using
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and
+ * let n represent half of the number of digits in
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b =>
+ a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be
+ * computed once. So in total three half size (half # of
+ * digit) multiplications are performed, a0b0, a1b1 and
+ * (a1+b1)(a0+b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in
+ * total after one call 25% of the single precision multiplications
+ * are saved. Note also that the call to mp_mul can end up back
+ * in this function if the a0, a1, b0, or b1 are above the threshold.
+ * This is known as divide-and-conquer and leads to the famous
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
+ * the standard O(N**2) that the baseline/comba methods use.
+ * Generally though the overhead of this method doesn't pay off
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
+ int B, err;
+
+ /* default the return code to an error */
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = MIN (a->used, b->used);
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+ if (mp_init_size (&y0, B) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+ goto Y0;
+
+ /* init temps */
+ if (mp_init_size (&t1, B * 2) != MP_OKAY)
+ goto Y1;
+ if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+ goto X0Y0;
+
+ /* now shift the digits */
+ x0.used = y0.used = B;
+ x1.used = a->used - B;
+ y1.used = b->used - B;
+
+ {
+ register int x;
+ register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+ /* we copy the digits directly instead of using higher level functions
+ * since we also need to shift the digits
+ */
+ tmpa = a->dp;
+ tmpb = b->dp;
+
+ tmpx = x0.dp;
+ tmpy = y0.dp;
+ for (x = 0; x < B; x++) {
+ *tmpx++ = *tmpa++;
+ *tmpy++ = *tmpb++;
+ }
+
+ tmpx = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *tmpx++ = *tmpa++;
+ }
+
+ tmpy = y1.dp;
+ for (x = B; x < b->used; x++) {
+ *tmpy++ = *tmpb++;
+ }
+ }
+
+ /* only need to clamp the lower words since by definition the
+ * upper words x1/y1 must have a known number of digits
+ */
+ mp_clamp (&x0);
+ mp_clamp (&y0);
+
+ /* now calc the products x0y0 and x1y1 */
+ /* after this x0 is no longer required, free temp [x0==t2]! */
+ if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
+ goto X1Y1; /* x0y0 = x0*y0 */
+ if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1*y1 */
+
+ /* now calc x1+x0 and y1+y0 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x1 - x0 */
+ if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = y1 - y0 */
+ if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
+
+ /* add x0y0 */
+ if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = x0y0 + x1y1 */
+ if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1y1 << 2*B */
+
+ if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 */
+ if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
+
+ /* Algorithm succeeded set the return code to MP_OKAY */
+ err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_mul.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c b/dep/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c
new file mode 100644
index 00000000000..b3a45abf70e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c
@@ -0,0 +1,121 @@
+#include "tommath.h"
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Karatsuba squaring, computes b = a*a using three
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details. It
+ * is essentially the same algorithm but merely
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+ mp_int x0, x1, t1, t2, x0x0, x1x1;
+ int B, err;
+
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = a->used;
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+
+ /* init temps */
+ if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+ goto T2;
+ if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+ goto X0X0;
+
+ {
+ register int x;
+ register mp_digit *dst, *src;
+
+ src = a->dp;
+
+ /* now shift the digits */
+ dst = x0.dp;
+ for (x = 0; x < B; x++) {
+ *dst++ = *src++;
+ }
+
+ dst = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *dst++ = *src++;
+ }
+ }
+
+ x0.used = B;
+ x1.used = a->used - B;
+
+ mp_clamp (&x0);
+
+ /* now calc the products x0*x0 and x1*x1 */
+ if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+ goto X1X1; /* x0x0 = x0*x0 */
+ if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1*x1 */
+
+ /* now calc (x1+x0)**2 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x1 - x0 */
+ if (mp_sqr (&t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
+
+ /* add x0y0 */
+ if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+ goto X1X1; /* t2 = x0x0 + x1x1 */
+ if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+ if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1x1 << 2*B */
+
+ if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 */
+ if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
+
+ err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_sqr.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_lcm.c b/dep/StormLib/src/libtommath/bn_mp_lcm.c
new file mode 100644
index 00000000000..af7ae23729e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_lcm.c
@@ -0,0 +1,60 @@
+#include "tommath.h"
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t1, t2;
+
+
+ if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* t1 = get the GCD of the two inputs */
+ if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* divide the smallest by the GCD */
+ if (mp_cmp_mag(a, b) == MP_LT) {
+ /* store quotient in t2 such that t2 * b is the LCM */
+ if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(b, &t2, c);
+ } else {
+ /* store quotient in t2 such that t2 * a is the LCM */
+ if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(a, &t2, c);
+ }
+
+ /* fix the sign to positive */
+ c->sign = MP_ZPOS;
+
+LBL_T:
+ mp_clear_multi (&t1, &t2, NULL);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_lshd.c b/dep/StormLib/src/libtommath/bn_mp_lshd.c
new file mode 100644
index 00000000000..ffb0defd06b
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_lshd.c
@@ -0,0 +1,67 @@
+#include "tommath.h"
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+ int x, res;
+
+ /* if its less than zero return */
+ if (b <= 0) {
+ return MP_OKAY;
+ }
+
+ /* grow to fit the new digits */
+ if (a->alloc < a->used + b) {
+ if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ {
+ register mp_digit *top, *bottom;
+
+ /* increment the used by the shift amount then copy upwards */
+ a->used += b;
+
+ /* top */
+ top = a->dp + a->used - 1;
+
+ /* base */
+ bottom = a->dp + a->used - 1 - b;
+
+ /* much like mp_rshd this is implemented using a sliding window
+ * except the window goes the otherway around. Copying from
+ * the bottom to the top. see bn_mp_rshd.c for more info.
+ */
+ for (x = a->used - 1; x >= b; x--) {
+ *top-- = *bottom--;
+ }
+
+ /* zero the lower digits */
+ top = a->dp;
+ for (x = 0; x < b; x++) {
+ *top++ = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mod.c b/dep/StormLib/src/libtommath/bn_mp_mod.c
new file mode 100644
index 00000000000..b24c71f9d95
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mod.c
@@ -0,0 +1,48 @@
+#include "tommath.h"
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int t;
+ int res;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ if (t.sign != b->sign) {
+ res = mp_add (b, &t, c);
+ } else {
+ res = MP_OKAY;
+ mp_exch (&t, c);
+ }
+
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mod_2d.c b/dep/StormLib/src/libtommath/bn_mp_mod_2d.c
new file mode 100644
index 00000000000..a54a0242644
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mod_2d.c
@@ -0,0 +1,55 @@
+#include "tommath.h"
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+ int x, res;
+
+ /* if b is <= 0 then zero the int */
+ if (b <= 0) {
+ mp_zero (c);
+ return MP_OKAY;
+ }
+
+ /* if the modulus is larger than the value than return */
+ if (b >= (int) (a->used * DIGIT_BIT)) {
+ res = mp_copy (a, c);
+ return res;
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+
+ /* zero digits above the last digit of the modulus */
+ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+ c->dp[x] = 0;
+ }
+ /* clear the digit that is not completely outside/inside the modulus */
+ c->dp[b / DIGIT_BIT] &=
+ (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mod_d.c b/dep/StormLib/src/libtommath/bn_mp_mod_d.c
new file mode 100644
index 00000000000..59886e7734a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mod_d.c
@@ -0,0 +1,27 @@
+#include "tommath.h"
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+ return mp_div_d(a, b, NULL, c);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c b/dep/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c
new file mode 100644
index 00000000000..fdefcbd99d2
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c
@@ -0,0 +1,59 @@
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+ int x, bits, res;
+
+ /* how many bits of last digit does b use */
+ bits = mp_count_bits (b) % DIGIT_BIT;
+
+ if (b->used > 1) {
+ if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ mp_set(a, 1);
+ bits = 1;
+ }
+
+
+ /* now compute C = A * B mod b */
+ for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+ if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+ return res;
+ }
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+ return res;
+ }
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_montgomery_reduce.c b/dep/StormLib/src/libtommath/bn_mp_montgomery_reduce.c
new file mode 100644
index 00000000000..173848e0ac8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_montgomery_reduce.c
@@ -0,0 +1,118 @@
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, digs;
+ mp_digit mu;
+
+ /* can the fast reduction [comba] method be used?
+ *
+ * Note that unlike in mul you're safely allowed *less*
+ * than the available columns [255 per default] since carries
+ * are fixed up in the inner loop.
+ */
+ digs = n->used * 2 + 1;
+ if ((digs < MP_WARRAY) &&
+ n->used <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_mp_montgomery_reduce (x, n, rho);
+ }
+
+ /* grow the input as required */
+ if (x->alloc < digs) {
+ if ((res = mp_grow (x, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+ x->used = digs;
+
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * rho mod b
+ *
+ * The value of rho must be precalculated via
+ * montgomery_setup() such that
+ * it equals -1/n0 mod b this allows the
+ * following inner loop to reduce the
+ * input one digit at a time
+ */
+ mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i */
+ {
+ register int iy;
+ register mp_digit *tmpn, *tmpx, u;
+ register mp_word r;
+
+ /* alias for digits of the modulus */
+ tmpn = n->dp;
+
+ /* alias for the digits of x [the input] */
+ tmpx = x->dp + ix;
+
+ /* set the carry to zero */
+ u = 0;
+
+ /* Multiply and add in place */
+ for (iy = 0; iy < n->used; iy++) {
+ /* compute product and sum */
+ r = ((mp_word)mu) * ((mp_word)*tmpn++) +
+ ((mp_word) u) + ((mp_word) * tmpx);
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* fix digit */
+ *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+ }
+ /* At this point the ix'th digit of x should be zero */
+
+
+ /* propagate carries upwards as required*/
+ while (u) {
+ *tmpx += u;
+ u = *tmpx >> DIGIT_BIT;
+ *tmpx++ &= MP_MASK;
+ }
+ }
+ }
+
+ /* at this point the n.used'th least
+ * significant digits of x are all zero
+ * which means we can shift x to the
+ * right by n.used digits and the
+ * residue is unchanged.
+ */
+
+ /* x = x/b**n.used */
+ mp_clamp(x);
+ mp_rshd (x, n->used);
+
+ /* if x >= n then x = x - n */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_montgomery_setup.c b/dep/StormLib/src/libtommath/bn_mp_montgomery_setup.c
new file mode 100644
index 00000000000..6f277320eb7
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_montgomery_setup.c
@@ -0,0 +1,59 @@
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+ mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
+ * => 2*X*A - X*X*A*A = 1
+ * => 2*(1) - (1) = 1
+ */
+ b = n->dp[0];
+
+ if ((b & 1) == 0) {
+ return MP_VAL;
+ }
+
+ x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+ x *= 2 - b * x; /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+ x *= 2 - b * x; /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+ x *= 2 - b * x; /* here x*a==1 mod 2**64 */
+#endif
+
+ /* rho = -1/m mod b */
+ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mul.c b/dep/StormLib/src/libtommath/bn_mp_mul.c
new file mode 100644
index 00000000000..a1315dac30c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mul.c
@@ -0,0 +1,66 @@
+#include "tommath.h"
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, neg;
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+ /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+ res = mp_toom_mul(a, b, c);
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+ /* use Karatsuba? */
+ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+ res = mp_karatsuba_mul (a, b, c);
+ } else
+#endif
+ {
+ /* can we use the fast multiplier?
+ *
+ * The fast multiplier can be used if the output will
+ * have less than MP_WARRAY digits and the number of
+ * digits won't affect carry propagation
+ */
+ int digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+ if ((digs < MP_WARRAY) &&
+ MIN(a->used, b->used) <=
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ res = fast_s_mp_mul_digs (a, b, c, digs);
+ } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+ res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+ res = MP_VAL;
+#endif
+
+ }
+ c->sign = (c->used > 0) ? neg : MP_ZPOS;
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mul_2.c b/dep/StormLib/src/libtommath/bn_mp_mul_2.c
new file mode 100644
index 00000000000..3315744f1ec
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mul_2.c
@@ -0,0 +1,82 @@
+#include "tommath.h"
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* grow to accomodate result */
+ if (b->alloc < a->used + 1) {
+ if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* alias for source */
+ tmpa = a->dp;
+
+ /* alias for dest */
+ tmpb = b->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < a->used; x++) {
+
+ /* get what will be the *next* carry bit from the
+ * MSB of the current digit
+ */
+ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+ /* now shift up this digit, add in the carry [from the previous] */
+ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+ /* copy the carry that would be from the source
+ * digit into the next iteration
+ */
+ r = rr;
+ }
+
+ /* new leading digit? */
+ if (r != 0) {
+ /* add a MSB which is always 1 at this point */
+ *tmpb = 1;
+ ++(b->used);
+ }
+
+ /* now zero any excess digits on the destination
+ * that we didn't write to
+ */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mul_2d.c b/dep/StormLib/src/libtommath/bn_mp_mul_2d.c
new file mode 100644
index 00000000000..c636c179884
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mul_2d.c
@@ -0,0 +1,85 @@
+#include "tommath.h"
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+ mp_digit d;
+ int res;
+
+ /* copy */
+ if (a != c) {
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+ if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ d = (mp_digit) (b % DIGIT_BIT);
+ if (d != 0) {
+ register mp_digit *tmpc, shift, mask, r, rr;
+ register int x;
+
+ /* bitmask for carries */
+ mask = (((mp_digit)1) << d) - 1;
+
+ /* shift for msbs */
+ shift = DIGIT_BIT - d;
+
+ /* alias */
+ tmpc = c->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < c->used; x++) {
+ /* get the higher bits of the current word */
+ rr = (*tmpc >> shift) & mask;
+
+ /* shift the current word and OR in the carry */
+ *tmpc = ((*tmpc << d) | r) & MP_MASK;
+ ++tmpc;
+
+ /* set the carry to the carry bits of the current word */
+ r = rr;
+ }
+
+ /* set final carry */
+ if (r != 0) {
+ c->dp[(c->used)++] = r;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mul_d.c b/dep/StormLib/src/libtommath/bn_mp_mul_d.c
new file mode 100644
index 00000000000..a36a76bbacf
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mul_d.c
@@ -0,0 +1,79 @@
+#include "tommath.h"
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit u, *tmpa, *tmpc;
+ mp_word r;
+ int ix, res, olduse;
+
+ /* make sure c is big enough to hold a*b */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get the original destinations used count */
+ olduse = c->used;
+
+ /* set the sign */
+ c->sign = a->sign;
+
+ /* alias for a->dp [source] */
+ tmpa = a->dp;
+
+ /* alias for c->dp [dest] */
+ tmpc = c->dp;
+
+ /* zero carry */
+ u = 0;
+
+ /* compute columns */
+ for (ix = 0; ix < a->used; ix++) {
+ /* compute product and carry sum for this term */
+ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+ /* mask off higher bits to get a single digit */
+ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* send carry into next iteration */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+
+ /* store final carry [if any] and increment ix offset */
+ *tmpc++ = u;
+ ++ix;
+
+ /* now zero digits above the top */
+ while (ix++ < olduse) {
+ *tmpc++ = 0;
+ }
+
+ /* set used count */
+ c->used = a->used + 1;
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_mulmod.c b/dep/StormLib/src/libtommath/bn_mp_mulmod.c
new file mode 100644
index 00000000000..8ec98bbddb2
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_mulmod.c
@@ -0,0 +1,40 @@
+#include "tommath.h"
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_n_root.c b/dep/StormLib/src/libtommath/bn_mp_n_root.c
new file mode 100644
index 00000000000..f188f5255b3
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_n_root.c
@@ -0,0 +1,132 @@
+#include "tommath.h"
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* find the n'th root of an integer
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a
+ *
+ * This algorithm uses Newton's approximation
+ * x[i+1] = x[i] - f(x[i])/f'(x[i])
+ * which will find the root in log(N) time where
+ * each step involves a fair bit. This is not meant to
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_int t1, t2, t3;
+ int res, neg;
+
+ /* input must be positive if b is even */
+ if ((b & 1) == 0 && a->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init (&t3)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ /* if a is negative fudge the sign but keep track */
+ neg = a->sign;
+ a->sign = MP_ZPOS;
+
+ /* t2 = 2 */
+ mp_set (&t2, 2);
+
+ do {
+ /* t1 = t2 */
+ if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+
+ /* t3 = t1**(b-1) */
+ if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* numerator */
+ /* t2 = t1**b */
+ if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1**b - a */
+ if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* denominator */
+ /* t3 = t1**(b-1) * b */
+ if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+ if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } while (mp_cmp (&t1, &t2) != MP_EQ);
+
+ /* result can be off by a few so check */
+ for (;;) {
+ if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if (mp_cmp (&t2, a) == MP_GT) {
+ if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* reset the sign of a first */
+ a->sign = neg;
+
+ /* set the result */
+ mp_exch (&t1, c);
+
+ /* set the sign of the result */
+ c->sign = neg;
+
+ res = MP_OKAY;
+
+LBL_T3:mp_clear (&t3);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_neg.c b/dep/StormLib/src/libtommath/bn_mp_neg.c
new file mode 100644
index 00000000000..87a8b500449
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_neg.c
@@ -0,0 +1,40 @@
+#include "tommath.h"
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+ int res;
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (mp_iszero(b) != MP_YES) {
+ b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ } else {
+ b->sign = MP_ZPOS;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_or.c b/dep/StormLib/src/libtommath/bn_mp_or.c
new file mode 100644
index 00000000000..12601eaf78e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_or.c
@@ -0,0 +1,50 @@
+#include "tommath.h"
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] |= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_fermat.c b/dep/StormLib/src/libtommath/bn_mp_prime_fermat.c
new file mode 100644
index 00000000000..297e13c7960
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_fermat.c
@@ -0,0 +1,62 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* performs one Fermat test.
+ *
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1. That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+ mp_int t;
+ int err;
+
+ /* default to composite */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* init t */
+ if ((err = mp_init (&t)) != MP_OKAY) {
+ return err;
+ }
+
+ /* compute t = b**a mod a */
+ if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* is it equal to b? */
+ if (mp_cmp (&t, b) == MP_EQ) {
+ *result = MP_YES;
+ }
+
+ err = MP_OKAY;
+LBL_T:mp_clear (&t);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_is_divisible.c b/dep/StormLib/src/libtommath/bn_mp_prime_is_divisible.c
new file mode 100644
index 00000000000..0ae64983512
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_is_divisible.c
@@ -0,0 +1,50 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines if an integers is divisible by one
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+ int err, ix;
+ mp_digit res;
+
+ /* default to not */
+ *result = MP_NO;
+
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ /* what is a mod LBL_prime_tab[ix] */
+ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* is the residue zero? */
+ if (res == 0) {
+ *result = MP_YES;
+ return MP_OKAY;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_is_prime.c b/dep/StormLib/src/libtommath/bn_mp_prime_is_prime.c
new file mode 100644
index 00000000000..0e1e94bad5b
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_is_prime.c
@@ -0,0 +1,83 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+ mp_int b;
+ int ix, err, res;
+
+ /* default to no */
+ *result = MP_NO;
+
+ /* valid value of t? */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* is the input equal to one of the primes in the table? */
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+ *result = 1;
+ return MP_OKAY;
+ }
+ }
+
+ /* first perform trial division */
+ if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* return if it was trivially divisible */
+ if (res == MP_YES) {
+ return MP_OKAY;
+ }
+
+ /* now perform the miller-rabin rounds */
+ if ((err = mp_init (&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (ix = 0; ix < t; ix++) {
+ /* set the prime */
+ mp_set (&b, ltm_prime_tab[ix]);
+
+ if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if (res == MP_NO) {
+ goto LBL_B;
+ }
+ }
+
+ /* passed the test */
+ *result = MP_YES;
+LBL_B:mp_clear (&b);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c b/dep/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c
new file mode 100644
index 00000000000..47385bc815c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c
@@ -0,0 +1,103 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+ mp_int n1, y, r;
+ int s, j, err;
+
+ /* default */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* get n1 = a - 1 */
+ if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* set 2**s * r = n1 */
+ if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* count the number of least significant bits
+ * which are zero
+ */
+ s = mp_cnt_lsb(&r);
+
+ /* now divide n - 1 by 2**s */
+ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+ goto LBL_R;
+ }
+
+ /* compute y = b**r mod a */
+ if ((err = mp_init (&y)) != MP_OKAY) {
+ goto LBL_R;
+ }
+ if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y != 1 and y != n1 do */
+ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+ j = 1;
+ /* while j <= s-1 and y != n1 */
+ while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+ if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y == 1 then composite */
+ if (mp_cmp_d (&y, 1) == MP_EQ) {
+ goto LBL_Y;
+ }
+
+ ++j;
+ }
+
+ /* if y != n1 then composite */
+ if (mp_cmp (&y, &n1) != MP_EQ) {
+ goto LBL_Y;
+ }
+ }
+
+ /* probably prime now */
+ *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_next_prime.c b/dep/StormLib/src/libtommath/bn_mp_prime_next_prime.c
new file mode 100644
index 00000000000..833992bac48
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_next_prime.c
@@ -0,0 +1,170 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+ int err, res, x, y;
+ mp_digit res_tab[PRIME_SIZE], step, kstep;
+ mp_int b;
+
+ /* ensure t is valid */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* force positive */
+ a->sign = MP_ZPOS;
+
+ /* simple algo if a is less than the largest prime in the table */
+ if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+ /* find which prime it is bigger than */
+ for (x = PRIME_SIZE - 2; x >= 0; x--) {
+ if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+ if (bbs_style == 1) {
+ /* ok we found a prime smaller or
+ * equal [so the next is larger]
+ *
+ * however, the prime must be
+ * congruent to 3 mod 4
+ */
+ if ((ltm_prime_tab[x + 1] & 3) != 3) {
+ /* scan upwards for a prime congruent to 3 mod 4 */
+ for (y = x + 1; y < PRIME_SIZE; y++) {
+ if ((ltm_prime_tab[y] & 3) == 3) {
+ mp_set(a, ltm_prime_tab[y]);
+ return MP_OKAY;
+ }
+ }
+ }
+ } else {
+ mp_set(a, ltm_prime_tab[x + 1]);
+ return MP_OKAY;
+ }
+ }
+ }
+ /* at this point a maybe 1 */
+ if (mp_cmp_d(a, 1) == MP_EQ) {
+ mp_set(a, 2);
+ return MP_OKAY;
+ }
+ /* fall through to the sieve */
+ }
+
+ /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+ if (bbs_style == 1) {
+ kstep = 4;
+ } else {
+ kstep = 2;
+ }
+
+ /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+ if (bbs_style == 1) {
+ /* if a mod 4 != 3 subtract the correct value to make it so */
+ if ((a->dp[0] & 3) != 3) {
+ if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+ }
+ } else {
+ if (mp_iseven(a) == 1) {
+ /* force odd */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+ return err;
+ }
+ }
+ }
+
+ /* generate the restable */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+ /* init temp used for Miller-Rabin Testing */
+ if ((err = mp_init(&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (;;) {
+ /* skip to the next non-trivially divisible candidate */
+ step = 0;
+ do {
+ /* y == 1 if any residue was zero [e.g. cannot be prime] */
+ y = 0;
+
+ /* increase step to next candidate */
+ step += kstep;
+
+ /* compute the new residue without using division */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ /* add the step to each residue */
+ res_tab[x] += kstep;
+
+ /* subtract the modulus [instead of using division] */
+ if (res_tab[x] >= ltm_prime_tab[x]) {
+ res_tab[x] -= ltm_prime_tab[x];
+ }
+
+ /* set flag if zero */
+ if (res_tab[x] == 0) {
+ y = 1;
+ }
+ }
+ } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+ /* add the step */
+ if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* if didn't pass sieve and step == MAX then skip test */
+ if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+ continue;
+ }
+
+ /* is this prime? */
+ for (x = 0; x < t; x++) {
+ mp_set(&b, ltm_prime_tab[t]);
+ if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if (res == MP_NO) {
+ break;
+ }
+ }
+
+ if (res == MP_YES) {
+ break;
+ }
+ }
+
+ err = MP_OKAY;
+LBL_ERR:
+ mp_clear(&b);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_next_prime.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c b/dep/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c
new file mode 100644
index 00000000000..3f7608aa7f3
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c
@@ -0,0 +1,52 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+
+static const struct {
+ int k, t;
+} sizes[] = {
+{ 128, 28 },
+{ 256, 16 },
+{ 384, 10 },
+{ 512, 7 },
+{ 640, 6 },
+{ 768, 5 },
+{ 896, 4 },
+{ 1024, 4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+ if (sizes[x].k == size) {
+ return sizes[x].t;
+ } else if (sizes[x].k > size) {
+ return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+ }
+ }
+ return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_prime_random_ex.c b/dep/StormLib/src/libtommath/bn_mp_prime_random_ex.c
new file mode 100644
index 00000000000..4eec3f69e3e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_prime_random_ex.c
@@ -0,0 +1,125 @@
+#include "tommath.h"
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+ unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+ int res, err, bsize, maskOR_msb_offset;
+
+ /* sanity check the input */
+ if (size <= 1 || t <= 0) {
+ return MP_VAL;
+ }
+
+ /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+ if (flags & LTM_PRIME_SAFE) {
+ flags |= LTM_PRIME_BBS;
+ }
+
+ /* calc the byte size */
+ bsize = (size>>3) + ((size&7)?1:0);
+
+ /* we need a buffer of bsize bytes */
+ tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+ if (tmp == NULL) {
+ return MP_MEM;
+ }
+
+ /* calc the maskAND value for the MSbyte*/
+ maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
+
+ /* calc the maskOR_msb */
+ maskOR_msb = 0;
+ maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+ if (flags & LTM_PRIME_2MSB_ON) {
+ maskOR_msb |= 0x80 >> ((9 - size) & 7);
+ }
+
+ /* get the maskOR_lsb */
+ maskOR_lsb = 1;
+ if (flags & LTM_PRIME_BBS) {
+ maskOR_lsb |= 3;
+ }
+
+ do {
+ /* read the bytes */
+ if (cb(tmp, bsize, dat) != bsize) {
+ err = MP_VAL;
+ goto error;
+ }
+
+ /* work over the MSbyte */
+ tmp[0] &= maskAND;
+ tmp[0] |= 1 << ((size - 1) & 7);
+
+ /* mix in the maskORs */
+ tmp[maskOR_msb_offset] |= maskOR_msb;
+ tmp[bsize-1] |= maskOR_lsb;
+
+ /* read it in */
+ if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ if (res == MP_NO) {
+ continue;
+ }
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* see if (a-1)/2 is prime */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ }
+ } while (res == MP_NO);
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* restore a to the original value */
+ if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
+ }
+
+ err = MP_OKAY;
+error:
+ XFREE(tmp);
+ return err;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_radix_size.c b/dep/StormLib/src/libtommath/bn_mp_radix_size.c
new file mode 100644
index 00000000000..2378f1fc1ac
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_radix_size.c
@@ -0,0 +1,78 @@
+#include "tommath.h"
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+
+ *size = 0;
+
+ /* special case for binary */
+ if (radix == 2) {
+ *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+ return MP_OKAY;
+ }
+
+ /* make sure the radix is in range */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ if (mp_iszero(a) == MP_YES) {
+ *size = 2;
+ return MP_OKAY;
+ }
+
+ /* digs is the digit count */
+ digs = 0;
+
+ /* if it's negative add one for the sign */
+ if (a->sign == MP_NEG) {
+ ++digs;
+ }
+
+ /* init a copy of the input */
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* force temp to positive */
+ t.sign = MP_ZPOS;
+
+ /* fetch out all of the digits */
+ while (mp_iszero (&t) == MP_NO) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ ++digs;
+ }
+ mp_clear (&t);
+
+ /* return digs + 1, the 1 is for the NULL byte that would be required. */
+ *size = digs + 1;
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_radix_smap.c b/dep/StormLib/src/libtommath/bn_mp_radix_smap.c
new file mode 100644
index 00000000000..5cbe9520b5b
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_radix_smap.c
@@ -0,0 +1,24 @@
+#include "tommath.h"
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_rand.c b/dep/StormLib/src/libtommath/bn_mp_rand.c
new file mode 100644
index 00000000000..e1241785e88
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_rand.c
@@ -0,0 +1,55 @@
+#include "tommath.h"
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+ int res;
+ mp_digit d;
+
+ mp_zero (a);
+ if (digits <= 0) {
+ return MP_OKAY;
+ }
+
+ /* first place a random non-zero digit */
+ do {
+ d = ((mp_digit) abs (rand ())) & MP_MASK;
+ } while (d == 0);
+
+ if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+ return res;
+ }
+
+ while (--digits > 0) {
+ if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_read_radix.c b/dep/StormLib/src/libtommath/bn_mp_read_radix.c
new file mode 100644
index 00000000000..6869668fb88
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_read_radix.c
@@ -0,0 +1,85 @@
+#include "tommath.h"
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+ int y, res, neg;
+ char ch;
+
+ /* zero the digit bignum */
+ mp_zero(a);
+
+ /* make sure the radix is ok */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* if the leading digit is a
+ * minus set the sign to negative.
+ */
+ if (*str == '-') {
+ ++str;
+ neg = MP_NEG;
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ /* set the integer to the default of zero */
+ mp_zero (a);
+
+ /* process each digit of the string */
+ while (*str) {
+ /* if the radix < 36 the conversion is case insensitive
+ * this allows numbers like 1AB and 1ab to represent the same value
+ * [e.g. in hex]
+ */
+ ch = (char) ((radix < 36) ? toupper (*str) : *str);
+ for (y = 0; y < 64; y++) {
+ if (ch == mp_s_rmap[y]) {
+ break;
+ }
+ }
+
+ /* if the char was found in the map
+ * and is less than the given radix add it
+ * to the number, otherwise exit the loop.
+ */
+ if (y < radix) {
+ if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ break;
+ }
+ ++str;
+ }
+
+ /* set the sign only if a != 0 */
+ if (mp_iszero(a) != 1) {
+ a->sign = neg;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_read_signed_bin.c b/dep/StormLib/src/libtommath/bn_mp_read_signed_bin.c
new file mode 100644
index 00000000000..e9a780c28aa
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_read_signed_bin.c
@@ -0,0 +1,41 @@
+#include "tommath.h"
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* read magnitude */
+ if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* first byte is 0 for positive, non-zero for negative */
+ if (b[0] == 0) {
+ a->sign = MP_ZPOS;
+ } else {
+ a->sign = MP_NEG;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c b/dep/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c
new file mode 100644
index 00000000000..7d35370418c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c
@@ -0,0 +1,55 @@
+#include "tommath.h"
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* make sure there are at least two digits */
+ if (a->alloc < 2) {
+ if ((res = mp_grow(a, 2)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero the int */
+ mp_zero (a);
+
+ /* read the bytes in */
+ while (c-- > 0) {
+ if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+ return res;
+ }
+
+#ifndef MP_8BIT
+ a->dp[0] |= *b++;
+ a->used += 1;
+#else
+ a->dp[0] = (*b & MP_MASK);
+ a->dp[1] |= ((*b++ >> 7U) & 1);
+ a->used += 2;
+#endif
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce.c b/dep/StormLib/src/libtommath/bn_mp_reduce.c
new file mode 100644
index 00000000000..3a6bb5aca90
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce.c
@@ -0,0 +1,100 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+ mp_int q;
+ int res, um = m->used;
+
+ /* q = x */
+ if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+ return res;
+ }
+
+ /* q1 = x / b**(k-1) */
+ mp_rshd (&q, um - 1);
+
+ /* according to HAC this optimization is ok */
+ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+ if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+ if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#else
+ {
+ res = MP_VAL;
+ goto CLEANUP;
+ }
+#endif
+ }
+
+ /* q3 = q2 / b**(k+1) */
+ mp_rshd (&q, um + 1);
+
+ /* x = x mod b**(k+1), quick (no division) */
+ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* q = q * m mod b**(k+1), quick (no division) */
+ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* x = x - q */
+ if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* If x < 0, add b**(k+1) to it */
+ if (mp_cmp_d (x, 0) == MP_LT) {
+ mp_set (&q, 1);
+ if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if ((res = mp_add (x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while (mp_cmp (x, m) != MP_LT) {
+ if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+CLEANUP:
+ mp_clear (&q);
+
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_2k.c b/dep/StormLib/src/libtommath/bn_mp_reduce_2k.c
new file mode 100644
index 00000000000..3191d829179
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_2k.c
@@ -0,0 +1,61 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (d != 1) {
+ /* q = q * d */
+ if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_2k_l.c b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_l.c
new file mode 100644
index 00000000000..49b7e344ed9
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_l.c
@@ -0,0 +1,62 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d
+ This differs from reduce_2k since "d" can be larger
+ than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* q = q * d */
+ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c
new file mode 100644
index 00000000000..aa3b3bad8db
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c
@@ -0,0 +1,47 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+ int res, p;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(a);
+ if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ *d = tmp.dp[0];
+ mp_clear(&tmp);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c
new file mode 100644
index 00000000000..4eca87040bc
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c
@@ -0,0 +1,44 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+ int res;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear(&tmp);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k.c b/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k.c
new file mode 100644
index 00000000000..b9ede978964
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k.c
@@ -0,0 +1,52 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+ int ix, iy, iw;
+ mp_digit iz;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ iy = mp_count_bits(a);
+ iz = 1;
+ iw = 1;
+
+ /* Test every bit from the second digit up, must be 1 */
+ for (ix = DIGIT_BIT; ix < iy; ix++) {
+ if ((a->dp[iw] & iz) == 0) {
+ return MP_NO;
+ }
+ iz <<= 1;
+ if (iz > (mp_digit)MP_MASK) {
+ ++iw;
+ iz = 1;
+ }
+ }
+ }
+ return MP_YES;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c b/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c
new file mode 100644
index 00000000000..787875f8bbb
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c
@@ -0,0 +1,44 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_IS_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+ int ix, iy;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ /* if more than half of the digits are -1 we're sold */
+ for (iy = ix = 0; ix < a->used; ix++) {
+ if (a->dp[ix] == MP_MASK) {
+ ++iy;
+ }
+ }
+ return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+ }
+ return MP_NO;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_reduce_setup.c b/dep/StormLib/src/libtommath/bn_mp_reduce_setup.c
new file mode 100644
index 00000000000..00e0a62b9bd
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_reduce_setup.c
@@ -0,0 +1,34 @@
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ return mp_div (a, b, a, NULL);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_rshd.c b/dep/StormLib/src/libtommath/bn_mp_rshd.c
new file mode 100644
index 00000000000..eac6721baf0
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_rshd.c
@@ -0,0 +1,72 @@
+#include "tommath.h"
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+ int x;
+
+ /* if b <= 0 then ignore it */
+ if (b <= 0) {
+ return;
+ }
+
+ /* if b > used then simply zero it and return */
+ if (a->used <= b) {
+ mp_zero (a);
+ return;
+ }
+
+ {
+ register mp_digit *bottom, *top;
+
+ /* shift the digits down */
+
+ /* bottom */
+ bottom = a->dp;
+
+ /* top [offset into digits] */
+ top = a->dp + b;
+
+ /* this is implemented as a sliding window where
+ * the window is b-digits long and digits from
+ * the top of the window are copied to the bottom
+ *
+ * e.g.
+
+ b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
+ /\ | ---->
+ \-------------------/ ---->
+ */
+ for (x = 0; x < (a->used - b); x++) {
+ *bottom++ = *top++;
+ }
+
+ /* zero the top digits */
+ for (; x < a->used; x++) {
+ *bottom++ = 0;
+ }
+ }
+
+ /* remove excess digits */
+ a->used -= b;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_set.c b/dep/StormLib/src/libtommath/bn_mp_set.c
new file mode 100644
index 00000000000..d76d5bbd324
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_set.c
@@ -0,0 +1,29 @@
+#include "tommath.h"
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+ mp_zero (a);
+ a->dp[0] = b & MP_MASK;
+ a->used = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_set_int.c b/dep/StormLib/src/libtommath/bn_mp_set_int.c
new file mode 100644
index 00000000000..68cf0e32b27
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_set_int.c
@@ -0,0 +1,48 @@
+#include "tommath.h"
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+ int x, res;
+
+ mp_zero (a);
+
+ /* set four bits at a time */
+ for (x = 0; x < 8; x++) {
+ /* shift the number up four bits */
+ if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* OR in the top four bits of the source */
+ a->dp[0] |= (b >> 28) & 15;
+
+ /* shift the source up to the next four bits */
+ b <<= 4;
+
+ /* ensure that digits are not clamped off */
+ a->used += 1;
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_shrink.c b/dep/StormLib/src/libtommath/bn_mp_shrink.c
new file mode 100644
index 00000000000..54920d1400a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_shrink.c
@@ -0,0 +1,35 @@
+#include "tommath.h"
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+ mp_digit *tmp;
+ if (a->alloc != a->used && a->used > 0) {
+ if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+ return MP_MEM;
+ }
+ a->dp = tmp;
+ a->alloc = a->used;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_signed_bin_size.c b/dep/StormLib/src/libtommath/bn_mp_signed_bin_size.c
new file mode 100644
index 00000000000..b9492a5e5ed
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_signed_bin_size.c
@@ -0,0 +1,27 @@
+#include "tommath.h"
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+ return 1 + mp_unsigned_bin_size (a);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_sqr.c b/dep/StormLib/src/libtommath/bn_mp_sqr.c
new file mode 100644
index 00000000000..c10fa6f3b6e
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_sqr.c
@@ -0,0 +1,58 @@
+#include "tommath.h"
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+ int res;
+
+#ifdef BN_MP_TOOM_SQR_C
+ /* use Toom-Cook? */
+ if (a->used >= TOOM_SQR_CUTOFF) {
+ res = mp_toom_sqr(a, b);
+ /* Karatsuba? */
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+ res = mp_karatsuba_sqr (a, b);
+ } else
+#endif
+ {
+#ifdef BN_FAST_S_MP_SQR_C
+ /* can we use the fast comba multiplier? */
+ if ((a->used * 2 + 1) < MP_WARRAY &&
+ a->used <
+ (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+ res = fast_s_mp_sqr (a, b);
+ } else
+#endif
+#ifdef BN_S_MP_SQR_C
+ res = s_mp_sqr (a, b);
+#else
+ res = MP_VAL;
+#endif
+ }
+ b->sign = MP_ZPOS;
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_sqrmod.c b/dep/StormLib/src/libtommath/bn_mp_sqrmod.c
new file mode 100644
index 00000000000..5f4b2f3d663
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_sqrmod.c
@@ -0,0 +1,41 @@
+#include "tommath.h"
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, b, c);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_sqrt.c b/dep/StormLib/src/libtommath/bn_mp_sqrt.c
new file mode 100644
index 00000000000..e15ba98ca88
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_sqrt.c
@@ -0,0 +1,81 @@
+#include "tommath.h"
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret)
+{
+ int res;
+ mp_int t1,t2;
+
+ /* must be positive */
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* easy out */
+ if (mp_iszero(arg) == MP_YES) {
+ mp_zero(ret);
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init(&t2)) != MP_OKAY) {
+ goto E2;
+ }
+
+ /* First approx. (not very bad for large arg) */
+ mp_rshd (&t1,t1.used/2);
+
+ /* t1 > 0 */
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* And now t1 > sqrt(arg) */
+ do {
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* t1 >= sqrt(arg) >= t2 at this point */
+ } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+ mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_sub.c b/dep/StormLib/src/libtommath/bn_mp_sub.c
new file mode 100644
index 00000000000..6e72138610f
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_sub.c
@@ -0,0 +1,59 @@
+#include "tommath.h"
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ sa = a->sign;
+ sb = b->sign;
+
+ if (sa != sb) {
+ /* subtract a negative from a positive, OR */
+ /* subtract a positive from a negative. */
+ /* In either case, ADD their magnitudes, */
+ /* and use the sign of the first number. */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* subtract a positive from a positive, OR */
+ /* subtract a negative from a negative. */
+ /* First, take the difference between their */
+ /* magnitudes, then... */
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ /* Copy the sign from the first */
+ c->sign = sa;
+ /* The first has a larger or equal magnitude */
+ res = s_mp_sub (a, b, c);
+ } else {
+ /* The result has the *opposite* sign from */
+ /* the first number. */
+ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ /* The second has a larger magnitude */
+ res = s_mp_sub (b, a, c);
+ }
+ }
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_sub_d.c b/dep/StormLib/src/libtommath/bn_mp_sub_d.c
new file mode 100644
index 00000000000..aa08e31b30b
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_sub_d.c
@@ -0,0 +1,93 @@
+#include "tommath.h"
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit *tmpa, *tmpc, mu;
+ int res, ix, oldused;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative just do an unsigned
+ * addition [with fudged signs]
+ */
+ if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ res = mp_add_d(a, b, c);
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* setup regs */
+ oldused = c->used;
+ tmpa = a->dp;
+ tmpc = c->dp;
+
+ /* if a <= b simply fix the single digit */
+ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+ if (a->used == 1) {
+ *tmpc++ = b - *tmpa;
+ } else {
+ *tmpc++ = b;
+ }
+ ix = 1;
+
+ /* negative/1digit */
+ c->sign = MP_NEG;
+ c->used = 1;
+ } else {
+ /* positive/size */
+ c->sign = MP_ZPOS;
+ c->used = a->used;
+
+ /* subtract first digit */
+ *tmpc = *tmpa++ - b;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+
+ /* handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ - mu;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* zero excess digits */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_submod.c b/dep/StormLib/src/libtommath/bn_mp_submod.c
new file mode 100644
index 00000000000..6617ff42ceb
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_submod.c
@@ -0,0 +1,42 @@
+#include "tommath.h"
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_to_signed_bin.c b/dep/StormLib/src/libtommath/bn_mp_to_signed_bin.c
new file mode 100644
index 00000000000..154f64b5667
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_to_signed_bin.c
@@ -0,0 +1,33 @@
+#include "tommath.h"
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+ int res;
+
+ if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+ return res;
+ }
+ b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c b/dep/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c
new file mode 100644
index 00000000000..e119c380a91
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c
@@ -0,0 +1,31 @@
+#include "tommath.h"
+#ifdef BN_MP_TO_SIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_signed_bin_size(a);
+ return mp_to_signed_bin(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c b/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c
new file mode 100644
index 00000000000..ce69e5bf364
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c
@@ -0,0 +1,48 @@
+#include "tommath.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+ int x, res;
+ mp_int t;
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ x = 0;
+ while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+ b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+ b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+ if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+ bn_reverse (b, x);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c b/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c
new file mode 100644
index 00000000000..dfa27c41bab
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c
@@ -0,0 +1,31 @@
+#include "tommath.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_unsigned_bin_size(a);
+ return mp_to_unsigned_bin(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_toom_mul.c b/dep/StormLib/src/libtommath/bn_mp_toom_mul.c
new file mode 100644
index 00000000000..e48c6b355c0
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_toom_mul.c
@@ -0,0 +1,284 @@
+#include "tommath.h"
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm
+ *
+ * Much more complicated than Karatsuba but has a lower
+ * asymptotic running time of O(N**1.464). This algorithm is
+ * only particularly useful on VERY large inputs
+ * (we're talking 1000s of digits here...).
+*/
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = MIN(a->used, b->used) / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* b = b2 * B**2 + b1 * B + b0 */
+ if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b1, B);
+ mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+ if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b2, B*2);
+
+ /* w0 = a0*b0 */
+ if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * b2 */
+ if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts,
+ 2 small divisions and 1 small multiplication
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL);
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_toom_sqr.c b/dep/StormLib/src/libtommath/bn_mp_toom_sqr.c
new file mode 100644
index 00000000000..fd8bc672a1a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_toom_sqr.c
@@ -0,0 +1,226 @@
+#include "tommath.h"
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = a->used / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* w0 = a0*a0 */
+ if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * a2 */
+ if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))**2 */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))**2 */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)**2 */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+ return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_toradix.c b/dep/StormLib/src/libtommath/bn_mp_toradix.c
new file mode 100644
index 00000000000..539abe9ba6d
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_toradix.c
@@ -0,0 +1,75 @@
+#include "tommath.h"
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the radix */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == 1) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ ++_s;
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number]
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_toradix_n.c b/dep/StormLib/src/libtommath/bn_mp_toradix_n.c
new file mode 100644
index 00000000000..0322f8d4b2a
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_toradix_n.c
@@ -0,0 +1,88 @@
+#include "tommath.h"
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64)
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the maxlen, radix */
+ if (maxlen < 2 || radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == MP_YES) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ /* we have to reverse our digits later... but not the - sign!! */
+ ++_s;
+
+ /* store the flag and mark the number as positive */
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+
+ /* subtract a char */
+ --maxlen;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if (--maxlen < 1) {
+ /* no more room */
+ break;
+ }
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c b/dep/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c
new file mode 100644
index 00000000000..88f3e92dde8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c
@@ -0,0 +1,28 @@
+#include "tommath.h"
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+ int size = mp_count_bits (a);
+ return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_xor.c b/dep/StormLib/src/libtommath/bn_mp_xor.c
new file mode 100644
index 00000000000..bf0446ecfe8
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_xor.c
@@ -0,0 +1,51 @@
+#include "tommath.h"
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] ^= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_mp_zero.c b/dep/StormLib/src/libtommath/bn_mp_zero.c
new file mode 100644
index 00000000000..f21db5ed589
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_mp_zero.c
@@ -0,0 +1,36 @@
+#include "tommath.h"
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+ int n;
+ mp_digit *tmp;
+
+ a->sign = MP_ZPOS;
+ a->used = 0;
+
+ tmp = a->dp;
+ for (n = 0; n < a->alloc; n++) {
+ *tmp++ = 0;
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_prime_tab.c b/dep/StormLib/src/libtommath/bn_prime_tab.c
new file mode 100644
index 00000000000..7d306dd56a6
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_prime_tab.c
@@ -0,0 +1,61 @@
+#include "tommath.h"
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+const mp_digit ltm_prime_tab[] = {
+ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+ 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+ 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+ 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+ 0x0083,
+ 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+ 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+ 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+ 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+ 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+ 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+ 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+ 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+ 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+ 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+ 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+ 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+ 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+ 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+ 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+ 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+ 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+ 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+ 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+ 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+ 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+ 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+ 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+ 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+ 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+ 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+ 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_reverse.c b/dep/StormLib/src/libtommath/bn_reverse.c
new file mode 100644
index 00000000000..d4a919af486
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_reverse.c
@@ -0,0 +1,39 @@
+#include "tommath.h"
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+ int ix, iy;
+ unsigned char t;
+
+ ix = 0;
+ iy = len - 1;
+ while (ix < iy) {
+ t = s[ix];
+ s[ix] = s[iy];
+ s[iy] = t;
+ ++ix;
+ --iy;
+ }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_add.c b/dep/StormLib/src/libtommath/bn_s_mp_add.c
new file mode 100644
index 00000000000..5ea9c6d205c
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_add.c
@@ -0,0 +1,109 @@
+#include "tommath.h"
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int *x;
+ int olduse, res, min, max;
+
+ /* find sizes, we let |a| <= |b| which means we have to sort
+ * them. "x" will point to the input with the most digits
+ */
+ if (a->used > b->used) {
+ min = b->used;
+ max = a->used;
+ x = a;
+ } else {
+ min = a->used;
+ max = b->used;
+ x = b;
+ }
+
+ /* init result */
+ if (c->alloc < max + 1) {
+ if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get old used digit count and set new one */
+ olduse = c->used;
+ c->used = max + 1;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+
+ /* first input */
+ tmpa = a->dp;
+
+ /* second input */
+ tmpb = b->dp;
+
+ /* destination */
+ tmpc = c->dp;
+
+ /* zero the carry */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+ *tmpc = *tmpa++ + *tmpb++ + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, that is in A+B
+ * if A or B has more digits add those in
+ */
+ if (min != max) {
+ for (; i < max; i++) {
+ /* T[i] = X[i] + U */
+ *tmpc = x->dp[i] + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* add carry */
+ *tmpc++ = u;
+
+ /* clear digits above oldused */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_exptmod.c b/dep/StormLib/src/libtommath/bn_s_mp_exptmod.c
new file mode 100644
index 00000000000..9fb2da8fd21
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_exptmod.c
@@ -0,0 +1,252 @@
+#include "tommath.h"
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res, mu;
+ mp_digit buf;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+ int (*redux)(mp_int*,mp_int*,mp_int*);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* create mu, used for Barrett reduction */
+ if ((err = mp_init (&mu)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ if (redmode == 0) {
+ if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce;
+ } else {
+ if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce_2k_l;
+ }
+
+ /* create M table
+ *
+ * The M table contains powers of the base,
+ * e.g. M[x] = G**x mod P
+ *
+ * The first half of the table is not
+ * computed though accept for M[0] and M[1]
+ */
+ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring
+ * M[1] (winsize-1) times
+ */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ /* square it */
+ if ((err = mp_sqr (&M[1 << (winsize - 1)],
+ &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* reduce modulo P */
+ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+ * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+ */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ mp_set (&res, 1);
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset the bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_mul_digs.c b/dep/StormLib/src/libtommath/bn_s_mp_mul_digs.c
new file mode 100644
index 00000000000..f04dacfb9ea
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_mul_digs.c
@@ -0,0 +1,90 @@
+#include "tommath.h"
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12 Modified so you can control how
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((digs) < MP_WARRAY) &&
+ MIN (a->used, b->used) <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+ return res;
+ }
+ t.used = digs;
+
+ /* compute the digits of the product directly */
+ pa = a->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* set the carry to zero */
+ u = 0;
+
+ /* limit ourselves to making digs digits of output */
+ pb = MIN (b->used, digs - ix);
+
+ /* setup some aliases */
+ /* copy of the digit from a used within the nested loop */
+ tmpx = a->dp[ix];
+
+ /* an alias for the destination shifted ix places */
+ tmpt = t.dp + ix;
+
+ /* an alias for the digits of b */
+ tmpy = b->dp;
+
+ /* compute the columns of the output and propagate the carry */
+ for (iy = 0; iy < pb; iy++) {
+ /* compute the column as a mp_word */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* the new column is the lower part of the result */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry word from the result */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ /* set carry if it is placed below digs */
+ if (ix + iy < digs) {
+ *tmpt = u;
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, c);
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c b/dep/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c
new file mode 100644
index 00000000000..b1d019925a6
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c
@@ -0,0 +1,81 @@
+#include "tommath.h"
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ if (((a->used + b->used + 1) < MP_WARRAY)
+ && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_high_digs (a, b, c, digs);
+ }
+#endif
+
+ if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ t.used = a->used + b->used + 1;
+
+ pa = a->used;
+ pb = b->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* clear the carry */
+ u = 0;
+
+ /* left hand side of A[ix] * B[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias to the address of where the digits will be stored */
+ tmpt = &(t.dp[digs]);
+
+ /* alias for where to read the right hand side from */
+ tmpy = b->dp + (digs - ix);
+
+ for (iy = digs - ix; iy < pb; iy++) {
+ /* calculate the double precision result */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* get the lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* carry the carry */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ *tmpt = u;
+ }
+ mp_clamp (&t);
+ mp_exch (&t, c);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_sqr.c b/dep/StormLib/src/libtommath/bn_s_mp_sqr.c
new file mode 100644
index 00000000000..c1e994efddf
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_sqr.c
@@ -0,0 +1,84 @@
+#include "tommath.h"
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+ mp_int t;
+ int res, ix, iy, pa;
+ mp_word r;
+ mp_digit u, tmpx, *tmpt;
+
+ pa = a->used;
+ if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* default used is maximum possible size */
+ t.used = 2*pa + 1;
+
+ for (ix = 0; ix < pa; ix++) {
+ /* first calculate the digit at 2*ix */
+ /* calculate double precision result */
+ r = ((mp_word) t.dp[2*ix]) +
+ ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+ /* store lower part in result */
+ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* left hand side of A[ix] * A[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias for where to store the results */
+ tmpt = t.dp + (2*ix + 1);
+
+ for (iy = ix + 1; iy < pa; iy++) {
+ /* first calculate the product */
+ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+ /* now calculate the double precision result, note we use
+ * addition instead of *2 since it's easier to optimize
+ */
+ r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+ /* store lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ /* propagate upwards */
+ while (u != ((mp_digit) 0)) {
+ r = ((mp_word) *tmpt) + ((mp_word) u);
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, b);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bn_s_mp_sub.c b/dep/StormLib/src/libtommath/bn_s_mp_sub.c
new file mode 100644
index 00000000000..0ae91cc4d17
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bn_s_mp_sub.c
@@ -0,0 +1,89 @@
+#include "tommath.h"
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int olduse, res, min, max;
+
+ /* find sizes */
+ min = b->used;
+ max = a->used;
+
+ /* init result */
+ if (c->alloc < max) {
+ if ((res = mp_grow (c, max)) != MP_OKAY) {
+ return res;
+ }
+ }
+ olduse = c->used;
+ c->used = max;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+ tmpa = a->dp;
+ tmpb = b->dp;
+ tmpc = c->dp;
+
+ /* set carry to zero */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* T[i] = A[i] - B[i] - U */
+ *tmpc = *tmpa++ - *tmpb++ - u;
+
+ /* U = carry bit of T[i]
+ * Note this saves performing an AND operation since
+ * if a carry does occur it will propagate all the way to the
+ * MSB. As a result a single shift is enough to get the carry
+ */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, e.g. if A has more digits than B */
+ for (; i < max; i++) {
+ /* T[i] = A[i] - U */
+ *tmpc = *tmpa++ - u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* clear digits above used (since we may not have grown result above) */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/bncore.c b/dep/StormLib/src/libtommath/bncore.c
new file mode 100644
index 00000000000..ad7347f8424
--- /dev/null
+++ b/dep/StormLib/src/libtommath/bncore.c
@@ -0,0 +1,36 @@
+#include "tommath.h"
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Known optimal configurations
+
+ CPU /Compiler /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
+ AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35
+
+*/
+
+int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */
+ KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */
+
+ TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */
+ TOOM_SQR_CUTOFF = 400;
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bncore.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/dep/StormLib/src/libtommath/tommath.h b/dep/StormLib/src/libtommath/tommath.h
new file mode 100644
index 00000000000..1ead3d04bf5
--- /dev/null
+++ b/dep/StormLib/src/libtommath/tommath.h
@@ -0,0 +1,584 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "tommath_class.h"
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define OPT_CAST(x) (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__)
+ #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+ #define MP_64BIT
+ #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+ typedef unsigned char mp_digit;
+ typedef unsigned short mp_word;
+#elif defined(MP_16BIT)
+ typedef unsigned short mp_digit;
+ typedef unsigned long mp_word;
+#elif defined(MP_64BIT)
+ /* for GCC only on supported platforms */
+#ifndef CRYPT
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+#endif
+
+ typedef unsigned long mp_digit;
+ typedef unsigned long mp_word __attribute__ ((mode(TI)));
+
+ #define DIGIT_BIT 60
+#else
+ /* this is the default case, 28-bit digits */
+
+ /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+ #if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 ulong64;
+ typedef signed __int64 long64;
+ #else
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+ #endif
+#endif
+
+ typedef unsigned long mp_digit;
+ typedef ulong64 mp_word;
+
+#ifdef MP_31BIT
+ /* this is an extension that uses 31-bit digits */
+ #define DIGIT_BIT 31
+#else
+ /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+ #define DIGIT_BIT 28
+ #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+ /* default to libc stuff */
+ #ifndef XMALLOC
+ #define XMALLOC malloc
+ #define XFREE free
+ #define XREALLOC realloc
+ #define XCALLOC calloc
+ #else
+ /* prototypes for our heap functions */
+ extern void *XMALLOC(size_t n);
+ extern void *XREALLOC(void *p, size_t n);
+ extern void *XCALLOC(size_t n, size_t s);
+ extern void XFREE(void *p);
+ #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+ #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT DIGIT_BIT
+#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX MP_MASK
+
+/* equalities */
+#define MP_LT -1 /* less than */
+#define MP_EQ 0 /* equal to */
+#define MP_GT 1 /* greater than */
+
+#define MP_ZPOS 0 /* positive integer */
+#define MP_NEG 1 /* negative */
+
+#define MP_OKAY 0 /* ok result */
+#define MP_MEM -2 /* out of mem */
+#define MP_VAL -3 /* invalid input */
+#define MP_RANGE MP_VAL
+
+#define MP_YES 1 /* yes response */
+#define MP_NO 0 /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS 0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
+
+typedef int mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+ KARATSUBA_SQR_CUTOFF,
+ TOOM_MUL_CUTOFF,
+ TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+ #ifndef MP_LOW_MEM
+ #define MP_PREC 32 /* default digits of precision */
+ #else
+ #define MP_PREC 8 /* default digits of precision */
+ #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct {
+ int used, alloc, sign;
+ mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m) ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m) ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime) */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+int mp_reduce_is_2k_l(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+ #define PRIME_SIZE 31
+#else
+ #define PRIME_SIZE 256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit ltm_prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases. Also performs an initial sieve of trial
+ * division. Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_read_radix(mp_int *a, const char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp) mp_signed_bin_size(mp)
+#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S) mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtommath/tommath.h,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/03/31 14:18:44 $ */
diff --git a/dep/StormLib/src/libtommath/tommath_class.h b/dep/StormLib/src/libtommath/tommath_class.h
new file mode 100644
index 00000000000..18d1553dee7
--- /dev/null
+++ b/dep/StormLib/src/libtommath/tommath_class.h
@@ -0,0 +1,999 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+ #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_COPY_C
+ #define BN_MP_MOD_C
+ #define BN_MP_SET_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_ADD_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+ #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+ #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_SET_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_ABS_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SUB_C
+ #define BN_MP_ADD_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_INIT_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_COPY_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_SET_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_INVMOD_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_ABS_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_REDUCE_IS_2K_L_C
+ #define BN_S_MP_EXPTMOD_C
+ #define BN_MP_DR_IS_MODULUS_C
+ #define BN_MP_REDUCE_IS_2K_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_EXPTMOD_FAST_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MONTGOMERY_SETUP_C
+ #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_DR_SETUP_C
+ #define BN_MP_DR_REDUCE_C
+ #define BN_MP_REDUCE_2K_SETUP_C
+ #define BN_MP_REDUCE_2K_C
+ #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ #define BN_MP_MULMOD_C
+ #define BN_MP_SET_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_SET_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SUB_C
+ #define BN_MP_NEG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_S_RMAP_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+ #define BN_MP_RADIX_SIZE_C
+ #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ABS_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+ #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+ #define BN_MP_ERR_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+ #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ISODD_C
+ #define BN_FAST_MP_INVMOD_C
+ #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_SET_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+ #define BN_MP_MOD_D_C
+ #define BN_MP_INIT_SET_INT_C
+ #define BN_MP_MOD_C
+ #define BN_MP_GET_INT_C
+ #define BN_MP_SQRT_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MOD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+ #define BN_MP_MUL_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_SUB_C
+ #define BN_MP_ADD_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_SQR_C
+ #define BN_MP_SUB_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_GCD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_DIV_C
+ #define BN_MP_MUL_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_DIV_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_ADD_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_COPY_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+ #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_SET_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+ #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+ #define BN_MP_TOOM_MUL_C
+ #define BN_MP_KARATSUBA_MUL_C
+ #define BN_FAST_S_MP_MUL_DIGS_C
+ #define BN_S_MP_MUL_C
+ #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_GROW_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_MUL_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+ #define BN_MP_COPY_C
+ #define BN_MP_EXPT_D_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SUB_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_INIT_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_CMP_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+ #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_PRIME_IS_DIVISIBLE_C
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+ #define BN_MP_PRIME_MILLER_RABIN_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SQRMOD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_SET_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_MOD_D_C
+ #define BN_MP_INIT_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_PRIME_MILLER_RABIN_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+ #define BN_MP_READ_UNSIGNED_BIN_C
+ #define BN_MP_PRIME_IS_PRIME_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_S_RMAP_C
+ #define BN_MP_RADIX_SMAP_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+ #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+ #define BN_MP_REDUCE_SETUP_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_C
+ #define BN_S_MP_MUL_HIGH_DIGS_C
+ #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #define BN_MP_MOD_2D_C
+ #define BN_S_MP_MUL_DIGS_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_SET_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CMP_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MUL_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_CLEAR_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+ #define BN_MP_REDUCE_2K_C
+ #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+ #define BN_MP_2EXPT_C
+ #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+ #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+ #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+ #define BN_MP_TOOM_SQR_C
+ #define BN_MP_KARATSUBA_SQR_C
+ #define BN_FAST_S_MP_SQR_C
+ #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+ #define BN_MP_N_ROOT_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_DIV_C
+ #define BN_MP_ADD_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+ #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+ #define BN_MP_SIGNED_BIN_SIZE_C
+ #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+ #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+ #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_REDUCE_SETUP_C
+ #define BN_MP_REDUCE_C
+ #define BN_MP_REDUCE_2K_SETUP_L_C
+ #define BN_MP_REDUCE_2K_L_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SET_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+ #define BN_FAST_S_MP_MUL_DIGS_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+ #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include "tommath_superclass.h"
+#include "tommath_class.h"
+#else
+#define LTM_LAST
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/07/28 11:59:32 $ */
diff --git a/dep/StormLib/src/libtommath/tommath_superclass.h b/dep/StormLib/src/libtommath/tommath_superclass.h
new file mode 100644
index 00000000000..2fdebe6838f
--- /dev/null
+++ b/dep/StormLib/src/libtommath/tommath_superclass.h
@@ -0,0 +1,76 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+ LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+ #define BN_MP_SHRINK_C
+ #define BN_MP_LCM_C
+ #define BN_MP_PRIME_RANDOM_EX_C
+ #define BN_MP_INVMOD_C
+ #define BN_MP_GCD_C
+ #define BN_MP_MOD_C
+ #define BN_MP_MULMOD_C
+ #define BN_MP_ADDMOD_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_SET_INT_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+ #define BN_MP_TO_UNSIGNED_BIN_C
+ #define BN_MP_MOD_D_C
+ #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+ #define BN_REVERSE_C
+ #define BN_PRIME_TAB_C
+
+ /* other modifiers */
+ #define BN_MP_DIV_SMALL /* Slower division, not critical */
+
+ /* here we are on the last pass so we turn things off. The functions classes are still there
+ * but we remove them specifically from the build. This also invokes tweaks in functions
+ * like removing support for even moduli, etc...
+ */
+#ifdef LTM_LAST
+ #undef BN_MP_TOOM_MUL_C
+ #undef BN_MP_TOOM_SQR_C
+ #undef BN_MP_KARATSUBA_MUL_C
+ #undef BN_MP_KARATSUBA_SQR_C
+ #undef BN_MP_REDUCE_C
+ #undef BN_MP_REDUCE_SETUP_C
+ #undef BN_MP_DR_IS_MODULUS_C
+ #undef BN_MP_DR_SETUP_C
+ #undef BN_MP_DR_REDUCE_C
+ #undef BN_MP_REDUCE_IS_2K_C
+ #undef BN_MP_REDUCE_2K_SETUP_C
+ #undef BN_MP_REDUCE_2K_C
+ #undef BN_S_MP_EXPTMOD_C
+ #undef BN_MP_DIV_3_C
+ #undef BN_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_MP_INVMOD_C
+
+ /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+ * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
+ * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+ * trouble.
+ */
+ #undef BN_S_MP_MUL_DIGS_C
+ #undef BN_S_MP_SQR_C
+ #undef BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/14 13:29:17 $ */
diff --git a/dep/StormLib/src/lzma/C/LzFind.c b/dep/StormLib/src/lzma/C/LzFind.c
new file mode 100644
index 00000000000..e3ecb05420e
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzFind.c
@@ -0,0 +1,761 @@
+/* LzFind.c -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+#include "LzFind.h"
+#include "LzHash.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ if (!p->directInput)
+ {
+ alloc->Free(alloc, p->bufferBase);
+ p->bufferBase = 0;
+ }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+ if (p->directInput)
+ {
+ p->blockSize = blockSize;
+ return 1;
+ }
+ if (p->bufferBase == 0 || p->blockSize != blockSize)
+ {
+ LzInWindow_Free(p, alloc);
+ p->blockSize = blockSize;
+ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
+ }
+ return (p->bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+ p->posLimit -= subValue;
+ p->pos -= subValue;
+ p->streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+ if (p->streamEndWasReached || p->result != SZ_OK)
+ return;
+ if (p->directInput)
+ {
+ UInt32 curSize = 0xFFFFFFFF - p->streamPos;
+ if (curSize > p->directInputRem)
+ curSize = (UInt32)p->directInputRem;
+ p->directInputRem -= curSize;
+ p->streamPos += curSize;
+ if (p->directInputRem == 0)
+ p->streamEndWasReached = 1;
+ return;
+ }
+ for (;;)
+ {
+ Byte *dest = p->buffer + (p->streamPos - p->pos);
+ size_t size = (p->bufferBase + p->blockSize - dest);
+ if (size == 0)
+ return;
+ p->result = p->stream->Read(p->stream, dest, &size);
+ if (p->result != SZ_OK)
+ return;
+ if (size == 0)
+ {
+ p->streamEndWasReached = 1;
+ return;
+ }
+ p->streamPos += (UInt32)size;
+ if (p->streamPos - p->pos > p->keepSizeAfter)
+ return;
+ }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+ memmove(p->bufferBase,
+ p->buffer - p->keepSizeBefore,
+ (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+ p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+ if (p->directInput)
+ return 0;
+ /* if (p->streamEndWasReached) return 0; */
+ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+ if (p->streamEndWasReached)
+ return;
+ if (p->keepSizeAfter >= p->streamPos - p->pos)
+ MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+ if (MatchFinder_NeedMove(p))
+ MatchFinder_MoveBlock(p);
+ MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+ p->cutValue = 32;
+ p->btMode = 1;
+ p->numHashBytes = 4;
+ p->bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+ UInt32 i;
+ p->bufferBase = 0;
+ p->directInput = 0;
+ p->hash = 0;
+ MatchFinder_SetDefaultSettings(p);
+
+ for (i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+ p->crc[i] = r;
+ }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->hash);
+ p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+ if (sizeInBytes / sizeof(CLzRef) != num)
+ return 0;
+ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc)
+{
+ UInt32 sizeReserv;
+ if (historySize > kMaxHistorySize)
+ {
+ MatchFinder_Free(p, alloc);
+ return 0;
+ }
+ sizeReserv = historySize >> 1;
+ if (historySize > ((UInt32)2 << 30))
+ sizeReserv = historySize >> 2;
+ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+ if (LzInWindow_Create(p, sizeReserv, alloc))
+ {
+ UInt32 newCyclicBufferSize = historySize + 1;
+ UInt32 hs;
+ p->matchMaxLen = matchMaxLen;
+ {
+ p->fixedHashSize = 0;
+ if (p->numHashBytes == 2)
+ hs = (1 << 16) - 1;
+ else
+ {
+ hs = historySize - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+ if (hs > (1 << 24))
+ {
+ if (p->numHashBytes == 3)
+ hs = (1 << 24) - 1;
+ else
+ hs >>= 1;
+ }
+ }
+ p->hashMask = hs;
+ hs++;
+ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+ hs += p->fixedHashSize;
+ }
+
+ {
+ UInt32 prevSize = p->hashSizeSum + p->numSons;
+ UInt32 newSize;
+ p->historySize = historySize;
+ p->hashSizeSum = hs;
+ p->cyclicBufferSize = newCyclicBufferSize;
+ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+ newSize = p->hashSizeSum + p->numSons;
+ if (p->hash != 0 && prevSize == newSize)
+ return 1;
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ p->hash = AllocRefs(newSize, alloc);
+ if (p->hash != 0)
+ {
+ p->son = p->hash + p->hashSizeSum;
+ return 1;
+ }
+ }
+ }
+ MatchFinder_Free(p, alloc);
+ return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+ UInt32 limit = kMaxValForNormalize - p->pos;
+ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+ if (limit2 < limit)
+ limit = limit2;
+ limit2 = p->streamPos - p->pos;
+ if (limit2 <= p->keepSizeAfter)
+ {
+ if (limit2 > 0)
+ limit2 = 1;
+ }
+ else
+ limit2 -= p->keepSizeAfter;
+ if (limit2 < limit)
+ limit = limit2;
+ {
+ UInt32 lenLimit = p->streamPos - p->pos;
+ if (lenLimit > p->matchMaxLen)
+ lenLimit = p->matchMaxLen;
+ p->lenLimit = lenLimit;
+ }
+ p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+ UInt32 i;
+ for (i = 0; i < p->hashSizeSum; i++)
+ p->hash[i] = kEmptyHashValue;
+ p->cyclicBufferPos = 0;
+ p->buffer = p->bufferBase;
+ p->pos = p->streamPos = p->cyclicBufferSize;
+ p->result = SZ_OK;
+ p->streamEndWasReached = 0;
+ MatchFinder_ReadBlock(p);
+ MatchFinder_SetLimits(p);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+ return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+ UInt32 subValue = MatchFinder_GetSubValue(p);
+ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+ MatchFinder_ReduceOffsets(p, subValue);
+}
+
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+ if (p->pos == kMaxValForNormalize)
+ MatchFinder_Normalize(p);
+ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+ MatchFinder_CheckAndMoveAndRead(p);
+ if (p->cyclicBufferPos == p->cyclicBufferSize)
+ p->cyclicBufferPos = 0;
+ MatchFinder_SetLimits(p);
+}
+
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ son[_cyclicBufferPos] = curMatch;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ return distances;
+ {
+ const Byte *pb = cur - delta;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+ {
+ UInt32 len = 0;
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ return distances;
+ }
+ }
+ }
+ }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return distances;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return distances;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ {
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+#define MOVE_POS \
+ ++p->cyclicBufferPos; \
+ p->buffer++; \
+ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+ distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, delta2, maxLen, offset;
+ GET_MATCHES_HEADER(3)
+
+ HASH3_CALC;
+
+ delta2 = p->pos - p->hash[hash2Value];
+ curMatch = p->hash[kFix3HashSize + hashValue];
+
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+
+
+ maxLen = 2;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[0] = maxLen;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[ hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+ {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[ hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+ {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances + offset, maxLen) - (distances));
+ MOVE_POS_RET
+}
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances, 2) - (distances));
+ MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value;
+ SKIP_HEADER(3)
+ HASH3_CALC;
+ curMatch = p->hash[kFix3HashSize + hashValue];
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] = p->pos;
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+ if (!p->btMode)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 2)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 3)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+ }
+ else
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+ }
+}
diff --git a/dep/StormLib/src/lzma/C/LzFind.h b/dep/StormLib/src/lzma/C/LzFind.h
new file mode 100644
index 00000000000..010c4b92ba3
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzFind.h
@@ -0,0 +1,115 @@
+/* LzFind.h -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_FIND_H
+#define __LZ_FIND_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+ Byte *buffer;
+ UInt32 pos;
+ UInt32 posLimit;
+ UInt32 streamPos;
+ UInt32 lenLimit;
+
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+ UInt32 matchMaxLen;
+ CLzRef *hash;
+ CLzRef *son;
+ UInt32 hashMask;
+ UInt32 cutValue;
+
+ Byte *bufferBase;
+ ISeqInStream *stream;
+ int streamEndWasReached;
+
+ UInt32 blockSize;
+ UInt32 keepSizeBefore;
+ UInt32 keepSizeAfter;
+
+ UInt32 numHashBytes;
+ int directInput;
+ size_t directInputRem;
+ int btMode;
+ int bigHash;
+ UInt32 historySize;
+ UInt32 fixedHashSize;
+ UInt32 hashSizeSum;
+ UInt32 numSons;
+ SRes result;
+ UInt32 crc[256];
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+ historySize <= 3 GB
+ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+ Mf_Init_Func Init;
+ Mf_GetIndexByte_Func GetIndexByte;
+ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+ Mf_GetMatches_Func GetMatches;
+ Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/LzFindMt.c b/dep/StormLib/src/lzma/C/LzFindMt.c
new file mode 100644
index 00000000000..aa41ed98a57
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzFindMt.c
@@ -0,0 +1,793 @@
+/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
+2009-09-20 : Igor Pavlov : Public domain */
+
+#include "LzHash.h"
+
+#include "LzFindMt.h"
+
+void MtSync_Construct(CMtSync *p)
+{
+ p->wasCreated = False;
+ p->csWasInitialized = False;
+ p->csWasEntered = False;
+ Thread_Construct(&p->thread);
+ Event_Construct(&p->canStart);
+ Event_Construct(&p->wasStarted);
+ Event_Construct(&p->wasStopped);
+ Semaphore_Construct(&p->freeSemaphore);
+ Semaphore_Construct(&p->filledSemaphore);
+}
+
+void MtSync_GetNextBlock(CMtSync *p)
+{
+ if (p->needStart)
+ {
+ p->numProcessedBlocks = 1;
+ p->needStart = False;
+ p->stopWriting = False;
+ p->exit = False;
+ Event_Reset(&p->wasStarted);
+ Event_Reset(&p->wasStopped);
+
+ Event_Set(&p->canStart);
+ Event_Wait(&p->wasStarted);
+ }
+ else
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ p->numProcessedBlocks++;
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ Semaphore_Wait(&p->filledSemaphore);
+ CriticalSection_Enter(&p->cs);
+ p->csWasEntered = True;
+}
+
+/* MtSync_StopWriting must be called if Writing was started */
+
+void MtSync_StopWriting(CMtSync *p)
+{
+ UInt32 myNumBlocks = p->numProcessedBlocks;
+ if (!Thread_WasCreated(&p->thread) || p->needStart)
+ return;
+ p->stopWriting = True;
+ if (p->csWasEntered)
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ }
+ Semaphore_Release1(&p->freeSemaphore);
+
+ Event_Wait(&p->wasStopped);
+
+ while (myNumBlocks++ != p->numProcessedBlocks)
+ {
+ Semaphore_Wait(&p->filledSemaphore);
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ p->needStart = True;
+}
+
+void MtSync_Destruct(CMtSync *p)
+{
+ if (Thread_WasCreated(&p->thread))
+ {
+ MtSync_StopWriting(p);
+ p->exit = True;
+ if (p->needStart)
+ Event_Set(&p->canStart);
+ Thread_Wait(&p->thread);
+ Thread_Close(&p->thread);
+ }
+ if (p->csWasInitialized)
+ {
+ CriticalSection_Delete(&p->cs);
+ p->csWasInitialized = False;
+ }
+
+ Event_Close(&p->canStart);
+ Event_Close(&p->wasStarted);
+ Event_Close(&p->wasStopped);
+ Semaphore_Close(&p->freeSemaphore);
+ Semaphore_Close(&p->filledSemaphore);
+
+ p->wasCreated = False;
+}
+
+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
+
+static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ if (p->wasCreated)
+ return SZ_OK;
+
+ RINOK_THREAD(CriticalSection_Init(&p->cs));
+ p->csWasInitialized = True;
+
+ RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
+ RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
+ RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
+
+ RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
+ RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
+
+ p->needStart = True;
+
+ RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
+ p->wasCreated = True;
+ return SZ_OK;
+}
+
+static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
+ if (res != SZ_OK)
+ MtSync_Destruct(p);
+ return res;
+}
+
+void MtSync_Init(CMtSync *p) { p->needStart = True; }
+
+#define kMtMaxValForNormalize 0xFFFFFFFF
+
+#define DEF_GetHeads2(name, v, action) \
+static void GetHeads ## name(const Byte *p, UInt32 pos, \
+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
+{ action; for (; numHeads != 0; numHeads--) { \
+const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
+
+#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
+
+DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
+DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
+DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
+DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
+/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
+
+void HashThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->hashSync;
+ for (;;)
+ {
+ UInt32 numProcessedBlocks = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = numProcessedBlocks;
+ Event_Set(&p->wasStopped);
+ break;
+ }
+
+ {
+ CMatchFinder *mf = mt->MatchFinder;
+ if (MatchFinder_NeedMove(mf))
+ {
+ CriticalSection_Enter(&mt->btSync.cs);
+ CriticalSection_Enter(&mt->hashSync.cs);
+ {
+ const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
+ const Byte *afterPtr;
+ MatchFinder_MoveBlock(mf);
+ afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
+ mt->pointerToCurPos -= beforePtr - afterPtr;
+ mt->buffer -= beforePtr - afterPtr;
+ }
+ CriticalSection_Leave(&mt->btSync.cs);
+ CriticalSection_Leave(&mt->hashSync.cs);
+ continue;
+ }
+
+ Semaphore_Wait(&p->freeSemaphore);
+
+ MatchFinder_ReadIfRequired(mf);
+ if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
+ {
+ UInt32 subValue = (mf->pos - mf->historySize - 1);
+ MatchFinder_ReduceOffsets(mf, subValue);
+ MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
+ }
+ {
+ UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ UInt32 num = mf->streamPos - mf->pos;
+ heads[0] = 2;
+ heads[1] = num;
+ if (num >= mf->numHashBytes)
+ {
+ num = num - mf->numHashBytes + 1;
+ if (num > kMtHashBlockSize - 2)
+ num = kMtHashBlockSize - 2;
+ mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
+ heads[0] += num;
+ }
+ mf->pos += num;
+ mf->buffer += num;
+ }
+ }
+
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
+{
+ MtSync_GetNextBlock(&p->hashSync);
+ p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
+ p->hashNumAvail = p->hashBuf[p->hashBufPos++];
+}
+
+#define kEmptyHashValue 0
+
+/* #define MFMT_GM_INLINE */
+
+#ifdef MFMT_GM_INLINE
+
+#define NO_INLINE MY_FAST_CALL
+
+Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
+{
+ do
+ {
+ UInt32 *distances = _distances + 1;
+ UInt32 curMatch = pos - *hash++;
+
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ UInt32 cutValue = _cutValue;
+ UInt32 maxLen = _maxLen;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ break;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ break;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+ pos++;
+ _cyclicBufferPos++;
+ cur++;
+ {
+ UInt32 num = (UInt32)(distances - _distances);
+ *_distances = num - 1;
+ _distances += num;
+ limit -= num;
+ }
+ }
+ while (limit > 0 && --size != 0);
+ *posRes = pos;
+ return limit;
+}
+
+#endif
+
+void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ UInt32 numProcessed = 0;
+ UInt32 curPos = 2;
+ UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
+ distances[1] = p->hashNumAvail;
+ while (curPos < limit)
+ {
+ if (p->hashBufPos == p->hashBufPosLimit)
+ {
+ MatchFinderMt_GetNextBlock_Hash(p);
+ distances[1] = numProcessed + p->hashNumAvail;
+ if (p->hashNumAvail >= p->numHashBytes)
+ continue;
+ for (; p->hashNumAvail != 0; p->hashNumAvail--)
+ distances[curPos++] = 0;
+ break;
+ }
+ {
+ UInt32 size = p->hashBufPosLimit - p->hashBufPos;
+ UInt32 lenLimit = p->matchMaxLen;
+ UInt32 pos = p->pos;
+ UInt32 cyclicBufferPos = p->cyclicBufferPos;
+ if (lenLimit >= p->hashNumAvail)
+ lenLimit = p->hashNumAvail;
+ {
+ UInt32 size2 = p->hashNumAvail - lenLimit + 1;
+ if (size2 < size)
+ size = size2;
+ size2 = p->cyclicBufferSize - cyclicBufferPos;
+ if (size2 < size)
+ size = size2;
+ }
+ #ifndef MFMT_GM_INLINE
+ while (curPos < limit && size-- != 0)
+ {
+ UInt32 *startDistances = distances + curPos;
+ UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
+ pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ startDistances + 1, p->numHashBytes - 1) - startDistances);
+ *startDistances = num - 1;
+ curPos += num;
+ cyclicBufferPos++;
+ pos++;
+ p->buffer++;
+ }
+ #else
+ {
+ UInt32 posRes;
+ curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
+ p->hashBufPos += posRes - pos;
+ cyclicBufferPos += posRes - pos;
+ p->buffer += posRes - pos;
+ pos = posRes;
+ }
+ #endif
+
+ numProcessed += pos - p->pos;
+ p->hashNumAvail -= pos - p->pos;
+ p->pos = pos;
+ if (cyclicBufferPos == p->cyclicBufferSize)
+ cyclicBufferPos = 0;
+ p->cyclicBufferPos = cyclicBufferPos;
+ }
+ }
+ distances[0] = curPos;
+}
+
+void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
+{
+ CMtSync *sync = &p->hashSync;
+ if (!sync->needStart)
+ {
+ CriticalSection_Enter(&sync->cs);
+ sync->csWasEntered = True;
+ }
+
+ BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
+
+ if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
+ {
+ UInt32 subValue = p->pos - p->cyclicBufferSize;
+ MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
+ p->pos -= subValue;
+ }
+
+ if (!sync->needStart)
+ {
+ CriticalSection_Leave(&sync->cs);
+ sync->csWasEntered = False;
+ }
+}
+
+void BtThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->btSync;
+ for (;;)
+ {
+ UInt32 blockIndex = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = blockIndex;
+ MtSync_StopWriting(&mt->hashSync);
+ Event_Set(&p->wasStopped);
+ break;
+ }
+ Semaphore_Wait(&p->freeSemaphore);
+ BtFillBlock(mt, blockIndex++);
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_Construct(CMatchFinderMt *p)
+{
+ p->hashBuf = 0;
+ MtSync_Construct(&p->hashSync);
+ MtSync_Construct(&p->btSync);
+}
+
+void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->hashBuf);
+ p->hashBuf = 0;
+}
+
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ MtSync_Destruct(&p->hashSync);
+ MtSync_Destruct(&p->btSync);
+ MatchFinderMt_FreeMem(p, alloc);
+}
+
+#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
+#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
+
+static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
+static unsigned MY_STD_CALL BtThreadFunc2(void *p)
+{
+ Byte allocaDummy[0x180];
+ int i = 0;
+ for (i = 0; i < 16; i++)
+ allocaDummy[i] = (Byte)i;
+ BtThreadFunc((CMatchFinderMt *)p);
+ return 0;
+}
+
+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->historySize = historySize;
+ if (kMtBtBlockSize <= matchMaxLen * 4)
+ return SZ_ERROR_PARAM;
+ if (p->hashBuf == 0)
+ {
+ p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
+ if (p->hashBuf == 0)
+ return SZ_ERROR_MEM;
+ p->btBuf = p->hashBuf + kHashBufferSize;
+ }
+ keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
+ keepAddBufferAfter += kMtHashBlockSize;
+ if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
+ return SZ_ERROR_MEM;
+
+ RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
+ RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
+ return SZ_OK;
+}
+
+/* Call it after ReleaseStream / SetStream */
+void MatchFinderMt_Init(CMatchFinderMt *p)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->btBufPos = p->btBufPosLimit = 0;
+ p->hashBufPos = p->hashBufPosLimit = 0;
+ MatchFinder_Init(mf);
+ p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
+ p->btNumAvailBytes = 0;
+ p->lzPos = p->historySize + 1;
+
+ p->hash = mf->hash;
+ p->fixedHashSize = mf->fixedHashSize;
+ p->crc = mf->crc;
+
+ p->son = mf->son;
+ p->matchMaxLen = mf->matchMaxLen;
+ p->numHashBytes = mf->numHashBytes;
+ p->pos = mf->pos;
+ p->buffer = mf->buffer;
+ p->cyclicBufferPos = mf->cyclicBufferPos;
+ p->cyclicBufferSize = mf->cyclicBufferSize;
+ p->cutValue = mf->cutValue;
+}
+
+/* ReleaseStream is required to finish multithreading */
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
+{
+ MtSync_StopWriting(&p->btSync);
+ /* p->MatchFinder->ReleaseStream(); */
+}
+
+void MatchFinderMt_Normalize(CMatchFinderMt *p)
+{
+ MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
+ p->lzPos = p->historySize + 1;
+}
+
+void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
+{
+ UInt32 blockIndex;
+ MtSync_GetNextBlock(&p->btSync);
+ blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
+ p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
+ p->btBufPosLimit += p->btBuf[p->btBufPos++];
+ p->btNumAvailBytes = p->btBuf[p->btBufPos++];
+ if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
+ MatchFinderMt_Normalize(p);
+}
+
+const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
+{
+ return p->pointerToCurPos;
+}
+
+#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
+
+UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
+{
+ GET_NEXT_BLOCK_IF_REQUIRED;
+ return p->btNumAvailBytes;
+}
+
+Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
+{
+ return p->pointerToCurPos[index];
+}
+
+UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, curMatch2;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH2_CALC
+
+ curMatch2 = hash[hash2Value];
+ hash[hash2Value] = lzPos;
+
+ if (curMatch2 >= matchMinPos)
+ if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ *distances++ = 2;
+ *distances++ = lzPos - curMatch2 - 1;
+ }
+ return distances;
+}
+
+UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH3_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
+ {
+ *distances++ = 3;
+ *distances++ = lzPos - curMatch3 - 1;
+ }
+ return distances;
+}
+
+/*
+UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH4_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+ curMatch4 = hash[kFix4HashSize + hash4Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[kFix4HashSize + hash4Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch3 - 1;
+ if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
+ {
+ distances[0] = 4;
+ return distances + 2;
+ }
+ distances[0] = 3;
+ distances += 2;
+ }
+
+ if (curMatch4 >= matchMinPos)
+ if (
+ cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
+ cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
+ )
+ {
+ *distances++ = 4;
+ *distances++ = lzPos - curMatch4 - 1;
+ }
+ return distances;
+}
+*/
+
+#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
+
+UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+ p->btNumAvailBytes--;
+ {
+ UInt32 i;
+ for (i = 0; i < len; i += 2)
+ {
+ *distances++ = *btBuf++;
+ *distances++ = *btBuf++;
+ }
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+
+ if (len == 0)
+ {
+ if (p->btNumAvailBytes-- >= 4)
+ len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
+ }
+ else
+ {
+ /* Condition: there are matches in btBuf with length < p->numHashBytes */
+ UInt32 *distances2;
+ p->btNumAvailBytes--;
+ distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
+ do
+ {
+ *distances2++ = *btBuf++;
+ *distances2++ = *btBuf++;
+ }
+ while ((len -= 2) != 0);
+ len = (UInt32)(distances2 - (distances));
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
+#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
+#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
+
+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER2_MT { p->btNumAvailBytes--;
+ SKIP_FOOTER_MT
+}
+
+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER_MT(2)
+ UInt32 hash2Value;
+ MT_HASH2_CALC
+ hash[hash2Value] = p->lzPos;
+ SKIP_FOOTER_MT
+}
+
+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER_MT(3)
+ UInt32 hash2Value, hash3Value;
+ MT_HASH3_CALC
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER_MT
+}
+
+/*
+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER_MT(4)
+ UInt32 hash2Value, hash3Value, hash4Value;
+ MT_HASH4_CALC
+ hash[kFix4HashSize + hash4Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER_MT
+}
+*/
+
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
+ switch(p->MatchFinder->numHashBytes)
+ {
+ case 2:
+ p->GetHeadsFunc = GetHeads2;
+ p->MixMatchesFunc = (Mf_Mix_Matches)0;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
+ break;
+ case 3:
+ p->GetHeadsFunc = GetHeads3;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
+ break;
+ default:
+ /* case 4: */
+ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
+ /* p->GetHeadsFunc = GetHeads4; */
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
+ break;
+ /*
+ default:
+ p->GetHeadsFunc = GetHeads5;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
+ break;
+ */
+ }
+}
diff --git a/dep/StormLib/src/lzma/C/LzFindMt.h b/dep/StormLib/src/lzma/C/LzFindMt.h
new file mode 100644
index 00000000000..b985af5fee2
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzFindMt.h
@@ -0,0 +1,105 @@
+/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_FIND_MT_H
+#define __LZ_FIND_MT_H
+
+#include "LzFind.h"
+#include "Threads.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kMtHashBlockSize (1 << 13)
+#define kMtHashNumBlocks (1 << 3)
+#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
+
+#define kMtBtBlockSize (1 << 14)
+#define kMtBtNumBlocks (1 << 6)
+#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
+
+typedef struct _CMtSync
+{
+ Bool wasCreated;
+ Bool needStart;
+ Bool exit;
+ Bool stopWriting;
+
+ CThread thread;
+ CAutoResetEvent canStart;
+ CAutoResetEvent wasStarted;
+ CAutoResetEvent wasStopped;
+ CSemaphore freeSemaphore;
+ CSemaphore filledSemaphore;
+ Bool csWasInitialized;
+ Bool csWasEntered;
+ CCriticalSection cs;
+ UInt32 numProcessedBlocks;
+} CMtSync;
+
+typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
+
+/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
+#define kMtCacheLineDummy 128
+
+typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
+ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
+
+typedef struct _CMatchFinderMt
+{
+ /* LZ */
+ const Byte *pointerToCurPos;
+ UInt32 *btBuf;
+ UInt32 btBufPos;
+ UInt32 btBufPosLimit;
+ UInt32 lzPos;
+ UInt32 btNumAvailBytes;
+
+ UInt32 *hash;
+ UInt32 fixedHashSize;
+ UInt32 historySize;
+ const UInt32 *crc;
+
+ Mf_Mix_Matches MixMatchesFunc;
+
+ /* LZ + BT */
+ CMtSync btSync;
+ Byte btDummy[kMtCacheLineDummy];
+
+ /* BT */
+ UInt32 *hashBuf;
+ UInt32 hashBufPos;
+ UInt32 hashBufPosLimit;
+ UInt32 hashNumAvail;
+
+ CLzRef *son;
+ UInt32 matchMaxLen;
+ UInt32 numHashBytes;
+ UInt32 pos;
+ Byte *buffer;
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be historySize + 1 */
+ UInt32 cutValue;
+
+ /* BT + Hash */
+ CMtSync hashSync;
+ /* Byte hashDummy[kMtCacheLineDummy]; */
+
+ /* Hash */
+ Mf_GetHeads GetHeadsFunc;
+ CMatchFinder *MatchFinder;
+} CMatchFinderMt;
+
+void MatchFinderMt_Construct(CMatchFinderMt *p);
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/LzHash.h b/dep/StormLib/src/lzma/C/LzHash.h
new file mode 100644
index 00000000000..f3e89966cc7
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzHash.h
@@ -0,0 +1,54 @@
+/* LzHash.h -- HASH functions for LZ algorithms
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_HASH_H
+#define __LZ_HASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
+ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
+ hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/LzmaDec.c b/dep/StormLib/src/lzma/C/LzmaDec.c
new file mode 100644
index 00000000000..2036761bf14
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzmaDec.c
@@ -0,0 +1,999 @@
+/* LzmaDec.c -- LZMA Decoder
+2009-09-20 : Igor Pavlov : Public domain */
+
+#include "LzmaDec.h"
+
+#include <string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+ { UPDATE_0(p); i = (i + i); A0; } else \
+ { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+ { i = 1; \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+ { UPDATE_0_CHECK; i = (i + i); A0; } else \
+ { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+ Result:
+ SZ_OK - OK
+ SZ_ERROR_DATA - Error
+ p->remainLen:
+ < kMatchSpecLenStart : normal remain
+ = kMatchSpecLenStart : finished
+ = kMatchSpecLenStart + 1 : Flush marker
+ = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ CLzmaProb *probs = p->probs;
+
+ unsigned state = p->state;
+ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+ unsigned lc = p->prop.lc;
+
+ Byte *dic = p->dic;
+ SizeT dicBufSize = p->dicBufSize;
+ SizeT dicPos = p->dicPos;
+
+ UInt32 processedPos = p->processedPos;
+ UInt32 checkDicSize = p->checkDicSize;
+ unsigned len = 0;
+
+ const Byte *buf = p->buf;
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+
+ do
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = processedPos & pbMask;
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ unsigned symbol;
+ UPDATE_0(prob);
+ prob = probs + Literal;
+ if (checkDicSize != 0 || processedPos != 0)
+ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+ if (state < kNumLitStates)
+ {
+ state -= (state < 4) ? state : 3;
+ symbol = 1;
+ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ unsigned offs = 0x100;
+ state -= (state < 10) ? 3 : 6;
+ symbol = 1;
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ dic[dicPos++] = (Byte)symbol;
+ processedPos++;
+ continue;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRep + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ state += kNumStates;
+ prob = probs + LenCoder;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ if (checkDicSize == 0 && processedPos == 0)
+ return SZ_ERROR_DATA;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ processedPos++;
+ state = state < kNumLitStates ? 9 : 11;
+ continue;
+ }
+ UPDATE_1(prob);
+ }
+ else
+ {
+ UInt32 distance;
+ UPDATE_1(prob);
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = (1 << kLenNumLowBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenChoice2;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = (1 << kLenNumMidBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = (1 << kLenNumHighBits);
+ }
+ }
+ TREE_DECODE(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state >= kNumStates)
+ {
+ UInt32 distance;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+ TREE_6_DECODE(prob, distance);
+ if (distance >= kStartPosModelIndex)
+ {
+ unsigned posSlot = (unsigned)distance;
+ int numDirectBits = (int)(((distance >> 1) - 1));
+ distance = (2 | (distance & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ distance <<= numDirectBits;
+ prob = probs + SpecPos + distance - posSlot - 1;
+ {
+ UInt32 mask = 1;
+ unsigned i = 1;
+ do
+ {
+ GET_BIT2(prob + i, i, ; , distance |= mask);
+ mask <<= 1;
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ NORMALIZE
+ range >>= 1;
+
+ {
+ UInt32 t;
+ code -= range;
+ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+ distance = (distance << 1) + (t + 1);
+ code += range & t;
+ }
+ /*
+ distance <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ distance |= 1;
+ }
+ */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ distance <<= kNumAlignBits;
+ {
+ unsigned i = 1;
+ GET_BIT2(prob + i, i, ; , distance |= 1);
+ GET_BIT2(prob + i, i, ; , distance |= 2);
+ GET_BIT2(prob + i, i, ; , distance |= 4);
+ GET_BIT2(prob + i, i, ; , distance |= 8);
+ }
+ if (distance == (UInt32)0xFFFFFFFF)
+ {
+ len += kMatchSpecLenStart;
+ state -= kNumStates;
+ break;
+ }
+ }
+ }
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ rep0 = distance + 1;
+ if (checkDicSize == 0)
+ {
+ if (distance >= processedPos)
+ return SZ_ERROR_DATA;
+ }
+ else if (distance >= checkDicSize)
+ return SZ_ERROR_DATA;
+ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+ }
+
+ len += kMatchMinLen;
+
+ if (limit == dicPos)
+ return SZ_ERROR_DATA;
+ {
+ SizeT rem = limit - dicPos;
+ unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+ processedPos += curLen;
+
+ len -= curLen;
+ if (pos + curLen <= dicBufSize)
+ {
+ Byte *dest = dic + dicPos;
+ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+ const Byte *lim = dest + curLen;
+ dicPos += curLen;
+ do
+ *(dest) = (Byte)*(dest + src);
+ while (++dest != lim);
+ }
+ else
+ {
+ do
+ {
+ dic[dicPos++] = dic[pos];
+ if (++pos == dicBufSize)
+ pos = 0;
+ }
+ while (--curLen != 0);
+ }
+ }
+ }
+ }
+ while (dicPos < limit && buf < bufLimit);
+ NORMALIZE;
+ p->buf = buf;
+ p->range = range;
+ p->code = code;
+ p->remainLen = len;
+ p->dicPos = dicPos;
+ p->processedPos = processedPos;
+ p->reps[0] = rep0;
+ p->reps[1] = rep1;
+ p->reps[2] = rep2;
+ p->reps[3] = rep3;
+ p->state = state;
+
+ return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+ {
+ Byte *dic = p->dic;
+ SizeT dicPos = p->dicPos;
+ SizeT dicBufSize = p->dicBufSize;
+ unsigned len = p->remainLen;
+ UInt32 rep0 = p->reps[0];
+ if (limit - dicPos < len)
+ len = (unsigned)(limit - dicPos);
+
+ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+ p->checkDicSize = p->prop.dicSize;
+
+ p->processedPos += len;
+ p->remainLen -= len;
+ while (len-- != 0)
+ {
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ }
+ p->dicPos = dicPos;
+ }
+}
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ do
+ {
+ SizeT limit2 = limit;
+ if (p->checkDicSize == 0)
+ {
+ UInt32 rem = p->prop.dicSize - p->processedPos;
+ if (limit - p->dicPos > rem)
+ limit2 = p->dicPos + rem;
+ }
+ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+ if (p->processedPos >= p->prop.dicSize)
+ p->checkDicSize = p->prop.dicSize;
+ LzmaDec_WriteRem(p, limit);
+ }
+ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+ if (p->remainLen > kMatchSpecLenStart)
+ {
+ p->remainLen = kMatchSpecLenStart;
+ }
+ return 0;
+}
+
+typedef enum
+{
+ DUMMY_ERROR, /* unexpected end of input stream */
+ DUMMY_LIT,
+ DUMMY_MATCH,
+ DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+ const Byte *bufLimit = buf + inSize;
+ CLzmaProb *probs = p->probs;
+ unsigned state = p->state;
+ ELzmaDummy res;
+
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK
+
+ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+ prob = probs + Literal;
+ if (p->checkDicSize != 0 || p->processedPos != 0)
+ prob += (LZMA_LIT_SIZE *
+ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+ if (state < kNumLitStates)
+ {
+ unsigned symbol = 1;
+ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+ unsigned offs = 0x100;
+ unsigned symbol = 1;
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ res = DUMMY_LIT;
+ }
+ else
+ {
+ unsigned len;
+ UPDATE_1_CHECK;
+
+ prob = probs + IsRep + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ state = 0;
+ prob = probs + LenCoder;
+ res = DUMMY_MATCH;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ res = DUMMY_REP;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ NORMALIZE_CHECK;
+ return DUMMY_REP;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ }
+ state = kNumStates;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = 1 << kLenNumLowBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenChoice2;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = 1 << kLenNumMidBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = 1 << kLenNumHighBits;
+ }
+ }
+ TREE_DECODE_CHECK(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ unsigned posSlot;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+
+ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+ if (posSlot < kEndPosModelIndex)
+ {
+ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ NORMALIZE_CHECK
+ range >>= 1;
+ code -= range & (((code - range) >> 31) - 1);
+ /* if (code >= range) code -= range; */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ unsigned i = 1;
+ do
+ {
+ GET_BIT_CHECK(prob + i, i);
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ }
+ }
+ }
+ NORMALIZE_CHECK;
+ return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+ p->range = 0xFFFFFFFF;
+ p->needFlush = 0;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+ p->needFlush = 1;
+ p->remainLen = 0;
+ p->tempBufSize = 0;
+
+ if (initDic)
+ {
+ p->processedPos = 0;
+ p->checkDicSize = 0;
+ p->needInitState = 1;
+ }
+ if (initState)
+ p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+ p->dicPos = 0;
+ LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+ UInt32 i;
+ CLzmaProb *probs = p->probs;
+ for (i = 0; i < numProbs; i++)
+ probs[i] = kBitModelTotal >> 1;
+ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+ p->state = 0;
+ p->needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+ ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT inSize = *srcLen;
+ (*srcLen) = 0;
+ LzmaDec_WriteRem(p, dicLimit);
+
+ *status = LZMA_STATUS_NOT_SPECIFIED;
+
+ while (p->remainLen != kMatchSpecLenStart)
+ {
+ int checkEndMarkNow;
+
+ if (p->needFlush != 0)
+ {
+ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+ p->tempBuf[p->tempBufSize++] = *src++;
+ if (p->tempBufSize < RC_INIT_SIZE)
+ {
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (p->tempBuf[0] != 0)
+ return SZ_ERROR_DATA;
+
+ LzmaDec_InitRc(p, p->tempBuf);
+ p->tempBufSize = 0;
+ }
+
+ checkEndMarkNow = 0;
+ if (p->dicPos >= dicLimit)
+ {
+ if (p->remainLen == 0 && p->code == 0)
+ {
+ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+ return SZ_OK;
+ }
+ if (finishMode == LZMA_FINISH_ANY)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_OK;
+ }
+ if (p->remainLen != 0)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ checkEndMarkNow = 1;
+ }
+
+ if (p->needInitState)
+ LzmaDec_InitStateReal(p);
+
+ if (p->tempBufSize == 0)
+ {
+ SizeT processed;
+ const Byte *bufLimit;
+ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ memcpy(p->tempBuf, src, inSize);
+ p->tempBufSize = (unsigned)inSize;
+ (*srcLen) += inSize;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ bufLimit = src;
+ }
+ else
+ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+ p->buf = src;
+ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+ return SZ_ERROR_DATA;
+ processed = (SizeT)(p->buf - src);
+ (*srcLen) += processed;
+ src += processed;
+ inSize -= processed;
+ }
+ else
+ {
+ unsigned rem = p->tempBufSize, lookAhead = 0;
+ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+ p->tempBuf[rem++] = src[lookAhead++];
+ p->tempBufSize = rem;
+ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ (*srcLen) += lookAhead;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ }
+ p->buf = p->tempBuf;
+ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+ return SZ_ERROR_DATA;
+ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+ (*srcLen) += lookAhead;
+ src += lookAhead;
+ inSize -= lookAhead;
+ p->tempBufSize = 0;
+ }
+ }
+ if (p->code == 0)
+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
+ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT outSize = *destLen;
+ SizeT inSize = *srcLen;
+ *srcLen = *destLen = 0;
+ for (;;)
+ {
+ SizeT inSizeCur = inSize, outSizeCur, dicPos;
+ ELzmaFinishMode curFinishMode;
+ SRes res;
+ if (p->dicPos == p->dicBufSize)
+ p->dicPos = 0;
+ dicPos = p->dicPos;
+ if (outSize > p->dicBufSize - dicPos)
+ {
+ outSizeCur = p->dicBufSize;
+ curFinishMode = LZMA_FINISH_ANY;
+ }
+ else
+ {
+ outSizeCur = dicPos + outSize;
+ curFinishMode = finishMode;
+ }
+
+ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+ src += inSizeCur;
+ inSize -= inSizeCur;
+ *srcLen += inSizeCur;
+ outSizeCur = p->dicPos - dicPos;
+ memcpy(dest, p->dic + dicPos, outSizeCur);
+ dest += outSizeCur;
+ outSize -= outSizeCur;
+ *destLen += outSizeCur;
+ if (res != 0)
+ return res;
+ if (outSizeCur == 0 || outSize == 0)
+ return SZ_OK;
+ }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->probs);
+ p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->dic);
+ p->dic = 0;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+ LzmaDec_FreeProbs(p, alloc);
+ LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+ UInt32 dicSize;
+ Byte d;
+
+ if (size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_UNSUPPORTED;
+ else
+ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+
+ if (dicSize < LZMA_DIC_MIN)
+ dicSize = LZMA_DIC_MIN;
+ p->dicSize = dicSize;
+
+ d = data[0];
+ if (d >= (9 * 5 * 5))
+ return SZ_ERROR_UNSUPPORTED;
+
+ p->lc = d % 9;
+ d /= 9;
+ p->pb = d / 5;
+ p->lp = d % 5;
+
+ return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+ UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+ if (p->probs == 0 || numProbs != p->numProbs)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+ p->numProbs = numProbs;
+ if (p->probs == 0)
+ return SZ_ERROR_MEM;
+ }
+ return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ SizeT dicBufSize;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ dicBufSize = propNew.dicSize;
+ if (p->dic == 0 || dicBufSize != p->dicBufSize)
+ {
+ LzmaDec_FreeDict(p, alloc);
+ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+ if (p->dic == 0)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ return SZ_ERROR_MEM;
+ }
+ }
+ p->dicBufSize = dicBufSize;
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc)
+{
+ CLzmaDec p;
+ SRes res;
+ SizeT inSize = *srcLen;
+ SizeT outSize = *destLen;
+ *srcLen = *destLen = 0;
+ if (inSize < RC_INIT_SIZE)
+ return SZ_ERROR_INPUT_EOF;
+
+ LzmaDec_Construct(&p);
+ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+ if (res != 0)
+ return res;
+ p.dic = dest;
+ p.dicBufSize = outSize;
+
+ LzmaDec_Init(&p);
+
+ *srcLen = inSize;
+ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+ res = SZ_ERROR_INPUT_EOF;
+
+ (*destLen) = p.dicPos;
+ LzmaDec_FreeProbs(&p, alloc);
+ return res;
+}
diff --git a/dep/StormLib/src/lzma/C/LzmaDec.h b/dep/StormLib/src/lzma/C/LzmaDec.h
new file mode 100644
index 00000000000..bf7f084ba3d
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzmaDec.h
@@ -0,0 +1,231 @@
+/* LzmaDec.h -- LZMA Decoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+ but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+ unsigned lc, lp, pb;
+ UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+ SZ_OK
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+ CLzmaProps prop;
+ CLzmaProb *probs;
+ Byte *dic;
+ const Byte *buf;
+ UInt32 range, code;
+ SizeT dicPos;
+ SizeT dicBufSize;
+ UInt32 processedPos;
+ UInt32 checkDicSize;
+ unsigned state;
+ UInt32 reps[4];
+ unsigned remainLen;
+ int needFlush;
+ int needInitState;
+ UInt32 numProbs;
+ unsigned tempBufSize;
+ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+ LZMA_FINISH_ANY, /* finish at any point */
+ LZMA_FINISH_END /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+ You must use LZMA_FINISH_END, when you know that current output buffer
+ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+ and output value of destLen will be less than output buffer size limit.
+ You can check status result also.
+
+ You can use multiple checks to test data integrity after full decompression:
+ 1) Check Result and "status" variable.
+ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+ You must use correct finish mode in that case. */
+
+typedef enum
+{
+ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
+ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
+ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
+ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+ 1) Dictionary Interface
+ 2) Buffer Interface
+ 3) One Call Interface
+ You can select any of these interfaces, but don't mix functions from different
+ groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+ 1) LzmaDec_Allocate / LzmaDec_Free
+ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+ You can use variant 2, if you set dictionary buffer manually.
+ For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+ SZ_OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+ dictionary to some other external buffer.
+ You must work with CLzmaDec variables directly in this interface.
+
+ STEPS:
+ LzmaDec_Constr()
+ LzmaDec_Allocate()
+ for (each new stream)
+ {
+ LzmaDec_Init()
+ while (it needs more decompression)
+ {
+ LzmaDec_DecodeToDic()
+ use data from CLzmaDec::dic and update CLzmaDec::dicPos
+ }
+ }
+ LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+
+ The decoding to internal dictionary buffer (CLzmaDec::dic).
+ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (dicLimit).
+ LZMA_FINISH_ANY - Decode just dicLimit bytes.
+ LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_NEEDS_MORE_INPUT
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+ See LzmaDec_DecodeToDic description for information about STEPS and return results,
+ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+ to work with CLzmaDec variables manually.
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/LzmaEnc.c b/dep/StormLib/src/lzma/C/LzmaEnc.c
new file mode 100644
index 00000000000..169d4f4639e
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzmaEnc.c
@@ -0,0 +1,2268 @@
+/* LzmaEnc.c -- LZMA Encoder
+2009-11-24 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
+#include <stdio.h>
+#endif
+
+#include "LzmaEnc.h"
+
+#include "LzFind.h"
+#ifndef _7ZIP_ST
+#include "LzFindMt.h"
+#endif
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
+
+#define kBlockSize (9 << 10)
+#define kUnpackBlockSize (1 << 18)
+#define kMatchArraySize (1 << 21)
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
+
+#define kNumMaxDirectBits (31)
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal >> 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 << kNumBitPriceShiftBits)
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+ p->level = 5;
+ p->dictSize = p->mc = 0;
+ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
+ p->writeEndMark = 0;
+}
+
+void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+ int level = p->level;
+ if (level < 0) level = 5;
+ p->level = level;
+ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
+ if (p->lc < 0) p->lc = 3;
+ if (p->lp < 0) p->lp = 0;
+ if (p->pb < 0) p->pb = 2;
+ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
+ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
+ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
+ if (p->numHashBytes < 0) p->numHashBytes = 4;
+ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+ if (p->numThreads < 0)
+ p->numThreads =
+ #ifndef _7ZIP_ST
+ ((p->btMode && p->algo) ? 2 : 1);
+ #else
+ 1;
+ #endif
+}
+
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+ CLzmaEncProps props = *props2;
+ LzmaEncProps_Normalize(&props);
+ return props.dictSize;
+}
+
+/* #define LZMA_LOG_BSR */
+/* Define it for Intel's CPU */
+
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 30
+
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
+
+UInt32 GetPosSlot1(UInt32 pos)
+{
+ UInt32 res;
+ BSR2_RET(pos, res);
+ return res;
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+ int c = 2, slotFast;
+ g_FastPos[0] = 0;
+ g_FastPos[1] = 1;
+
+ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
+ {
+ UInt32 k = (1 << ((slotFast >> 1) - 1));
+ UInt32 j;
+ for (j = 0; j < k; j++, c++)
+ g_FastPos[c] = (Byte)slotFast;
+ }
+}
+
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
+ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
+ res = p->g_FastPos[pos >> i] + (i * 2); }
+/*
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
+ p->g_FastPos[pos >> 6] + 12 : \
+ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+*/
+
+#define GetPosSlot1(pos) p->g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef unsigned CState;
+
+typedef struct
+{
+ UInt32 price;
+
+ CState state;
+ int prev1IsChar;
+ int prev2;
+
+ UInt32 posPrev2;
+ UInt32 backPrev2;
+
+ UInt32 posPrev;
+ UInt32 backPrev;
+ UInt32 backs[LZMA_NUM_REPS];
+} COptimal;
+
+#define kNumOpts (1 << 12)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6
+#define kDicLogSizeMin 0
+#define kDicLogSizeMax 32
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
+
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+ CLzmaProb choice;
+ CLzmaProb choice2;
+ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
+ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
+ CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+ CLenEnc p;
+ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+ UInt32 tableSize;
+ UInt32 counters[LZMA_NUM_PB_STATES_MAX];
+} CLenPriceEnc;
+
+typedef struct
+{
+ UInt32 range;
+ Byte cache;
+ UInt64 low;
+ UInt64 cacheSize;
+ Byte *buf;
+ Byte *bufLim;
+ Byte *bufBase;
+ ISeqOutStream *outStream;
+ UInt64 processed;
+ SRes res;
+} CRangeEnc;
+
+typedef struct
+{
+ CLzmaProb *litProbs;
+
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb isRep[kNumStates];
+ CLzmaProb isRepG0[kNumStates];
+ CLzmaProb isRepG1[kNumStates];
+ CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+ CLenPriceEnc lenEnc;
+ CLenPriceEnc repLenEnc;
+
+ UInt32 reps[LZMA_NUM_REPS];
+ UInt32 state;
+} CSaveState;
+
+typedef struct
+{
+ IMatchFinder matchFinder;
+ void *matchFinderObj;
+
+ #ifndef _7ZIP_ST
+ Bool mtMode;
+ CMatchFinderMt matchFinderMt;
+ #endif
+
+ CMatchFinder matchFinderBase;
+
+ #ifndef _7ZIP_ST
+ Byte pad[128];
+ #endif
+
+ UInt32 optimumEndIndex;
+ UInt32 optimumCurrentIndex;
+
+ UInt32 longestMatchLength;
+ UInt32 numPairs;
+ UInt32 numAvail;
+ COptimal opt[kNumOpts];
+
+ #ifndef LZMA_LOG_BSR
+ Byte g_FastPos[1 << kNumLogBits];
+ #endif
+
+ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+ UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+ UInt32 numFastBytes;
+ UInt32 additionalOffset;
+ UInt32 reps[LZMA_NUM_REPS];
+ UInt32 state;
+
+ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+ UInt32 alignPrices[kAlignTableSize];
+ UInt32 alignPriceCount;
+
+ UInt32 distTableSize;
+
+ unsigned lc, lp, pb;
+ unsigned lpMask, pbMask;
+
+ CLzmaProb *litProbs;
+
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb isRep[kNumStates];
+ CLzmaProb isRepG0[kNumStates];
+ CLzmaProb isRepG1[kNumStates];
+ CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+ CLenPriceEnc lenEnc;
+ CLenPriceEnc repLenEnc;
+
+ unsigned lclp;
+
+ Bool fastMode;
+
+ CRangeEnc rc;
+
+ Bool writeEndMark;
+ UInt64 nowPos64;
+ UInt32 matchPriceCount;
+ Bool finished;
+ Bool multiThread;
+
+ SRes result;
+ UInt32 dictSize;
+ UInt32 matchFinderCycles;
+
+ int needInit;
+
+ CSaveState saveState;
+} CLzmaEnc;
+
+void LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ CSaveState *dest = &p->saveState;
+ int i;
+ dest->lenEnc = p->lenEnc;
+ dest->repLenEnc = p->repLenEnc;
+ dest->state = p->state;
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+ }
+ for (i = 0; i < kNumLenToPosStates; i++)
+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+ memcpy(dest->reps, p->reps, sizeof(p->reps));
+ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
+}
+
+void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+ CLzmaEnc *dest = (CLzmaEnc *)pp;
+ const CSaveState *p = &dest->saveState;
+ int i;
+ dest->lenEnc = p->lenEnc;
+ dest->repLenEnc = p->repLenEnc;
+ dest->state = p->state;
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+ }
+ for (i = 0; i < kNumLenToPosStates; i++)
+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+ memcpy(dest->reps, p->reps, sizeof(p->reps));
+ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ CLzmaEncProps props = *props2;
+ LzmaEncProps_Normalize(&props);
+
+ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
+ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
+ return SZ_ERROR_PARAM;
+ p->dictSize = props.dictSize;
+ p->matchFinderCycles = props.mc;
+ {
+ unsigned fb = props.fb;
+ if (fb < 5)
+ fb = 5;
+ if (fb > LZMA_MATCH_LEN_MAX)
+ fb = LZMA_MATCH_LEN_MAX;
+ p->numFastBytes = fb;
+ }
+ p->lc = props.lc;
+ p->lp = props.lp;
+ p->pb = props.pb;
+ p->fastMode = (props.algo == 0);
+ p->matchFinderBase.btMode = props.btMode;
+ {
+ UInt32 numHashBytes = 4;
+ if (props.btMode)
+ {
+ if (props.numHashBytes < 2)
+ numHashBytes = 2;
+ else if (props.numHashBytes < 4)
+ numHashBytes = props.numHashBytes;
+ }
+ p->matchFinderBase.numHashBytes = numHashBytes;
+ }
+
+ p->matchFinderBase.cutValue = props.mc;
+
+ p->writeEndMark = props.writeEndMark;
+
+ #ifndef _7ZIP_ST
+ /*
+ if (newMultiThread != _multiThread)
+ {
+ ReleaseMatchFinder();
+ _multiThread = newMultiThread;
+ }
+ */
+ p->multiThread = (props.numThreads > 1);
+ #endif
+
+ return SZ_OK;
+}
+
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+#define IsCharState(s) ((s) < 7)
+
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 << 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+ p->outStream = 0;
+ p->bufBase = 0;
+}
+
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+
+#define RC_BUF_SIZE (1 << 16)
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+{
+ if (p->bufBase == 0)
+ {
+ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
+ if (p->bufBase == 0)
+ return 0;
+ p->bufLim = p->bufBase + RC_BUF_SIZE;
+ }
+ return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->bufBase);
+ p->bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+ /* Stream.Init(); */
+ p->low = 0;
+ p->range = 0xFFFFFFFF;
+ p->cacheSize = 1;
+ p->cache = 0;
+
+ p->buf = p->bufBase;
+
+ p->processed = 0;
+ p->res = SZ_OK;
+}
+
+static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+ size_t num;
+ if (p->res != SZ_OK)
+ return;
+ num = p->buf - p->bufBase;
+ if (num != p->outStream->Write(p->outStream, p->bufBase, num))
+ p->res = SZ_ERROR_WRITE;
+ p->processed += num;
+ p->buf = p->bufBase;
+}
+
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
+ {
+ Byte temp = p->cache;
+ do
+ {
+ Byte *buf = p->buf;
+ *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
+ p->buf = buf;
+ if (buf == p->bufLim)
+ RangeEnc_FlushStream(p);
+ temp = 0xFF;
+ }
+ while (--p->cacheSize != 0);
+ p->cache = (Byte)((UInt32)p->low >> 24);
+ }
+ p->cacheSize++;
+ p->low = (UInt32)p->low << 8;
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+ int i;
+ for (i = 0; i < 5; i++)
+ RangeEnc_ShiftLow(p);
+}
+
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
+{
+ do
+ {
+ p->range >>= 1;
+ p->low += p->range & (0 - ((value >> --numBits) & 1));
+ if (p->range < kTopValue)
+ {
+ p->range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+ }
+ while (numBits != 0);
+}
+
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
+{
+ UInt32 ttt = *prob;
+ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
+ if (symbol == 0)
+ {
+ p->range = newBound;
+ ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
+ }
+ else
+ {
+ p->low += newBound;
+ p->range -= newBound;
+ ttt -= ttt >> kNumMoveBits;
+ }
+ *prob = (CLzmaProb)ttt;
+ if (p->range < kTopValue)
+ {
+ p->range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+{
+ symbol |= 0x100;
+ do
+ {
+ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+ symbol <<= 1;
+ }
+ while (symbol < 0x10000);
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+{
+ UInt32 offs = 0x100;
+ symbol |= 0x100;
+ do
+ {
+ matchByte <<= 1;
+ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+ symbol <<= 1;
+ offs &= ~(matchByte ^ symbol);
+ }
+ while (symbol < 0x10000);
+}
+
+void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+{
+ UInt32 i;
+ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
+ {
+ const int kCyclesBits = kNumBitPriceShiftBits;
+ UInt32 w = i;
+ UInt32 bitCount = 0;
+ int j;
+ for (j = 0; j < kCyclesBits; j++)
+ {
+ w = w * w;
+ bitCount <<= 1;
+ while (w >= ((UInt32)1 << 16))
+ {
+ w >>= 1;
+ bitCount++;
+ }
+ }
+ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+ }
+}
+
+
+#define GET_PRICE(prob, symbol) \
+ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, symbol) \
+ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ symbol |= 0x100;
+ do
+ {
+ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
+ symbol <<= 1;
+ }
+ while (symbol < 0x10000);
+ return price;
+}
+
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ UInt32 offs = 0x100;
+ symbol |= 0x100;
+ do
+ {
+ matchByte <<= 1;
+ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
+ symbol <<= 1;
+ offs &= ~(matchByte ^ symbol);
+ }
+ while (symbol < 0x10000);
+ return price;
+}
+
+
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+ UInt32 m = 1;
+ int i;
+ for (i = numBitLevels; i != 0;)
+ {
+ UInt32 bit;
+ i--;
+ bit = (symbol >> i) & 1;
+ RangeEnc_EncodeBit(rc, probs + m, bit);
+ m = (m << 1) | bit;
+ }
+}
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+ UInt32 m = 1;
+ int i;
+ for (i = 0; i < numBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ RangeEnc_EncodeBit(rc, probs + m, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+}
+
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ symbol |= (1 << numBitLevels);
+ while (symbol != 1)
+ {
+ price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
+ symbol >>= 1;
+ }
+ return price;
+}
+
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ UInt32 m = 1;
+ int i;
+ for (i = numBitLevels; i != 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += GET_PRICEa(probs[m], bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+}
+
+
+static void LenEnc_Init(CLenEnc *p)
+{
+ unsigned i;
+ p->choice = p->choice2 = kProbInitValue;
+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
+ p->low[i] = kProbInitValue;
+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
+ p->mid[i] = kProbInitValue;
+ for (i = 0; i < kLenNumHighSymbols; i++)
+ p->high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+{
+ if (symbol < kLenNumLowSymbols)
+ {
+ RangeEnc_EncodeBit(rc, &p->choice, 0);
+ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
+ }
+ else
+ {
+ RangeEnc_EncodeBit(rc, &p->choice, 1);
+ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
+ {
+ RangeEnc_EncodeBit(rc, &p->choice2, 0);
+ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
+ }
+ else
+ {
+ RangeEnc_EncodeBit(rc, &p->choice2, 1);
+ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+ }
+ }
+}
+
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+{
+ UInt32 a0 = GET_PRICE_0a(p->choice);
+ UInt32 a1 = GET_PRICE_1a(p->choice);
+ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
+ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
+ UInt32 i = 0;
+ for (i = 0; i < kLenNumLowSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
+ }
+ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+ }
+ for (; i < numSymbols; i++)
+ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
+}
+
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+{
+ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
+ p->counters[posState] = p->tableSize;
+}
+
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+{
+ UInt32 posState;
+ for (posState = 0; posState < numPosStates; posState++)
+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+{
+ LenEnc_Encode(&p->p, rc, symbol, posState);
+ if (updatePrice)
+ if (--p->counters[posState] == 0)
+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+
+
+
+static void MovePos(CLzmaEnc *p, UInt32 num)
+{
+ #ifdef SHOW_STAT
+ ttt += num;
+ printf("\n MovePos %d", num);
+ #endif
+ if (num != 0)
+ {
+ p->additionalOffset += num;
+ p->matchFinder.Skip(p->matchFinderObj, num);
+ }
+}
+
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+{
+ UInt32 lenRes = 0, numPairs;
+ p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+ numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
+ #ifdef SHOW_STAT
+ printf("\n i = %d numPairs = %d ", ttt, numPairs / 2);
+ ttt++;
+ {
+ UInt32 i;
+ for (i = 0; i < numPairs; i += 2)
+ printf("%2d %6d | ", p->matches[i], p->matches[i + 1]);
+ }
+ #endif
+ if (numPairs > 0)
+ {
+ lenRes = p->matches[numPairs - 2];
+ if (lenRes == p->numFastBytes)
+ {
+ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ UInt32 distance = p->matches[numPairs - 1] + 1;
+ UInt32 numAvail = p->numAvail;
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+ {
+ const Byte *pby2 = pby - distance;
+ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+ }
+ }
+ }
+ p->additionalOffset++;
+ *numDistancePairsRes = numPairs;
+ return lenRes;
+}
+
+
+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
+#define IsShortRep(p) ((p)->backPrev == 0)
+
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
+{
+ return
+ GET_PRICE_0(p->isRepG0[state]) +
+ GET_PRICE_0(p->isRep0Long[state][posState]);
+}
+
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+{
+ UInt32 price;
+ if (repIndex == 0)
+ {
+ price = GET_PRICE_0(p->isRepG0[state]);
+ price += GET_PRICE_1(p->isRep0Long[state][posState]);
+ }
+ else
+ {
+ price = GET_PRICE_1(p->isRepG0[state]);
+ if (repIndex == 1)
+ price += GET_PRICE_0(p->isRepG1[state]);
+ else
+ {
+ price += GET_PRICE_1(p->isRepG1[state]);
+ price += GET_PRICE(p->isRepG2[state], repIndex - 2);
+ }
+ }
+ return price;
+}
+
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
+{
+ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
+ GetPureRepPrice(p, repIndex, state, posState);
+}
+
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+{
+ UInt32 posMem = p->opt[cur].posPrev;
+ UInt32 backMem = p->opt[cur].backPrev;
+ p->optimumEndIndex = cur;
+ do
+ {
+ if (p->opt[cur].prev1IsChar)
+ {
+ MakeAsChar(&p->opt[posMem])
+ p->opt[posMem].posPrev = posMem - 1;
+ if (p->opt[cur].prev2)
+ {
+ p->opt[posMem - 1].prev1IsChar = False;
+ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
+ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
+ }
+ }
+ {
+ UInt32 posPrev = posMem;
+ UInt32 backCur = backMem;
+
+ backMem = p->opt[posPrev].backPrev;
+ posMem = p->opt[posPrev].posPrev;
+
+ p->opt[posPrev].backPrev = backCur;
+ p->opt[posPrev].posPrev = cur;
+ cur = posPrev;
+ }
+ }
+ while (cur != 0);
+ *backRes = p->opt[0].backPrev;
+ p->optimumCurrentIndex = p->opt[0].posPrev;
+ return p->optimumCurrentIndex;
+}
+
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
+
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
+{
+ UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
+ UInt32 matchPrice, repMatchPrice, normalMatchPrice;
+ UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
+ UInt32 *matches;
+ const Byte *data;
+ Byte curByte, matchByte;
+ if (p->optimumEndIndex != p->optimumCurrentIndex)
+ {
+ const COptimal *opt = &p->opt[p->optimumCurrentIndex];
+ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
+ *backRes = opt->backPrev;
+ p->optimumCurrentIndex = opt->posPrev;
+ return lenRes;
+ }
+ p->optimumCurrentIndex = p->optimumEndIndex = 0;
+
+ if (p->additionalOffset == 0)
+ mainLen = ReadMatchDistances(p, &numPairs);
+ else
+ {
+ mainLen = p->longestMatchLength;
+ numPairs = p->numPairs;
+ }
+
+ numAvail = p->numAvail;
+ if (numAvail < 2)
+ {
+ *backRes = (UInt32)(-1);
+ return 1;
+ }
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ repMaxIndex = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 lenTest;
+ const Byte *data2;
+ reps[i] = p->reps[i];
+ data2 = data - (reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ {
+ repLens[i] = 0;
+ continue;
+ }
+ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+ repLens[i] = lenTest;
+ if (lenTest > repLens[repMaxIndex])
+ repMaxIndex = i;
+ }
+ if (repLens[repMaxIndex] >= p->numFastBytes)
+ {
+ UInt32 lenRes;
+ *backRes = repMaxIndex;
+ lenRes = repLens[repMaxIndex];
+ MovePos(p, lenRes - 1);
+ return lenRes;
+ }
+
+ matches = p->matches;
+ if (mainLen >= p->numFastBytes)
+ {
+ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 1);
+ return mainLen;
+ }
+ curByte = *data;
+ matchByte = *(data - (reps[0] + 1));
+
+ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ *backRes = (UInt32)-1;
+ return 1;
+ }
+
+ p->opt[0].state = (CState)p->state;
+
+ posState = (position & p->pbMask);
+
+ {
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+ (!IsCharState(p->state) ?
+ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+ }
+
+ MakeAsChar(&p->opt[1]);
+
+ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+ if (matchByte == curByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
+ if (shortRepPrice < p->opt[1].price)
+ {
+ p->opt[1].price = shortRepPrice;
+ MakeAsShortRep(&p->opt[1]);
+ }
+ }
+ lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
+
+ if (lenEnd < 2)
+ {
+ *backRes = p->opt[1].backPrev;
+ return 1;
+ }
+
+ p->opt[1].posPrev = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ p->opt[0].backs[i] = reps[i];
+
+ len = lenEnd;
+ do
+ p->opt[len--].price = kInfinityPrice;
+ while (len >= 2);
+
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 repLen = repLens[i];
+ UInt32 price;
+ if (repLen < 2)
+ continue;
+ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
+ COptimal *opt = &p->opt[repLen];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = 0;
+ opt->backPrev = i;
+ opt->prev1IsChar = False;
+ }
+ }
+ while (--repLen >= 2);
+ }
+
+ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ if (len <= mainLen)
+ {
+ UInt32 offs = 0;
+ while (len > matches[offs])
+ offs += 2;
+ for (; ; len++)
+ {
+ COptimal *opt;
+ UInt32 distance = matches[offs + 1];
+
+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
+ UInt32 lenToPosState = GetLenToPosState(len);
+ if (distance < kNumFullDistances)
+ curAndLenPrice += p->distancesPrices[lenToPosState][distance];
+ else
+ {
+ UInt32 slot;
+ GetPosSlot2(distance, slot);
+ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
+ }
+ opt = &p->opt[len];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = 0;
+ opt->backPrev = distance + LZMA_NUM_REPS;
+ opt->prev1IsChar = False;
+ }
+ if (len == matches[offs])
+ {
+ offs += 2;
+ if (offs == numPairs)
+ break;
+ }
+ }
+ }
+
+ cur = 0;
+
+ #ifdef SHOW_STAT2
+ if (position >= 0)
+ {
+ unsigned i;
+ printf("\n pos = %4X", position);
+ for (i = cur; i <= lenEnd; i++)
+ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
+ }
+ #endif
+
+ for (;;)
+ {
+ UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
+ UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
+ Bool nextIsChar;
+ Byte curByte, matchByte;
+ const Byte *data;
+ COptimal *curOpt;
+ COptimal *nextOpt;
+
+ cur++;
+ if (cur == lenEnd)
+ return Backward(p, backRes, cur);
+
+ newLen = ReadMatchDistances(p, &numPairs);
+ if (newLen >= p->numFastBytes)
+ {
+ p->numPairs = numPairs;
+ p->longestMatchLength = newLen;
+ return Backward(p, backRes, cur);
+ }
+ position++;
+ curOpt = &p->opt[cur];
+ posPrev = curOpt->posPrev;
+ if (curOpt->prev1IsChar)
+ {
+ posPrev--;
+ if (curOpt->prev2)
+ {
+ state = p->opt[curOpt->posPrev2].state;
+ if (curOpt->backPrev2 < LZMA_NUM_REPS)
+ state = kRepNextStates[state];
+ else
+ state = kMatchNextStates[state];
+ }
+ else
+ state = p->opt[posPrev].state;
+ state = kLiteralNextStates[state];
+ }
+ else
+ state = p->opt[posPrev].state;
+ if (posPrev == cur - 1)
+ {
+ if (IsShortRep(curOpt))
+ state = kShortRepNextStates[state];
+ else
+ state = kLiteralNextStates[state];
+ }
+ else
+ {
+ UInt32 pos;
+ const COptimal *prevOpt;
+ if (curOpt->prev1IsChar && curOpt->prev2)
+ {
+ posPrev = curOpt->posPrev2;
+ pos = curOpt->backPrev2;
+ state = kRepNextStates[state];
+ }
+ else
+ {
+ pos = curOpt->backPrev;
+ if (pos < LZMA_NUM_REPS)
+ state = kRepNextStates[state];
+ else
+ state = kMatchNextStates[state];
+ }
+ prevOpt = &p->opt[posPrev];
+ if (pos < LZMA_NUM_REPS)
+ {
+ UInt32 i;
+ reps[0] = prevOpt->backs[pos];
+ for (i = 1; i <= pos; i++)
+ reps[i] = prevOpt->backs[i - 1];
+ for (; i < LZMA_NUM_REPS; i++)
+ reps[i] = prevOpt->backs[i];
+ }
+ else
+ {
+ UInt32 i;
+ reps[0] = (pos - LZMA_NUM_REPS);
+ for (i = 1; i < LZMA_NUM_REPS; i++)
+ reps[i] = prevOpt->backs[i - 1];
+ }
+ }
+ curOpt->state = (CState)state;
+
+ curOpt->backs[0] = reps[0];
+ curOpt->backs[1] = reps[1];
+ curOpt->backs[2] = reps[2];
+ curOpt->backs[3] = reps[3];
+
+ curPrice = curOpt->price;
+ nextIsChar = False;
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ curByte = *data;
+ matchByte = *(data - (reps[0] + 1));
+
+ posState = (position & p->pbMask);
+
+ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
+ {
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ curAnd1Price +=
+ (!IsCharState(state) ?
+ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+ }
+
+ nextOpt = &p->opt[cur + 1];
+
+ if (curAnd1Price < nextOpt->price)
+ {
+ nextOpt->price = curAnd1Price;
+ nextOpt->posPrev = cur;
+ MakeAsChar(nextOpt);
+ nextIsChar = True;
+ }
+
+ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+
+ if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
+ if (shortRepPrice <= nextOpt->price)
+ {
+ nextOpt->price = shortRepPrice;
+ nextOpt->posPrev = cur;
+ MakeAsShortRep(nextOpt);
+ nextIsChar = True;
+ }
+ }
+ numAvailFull = p->numAvail;
+ {
+ UInt32 temp = kNumOpts - 1 - cur;
+ if (temp < numAvailFull)
+ numAvailFull = temp;
+ }
+
+ if (numAvailFull < 2)
+ continue;
+ numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
+
+ if (!nextIsChar && matchByte != curByte) /* speed optimization */
+ {
+ /* try Literal + rep0 */
+ UInt32 temp;
+ UInt32 lenTest2;
+ const Byte *data2 = data - (reps[0] + 1);
+ UInt32 limit = p->numFastBytes + 1;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+
+ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
+ lenTest2 = temp - 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kLiteralNextStates[state];
+ UInt32 posStateNext = (position + 1) & p->pbMask;
+ UInt32 nextRepMatchPrice = curAnd1Price +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ UInt32 offset = cur + 1 + lenTest2;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = False;
+ }
+ }
+ }
+ }
+
+ startLen = 2; /* speed optimization */
+ {
+ UInt32 repIndex;
+ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
+ {
+ UInt32 lenTest;
+ UInt32 lenTestTemp;
+ UInt32 price;
+ const Byte *data2 = data - (reps[repIndex] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+ while (lenEnd < cur + lenTest)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ lenTestTemp = lenTest;
+ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
+ COptimal *opt = &p->opt[cur + lenTest];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur;
+ opt->backPrev = repIndex;
+ opt->prev1IsChar = False;
+ }
+ }
+ while (--lenTest >= 2);
+ lenTest = lenTestTemp;
+
+ if (repIndex == 0)
+ startLen = lenTest + 1;
+
+ /* if (_maxMode) */
+ {
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = lenTest2 + p->numFastBytes;
+ UInt32 nextRepMatchPrice;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kRepNextStates[state];
+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
+ UInt32 curAndLenCharPrice =
+ price + p->repLenEnc.prices[posState][lenTest - 2] +
+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+ data[lenTest], data2[lenTest], p->ProbPrices);
+ state2 = kLiteralNextStates[state2];
+ posStateNext = (position + lenTest + 1) & p->pbMask;
+ nextRepMatchPrice = curAndLenCharPrice +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + lenTest + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = True;
+ opt->posPrev2 = cur;
+ opt->backPrev2 = repIndex;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
+ if (newLen > numAvail)
+ {
+ newLen = numAvail;
+ for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
+ matches[numPairs] = newLen;
+ numPairs += 2;
+ }
+ if (newLen >= startLen)
+ {
+ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
+ UInt32 offs, curBack, posSlot;
+ UInt32 lenTest;
+ while (lenEnd < cur + newLen)
+ p->opt[++lenEnd].price = kInfinityPrice;
+
+ offs = 0;
+ while (startLen > matches[offs])
+ offs += 2;
+ curBack = matches[offs + 1];
+ GetPosSlot2(curBack, posSlot);
+ for (lenTest = /*2*/ startLen; ; lenTest++)
+ {
+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+ UInt32 lenToPosState = GetLenToPosState(lenTest);
+ COptimal *opt;
+ if (curBack < kNumFullDistances)
+ curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
+ else
+ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
+
+ opt = &p->opt[cur + lenTest];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur;
+ opt->backPrev = curBack + LZMA_NUM_REPS;
+ opt->prev1IsChar = False;
+ }
+
+ if (/*_maxMode && */lenTest == matches[offs])
+ {
+ /* Try Match + Literal + Rep0 */
+ const Byte *data2 = data - (curBack + 1);
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = lenTest2 + p->numFastBytes;
+ UInt32 nextRepMatchPrice;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kMatchNextStates[state];
+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
+ UInt32 curAndLenCharPrice = curAndLenPrice +
+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+ data[lenTest], data2[lenTest], p->ProbPrices);
+ state2 = kLiteralNextStates[state2];
+ posStateNext = (posStateNext + 1) & p->pbMask;
+ nextRepMatchPrice = curAndLenCharPrice +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + lenTest + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = True;
+ opt->posPrev2 = cur;
+ opt->backPrev2 = curBack + LZMA_NUM_REPS;
+ }
+ }
+ }
+ offs += 2;
+ if (offs == numPairs)
+ break;
+ curBack = matches[offs + 1];
+ if (curBack >= kNumFullDistances)
+ GetPosSlot2(curBack, posSlot);
+ }
+ }
+ }
+ }
+}
+
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
+
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+{
+ UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
+ const Byte *data;
+ const UInt32 *matches;
+
+ if (p->additionalOffset == 0)
+ mainLen = ReadMatchDistances(p, &numPairs);
+ else
+ {
+ mainLen = p->longestMatchLength;
+ numPairs = p->numPairs;
+ }
+
+ numAvail = p->numAvail;
+ *backRes = (UInt32)-1;
+ if (numAvail < 2)
+ return 1;
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+
+ repLen = repIndex = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 len;
+ const Byte *data2 = data - (p->reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ if (len >= p->numFastBytes)
+ {
+ *backRes = i;
+ MovePos(p, len - 1);
+ return len;
+ }
+ if (len > repLen)
+ {
+ repIndex = i;
+ repLen = len;
+ }
+ }
+
+ matches = p->matches;
+ if (mainLen >= p->numFastBytes)
+ {
+ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 1);
+ return mainLen;
+ }
+
+ mainDist = 0; /* for GCC */
+ if (mainLen >= 2)
+ {
+ mainDist = matches[numPairs - 1];
+ while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
+ {
+ if (!ChangePair(matches[numPairs - 3], mainDist))
+ break;
+ numPairs -= 2;
+ mainLen = matches[numPairs - 2];
+ mainDist = matches[numPairs - 1];
+ }
+ if (mainLen == 2 && mainDist >= 0x80)
+ mainLen = 1;
+ }
+
+ if (repLen >= 2 && (
+ (repLen + 1 >= mainLen) ||
+ (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
+ (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
+ {
+ *backRes = repIndex;
+ MovePos(p, repLen - 1);
+ return repLen;
+ }
+
+ if (mainLen < 2 || numAvail <= 2)
+ return 1;
+
+ p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
+ if (p->longestMatchLength >= 2)
+ {
+ UInt32 newDistance = matches[p->numPairs - 1];
+ if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
+ (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
+ (p->longestMatchLength > mainLen + 1) ||
+ (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
+ return 1;
+ }
+
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 len, limit;
+ const Byte *data2 = data - (p->reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ limit = mainLen - 1;
+ for (len = 2; len < limit && data[len] == data2[len]; len++);
+ if (len >= limit)
+ return 1;
+ }
+ *backRes = mainDist + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 2);
+ return mainLen;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+{
+ UInt32 len;
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ p->state = kMatchNextStates[p->state];
+ len = LZMA_MATCH_LEN_MIN;
+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
+ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+ if (p->result != SZ_OK)
+ return p->result;
+ if (p->rc.res != SZ_OK)
+ p->result = SZ_ERROR_WRITE;
+ if (p->matchFinderBase.result != SZ_OK)
+ p->result = SZ_ERROR_READ;
+ if (p->result != SZ_OK)
+ p->finished = True;
+ return p->result;
+}
+
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+ /* ReleaseMFStream(); */
+ p->finished = True;
+ if (p->writeEndMark)
+ WriteEndMarker(p, nowPos & p->pbMask);
+ RangeEnc_FlushData(&p->rc);
+ RangeEnc_FlushStream(&p->rc);
+ return CheckErrors(p);
+}
+
+static void FillAlignPrices(CLzmaEnc *p)
+{
+ UInt32 i;
+ for (i = 0; i < kAlignTableSize; i++)
+ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+ p->alignPriceCount = 0;
+}
+
+static void FillDistancesPrices(CLzmaEnc *p)
+{
+ UInt32 tempPrices[kNumFullDistances];
+ UInt32 i, lenToPosState;
+ for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot1(i);
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
+ }
+
+ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 posSlot;
+ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
+ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
+ for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
+ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
+ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
+ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+
+ {
+ UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
+ UInt32 i;
+ for (i = 0; i < kStartPosModelIndex; i++)
+ distancesPrices[i] = posSlotPrices[i];
+ for (; i < kNumFullDistances; i++)
+ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+ }
+ }
+ p->matchPriceCount = 0;
+}
+
+void LzmaEnc_Construct(CLzmaEnc *p)
+{
+ RangeEnc_Construct(&p->rc);
+ MatchFinder_Construct(&p->matchFinderBase);
+ #ifndef _7ZIP_ST
+ MatchFinderMt_Construct(&p->matchFinderMt);
+ p->matchFinderMt.MatchFinder = &p->matchFinderBase;
+ #endif
+
+ {
+ CLzmaEncProps props;
+ LzmaEncProps_Init(&props);
+ LzmaEnc_SetProps(p, &props);
+ }
+
+ #ifndef LZMA_LOG_BSR
+ LzmaEnc_FastPosInit(p->g_FastPos);
+ #endif
+
+ LzmaEnc_InitPriceTables(p->ProbPrices);
+ p->litProbs = 0;
+ p->saveState.litProbs = 0;
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+{
+ void *p;
+ p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
+ if (p != 0)
+ LzmaEnc_Construct((CLzmaEnc *)p);
+ return p;
+}
+
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->litProbs);
+ alloc->Free(alloc, p->saveState.litProbs);
+ p->litProbs = 0;
+ p->saveState.litProbs = 0;
+}
+
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ #ifndef _7ZIP_ST
+ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
+ #endif
+ MatchFinder_Free(&p->matchFinderBase, allocBig);
+ LzmaEnc_FreeLits(p, alloc);
+ RangeEnc_Free(&p->rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
+ alloc->Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+ UInt32 nowPos32, startPos32;
+ if (p->needInit)
+ {
+ p->matchFinder.Init(p->matchFinderObj);
+ p->needInit = 0;
+ }
+
+ if (p->finished)
+ return p->result;
+ RINOK(CheckErrors(p));
+
+ nowPos32 = (UInt32)p->nowPos64;
+ startPos32 = nowPos32;
+
+ if (p->nowPos64 == 0)
+ {
+ UInt32 numPairs;
+ Byte curByte;
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+ return Flush(p, nowPos32);
+ ReadMatchDistances(p, &numPairs);
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
+ p->state = kLiteralNextStates[p->state];
+ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
+ LitEnc_Encode(&p->rc, p->litProbs, curByte);
+ p->additionalOffset--;
+ nowPos32++;
+ }
+
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+ for (;;)
+ {
+ UInt32 pos, len, posState;
+
+ if (p->fastMode)
+ len = GetOptimumFast(p, &pos);
+ else
+ len = GetOptimum(p, nowPos32, &pos);
+
+ #ifdef SHOW_STAT2
+ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
+ #endif
+
+ posState = nowPos32 & p->pbMask;
+ if (len == 1 && pos == (UInt32)-1)
+ {
+ Byte curByte;
+ CLzmaProb *probs;
+ const Byte *data;
+
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+ curByte = *data;
+ probs = LIT_PROBS(nowPos32, *(data - 1));
+ if (IsCharState(p->state))
+ LitEnc_Encode(&p->rc, probs, curByte);
+ else
+ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
+ p->state = kLiteralNextStates[p->state];
+ }
+ else
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+ if (pos < LZMA_NUM_REPS)
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
+ if (pos == 0)
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
+ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
+ }
+ else
+ {
+ UInt32 distance = p->reps[pos];
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
+ if (pos == 1)
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
+ else
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
+ if (pos == 3)
+ p->reps[3] = p->reps[2];
+ p->reps[2] = p->reps[1];
+ }
+ p->reps[1] = p->reps[0];
+ p->reps[0] = distance;
+ }
+ if (len == 1)
+ p->state = kShortRepNextStates[p->state];
+ else
+ {
+ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ p->state = kRepNextStates[p->state];
+ }
+ }
+ else
+ {
+ UInt32 posSlot;
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ p->state = kMatchNextStates[p->state];
+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ pos -= LZMA_NUM_REPS;
+ GetPosSlot(pos, posSlot);
+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+
+ if (posSlot >= kStartPosModelIndex)
+ {
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ UInt32 posReduced = pos - base;
+
+ if (posSlot < kEndPosModelIndex)
+ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
+ else
+ {
+ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+ p->alignPriceCount++;
+ }
+ }
+ p->reps[3] = p->reps[2];
+ p->reps[2] = p->reps[1];
+ p->reps[1] = p->reps[0];
+ p->reps[0] = pos;
+ p->matchPriceCount++;
+ }
+ }
+ p->additionalOffset -= len;
+ nowPos32 += len;
+ if (p->additionalOffset == 0)
+ {
+ UInt32 processed;
+ if (!p->fastMode)
+ {
+ if (p->matchPriceCount >= (1 << 7))
+ FillDistancesPrices(p);
+ if (p->alignPriceCount >= kAlignTableSize)
+ FillAlignPrices(p);
+ }
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+ break;
+ processed = nowPos32 - startPos32;
+ if (useLimits)
+ {
+ if (processed + kNumOpts + 300 >= maxUnpackSize ||
+ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
+ break;
+ }
+ else if (processed >= (1 << 15))
+ {
+ p->nowPos64 += nowPos32 - startPos32;
+ return CheckErrors(p);
+ }
+ }
+ }
+ p->nowPos64 += nowPos32 - startPos32;
+ return Flush(p, nowPos32);
+}
+
+#define kBigHashDicLimit ((UInt32)1 << 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ UInt32 beforeSize = kNumOpts;
+ Bool btMode;
+ if (!RangeEnc_Alloc(&p->rc, alloc))
+ return SZ_ERROR_MEM;
+ btMode = (p->matchFinderBase.btMode != 0);
+ #ifndef _7ZIP_ST
+ p->mtMode = (p->multiThread && !p->fastMode && btMode);
+ #endif
+
+ {
+ unsigned lclp = p->lc + p->lp;
+ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
+ {
+ LzmaEnc_FreeLits(p, alloc);
+ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+ if (p->litProbs == 0 || p->saveState.litProbs == 0)
+ {
+ LzmaEnc_FreeLits(p, alloc);
+ return SZ_ERROR_MEM;
+ }
+ p->lclp = lclp;
+ }
+ }
+
+ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
+
+ if (beforeSize + p->dictSize < keepWindowSize)
+ beforeSize = keepWindowSize - p->dictSize;
+
+ #ifndef _7ZIP_ST
+ if (p->mtMode)
+ {
+ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+ p->matchFinderObj = &p->matchFinderMt;
+ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
+ }
+ else
+ #endif
+ {
+ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+ return SZ_ERROR_MEM;
+ p->matchFinderObj = &p->matchFinderBase;
+ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
+ }
+ return SZ_OK;
+}
+
+void LzmaEnc_Init(CLzmaEnc *p)
+{
+ UInt32 i;
+ p->state = 0;
+ for (i = 0 ; i < LZMA_NUM_REPS; i++)
+ p->reps[i] = 0;
+
+ RangeEnc_Init(&p->rc);
+
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ UInt32 j;
+ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
+ {
+ p->isMatch[i][j] = kProbInitValue;
+ p->isRep0Long[i][j] = kProbInitValue;
+ }
+ p->isRep[i] = kProbInitValue;
+ p->isRepG0[i] = kProbInitValue;
+ p->isRepG1[i] = kProbInitValue;
+ p->isRepG2[i] = kProbInitValue;
+ }
+
+ {
+ UInt32 num = 0x300 << (p->lp + p->lc);
+ for (i = 0; i < num; i++)
+ p->litProbs[i] = kProbInitValue;
+ }
+
+ {
+ for (i = 0; i < kNumLenToPosStates; i++)
+ {
+ CLzmaProb *probs = p->posSlotEncoder[i];
+ UInt32 j;
+ for (j = 0; j < (1 << kNumPosSlotBits); j++)
+ probs[j] = kProbInitValue;
+ }
+ }
+ {
+ for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+ p->posEncoders[i] = kProbInitValue;
+ }
+
+ LenEnc_Init(&p->lenEnc.p);
+ LenEnc_Init(&p->repLenEnc.p);
+
+ for (i = 0; i < (1 << kNumAlignBits); i++)
+ p->posAlignEncoder[i] = kProbInitValue;
+
+ p->optimumEndIndex = 0;
+ p->optimumCurrentIndex = 0;
+ p->additionalOffset = 0;
+
+ p->pbMask = (1 << p->pb) - 1;
+ p->lpMask = (1 << p->lp) - 1;
+}
+
+void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+ if (!p->fastMode)
+ {
+ FillDistancesPrices(p);
+ FillAlignPrices(p);
+ }
+
+ p->lenEnc.tableSize =
+ p->repLenEnc.tableSize =
+ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
+ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ UInt32 i;
+ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
+ if (p->dictSize <= ((UInt32)1 << i))
+ break;
+ p->distTableSize = i * 2;
+
+ p->finished = False;
+ p->result = SZ_OK;
+ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+ LzmaEnc_Init(p);
+ LzmaEnc_InitPrices(p);
+ p->nowPos64 = 0;
+ return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ p->matchFinderBase.stream = inStream;
+ p->needInit = 1;
+ p->rc.outStream = outStream;
+ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
+ ISeqInStream *inStream, UInt32 keepWindowSize,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ p->matchFinderBase.stream = inStream;
+ p->needInit = 1;
+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+ p->matchFinderBase.directInput = 1;
+ p->matchFinderBase.bufferBase = (Byte *)src;
+ p->matchFinderBase.directInputRem = srcLen;
+}
+
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ LzmaEnc_SetInputBuf(p, src, srcLen);
+ p->needInit = 1;
+
+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+ #ifndef _7ZIP_ST
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ if (p->mtMode)
+ MatchFinderMt_ReleaseStream(&p->matchFinderMt);
+ #else
+ pp = pp;
+ #endif
+}
+
+typedef struct
+{
+ ISeqOutStream funcTable;
+ Byte *data;
+ SizeT rem;
+ Bool overflow;
+} CSeqOutStreamBuf;
+
+static size_t MyWrite(void *pp, const void *data, size_t size)
+{
+ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+ if (p->rem < size)
+ {
+ size = p->rem;
+ p->overflow = True;
+ }
+ memcpy(p->data, data, size);
+ p->rem -= size;
+ p->data += size;
+ return size;
+}
+
+
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+ const CLzmaEnc *p = (CLzmaEnc *)pp;
+ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+}
+
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+ const CLzmaEnc *p = (CLzmaEnc *)pp;
+ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+}
+
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ UInt64 nowPos64;
+ SRes res;
+ CSeqOutStreamBuf outStream;
+
+ outStream.funcTable.Write = MyWrite;
+ outStream.data = dest;
+ outStream.rem = *destLen;
+ outStream.overflow = False;
+
+ p->writeEndMark = False;
+ p->finished = False;
+ p->result = SZ_OK;
+
+ if (reInit)
+ LzmaEnc_Init(p);
+ LzmaEnc_InitPrices(p);
+ nowPos64 = p->nowPos64;
+ RangeEnc_Init(&p->rc);
+ p->rc.outStream = &outStream.funcTable;
+
+ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
+
+ *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
+ *destLen -= outStream.rem;
+ if (outStream.overflow)
+ return SZ_ERROR_OUTPUT_EOF;
+
+ return res;
+}
+
+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
+{
+ SRes res = SZ_OK;
+
+ #ifndef _7ZIP_ST
+ Byte allocaDummy[0x300];
+ int i = 0;
+ for (i = 0; i < 16; i++)
+ allocaDummy[i] = (Byte)i;
+ #endif
+
+ for (;;)
+ {
+ res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
+ if (res != SZ_OK || p->finished != 0)
+ break;
+ if (progress != 0)
+ {
+ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+ if (res != SZ_OK)
+ {
+ res = SZ_ERROR_PROGRESS;
+ break;
+ }
+ }
+ }
+ LzmaEnc_Finish(p);
+ return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
+ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ int i;
+ UInt32 dictSize = p->dictSize;
+ if (*size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_PARAM;
+ *size = LZMA_PROPS_SIZE;
+ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
+
+ for (i = 11; i <= 30; i++)
+ {
+ if (dictSize <= ((UInt32)2 << i))
+ {
+ dictSize = (2 << i);
+ break;
+ }
+ if (dictSize <= ((UInt32)3 << i))
+ {
+ dictSize = (3 << i);
+ break;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ props[1 + i] = (Byte)(dictSize >> (8 * i));
+ return SZ_OK;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ SRes res;
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+
+ CSeqOutStreamBuf outStream;
+
+ LzmaEnc_SetInputBuf(p, src, srcLen);
+
+ outStream.funcTable.Write = MyWrite;
+ outStream.data = dest;
+ outStream.rem = *destLen;
+ outStream.overflow = False;
+
+ p->writeEndMark = writeEndMark;
+
+ p->rc.outStream = &outStream.funcTable;
+ res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
+ if (res == SZ_OK)
+ res = LzmaEnc_Encode2(p, progress);
+
+ *destLen -= outStream.rem;
+ if (outStream.overflow)
+ return SZ_ERROR_OUTPUT_EOF;
+ return res;
+}
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
+ SRes res;
+ if (p == 0)
+ return SZ_ERROR_MEM;
+
+ res = LzmaEnc_SetProps(p, props);
+ if (res == SZ_OK)
+ {
+ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+ if (res == SZ_OK)
+ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+ writeEndMark, progress, alloc, allocBig);
+ }
+
+ LzmaEnc_Destroy(p, alloc, allocBig);
+ return res;
+}
diff --git a/dep/StormLib/src/lzma/C/LzmaEnc.h b/dep/StormLib/src/lzma/C/LzmaEnc.h
new file mode 100644
index 00000000000..200d60eb83c
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/LzmaEnc.h
@@ -0,0 +1,80 @@
+/* LzmaEnc.h -- LZMA Encoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_ENC_H
+#define __LZMA_ENC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+ int level; /* 0 <= level <= 9 */
+ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
+ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
+ default = (1 << 24) */
+ int lc; /* 0 <= lc <= 8, default = 3 */
+ int lp; /* 0 <= lp <= 4, default = 0 */
+ int pb; /* 0 <= pb <= 4, default = 2 */
+ int algo; /* 0 - fast, 1 - normal, default = 1 */
+ int fb; /* 5 <= fb <= 273, default = 32 */
+ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+ int numHashBytes; /* 2, 3 or 4, default = 4 */
+ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
+ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+ int numThreads; /* 1 or 2, default = 2 */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+void LzmaEncProps_Normalize(CLzmaEncProps *p);
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
+
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc_* functions can return the following exit codes:
+Returns:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_PARAM - Incorrect paramater in props
+ SZ_ERROR_WRITE - Write callback error.
+ SZ_ERROR_PROGRESS - some break from progress callback
+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaEncode
+Return code:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_PARAM - Incorrect paramater
+ SZ_ERROR_OUTPUT_EOF - output buffer overflow
+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/Threads.c b/dep/StormLib/src/lzma/C/Threads.c
new file mode 100644
index 00000000000..7af1da2e26e
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/Threads.c
@@ -0,0 +1,84 @@
+/* Threads.c -- multithreading library
+2009-09-20 : Igor Pavlov : Public domain */
+
+#ifndef _WIN32_WCE
+#include <process.h>
+#endif
+
+#include "Threads.h"
+
+static WRes GetError()
+{
+ DWORD res = GetLastError();
+ return (res) ? (WRes)(res) : 1;
+}
+
+WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
+WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
+
+WRes HandlePtr_Close(HANDLE *p)
+{
+ if (*p != NULL)
+ if (!CloseHandle(*p))
+ return GetError();
+ *p = NULL;
+ return 0;
+}
+
+WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
+
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
+{
+ unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+ *p =
+ #ifdef UNDER_CE
+ CreateThread(0, 0, func, param, 0, &threadId);
+ #else
+ (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
+ #endif
+ /* maybe we must use errno here, but probably GetLastError() is also OK. */
+ return HandleToWRes(*p);
+}
+
+WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
+{
+ *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
+ return HandleToWRes(*p);
+}
+
+WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
+WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
+
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
+
+
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
+{
+ *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
+ return HandleToWRes(*p);
+}
+
+static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
+ { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
+ { return Semaphore_Release(p, (LONG)num, NULL); }
+WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
+
+WRes CriticalSection_Init(CCriticalSection *p)
+{
+ /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+ #ifdef _MSC_VER
+ __try
+ #endif
+ {
+ InitializeCriticalSection(p);
+ /* InitializeCriticalSectionAndSpinCount(p, 0); */
+ }
+ #ifdef _MSC_VER
+ __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
+ #endif
+ return 0;
+}
diff --git a/dep/StormLib/src/lzma/C/Threads.h b/dep/StormLib/src/lzma/C/Threads.h
new file mode 100644
index 00000000000..d0ddd80e227
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/Threads.h
@@ -0,0 +1,59 @@
+/* Threads.h -- multithreading library
+2009-03-27 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_THREADS_H
+#define __7Z_THREADS_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WRes HandlePtr_Close(HANDLE *h);
+WRes Handle_WaitObject(HANDLE h);
+
+typedef HANDLE CThread;
+#define Thread_Construct(p) *(p) = NULL
+#define Thread_WasCreated(p) (*(p) != NULL)
+#define Thread_Close(p) HandlePtr_Close(p)
+#define Thread_Wait(p) Handle_WaitObject(*(p))
+typedef unsigned THREAD_FUNC_RET_TYPE;
+#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
+typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
+
+typedef HANDLE CEvent;
+typedef CEvent CAutoResetEvent;
+typedef CEvent CManualResetEvent;
+#define Event_Construct(p) *(p) = NULL
+#define Event_IsCreated(p) (*(p) != NULL)
+#define Event_Close(p) HandlePtr_Close(p)
+#define Event_Wait(p) Handle_WaitObject(*(p))
+WRes Event_Set(CEvent *p);
+WRes Event_Reset(CEvent *p);
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
+
+typedef HANDLE CSemaphore;
+#define Semaphore_Construct(p) (*p) = NULL
+#define Semaphore_Close(p) HandlePtr_Close(p)
+#define Semaphore_Wait(p) Handle_WaitObject(*(p))
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
+WRes Semaphore_Release1(CSemaphore *p);
+
+typedef CRITICAL_SECTION CCriticalSection;
+WRes CriticalSection_Init(CCriticalSection *p);
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)
+#define CriticalSection_Enter(p) EnterCriticalSection(p)
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/StormLib/src/lzma/C/Types.h b/dep/StormLib/src/lzma/C/Types.h
new file mode 100644
index 00000000000..0526cb47b6e
--- /dev/null
+++ b/dep/StormLib/src/lzma/C/Types.h
@@ -0,0 +1,236 @@
+/* Types.h -- Basic types
+2010-03-11 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifndef EXTERN_C_BEGIN
+#ifdef __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+#endif
+
+EXTERN_C_BEGIN
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifdef _WIN32
+typedef DWORD WRes;
+#else
+typedef int WRes;
+#endif
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+ NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _WIN32
+#define MY_STD_CALL __stdcall
+#else
+#define MY_STD_CALL
+#endif
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+ Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
+} IByteIn;
+
+typedef struct
+{
+ void (*Write)(void *p, Byte b);
+} IByteOut;
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+
+typedef struct
+{
+ size_t (*Write)(void *p, const void *buf, size_t size);
+ /* Returns: result - the number of actually written bytes.
+ (result < size) means error */
+} ISeqOutStream;
+
+typedef enum
+{
+ SZ_SEEK_SET = 0,
+ SZ_SEEK_CUR = 1,
+ SZ_SEEK_END = 2
+} ESzSeek;
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ISeekInStream;
+
+typedef struct
+{
+ SRes (*Look)(void *p, const void **buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) > input(*size)) is not allowed
+ (output(*size) < input(*size)) is allowed */
+ SRes (*Skip)(void *p, size_t offset);
+ /* offset must be <= output(*size) of Look */
+
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* reads directly (without buffer). It's same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ILookInStream;
+
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+
+#define LookToRead_BUF_SIZE (1 << 14)
+
+typedef struct
+{
+ ILookInStream s;
+ ISeekInStream *realStream;
+ size_t pos;
+ size_t size;
+ Byte buf[LookToRead_BUF_SIZE];
+} CLookToRead;
+
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
+void LookToRead_Init(CLookToRead *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+typedef struct
+{
+ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+ /* Returns: result. (result != SZ_OK) means break.
+ Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+ void *(*Alloc)(void *p, size_t size);
+ void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+EXTERN_C_END
+
+#endif
diff --git a/dep/StormLib/src/lzma/info.txt b/dep/StormLib/src/lzma/info.txt
new file mode 100644
index 00000000000..4cee86e3542
--- /dev/null
+++ b/dep/StormLib/src/lzma/info.txt
@@ -0,0 +1 @@
+Taken from LZMA SDK v 9.11 \ No newline at end of file
diff --git a/dep/StormLib/src/pklib/crc32.c b/dep/StormLib/src/pklib/crc32.c
new file mode 100644
index 00000000000..cd47b1d4a9b
--- /dev/null
+++ b/dep/StormLib/src/pklib/crc32.c
@@ -0,0 +1,66 @@
+/*****************************************************************************/
+/* crc32.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Pkware Data Compression Library Version 1.11 */
+/* Dissassembled method crc32 - cdecl version */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 09.04.03 1.00 Lad The first version of crc32.c */
+/* 02.05.03 1.00 Lad Stress test done */
+/*****************************************************************************/
+
+#include "pklib.h"
+
+static unsigned long crc_table[] =
+{
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+
+unsigned long PKEXPORT crc32_pklib(char * buffer, unsigned int * psize, unsigned long * old_crc)
+{
+ unsigned int size = *psize;
+ unsigned long ch;
+ unsigned long crc_value = *old_crc;
+
+ while(size-- != 0)
+ {
+ ch = *buffer++ ^ (char)crc_value;
+ crc_value >>= 8;
+
+ crc_value = crc_table[ch & 0x0FF] ^ crc_value;
+ }
+ return crc_value;
+}
diff --git a/dep/StormLib/src/pklib/explode.c b/dep/StormLib/src/pklib/explode.c
new file mode 100644
index 00000000000..0d327a5da84
--- /dev/null
+++ b/dep/StormLib/src/pklib/explode.c
@@ -0,0 +1,522 @@
+/*****************************************************************************/
+/* explode.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Implode function of PKWARE Data Compression library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
+/* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */
+/* 02.05.03 1.01 Lad Stress test done */
+/* 22.04.10 1.01 Lad Documented */
+/*****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "pklib.h"
+
+#define PKDCL_OK 0
+#define PKDCL_STREAM_END 1 // All data from the input stream is read
+#define PKDCL_NEED_DICT 2 // Need more data (dictionary)
+#define PKDCL_CONTINUE 10 // Internal flag, not returned to user
+#define PKDCL_GET_INPUT 11 // Internal flag, not returned to user
+
+char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
+ "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
+ "Patent No. 5,051,745\r\n"
+ "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
+ "Version 1.11\r\n";
+
+//-----------------------------------------------------------------------------
+// Tables
+
+static unsigned char DistBits[] =
+{
+ 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+static unsigned char DistCode[] =
+{
+ 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
+ 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
+ 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
+ 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
+};
+
+static unsigned char ExLenBits[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+};
+
+static unsigned short LenBase[] =
+{
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
+};
+
+static unsigned char LenBits[] =
+{
+ 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
+};
+
+static unsigned char LenCode[] =
+{
+ 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
+};
+
+static unsigned char ChBitsAsc[] =
+{
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
+ 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
+ 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
+ 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
+ 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
+ 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
+ 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
+};
+
+static unsigned short ChCodeAsc[] =
+{
+ 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
+ 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
+ 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
+ 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
+ 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
+ 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
+ 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
+ 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
+ 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
+ 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
+ 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
+ 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
+ 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
+ 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
+ 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
+ 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
+ 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
+ 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
+ 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
+ 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
+ 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
+ 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
+ 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
+ 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
+ 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
+ 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
+ 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
+ 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
+ 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
+ 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
+ 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
+ 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
+};
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static void GenDecodeTabs(
+ unsigned char * positions, // [out] Table of positions
+ unsigned char * start_indexes, // [in] Table of start indexes
+ unsigned char * length_bits, // [in] Table of lengths. Each length is stored as number of bits
+ size_t elements) // [in] Number of elements in start_indexes and length_bits
+{
+ unsigned long index;
+ unsigned long length;
+ size_t i;
+
+ for(i = 0; i < elements; i++)
+ {
+ length = 1 << length_bits[i]; // Get the length in bytes
+
+ for(index = start_indexes[i]; index < 0x100; index += length)
+ {
+ positions[index] = (unsigned char)i;
+ }
+ }
+}
+
+static void GenAscTabs(TDcmpStruct * pWork)
+{
+ unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];
+ unsigned long acc, add;
+ unsigned short count;
+
+ for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)
+ {
+ unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;
+ unsigned char bits_asc = *pChBitsAsc;
+
+ if(bits_asc <= 8)
+ {
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc;
+
+ do
+ {
+ pWork->offs2C34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ else if((acc = (*pChCodeAsc & 0xFF)) != 0)
+ {
+ pWork->offs2C34[acc] = 0xFF;
+
+ if(*pChCodeAsc & 0x3F)
+ {
+ bits_asc -= 4;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 4;
+ do
+ {
+ pWork->offs2D34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ else
+ {
+ bits_asc -= 6;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 6;
+ do
+ {
+ pWork->offs2E34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x80);
+ }
+ }
+ else
+ {
+ bits_asc -= 8;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 8;
+ do
+ {
+ pWork->offs2EB4[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Removes given number of bits in the bit buffer. New bits are reloaded from
+// the input buffer, if needed.
+// Returns: PKDCL_OK: Operation was successful
+// PKDCL_STREAM_END: There are no more bits in the input buffer
+
+static int WasteBits(TDcmpStruct * pWork, unsigned long nBits)
+{
+ // If number of bits required is less than number of (bits in the buffer) ?
+ if(nBits <= pWork->extra_bits)
+ {
+ pWork->extra_bits -= nBits;
+ pWork->bit_buff >>= nBits;
+ return PKDCL_OK;
+ }
+
+ // Load input buffer if necessary
+ pWork->bit_buff >>= pWork->extra_bits;
+ if(pWork->in_pos == pWork->in_bytes)
+ {
+ pWork->in_pos = sizeof(pWork->in_buff);
+ if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
+ return PKDCL_STREAM_END;
+ pWork->in_pos = 0;
+ }
+
+ // Update bit buffer
+ pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
+ pWork->bit_buff >>= (nBits - pWork->extra_bits);
+ pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
+ return PKDCL_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Decodes next literal from the input (compressed) data.
+// Returns : 0x000: One byte 0x00
+// 0x001: One byte 0x01
+// ...
+// 0x0FF: One byte 0xFF
+// 0x100: Repetition, length of 0x02 bytes
+// 0x101: Repetition, length of 0x03 bytes
+// ...
+// 0x304: Repetition, length of 0x206 bytes
+// 0x305: End of stream
+// 0x306: Error
+
+static unsigned long DecodeLit(TDcmpStruct * pWork)
+{
+ unsigned long extra_length_bits; // Number of bits of extra literal length
+ unsigned long length_code; // Length code
+ unsigned long value;
+
+ // Test the current bit in byte buffer. If is not set, simply return the next 8 bits.
+ if(pWork->bit_buff & 1)
+ {
+ // Remove one bit from the input data
+ if(WasteBits(pWork, 1))
+ return 0x306;
+
+ // The next 8 bits hold the index to the length code table
+ length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF];
+
+ // Remove the apropriate number of bits
+ if(WasteBits(pWork, pWork->LenBits[length_code]))
+ return 0x306;
+
+ // Are there some extra bits for the obtained length code ?
+ if((extra_length_bits = pWork->ExLenBits[length_code]) != 0)
+ {
+ unsigned long extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1);
+
+ if(WasteBits(pWork, extra_length_bits))
+ {
+ if((length_code + extra_length) != 0x10E)
+ return 0x306;
+ }
+ length_code = pWork->LenBase[length_code] + extra_length;
+ }
+
+ // In order to distinguish uncompressed byte from repetition length,
+ // we have to add 0x100 to the length.
+ return length_code + 0x100;
+ }
+
+ // Remove one bit from the input data
+ if(WasteBits(pWork, 1))
+ return 0x306;
+
+ // If the binary compression type, read 8 bits and return them as one byte.
+ if(pWork->ctype == CMP_BINARY)
+ {
+ unsigned long uncompressed_byte = pWork->bit_buff & 0xFF;
+
+ if(WasteBits(pWork, 8))
+ return 0x306;
+ return uncompressed_byte;
+ }
+
+ // When ASCII compression ...
+ if(pWork->bit_buff & 0xFF)
+ {
+ value = pWork->offs2C34[pWork->bit_buff & 0xFF];
+
+ if(value == 0xFF)
+ {
+ if(pWork->bit_buff & 0x3F)
+ {
+ if(WasteBits(pWork, 4))
+ return 0x306;
+
+ value = pWork->offs2D34[pWork->bit_buff & 0xFF];
+ }
+ else
+ {
+ if(WasteBits(pWork, 6))
+ return 0x306;
+
+ value = pWork->offs2E34[pWork->bit_buff & 0x7F];
+ }
+ }
+ }
+ else
+ {
+ if(WasteBits(pWork, 8))
+ return 0x306;
+
+ value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
+ }
+
+ return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
+}
+
+//-----------------------------------------------------------------------------
+// Decodes the distance of the repetition, backwards relative to the
+// current output buffer position
+
+static unsigned long DecodeDist(TDcmpStruct * pWork, unsigned long rep_length)
+{
+ unsigned long dist_pos_code; // Distance position code
+ unsigned long dist_pos_bits; // Number of bits of distance position
+ unsigned long distance; // Distance position
+
+ // Next 2-8 bits in the input buffer is the distance position code
+ dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF];
+ dist_pos_bits = pWork->DistBits[dist_pos_code];
+ if(WasteBits(pWork, dist_pos_bits))
+ return 0;
+
+ if(rep_length == 2)
+ {
+ // If the repetition is only 2 bytes length,
+ // then take 2 bits from the stream in order to get the distance
+ distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03);
+ if(WasteBits(pWork, 2))
+ return 0;
+ }
+ else
+ {
+ // If the repetition is more than 2 bytes length,
+ // then take "dsize_bits" bits in order to get the distance
+ distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
+ if(WasteBits(pWork, pWork->dsize_bits))
+ return 0;
+ }
+ return distance + 1;
+}
+
+static unsigned long Expand(TDcmpStruct * pWork)
+{
+ unsigned long next_literal; // Literal decoded from the compressed data
+ unsigned long result; // Value to be returned
+ unsigned int copyBytes; // Number of bytes to copy to the output buffer
+
+ pWork->outputPos = 0x1000; // Initialize output buffer position
+
+ // Decode the next literal from the input data.
+ // The returned literal can either be an uncompressed byte (next_literal < 0x100)
+ // or an encoded length of the repeating byte sequence that
+ // is to be copied to the current buffer position
+ while((result = next_literal = DecodeLit(pWork)) < 0x305)
+ {
+ // If the literal is greater than 0x100, it holds length
+ // of repeating byte sequence
+ // literal of 0x100 means repeating sequence of 0x2 bytes
+ // literal of 0x101 means repeating sequence of 0x3 bytes
+ // ...
+ // literal of 0x305 means repeating sequence of 0x207 bytes
+ if(next_literal >= 0x100)
+ {
+ unsigned char * source;
+ unsigned char * target;
+ unsigned long rep_length; // Length of the repetition, in bytes
+ unsigned long minus_dist; // Backward distance to the repetition, relative to the current buffer position
+
+ // Get the length of the repeating sequence.
+ // Note that the repeating block may overlap the current output position,
+ // for example if there was a sequence of equal bytes
+ rep_length = next_literal - 0xFE;
+
+ // Get backward distance to the repetition
+ if((minus_dist = DecodeDist(pWork, rep_length)) == 0)
+ {
+ result = 0x306;
+ break;
+ }
+
+ // Target and source pointer
+ target = &pWork->out_buff[pWork->outputPos];
+ source = target - minus_dist;
+
+ // Update buffer output position
+ pWork->outputPos += rep_length;
+
+ // Copy the repeating sequence
+ while(rep_length-- > 0)
+ *target++ = *source++;
+ }
+ else
+ {
+ pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal;
+ }
+
+ // Flush the output buffer, if number of extracted bytes has reached the end
+ if(pWork->outputPos >= 0x2000)
+ {
+ // Copy decompressed data into user buffer
+ copyBytes = 0x1000;
+ pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);
+
+ // Now copy the decompressed data to the first half of the buffer.
+ // This is needed because the decompression might reuse them as repetitions.
+ // Note that if the output buffer overflowed previously, the extra decompressed bytes
+ // are stored in "out_buff_overflow", and they will now be
+ // within decompressed part of the output buffer.
+ memcpy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
+ pWork->outputPos -= 0x1000;
+ }
+ }
+
+ // Flush any remaining decompressed bytes
+ copyBytes = pWork->outputPos - 0x1000;
+ pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// Main exploding function.
+
+unsigned int explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param)
+{
+ TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
+
+ // Initialize work struct and load compressed data
+ // Note: The caller must zero the "work_buff" before passing it to explode
+ pWork->read_buf = read_buf;
+ pWork->write_buf = write_buf;
+ pWork->param = param;
+ pWork->in_pos = sizeof(pWork->in_buff);
+ pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
+ if(pWork->in_bytes <= 4)
+ return CMP_BAD_DATA;
+
+ pWork->ctype = pWork->in_buff[0]; // Get the compression type (CMP_BINARY or CMP_ASCII)
+ pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
+ pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
+ pWork->extra_bits = 0; // Extra (over 8) bits
+ pWork->in_pos = 3; // Position in input buffer
+
+ // Test for the valid dictionary size
+ if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
+ return CMP_INVALID_DICTSIZE;
+
+ pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
+
+ if(pWork->ctype != CMP_BINARY)
+ {
+ if(pWork->ctype != CMP_ASCII)
+ return CMP_INVALID_MODE;
+
+ memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
+ GenAscTabs(pWork);
+ }
+
+ memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
+ GenDecodeTabs(pWork->LengthCodes, LenCode, pWork->LenBits, sizeof(pWork->LenBits));
+ memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
+ memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
+ memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
+ GenDecodeTabs(pWork->DistPosCodes, DistCode, pWork->DistBits, sizeof(pWork->DistBits));
+ if(Expand(pWork) != 0x306)
+ return CMP_NO_ERROR;
+
+ return CMP_ABORT;
+}
diff --git a/dep/StormLib/src/pklib/implode.c b/dep/StormLib/src/pklib/implode.c
new file mode 100644
index 00000000000..1771b1862a0
--- /dev/null
+++ b/dep/StormLib/src/pklib/implode.c
@@ -0,0 +1,769 @@
+/*****************************************************************************/
+/* implode.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Implode function of PKWARE Data Compression library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.04.03 1.00 Lad First version of implode.c */
+/* 02.05.03 1.00 Lad Stress test done */
+/* 22.04.10 1.01 Lad Documented */
+/*****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "pklib.h"
+
+#if ((1200 < _MSC_VER) && (_MSC_VER < 1400))
+#pragma optimize("", off) // Fucking Microsoft VS.NET 2003 compiler !!! (_MSC_VER=1310)
+#endif
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define MAX_REP_LENGTH 0x204 // The longest allowed repetition
+
+//-----------------------------------------------------------------------------
+// Tables
+
+static unsigned char DistBits[] =
+{
+ 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+static unsigned char DistCode[] =
+{
+ 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
+ 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
+ 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
+ 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
+};
+
+static unsigned char ExLenBits[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+};
+
+static unsigned char LenBits[] =
+{
+ 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
+};
+
+static unsigned char LenCode[] =
+{
+ 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
+};
+
+static unsigned char ChBitsAsc[] =
+{
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
+ 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
+ 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
+ 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
+ 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
+ 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
+ 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
+};
+
+static unsigned short ChCodeAsc[] =
+{
+ 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
+ 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
+ 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
+ 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
+ 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
+ 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
+ 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
+ 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
+ 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
+ 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
+ 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
+ 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
+ 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
+ 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
+ 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
+ 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
+ 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
+ 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
+ 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
+ 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
+ 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
+ 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
+ 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
+ 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
+ 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
+ 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
+ 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
+ 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
+ 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
+ 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
+ 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
+ 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
+};
+
+//-----------------------------------------------------------------------------
+// Macros
+
+// Macro for calculating hash of the current byte pair.
+// Note that most exact byte pair hash would be buffer[0] + buffer[1] << 0x08,
+// but even this way gives nice indication of equal byte pairs, with significantly
+// smaller size of the array that holds numbers of those hashes
+#define BYTE_PAIR_HASH(buffer) ((buffer[0] * 4) + (buffer[1] * 5))
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+// Builds the "hash_to_index" table and "pair_hash_offsets" table.
+// Every element of "hash_to_index" will contain lowest index to the
+// "pair_hash_offsets" table, effectively giving offset of the first
+// occurence of the given PAIR_HASH in the input data.
+static void SortBuffer(TCmpStruct * pWork, unsigned char * buffer_begin, unsigned char * buffer_end)
+{
+ unsigned short * phash_to_index;
+ unsigned char * buffer_ptr;
+ unsigned short total_sum = 0;
+ unsigned long byte_pair_hash; // Hash value of the byte pair
+ unsigned short byte_pair_offs; // Offset of the byte pair, relative to "work_buff"
+
+ // Zero the entire "phash_to_index" table
+ memset(pWork->phash_to_index, 0, sizeof(pWork->phash_to_index));
+
+ // Step 1: Count amount of each PAIR_HASH in the input buffer
+ // The table will look like this:
+ // offs 0x000: Number of occurences of PAIR_HASH 0
+ // offs 0x001: Number of occurences of PAIR_HASH 1
+ // ...
+ // offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 (the highest hash value)
+ for(buffer_ptr = buffer_begin; buffer_ptr < buffer_end; buffer_ptr++)
+ pWork->phash_to_index[BYTE_PAIR_HASH(buffer_ptr)]++;
+
+ // Step 2: Convert the table to the array of PAIR_HASH amounts.
+ // Each element contains count of PAIR_HASHes that is less or equal
+ // to element index
+ // The table will look like this:
+ // offs 0x000: Number of occurences of PAIR_HASH 0 or lower
+ // offs 0x001: Number of occurences of PAIR_HASH 1 or lower
+ // ...
+ // offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 or lower
+ for(phash_to_index = pWork->phash_to_index; phash_to_index < &pWork->phash_to_index_end; phash_to_index++)
+ {
+ total_sum = total_sum + phash_to_index[0];
+ phash_to_index[0] = total_sum;
+ }
+
+ // Step 3: Convert the table to the array of indexes.
+ // Now, each element contains index to the first occurence of given PAIR_HASH
+ for(buffer_end--; buffer_end >= buffer_begin; buffer_end--)
+ {
+ byte_pair_hash = BYTE_PAIR_HASH(buffer_end);
+ byte_pair_offs = (unsigned short)(buffer_end - pWork->work_buff);
+
+ pWork->phash_to_index[byte_pair_hash]--;
+ pWork->phash_offs[pWork->phash_to_index[byte_pair_hash]] = byte_pair_offs;
+ }
+}
+
+static void FlushBuf(TCmpStruct * pWork)
+{
+ unsigned char save_ch1;
+ unsigned char save_ch2;
+ unsigned int size = 0x800;
+
+ pWork->write_buf(pWork->out_buff, &size, pWork->param);
+
+ save_ch1 = pWork->out_buff[0x800];
+ save_ch2 = pWork->out_buff[pWork->out_bytes];
+ pWork->out_bytes -= 0x800;
+
+ memset(pWork->out_buff, 0, sizeof(pWork->out_buff));
+
+ if(pWork->out_bytes != 0)
+ pWork->out_buff[0] = save_ch1;
+ if(pWork->out_bits != 0)
+ pWork->out_buff[pWork->out_bytes] = save_ch2;
+}
+
+static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
+{
+ unsigned int out_bits;
+
+ // If more than 8 bits to output, do recursion
+ if(nbits > 8)
+ {
+ OutputBits(pWork, 8, bit_buff);
+ bit_buff >>= 8;
+ nbits -= 8;
+ }
+
+ // Add bits to the last out byte in out_buff;
+ out_bits = pWork->out_bits;
+ pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
+ pWork->out_bits += nbits;
+
+ // If 8 or more bits, increment number of bytes
+ if(pWork->out_bits > 8)
+ {
+ pWork->out_bytes++;
+ bit_buff >>= (8 - out_bits);
+
+ pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
+ pWork->out_bits &= 7;
+ }
+ else
+ {
+ pWork->out_bits &= 7;
+ if(pWork->out_bits == 0)
+ pWork->out_bytes++;
+ }
+
+ // If there is enough compressed bytes, flush them
+ if(pWork->out_bytes >= 0x800)
+ FlushBuf(pWork);
+}
+
+// This function searches for a repetition
+// (a previous occurence of the current byte sequence)
+// Returns length of the repetition, and stores the backward distance
+// to pWork structure.
+static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data)
+{
+ unsigned short * phash_to_index; // Pointer into pWork->phash_to_index table
+ unsigned short * phash_offs; // Pointer to the table containing offsets of each PAIR_HASH
+ unsigned char * repetition_limit; // An eventual repetition must be at position below this pointer
+ unsigned char * prev_repetition; // Pointer to the previous occurence of the current PAIR_HASH
+ unsigned char * prev_rep_end; // End of the previous repetition
+ unsigned char * input_data_ptr;
+ unsigned short phash_offs_index; // Index to the table with PAIR_HASH positions
+ unsigned short min_phash_offs; // The lowest allowed hash offset
+ unsigned short offs_in_rep; // Offset within found repetition
+ unsigned int equal_byte_count; // Number of bytes that are equal to the previous occurence
+ unsigned int rep_length = 1; // Length of the found repetition
+ unsigned int rep_length2; // Secondary repetition
+ unsigned char pre_last_byte; // Last but one byte from a repetion
+ unsigned short di_val;
+
+ // Calculate the previous position of the PAIR_HASH
+ phash_to_index = pWork->phash_to_index + BYTE_PAIR_HASH(input_data);
+ min_phash_offs = (unsigned short)((input_data - pWork->work_buff) - pWork->dsize_bytes + 1);
+ phash_offs_index = phash_to_index[0];
+
+ // If the PAIR_HASH offset is below the limit, find a next one
+ phash_offs = pWork->phash_offs + phash_offs_index;
+ if(*phash_offs < min_phash_offs)
+ {
+ while(*phash_offs < min_phash_offs)
+ {
+ phash_offs_index++;
+ phash_offs++;
+ }
+ *phash_to_index = phash_offs_index;
+ }
+
+ // Get the first location of the PAIR_HASH,
+ // and thus the first eventual location of byte repetition
+ phash_offs = pWork->phash_offs + phash_offs_index;
+ prev_repetition = pWork->work_buff + phash_offs[0];
+ repetition_limit = input_data - 1;
+
+ // If the current PAIR_HASH was not encountered before,
+ // we haven't found a repetition.
+ if(prev_repetition >= repetition_limit)
+ return 0;
+
+ // We have found a match of a PAIR_HASH. Now we have to make sure
+ // that it is also a byte match, because PAIR_HASH is not unique.
+ // We compare the bytes and count the length of the repetition
+ input_data_ptr = input_data;
+ for(;;)
+ {
+ // If the first byte of the repetition and the so-far-last byte
+ // of the repetition are equal, we will compare the blocks.
+ if(*input_data_ptr == *prev_repetition && input_data_ptr[rep_length-1] == prev_repetition[rep_length-1])
+ {
+ // Skip the current byte
+ prev_repetition++;
+ input_data_ptr++;
+ equal_byte_count = 2;
+
+ // Now count how many more bytes are equal
+ while(equal_byte_count < MAX_REP_LENGTH)
+ {
+ prev_repetition++;
+ input_data_ptr++;
+
+ // Are the bytes different ?
+ if(*prev_repetition != *input_data_ptr)
+ break;
+
+ equal_byte_count++;
+ }
+
+ // If we found a repetition of at least the same length, take it.
+ // If there are multiple repetitions in the input buffer, this will
+ // make sure that we find the most recent one, which in turn allows
+ // us to store backward length in less amount of bits
+ input_data_ptr = input_data;
+ if(equal_byte_count >= rep_length)
+ {
+ // Calculate the backward distance of the repetition.
+ // Note that the distance is stored as decremented by 1
+ pWork->distance = (unsigned int)(input_data - prev_repetition + equal_byte_count - 1);
+
+ // Repetitions longer than 10 bytes will be stored in more bits,
+ // so they need a bit different handling
+ if((rep_length = equal_byte_count) > 10)
+ break;
+ }
+ }
+
+ // Move forward in the table of PAIR_HASH repetitions.
+ // There might be a more recent occurence of the same repetition.
+ phash_offs_index++;
+ phash_offs++;
+ prev_repetition = pWork->work_buff + phash_offs[0];
+
+ // If the next repetition is beyond the minimum allowed repetition, we are done.
+ if(prev_repetition >= repetition_limit)
+ {
+ // A repetition must have at least 2 bytes, otherwise it's not worth it
+ return (rep_length >= 2) ? rep_length : 0;
+ }
+ }
+
+ // If the repetition has max length of 0x204 bytes, we can't go any fuhrter
+ if(equal_byte_count == MAX_REP_LENGTH)
+ {
+ pWork->distance--;
+ return equal_byte_count;
+ }
+
+ // Check for possibility of a repetition that occurs at more recent position
+ phash_offs = pWork->phash_offs + phash_offs_index;
+ if(pWork->work_buff + phash_offs[1] >= repetition_limit)
+ return rep_length;
+
+ //
+ // The following part checks if there isn't a longer repetition at
+ // a latter offset, that would lead to better compression.
+ //
+ // Example of data that can trigger this optimization:
+ //
+ // "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
+ // "XYZ"
+ // "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ";
+ //
+ // Description of data in this buffer
+ // [0x00] Single byte "E"
+ // [0x01] Single byte "E"
+ // [0x02] Repeat 0x1E bytes from [0x00]
+ // [0x20] Single byte "X"
+ // [0x21] Single byte "Y"
+ // [0x22] Single byte "Z"
+ // [0x23] 17 possible previous repetitions of length at least 0x10 bytes:
+ // - Repetition of 0x10 bytes from [0x00] "EEEEEEEEEEEEEEEE"
+ // - Repetition of 0x10 bytes from [0x01] "EEEEEEEEEEEEEEEE"
+ // - Repetition of 0x10 bytes from [0x02] "EEEEEEEEEEEEEEEE"
+ // ...
+ // - Repetition of 0x10 bytes from [0x0F] "EEEEEEEEEEEEEEEE"
+ // - Repetition of 0x1C bytes from [0x10] "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
+ // The last repetition is the best one.
+ //
+
+ pWork->offs09BC[0] = 0xFFFF;
+ pWork->offs09BC[1] = 0x0000;
+ di_val = 0;
+
+ // Note: I failed to figure out what does the table "offs09BC" mean.
+ // If anyone has an idea, let me know to zezula_at_volny_dot_cz
+ for(offs_in_rep = 1; offs_in_rep < rep_length; )
+ {
+ if(input_data[offs_in_rep] != input_data[di_val])
+ {
+ di_val = pWork->offs09BC[di_val];
+ if(di_val != 0xFFFF)
+ continue;
+ }
+ pWork->offs09BC[++offs_in_rep] = ++di_val;
+ }
+
+ //
+ // Now go through all the repetitions from the first found one
+ // to the current input data, and check if any of them migh be
+ // a start of a greater sequence match.
+ //
+
+ prev_repetition = pWork->work_buff + phash_offs[0];
+ prev_rep_end = prev_repetition + rep_length;
+ rep_length2 = rep_length;
+
+ for(;;)
+ {
+ rep_length2 = pWork->offs09BC[rep_length2];
+ if(rep_length2 == 0xFFFF)
+ rep_length2 = 0;
+
+ // Get the pointer to the previous repetition
+ phash_offs = pWork->phash_offs + phash_offs_index;
+
+ // Skip those repetitions that don't reach the end
+ // of the first found repetition
+ do
+ {
+ phash_offs++;
+ phash_offs_index++;
+ prev_repetition = pWork->work_buff + *phash_offs;
+ if(prev_repetition >= repetition_limit)
+ return rep_length;
+ }
+ while(prev_repetition + rep_length2 < prev_rep_end);
+
+ // Verify if the last but one byte from the repetition matches
+ // the last but one byte from the input data.
+ // If not, find a next repetition
+ pre_last_byte = input_data[rep_length - 2];
+ if(pre_last_byte == prev_repetition[rep_length - 2])
+ {
+ // If the new repetition reaches beyond the end
+ // of previously found repetition, reset the repetition length to zero.
+ if(prev_repetition + rep_length2 != prev_rep_end)
+ {
+ prev_rep_end = prev_repetition;
+ rep_length2 = 0;
+ }
+ }
+ else
+ {
+ phash_offs = pWork->phash_offs + phash_offs_index;
+ do
+ {
+ phash_offs++;
+ phash_offs_index++;
+ prev_repetition = pWork->work_buff + *phash_offs;
+ if(prev_repetition >= repetition_limit)
+ return rep_length;
+ }
+ while(prev_repetition[rep_length - 2] != pre_last_byte || prev_repetition[0] != input_data[0]);
+
+ // Reset the length of the repetition to 2 bytes only
+ prev_rep_end = prev_repetition + 2;
+ rep_length2 = 2;
+ }
+
+ // Find out how many more characters are equal to the first repetition.
+ while(*prev_rep_end == input_data[rep_length2])
+ {
+ if(++rep_length2 >= 0x204)
+ break;
+ prev_rep_end++;
+ }
+
+ // Is the newly found repetion at least as long as the previous one ?
+ if(rep_length2 >= rep_length)
+ {
+ // Calculate the distance of the new repetition
+ pWork->distance = (unsigned int)(input_data - prev_repetition - 1);
+ if((rep_length = rep_length2) == 0x204)
+ return rep_length;
+
+ // Update the additional elements in the "offs09BC" table
+ // to reflect new rep length
+ while(offs_in_rep < rep_length2)
+ {
+ if(input_data[offs_in_rep] != input_data[di_val])
+ {
+ di_val = pWork->offs09BC[di_val];
+ if(di_val != 0xFFFF)
+ continue;
+ }
+ pWork->offs09BC[++offs_in_rep] = ++di_val;
+ }
+ }
+ }
+}
+
+static void WriteCmpData(TCmpStruct * pWork)
+{
+ unsigned char * input_data_end; // Pointer to the end of the input data
+ unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + 0x204;
+ unsigned int input_data_ended = 0; // If 1, then all data from the input stream have been already loaded
+ unsigned int save_rep_length; // Saved length of current repetition
+ unsigned int save_distance = 0; // Saved distance of current repetition
+ unsigned int rep_length; // Length of the found repetition
+ unsigned int phase = 0; //
+
+ // Store the compression type and dictionary size
+ pWork->out_buff[0] = (char)pWork->ctype;
+ pWork->out_buff[1] = (char)pWork->dsize_bits;
+ pWork->out_bytes = 2;
+
+ // Reset output buffer to zero
+ memset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);
+ pWork->out_bits = 0;
+
+ while(input_data_ended == 0)
+ {
+ unsigned int bytes_to_load = 0x1000;
+ int total_loaded = 0;
+ int bytes_loaded;
+
+ // Load the bytes from the input stream, up to 0x1000 bytes
+ while(bytes_to_load != 0)
+ {
+ bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + 0x204 + total_loaded,
+ &bytes_to_load,
+ pWork->param);
+ if(bytes_loaded == 0)
+ {
+ if(total_loaded == 0 && phase == 0)
+ goto __Exit;
+ input_data_ended = 1;
+ break;
+ }
+ else
+ {
+ bytes_to_load -= bytes_loaded;
+ total_loaded += bytes_loaded;
+ }
+ }
+
+ input_data_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;
+ if(input_data_ended)
+ input_data_end += 0x204;
+
+ //
+ // Warning: The end of the buffer passed to "SortBuffer" is actually 2 bytes beyond
+ // valid data. It is questionable if this is actually a bug or not,
+ // but it might cause the compressed data output to be dependent on random bytes
+ // that are in the buffer.
+ // To prevent that, the calling application must always zero the compression
+ // buffer before passing it to "implode"
+ //
+
+ // Search the PAIR_HASHes of the loaded blocks. Also, include
+ // previously compressed data, if any.
+ switch(phase)
+ {
+ case 0:
+ SortBuffer(pWork, input_data, input_data_end + 1);
+ phase++;
+ if(pWork->dsize_bytes != 0x1000)
+ phase++;
+ break;
+
+ case 1:
+ SortBuffer(pWork, input_data - pWork->dsize_bytes + 0x204, input_data_end + 1);
+ phase++;
+ break;
+
+ default:
+ SortBuffer(pWork, input_data - pWork->dsize_bytes, input_data_end + 1);
+ break;
+ }
+
+ // Perform the compression of the current block
+ while(input_data < input_data_end)
+ {
+ // Find if the current byte sequence wasn't there before.
+ rep_length = FindRep(pWork, input_data);
+ while(rep_length != 0)
+ {
+ // If we found repetition of 2 bytes, that is 0x100 or fuhrter back,
+ // don't bother. Storing the distance of 0x100 bytes would actually
+ // take more space than storing the 2 bytes as-is.
+ if(rep_length == 2 && pWork->distance >= 0x100)
+ break;
+
+ // When we are at the end of the input data, we cannot allow
+ // the repetition to go past the end of the input data.
+ if(input_data_ended && input_data + rep_length > input_data_end)
+ {
+ // Shorten the repetition length so that it only covers valid data
+ rep_length = (unsigned long)(input_data_end - input_data);
+ if(rep_length < 2)
+ break;
+
+ // If we got repetition of 2 bytes, that is 0x100 or more backward, don't bother
+ if(rep_length == 2 && pWork->distance >= 0x100)
+ break;
+ goto __FlushRepetition;
+ }
+
+ if(rep_length >= 8 || input_data + 1 >= input_data_end)
+ goto __FlushRepetition;
+
+ // Try to find better repetition 1 byte later.
+ // Example: "ARROCKFORT" "AROCKFORT"
+ // When "input_data" points to the second string, FindRep
+ // returns the occurence of "AR". But there is longer repetition "ROCKFORT",
+ // beginning 1 byte after.
+ save_rep_length = rep_length;
+ save_distance = pWork->distance;
+ rep_length = FindRep(pWork, input_data + 1);
+
+ // Only use the new repetition if it's length is greater than the previous one
+ if(rep_length > save_rep_length)
+ {
+ // If the new repetition if only 1 byte better
+ // and the previous distance is less than 0x80 bytes, use the previous repetition
+ if(rep_length > save_rep_length + 1 || save_distance > 0x80)
+ {
+ // Flush one byte, so that input_data will point to the secondary repetition
+ OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
+ input_data++;
+ continue;
+ }
+ }
+
+ // Revert to the previous repetition
+ rep_length = save_rep_length;
+ pWork->distance = save_distance;
+
+ __FlushRepetition:
+
+ OutputBits(pWork, pWork->nChBits[rep_length + 0xFE], pWork->nChCodes[rep_length + 0xFE]);
+ if(rep_length == 2)
+ {
+ OutputBits(pWork, pWork->dist_bits[pWork->distance >> 2],
+ pWork->dist_codes[pWork->distance >> 2]);
+ OutputBits(pWork, 2, pWork->distance & 3);
+ }
+ else
+ {
+ OutputBits(pWork, pWork->dist_bits[pWork->distance >> pWork->dsize_bits],
+ pWork->dist_codes[pWork->distance >> pWork->dsize_bits]);
+ OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->distance);
+ }
+
+ // Move the begin of the input data by the length of the repetition
+ input_data += rep_length;
+ goto _00402252;
+ }
+
+ // If there was no previous repetition for the current position in the input data,
+ // just output the 9-bit literal for the one character
+ OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
+ input_data++;
+_00402252:;
+ }
+
+ if(input_data_ended == 0)
+ {
+ input_data -= 0x1000;
+ memcpy(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);
+ }
+ }
+
+__Exit:
+
+ // Write the termination literal
+ OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
+ if(pWork->out_bits != 0)
+ pWork->out_bytes++;
+ pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
+ return;
+}
+
+//-----------------------------------------------------------------------------
+// Main imploding function
+
+unsigned int PKEXPORT implode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param,
+ unsigned int *type,
+ unsigned int *dsize)
+{
+ TCmpStruct * pWork = (TCmpStruct *)work_buf;
+ unsigned int nChCode;
+ unsigned int nCount;
+ unsigned int i;
+ int nCount2;
+
+ // Fill the work buffer information
+ // Note: The caller must zero the "work_buff" before passing it to implode
+ pWork->read_buf = read_buf;
+ pWork->write_buf = write_buf;
+ pWork->dsize_bytes = *dsize;
+ pWork->ctype = *type;
+ pWork->param = param;
+ pWork->dsize_bits = 4;
+ pWork->dsize_mask = 0x0F;
+
+ // Test dictionary size
+ switch(*dsize)
+ {
+ case CMP_IMPLODE_DICT_SIZE3: // 0x1000 bytes
+ pWork->dsize_bits++;
+ pWork->dsize_mask |= 0x20;
+ // No break here !!!
+
+ case CMP_IMPLODE_DICT_SIZE2: // 0x800 bytes
+ pWork->dsize_bits++;
+ pWork->dsize_mask |= 0x10;
+ // No break here !!!
+
+ case CMP_IMPLODE_DICT_SIZE1: // 0x400
+ break;
+
+ default:
+ return CMP_INVALID_DICTSIZE;
+ }
+
+ // Test the compression type
+ switch(*type)
+ {
+ case CMP_BINARY: // We will compress data with binary compression type
+ for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
+ {
+ pWork->nChBits[nCount] = 9;
+ pWork->nChCodes[nCount] = (unsigned short)nChCode;
+ nChCode = (nChCode & 0x0000FFFF) + 2;
+ }
+ break;
+
+
+ case CMP_ASCII: // We will compress data with ASCII compression type
+ for(nCount = 0; nCount < 0x100; nCount++)
+ {
+ pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
+ pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
+ }
+ break;
+
+ default:
+ return CMP_INVALID_MODE;
+ }
+
+ for(i = 0; i < 0x10; i++)
+ {
+ if(1 << ExLenBits[i])
+ {
+ for(nCount2 = 0; nCount2 < (1 << ExLenBits[i]); nCount2++)
+ {
+ pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
+ pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
+ nCount++;
+ }
+ }
+ }
+
+ // Copy the distance codes and distance bits and perform the compression
+ memcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));
+ memcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));
+ WriteCmpData(pWork);
+ return CMP_NO_ERROR;
+}
diff --git a/dep/StormLib/src/pklib/pklib.h b/dep/StormLib/src/pklib/pklib.h
new file mode 100644
index 00000000000..f43da153be6
--- /dev/null
+++ b/dep/StormLib/src/pklib/pklib.h
@@ -0,0 +1,148 @@
+/*****************************************************************************/
+/* pklib.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Header file for PKWARE Data Compression Library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 31.03.03 1.00 Lad The first version of pkware.h */
+/*****************************************************************************/
+
+#ifndef __PKLIB_H__
+#define __PKLIB_H__
+
+#include "../StormPort.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define CMP_BINARY 0 // Binary compression
+#define CMP_ASCII 1 // Ascii compression
+
+#define CMP_NO_ERROR 0
+#define CMP_INVALID_DICTSIZE 1
+#define CMP_INVALID_MODE 2
+#define CMP_BAD_DATA 3
+#define CMP_ABORT 4
+
+#define CMP_IMPLODE_DICT_SIZE1 1024 // Dictionary size of 1024
+#define CMP_IMPLODE_DICT_SIZE2 2048 // Dictionary size of 2048
+#define CMP_IMPLODE_DICT_SIZE3 4096 // Dictionary size of 4096
+
+//-----------------------------------------------------------------------------
+// Define calling convention
+
+#ifndef PKEXPORT
+#ifdef WIN32
+#define PKEXPORT __cdecl // Use for normal __cdecl calling
+#else
+#define PKEXPORT
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Internal structures
+
+// Compression structure
+typedef struct
+{
+ unsigned int distance; // 0000: Backward distance of the currently found repetition, decreased by 1
+ unsigned int out_bytes; // 0004: # bytes available in out_buff
+ unsigned int out_bits; // 0008: # of bits available in the last out byte
+ unsigned int dsize_bits; // 000C: Number of bits needed for dictionary size. 4 = 0x400, 5 = 0x800, 6 = 0x1000
+ unsigned int dsize_mask; // 0010: Bit mask for dictionary. 0x0F = 0x400, 0x1F = 0x800, 0x3F = 0x1000
+ unsigned int ctype; // 0014: Compression type (CMP_ASCII or CMP_BINARY)
+ unsigned int dsize_bytes; // 0018: Dictionary size in bytes
+ unsigned char dist_bits[0x40]; // 001C: Distance bits
+ unsigned char dist_codes[0x40]; // 005C: Distance codes
+ unsigned char nChBits[0x306]; // 009C: Table of literal bit lengths to be put to the output stream
+ unsigned short nChCodes[0x306]; // 03A2: Table of literal codes to be put to the output stream
+ unsigned short offs09AE; // 09AE:
+
+ void * param; // 09B0: User parameter
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4
+ void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8
+
+ unsigned short offs09BC[0x204]; // 09BC:
+ unsigned long offs0DC4; // 0DC4:
+ unsigned short phash_to_index[0x900]; // 0DC8: Array of indexes (one for each PAIR_HASH) to the "pair_hash_offsets" table
+ unsigned short phash_to_index_end; // 1FC8: End marker for "phash_to_index" table
+ char out_buff[0x802]; // 1FCA: Compressed data
+ unsigned char work_buff[0x2204]; // 27CC: Work buffer
+ // + DICT_OFFSET => Dictionary
+ // + UNCMP_OFFSET => Uncompressed data
+ unsigned short phash_offs[0x2204]; // 49D0: Table of offsets for each PAIR_HASH
+} TCmpStruct;
+
+#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression structure.
+ // Defined as 36312 in pkware header file
+
+
+// Decompression structure
+typedef struct
+{
+ unsigned long offs0000; // 0000
+ unsigned long ctype; // 0004: Compression type (CMP_BINARY or CMP_ASCII)
+ unsigned long outputPos; // 0008: Position in output buffer
+ unsigned long dsize_bits; // 000C: Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)
+ unsigned long dsize_mask; // 0010: Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)
+ unsigned long bit_buff; // 0014: 16-bit buffer for processing input data
+ unsigned long extra_bits; // 0018: Number of extra (above 8) bits in bit buffer
+ unsigned int in_pos; // 001C: Position in in_buff
+ unsigned long in_bytes; // 0020: Number of bytes in input buffer
+ void * param; // 0024: Custom parameter
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // Pointer to function that reads data from the input stream
+ void (*write_buf)(char *buf, unsigned int *size, void *param);// Pointer to function that writes data to the output stream
+
+ unsigned char out_buff[0x2204]; // 0030: Output circle buffer.
+ // 0x0000 - 0x0FFF: Previous uncompressed data, kept for repetitions
+ // 0x1000 - 0x1FFF: Currently decompressed data
+ // 0x2000 - 0x2203: Reserve space for the longest possible repetition
+ unsigned char in_buff[0x800]; // 2234: Buffer for data to be decompressed
+ unsigned char DistPosCodes[0x100]; // 2A34: Table of distance position codes
+ unsigned char LengthCodes[0x100]; // 2B34: Table of length codes
+ unsigned char offs2C34[0x100]; // 2C34: Buffer for
+ unsigned char offs2D34[0x100]; // 2D34: Buffer for
+ unsigned char offs2E34[0x80]; // 2EB4: Buffer for
+ unsigned char offs2EB4[0x100]; // 2EB4: Buffer for
+ unsigned char ChBitsAsc[0x100]; // 2FB4: Buffer for
+ unsigned char DistBits[0x40]; // 30B4: Numbers of bytes to skip copied block length
+ unsigned char LenBits[0x10]; // 30F4: Numbers of bits for skip copied block length
+ unsigned char ExLenBits[0x10]; // 3104: Number of valid bits for copied block
+ unsigned short LenBase[0x10]; // 3114: Buffer for
+} TDcmpStruct;
+
+#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompression structure
+ // Defined as 12596 in pkware headers
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+unsigned int PKEXPORT implode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param,
+ unsigned int *type,
+ unsigned int *dsize);
+
+
+unsigned int PKEXPORT explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param);
+
+// The original name "crc32" was changed to "crc32pk" due
+// to compatibility with zlib
+unsigned long PKEXPORT crc32_pklib(char *buffer, unsigned int *size, unsigned long *old_crc);
+
+#ifdef __cplusplus
+ } // End of 'extern "C"' declaration
+#endif
+
+#endif // __PKLIB_H__
diff --git a/dep/StormLib/src/sparse/sparse.cpp b/dep/StormLib/src/sparse/sparse.cpp
new file mode 100644
index 00000000000..6df7021fc8a
--- /dev/null
+++ b/dep/StormLib/src/sparse/sparse.cpp
@@ -0,0 +1,292 @@
+/*****************************************************************************/
+/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains Huffmann (de)compression methods */
+/* */
+/* Authors : Ladislav Zezula (ladik.zezula.net) */
+/* ShadowFlare (BlakFlare@hotmail.com) */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */
+/* 03.05.03 1.00 Lad Added compression methods */
+/* 19.11.03 1.01 Dan Big endian handling */
+/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
+/*****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "sparse.h"
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+void CompressSparse(unsigned char * pbOutBuffer, int * pcbOutBuffer, unsigned char * pbInBuffer, int cbInBuffer)
+{
+ unsigned char * pbOutBufferEnd = pbOutBuffer + *pcbOutBuffer;
+ unsigned char * pbInBufferEnd = pbInBuffer + cbInBuffer;
+ unsigned char * pbLastNonZero = pbInBuffer;
+ unsigned char * pbOutBuffer0 = pbOutBuffer;
+ unsigned char * pbInBuffPtr = pbInBuffer;
+ size_t NumberOfNonZeros;
+ size_t NumberOfZeros;
+
+ // There must be at least 4 bytes of free space in the output buffer now
+ if((pbInBuffer + 4) >= pbInBufferEnd)
+ return;
+
+ // Put the original data length (in little endian)
+ *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x18);
+ *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x10);
+ *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x08);
+ *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x00);
+
+ // If there is at least 3 bytes in the input buffer, do this loop
+ while(pbInBuffer < (pbInBufferEnd - 3))
+ {
+ // Reset the zero count and frontal pointer
+ pbLastNonZero = pbInBuffer;
+ pbInBuffPtr = pbInBuffer;
+ NumberOfZeros = 0;
+
+ if(pbInBuffPtr < pbInBufferEnd)
+ {
+ do
+ {
+ // Count number of zeros
+ if(*pbInBuffPtr == 0)
+ {
+ NumberOfZeros++;
+ }
+ else
+ {
+ // Were there at least 3 zeros before? If yes, we need to flush the data
+ if(NumberOfZeros >= 3)
+ break;
+ pbLastNonZero = pbInBuffPtr + 1;
+ NumberOfZeros = 0;
+ }
+ }
+ while(++pbInBuffPtr < pbInBufferEnd);
+ }
+
+ // Get number of nonzeros that we found so far and flush them
+ NumberOfNonZeros = pbLastNonZero - pbInBuffer;
+ if(NumberOfNonZeros != 0)
+ {
+ // Process blocks that are longer than 0x81 nonzero bytes
+ while(NumberOfNonZeros > 0x81)
+ {
+ // Verify if we still have enough space in output buffer
+ if((pbOutBuffer + 0x81) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "0x80 of nonzeros"
+ *pbOutBuffer++ = 0xFF;
+ memcpy(pbOutBuffer, pbInBuffer, 0x80);
+
+ // Adjust counter of nonzeros and both pointers
+ NumberOfNonZeros -= 0x80;
+ pbOutBuffer += 0x80;
+ pbInBuffer += 0x80;
+ }
+
+ // BUGBUG: The following code will be triggered if the NumberOfNonZeros
+ // was 0x81 before. It will copy just one byte. This seems like a bug to me,
+ // but since I want StormLib to be exact like Blizzard code is, I will keep
+ // it that way here
+ if(NumberOfNonZeros > 0x80)
+ {
+ // Verify if we still have enough space in output buffer
+ if((pbOutBuffer + 2) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "1 nonzero byte"
+ *pbOutBuffer++ = 0x80;
+ memcpy(pbOutBuffer, pbInBuffer, 1);
+
+ // Adjust counter of nonzeros and both pointers
+ NumberOfNonZeros--;
+ pbOutBuffer++;
+ pbInBuffer++;
+ }
+
+ // If there is 1 nonzero or more, put the block
+ if(NumberOfNonZeros >= 0x01)
+ {
+ // Verify if we still have enough space in output buffer
+ if((pbOutBuffer + NumberOfNonZeros + 1) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "Several nonzero bytes"
+ *pbOutBuffer++ = (unsigned char)(0x80 | (NumberOfNonZeros - 1));
+ memcpy(pbOutBuffer, pbInBuffer, NumberOfNonZeros);
+
+ // Adjust pointers
+ pbOutBuffer += NumberOfNonZeros;
+ pbInBuffer += NumberOfNonZeros;
+ }
+ else
+ {
+ // Verify if we still have enough space in output buffer
+ if((pbOutBuffer + 2) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "1 nonzero byte"
+ *pbOutBuffer++ = 0x80;
+ memcpy(pbOutBuffer, pbInBuffer, 1);
+
+ // Adjust pointers
+ pbOutBuffer++;
+ pbInBuffer++;
+ }
+ }
+
+ // Now flush all zero bytes
+ while(NumberOfZeros > 0x85)
+ {
+ // Do we have at least 2 bytes in the output buffer ?
+ if((pbOutBuffer + 1) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "0x82 zeros"
+ *pbOutBuffer++ = 0x7F;
+
+ // Adjust zero counter and input pointer
+ NumberOfZeros -= 0x82;
+ pbInBuffer += 0x82;
+ }
+
+ // If we got more than 0x82 zeros, flush 3 of them now
+ if(NumberOfZeros > 0x82)
+ {
+ // Do we have at least 2 bytes in the output buffer ?
+ if((pbOutBuffer + 1) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "0x03 zeros"
+ *pbOutBuffer++ = 0;
+
+ // Adjust zero counter and input pointer
+ NumberOfZeros -= 0x03;
+ pbInBuffer += 0x03;
+ }
+
+ // Is there at least three zeros ?
+ if(NumberOfZeros >= 3)
+ {
+ // Do we have at least 2 bytes in the output buffer ?
+ if((pbOutBuffer + 1) >= pbOutBufferEnd)
+ return;
+
+ // Put marker that means "Several zeros"
+ *pbOutBuffer++ = (unsigned char)(NumberOfZeros - 3);
+
+ // Adjust pointer
+ pbInBuffer += NumberOfZeros;
+ }
+ }
+
+ // Flush last three bytes
+ if(pbInBuffer < pbInBufferEnd)
+ {
+ pbInBuffPtr = pbInBuffer;
+
+ for(;;)
+ {
+ if(*pbInBuffPtr++ != 0)
+ {
+ // Get number of bytes remaining
+ NumberOfNonZeros = (pbInBufferEnd - pbInBuffer);
+
+ // Not enough space in the output buffer ==> exit
+ if((pbOutBuffer + NumberOfNonZeros + 1) >= pbOutBufferEnd)
+ return;
+
+ // Terminate with a marker that means "0x80 of nonzeros"
+ *pbOutBuffer++ = 0xFF;
+ memcpy(pbOutBuffer, pbInBuffer, NumberOfNonZeros);
+
+ // Adjust pointer
+ pbOutBuffer += NumberOfNonZeros;
+ break;
+ }
+ else
+ {
+ // Is there are more chars in the input buffer
+ if(pbInBuffPtr < pbInBufferEnd)
+ continue;
+
+ // If the compression will not compress it by even 1 byte, do nothing
+ if((pbOutBuffer + 1) >= pbOutBufferEnd)
+ return;
+
+ // Terminate with a chunk that means "0x82 of zeros"
+ *pbOutBuffer++ = 0x7F;
+ break;
+ }
+ }
+ }
+
+ // Out the length of the output buffer
+ *pcbOutBuffer = (int)(pbOutBuffer - pbOutBuffer0);
+}
+
+int DecompressSparse(unsigned char * pbOutBuffer, int * pcbOutBuffer, unsigned char * pbInBuffer, int cbInBuffer)
+{
+ unsigned char * pbInBufferEnd = pbInBuffer + cbInBuffer;
+ unsigned int cbChunkSize;
+ unsigned int cbOutBuffer = 0;
+ unsigned int OneByte;
+
+ // Don't decompress anything that is shorter than 5 bytes
+ if(cbInBuffer < 5)
+ return 0;
+
+ // Get the 32-bits from the input stream
+ OneByte = *pbInBuffer++;
+ cbOutBuffer |= (OneByte << 0x18);
+ OneByte = *pbInBuffer++;
+ cbOutBuffer |= (OneByte << 0x10);
+ OneByte = *pbInBuffer++;
+ cbOutBuffer |= (OneByte << 0x08);
+ OneByte = *pbInBuffer++;
+ cbOutBuffer |= (OneByte << 0x00);
+
+ // Verify the size of the stream against the output buffer size
+ if(cbOutBuffer > *pcbOutBuffer)
+ return 0;
+
+ // Put the output size to the buffer
+ *pcbOutBuffer = cbOutBuffer;
+
+ // Process the input buffer
+ while(pbInBuffer < pbInBufferEnd)
+ {
+ // Get (next) byte from the stream
+ OneByte = *pbInBuffer++;
+
+ // If highest bit, it means that that normal data follow
+ if(OneByte & 0x80)
+ {
+ cbChunkSize = (OneByte & 0x7F) + 1;
+ cbChunkSize = (cbChunkSize < cbOutBuffer) ? cbChunkSize : cbOutBuffer;
+ memcpy(pbOutBuffer, pbInBuffer, cbChunkSize);
+ pbInBuffer += cbChunkSize;
+ }
+ else
+ {
+ cbChunkSize = (OneByte & 0x7F) + 3;
+ cbChunkSize = (cbChunkSize < cbOutBuffer) ? cbChunkSize : cbOutBuffer;
+ memset(pbOutBuffer, 0, cbChunkSize);
+ }
+
+ // Increment output buffer pointer
+ pbOutBuffer += cbChunkSize;
+ cbOutBuffer -= cbChunkSize;
+ }
+
+ return 1;
+}
diff --git a/dep/StormLib/src/sparse/sparse.h b/dep/StormLib/src/sparse/sparse.h
new file mode 100644
index 00000000000..032395f0b94
--- /dev/null
+++ b/dep/StormLib/src/sparse/sparse.h
@@ -0,0 +1,19 @@
+/*****************************************************************************/
+/* sparse.h Copyright (c) Ladislav Zezula 2010 */
+/*---------------------------------------------------------------------------*/
+/* implementation of Sparse compression, used in Starcraft II */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 05.03.10 1.00 Lad The first version of sparse.h */
+/*****************************************************************************/
+
+#ifndef __SPARSE_H__
+#define __SPARSE_H__
+
+#include "../StormPort.h"
+
+void CompressSparse(unsigned char * pbOutBuffer, int * pcbOutLength, unsigned char * pbInBuffer, int cbInLength);
+int DecompressSparse(unsigned char * pbOutBuffer, int * pcbOutLength, unsigned char * pbInBuffer, int cbInLength);
+
+#endif // __SPARSE_H__
diff --git a/dep/StormLib/src/zlib/adler32.c b/dep/StormLib/src/zlib/adler32.c
new file mode 100644
index 00000000000..007ba26277c
--- /dev/null
+++ b/dep/StormLib/src/zlib/adler32.c
@@ -0,0 +1,149 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off_t len2;
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ rem = (unsigned)(len2 % BASE);
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 > BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
diff --git a/dep/StormLib/src/zlib/compress2.c b/dep/StormLib/src/zlib/compress2.c
new file mode 100644
index 00000000000..df04f0148e6
--- /dev/null
+++ b/dep/StormLib/src/zlib/compress2.c
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+ int level;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+ uLong sourceLen;
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
diff --git a/dep/StormLib/src/zlib/crc32.c b/dep/StormLib/src/zlib/crc32.c
new file mode 100644
index 00000000000..f658a9ef55e
--- /dev/null
+++ b/dep/StormLib/src/zlib/crc32.c
@@ -0,0 +1,423 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+# ifdef STDC /* need ANSI C limits.h to determine sizes */
+# include <limits.h>
+# define BYFOUR
+# if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int u4;
+# else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short u4;
+# else
+# undef BYFOUR /* can't find a four-byte integer type! */
+# endif
+# endif
+# endif
+# endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+ (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+ local unsigned long crc32_little OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+ local unsigned long crc32_big OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+# define TBLS 8
+#else
+# define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The first table is simply the CRC of all possible eight bit values. This is
+ all the information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes. The remaining tables
+ allow for word-at-a-time CRC calculation for both big-endian and little-
+ endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+ unsigned long c;
+ int n, k;
+ unsigned long poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static volatile int first = 1; /* flag to limit concurrent making */
+ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* See if another task is already doing this (not thread-safe, but better
+ than nothing -- significantly reduces duration of vulnerability in
+ case the advice about DYNAMIC_CRC_TABLE is ignored) */
+ if (first) {
+ first = 0;
+
+ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+ poly = 0UL;
+ for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+ poly |= 1UL << (31 - p[n]);
+
+ /* generate a crc for every 8-bit value */
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[0][n] = c;
+ }
+
+#ifdef BYFOUR
+ /* generate crc for each value followed by one, two, and three zeros,
+ and then the byte reversal of those as well as the first table */
+ for (n = 0; n < 256; n++) {
+ c = crc_table[0][n];
+ crc_table[4][n] = REV(c);
+ for (k = 1; k < 4; k++) {
+ c = crc_table[0][c & 0xff] ^ (c >> 8);
+ crc_table[k][n] = c;
+ crc_table[k + 4][n] = REV(c);
+ }
+ }
+#endif /* BYFOUR */
+
+ crc_table_empty = 0;
+ }
+ else { /* not first */
+ /* wait for the other guy to finish (not efficient, but rare) */
+ while (crc_table_empty)
+ ;
+ }
+
+#ifdef MAKECRCH
+ /* write out CRC tables to crc32.h */
+ {
+ FILE *out;
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+ fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+ fprintf(out, "local const unsigned long FAR ");
+ fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
+ write_table(out, crc_table[0]);
+# ifdef BYFOUR
+ fprintf(out, "#ifdef BYFOUR\n");
+ for (k = 1; k < 8; k++) {
+ fprintf(out, " },\n {\n");
+ write_table(out, crc_table[k]);
+ }
+ fprintf(out, "#endif\n");
+# endif /* BYFOUR */
+ fprintf(out, " }\n};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+ FILE *out;
+ const unsigned long FAR *table;
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
+ n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = (u4)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = REV((u4)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+ unsigned long *mat;
+ unsigned long vec;
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+ unsigned long *square;
+ unsigned long *mat;
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off_t len2;
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case */
+ if (len2 == 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320L; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
diff --git a/dep/StormLib/src/zlib/crc32.h b/dep/StormLib/src/zlib/crc32.h
new file mode 100644
index 00000000000..8053b6117c0
--- /dev/null
+++ b/dep/StormLib/src/zlib/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+#ifdef BYFOUR
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+#endif
+ }
+};
diff --git a/dep/StormLib/src/zlib/deflate.c b/dep/StormLib/src/zlib/deflate.c
new file mode 100644
index 00000000000..29ce1f64a57
--- /dev/null
+++ b/dep/StormLib/src/zlib/deflate.c
@@ -0,0 +1,1736 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->wrap == 2 ||
+ (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+ return Z_STREAM_ERROR;
+
+ s = strm->state;
+ if (s->wrap)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+ z_streamp strm;
+ int bits;
+ int value;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ strm->state->bi_valid = bits;
+ strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+ z_streamp strm;
+ uLong sourceLen;
+{
+ deflate_state *s;
+ uLong destLen;
+
+ /* conservative upper bound */
+ destLen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+ /* if can't get parameters, return conservative bound */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return destLen;
+
+ /* if not default parameters, return conservative bound */
+ s = strm->state;
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return destLen;
+
+ /* default settings: return tight bound for that case */
+ return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy(dest, source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, strm->next_in, len);
+ }
+#endif
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ /* %%% avoid this when Z_RLE */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+#ifdef FASTEST
+ if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+ (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#else
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#endif
+ /* longest_match() or longest_match_fast() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+ /* longest_match() or longest_match_fast() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt run; /* length of run */
+ uInt max; /* maximum length of run */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan; /* scan for end of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ run = 0;
+ if (s->strstart > 0) { /* if there is a previous byte, that is */
+ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ scan = s->window + s->strstart - 1;
+ prev = *scan++;
+ do {
+ if (*scan++ != prev)
+ break;
+ } while (++run < max);
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (run >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, run);
+ _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+ s->lookahead -= run;
+ s->strstart += run;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
diff --git a/dep/StormLib/src/zlib/deflate.h b/dep/StormLib/src/zlib/deflate.h
new file mode 100644
index 00000000000..05a5ab3a2c1
--- /dev/null
+++ b/dep/StormLib/src/zlib/deflate.h
@@ -0,0 +1,331 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/dep/StormLib/src/zlib/inffast.c b/dep/StormLib/src/zlib/inffast.c
new file mode 100644
index 00000000000..bbee92ed1e6
--- /dev/null
+++ b/dep/StormLib/src/zlib/inffast.c
@@ -0,0 +1,318 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code this; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ PUP(out) = (unsigned char)(this.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ this = dcode[this.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ this = lcode[this.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/dep/StormLib/src/zlib/inffast.h b/dep/StormLib/src/zlib/inffast.h
new file mode 100644
index 00000000000..1e88d2d97b5
--- /dev/null
+++ b/dep/StormLib/src/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/dep/StormLib/src/zlib/inffixed.h b/dep/StormLib/src/zlib/inffixed.h
new file mode 100644
index 00000000000..75ed4b5978d
--- /dev/null
+++ b/dep/StormLib/src/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications. It
+ is part of the implementation of the compression library and
+ is subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/dep/StormLib/src/zlib/inflate.c b/dep/StormLib/src/zlib/inflate.c
new file mode 100644
index 00000000000..792fdee8e9c
--- /dev/null
+++ b/dep/StormLib/src/zlib/inflate.c
@@ -0,0 +1,1368 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+ state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+ if ((int)(this.op) == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ state->mode = LIT;
+ break;
+ }
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long id;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
diff --git a/dep/StormLib/src/zlib/inflate.h b/dep/StormLib/src/zlib/inflate.h
new file mode 100644
index 00000000000..07bd3e78a7c
--- /dev/null
+++ b/dep/StormLib/src/zlib/inflate.h
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
diff --git a/dep/StormLib/src/zlib/inftrees.c b/dep/StormLib/src/zlib/inftrees.c
new file mode 100644
index 00000000000..8a9c13ff03d
--- /dev/null
+++ b/dep/StormLib/src/zlib/inftrees.c
@@ -0,0 +1,329 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code this; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)1;
+ this.val = (unsigned short)0;
+ *(*table)++ = this; /* make a table to force an error */
+ *(*table)++ = this;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ this.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ this.op = (unsigned char)0;
+ this.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ this.op = (unsigned char)(extra[work[sym]]);
+ this.val = base[work[sym]];
+ }
+ else {
+ this.op = (unsigned char)(32 + 64); /* end of block */
+ this.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = this;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)(len - drop);
+ this.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ this.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = this;
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/dep/StormLib/src/zlib/inftrees.h b/dep/StormLib/src/zlib/inftrees.h
new file mode 100644
index 00000000000..b1104c87e76
--- /dev/null
+++ b/dep/StormLib/src/zlib/inftrees.h
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/dep/StormLib/src/zlib/trees.c b/dep/StormLib/src/zlib/trees.c
new file mode 100644
index 00000000000..395e4e16814
--- /dev/null
+++ b/dep/StormLib/src/zlib/trees.c
@@ -0,0 +1,1219 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+ set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type(s)
+ deflate_state *s;
+{
+ int n;
+
+ for (n = 0; n < 9; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ if (n == 9)
+ for (n = 14; n < 32; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/dep/StormLib/src/zlib/trees.h b/dep/StormLib/src/zlib/trees.h
new file mode 100644
index 00000000000..72facf900f7
--- /dev/null
+++ b/dep/StormLib/src/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/dep/StormLib/src/zlib/zconf.h b/dep/StormLib/src/zlib/zconf.h
new file mode 100644
index 00000000000..03a9431c8be
--- /dev/null
+++ b/dep/StormLib/src/zlib/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/dep/StormLib/src/zlib/zlib.h b/dep/StormLib/src/zlib/zlib.h
new file mode 100644
index 00000000000..022817927ce
--- /dev/null
+++ b/dep/StormLib/src/zlib/zlib.h
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/dep/StormLib/src/zlib/zutil.c b/dep/StormLib/src/zlib/zutil.c
new file mode 100644
index 00000000000..d55f5948a37
--- /dev/null
+++ b/dep/StormLib/src/zlib/zutil.c
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch (sizeof(uInt)) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch (sizeof(uLong)) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch (sizeof(voidpf)) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch (sizeof(z_off_t)) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#ifdef STDC
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef DEBUG
+
+# ifndef verbose
+# define verbose 0
+# endif
+int z_verbose = verbose;
+
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+ int err;
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/dep/StormLib/src/zlib/zutil.h b/dep/StormLib/src/zlib/zutil.h
new file mode 100644
index 00000000000..b7d5eff81b6
--- /dev/null
+++ b/dep/StormLib/src/zlib/zutil.h
@@ -0,0 +1,269 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
+ extern int errno;
+#else
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/dep/StormLib/storm_dll/storm_dll.cpp b/dep/StormLib/storm_dll/storm_dll.cpp
new file mode 100644
index 00000000000..2941f2a37f5
--- /dev/null
+++ b/dep/StormLib/storm_dll/storm_dll.cpp
@@ -0,0 +1,117 @@
+/*****************************************************************************/
+/* Storm.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* This is just a dummy module for building import library for Storm.dll */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.04.03 1.00 Lad The first version of Storm.cpp */
+/*****************************************************************************/
+
+#include <windows.h>
+
+#define BUILDING_STORM_CPP
+#define STORM_ALTERNATE_NAMES
+#include "storm_dll.h"
+
+BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(CloseFile)(HANDLE hFile)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+LCID WINAPI SFILE(SetLocale)(LCID nNewLocale)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SFILE(Destroy)()
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SCOMP(Compress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
diff --git a/dep/StormLib/storm_dll/storm_dll.def b/dep/StormLib/storm_dll/storm_dll.def
new file mode 100644
index 00000000000..8de88f5db3d
--- /dev/null
+++ b/dep/StormLib/storm_dll/storm_dll.def
@@ -0,0 +1,25 @@
+; Storm definition file with alternate Storm.dll names
+LIBRARY "Storm"
+
+EXPORTS
+ StormCloseArchive @252 ; 0x0FC
+ StormCloseFile @253 ; 0x0FD
+ StormDestroy @262 ; 0x106
+ StormGetFileArchive @264 ; 0x108
+ StormGetFileSize @265 ; 0x109
+ StormOpenArchive @266 ; 0x10A
+ StormOpenFile @267 ; 0x10B
+ StormOpenFileEx @268 ; 0x10C
+ StormReadFile @269 ; 0x10D
+ StormSetBasePath @270 ; 0x10E
+ StormSetFilePointer @271 ; 0x10F
+ StormSetLocale @272 ; 0x110
+ StormGetBasePath @273 ; 0x111
+ StormGetArchiveName @275 ; 0x113
+ StormGetFileName @276 ; 0x114
+
+; StormSetLastError @465 ; 0x
+
+ StormCompress @551 ; 0x227
+ StormDecompress @552 ; 0x228
+ \ No newline at end of file
diff --git a/dep/StormLib/storm_dll/storm_dll.h b/dep/StormLib/storm_dll/storm_dll.h
new file mode 100644
index 00000000000..6d67820a22f
--- /dev/null
+++ b/dep/StormLib/storm_dll/storm_dll.h
@@ -0,0 +1,67 @@
+/*****************************************************************************/
+/* Storm.h Copyright Justin Olbrantz(Quantam) 2000 */
+/*---------------------------------------------------------------------------*/
+/* Storm Interface Library v1.0 for Windows */
+/* */
+/* Author : Justin Olbrantz(Quantam) */
+/* E-mail : omega@dragonfire.net */
+/* WWW : www.campaigncreations.com/starcraft/mpq2k/inside_mopaq/ */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.00 1.00 Qua The first version of Storm.h */
+/* 11.04.03 1.00 Lad Added some functions */
+/*****************************************************************************/
+
+// We need the Windows data types for the Storm prototypes
+#include <windows.h>
+
+#ifndef __STORM_H__
+#define __STORM_H__
+
+// Somethimes is necessary to change the function names so they
+// will not conflict with other MPQ tools.
+#ifdef STORM_ALTERNATE_NAMES
+ #define SFILE(Name) Storm##Name
+ #define SCOMP(Name) Storm##Name
+#else
+ #define SFILE(Name) SFile##Name
+ #define SCOMP(Name) SComp##Name
+#endif
+
+
+// Just in case anyone is still using C out there
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Storm file function prototypes
+BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ);
+BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ);
+BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength);
+BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile);
+BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile);
+BOOL WINAPI SFILE(CloseFile)(HANDLE hFile);
+DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh);
+BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ);
+BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength);
+DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod);
+BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped);
+LCID WINAPI SFILE(SetLocale)(LCID nNewLocale);
+BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength);
+BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath);
+
+// Storm (de)compression functions
+BOOL WINAPI SCOMP(Compress) (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel);
+BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
+
+
+#if defined(_MSC_VER) && !defined(BUILDING_STORM_CPP)
+#pragma comment(lib, "Storm.lib") // Force linking Storm.lib and thus Storm.dll
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __STORM_H__
diff --git a/dep/StormLib/stormlib_dll/DllMain.c b/dep/StormLib/stormlib_dll/DllMain.c
new file mode 100644
index 00000000000..cbfa84a08a8
--- /dev/null
+++ b/dep/StormLib/stormlib_dll/DllMain.c
@@ -0,0 +1,24 @@
+/*****************************************************************************/
+/* DllMain.c Copyright (c) Ladislav Zezula 2006 */
+/*---------------------------------------------------------------------------*/
+/* Description: DllMain for the StormLib.dll library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 23.11.06 1.00 Lad The first version of DllMain.c */
+/*****************************************************************************/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+//-----------------------------------------------------------------------------
+// DllMain
+
+DWORD WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
+{
+ UNREFERENCED_PARAMETER(hInst);
+ UNREFERENCED_PARAMETER(dwReason);
+ UNREFERENCED_PARAMETER(lpReserved);
+
+ return TRUE;
+}
diff --git a/dep/StormLib/stormlib_dll/StormLib.def b/dep/StormLib/stormlib_dll/StormLib.def
new file mode 100644
index 00000000000..0ba91884313
--- /dev/null
+++ b/dep/StormLib/stormlib_dll/StormLib.def
@@ -0,0 +1,76 @@
+;
+; Export file for Windows
+; Copyright (c) 2007-2010 Ladislav Zezula
+; ladik@zezula.net
+;
+
+LIBRARY StormLib.dll
+
+EXPORTS
+
+ SFileSetLocale
+ SFileGetLocale
+
+ SFileOpenArchive
+ SFileCreateArchive
+ SFileGetArchiveBitmap
+ SFileFlushArchive
+ SFileCloseArchive
+
+ SFileAddListFile
+
+ SFileSetCompactCallback
+ SFileCompactArchive
+
+ SFileGetMaxFileCount
+ SFileSetMaxFileCount
+
+ SFileGetAttributes
+ SFileSetAttributes
+ SFileUpdateFileAttributes
+
+ SFileOpenPatchArchive
+ SFileIsPatchedArchive
+
+ SFileOpenFileEx
+ SFileGetFileSize
+ SFileSetFilePointer
+ SFileReadFile
+ SFileCloseFile
+
+ SFileHasFile
+ SFileGetFileName
+ SFileGetFileInfo
+
+ SFileExtractFile
+
+ SFileVerifyFile
+ SFileVerifyRawData
+ SFileVerifyArchive
+
+ SFileFindFirstFile
+ SFileFindNextFile
+ SFileFindClose
+
+ SListFileFindFirstFile
+ SListFileFindNextFile
+ SListFileFindClose
+
+ SFileEnumLocales
+
+ SFileCreateFile
+ SFileWriteFile
+ SFileFinishFile
+ SFileAddFileEx
+ SFileAddFile
+ SFileAddWave
+ SFileRemoveFile
+ SFileRenameFile
+ SFileSetFileLocale
+ SFileSetDataCompression
+ SFileSetAddFileCallback
+
+ SCompImplode
+ SCompExplode
+ SCompCompress
+ SCompDecompress
diff --git a/dep/StormLib/stormlib_dll/StormLib.exp b/dep/StormLib/stormlib_dll/StormLib.exp
new file mode 100644
index 00000000000..aa18edb7aab
--- /dev/null
+++ b/dep/StormLib/stormlib_dll/StormLib.exp
@@ -0,0 +1,75 @@
+#
+# Export file for Mac OS X
+# Copyright (c) 2009 Sam Wilkins
+# swilkins1337@gmail.com
+#
+
+_SFileSetLocale
+_SFileGetLocale
+
+_SFileOpenArchive
+_SFileCreateArchive
+_SFileGetArchiveBitmap
+_SFileFlushArchive
+_SFileCloseArchive
+
+_SFileAddListFile
+
+_SFileSetCompactCallback
+_SFileCompactArchive
+
+_SFileGetMaxFileCount
+_SFileSetMaxFileCount
+
+_SFileGetAttributes
+_SFileSetAttributes
+_SFileUpdateFileAttributes
+
+_SFileOpenPatchArchive
+_SFileIsPatchedArchive
+
+_SFileOpenFileEx
+_SFileGetFileSize
+_SFileSetFilePointer
+_SFileReadFile
+_SFileCloseFile
+
+_SFileHasFile
+_SFileGetFileName
+_SFileGetFileInfo
+
+_SFileExtractFile
+
+_SFileVerifyFile
+_SFileVerifyRawData
+_SFileVerifyArchive
+
+_SFileFindFirstFile
+_SFileFindNextFile
+_SFileFindClose
+
+_SListFileFindFirstFile
+_SListFileFindNextFile
+_SListFileFindClose
+
+_SFileEnumLocales
+
+_SFileCreateFile
+_SFileWriteFile
+_SFileFinishFile
+_SFileAddFileEx
+_SFileAddFile
+_SFileAddWave
+_SFileRemoveFile
+_SFileRenameFile
+_SFileSetFileLocale
+_SFileSetDataCompression
+_SFileSetAddFileCallback
+
+_SCompImplode
+_SCompExplode
+_SCompCompress
+_SCompDecompress
+
+_SetLastError
+_GetLastError
diff --git a/dep/StormLib/test/Test.cpp b/dep/StormLib/test/Test.cpp
new file mode 100644
index 00000000000..e31c15fee29
--- /dev/null
+++ b/dep/StormLib/test/Test.cpp
@@ -0,0 +1,1892 @@
+/*****************************************************************************/
+/* StormLibTest.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Test module for StormLib */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 25.03.03 1.00 Lad The first version of StormLibTest.cpp */
+/*****************************************************************************/
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define __INCLUDE_CRYPTOGRAPHY__
+#define __STORMLIB_SELF__ // Don't use StormLib.lib
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
+#include "../src/StormLib.h"
+#include "../src/StormCommon.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4505) // 'XXX' : unreferenced local function has been removed
+#endif
+
+//------------------------------------------------------------------------------
+// Defines
+
+#ifdef PLATFORM_WINDOWS
+#define WORK_PATH_ROOT "E:\\Multimedia\\MPQs\\"
+#endif
+
+#ifdef PLATFORM_LINUX
+#define WORK_PATH_ROOT "/home/user/MPQs/"
+#endif
+
+#ifdef PLATFORM_MAC
+#define WORK_PATH_ROOT "/Users/sam/StormLib/test"
+#endif
+
+#ifndef LANG_CZECH
+#define LANG_CZECH 0x0405
+#endif
+
+#define MPQ_SECTOR_SIZE 0x1000
+
+#define MAKE_PATH(path) _T(WORK_PATH_ROOT) _T(path)
+
+// Unicode MPQ names
+/* Czech */ static const wchar_t szUnicodeName1[] = {0x010C, 0x0065, 0x0073, 0x006B, 0x00FD, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+/* Russian */ static const wchar_t szUnicodeName2[] = {0x0420, 0x0443, 0x0441, 0x0441, 0x043A, 0x0438, 0x0439, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+/* Greece */ static const wchar_t szUnicodeName3[] = {0x03B5, 0x03BB, 0x03BB, 0x03B7, 0x03BD, 0x03B9, 0x03BA, 0x03AC, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+/* Chinese */ static const wchar_t szUnicodeName4[] = {0x65E5, 0x672C, 0x8A9E, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+/* Japanese */ static const wchar_t szUnicodeName5[] = {0x7B80, 0x4F53, 0x4E2D, 0x6587, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+/* Arabic */ static const wchar_t szUnicodeName6[] = {0x0627, 0x0644, 0x0639, 0x0639, 0x0631, 0x0628, 0x064A, 0x0629, _T('.'), _T('m'), _T('p'), _T('q'), 0};
+
+//-----------------------------------------------------------------------------
+// Constants
+
+static const TCHAR * szWorkDir = MAKE_PATH("Work");
+
+static unsigned int AddFlags[] =
+{
+// Compression Encryption Fixed key Single Unit Sector CRC
+ 0 | 0 | 0 | 0 | 0,
+ 0 | MPQ_FILE_ENCRYPTED | 0 | 0 | 0,
+ 0 | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | 0 | 0,
+ 0 | 0 | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ 0 | MPQ_FILE_ENCRYPTED | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ 0 | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_IMPLODE | 0 | 0 | 0 | 0,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | 0 | 0 | 0,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | 0 | 0,
+ MPQ_FILE_IMPLODE | 0 | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_IMPLODE | 0 | 0 | 0 | MPQ_FILE_SECTOR_CRC,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | 0 | 0 | MPQ_FILE_SECTOR_CRC,
+ MPQ_FILE_IMPLODE | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | 0 | MPQ_FILE_SECTOR_CRC,
+ MPQ_FILE_COMPRESS | 0 | 0 | 0 | 0,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | 0 | 0 | 0,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | 0 | 0,
+ MPQ_FILE_COMPRESS | 0 | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | 0 | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | MPQ_FILE_SINGLE_UNIT | 0,
+ MPQ_FILE_COMPRESS | 0 | 0 | 0 | MPQ_FILE_SECTOR_CRC,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | 0 | 0 | MPQ_FILE_SECTOR_CRC,
+ MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY | 0 | MPQ_FILE_SECTOR_CRC,
+ 0xFFFFFFFF
+};
+
+//-----------------------------------------------------------------------------
+// Local testing functions
+
+static void clreol()
+{
+#ifdef PLATFORM_WINDOWS
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ LPTSTR szConsoleLine;
+ int nConsoleChars;
+ int i = 0;
+
+ GetConsoleScreenBufferInfo(hConsole, &ScreenInfo);
+ nConsoleChars = (ScreenInfo.srWindow.Right - ScreenInfo.srWindow.Left);
+ if(nConsoleChars > 0)
+ {
+ szConsoleLine = new TCHAR[nConsoleChars + 3];
+ if(szConsoleLine != NULL)
+ {
+ szConsoleLine[i++] = '\r';
+ for(; i < nConsoleChars; i++)
+ szConsoleLine[i] = ' ';
+ szConsoleLine[i++] = '\r';
+ szConsoleLine[i] = 0;
+
+ _tprintf(szConsoleLine);
+ delete [] szConsoleLine;
+ }
+ }
+#endif // PLATFORM_WINDOWS
+}
+
+static void PrintfTA(const TCHAR * szFormat, const TCHAR * szStrT, const char * szStrA, int lcLocale = 0)
+{
+ TCHAR * szTemp;
+ TCHAR szBuffer[MAX_PATH];
+
+ // Convert ANSI string to TCHAR
+ for(szTemp = szBuffer; *szStrA != 0; szTemp++, szStrA++)
+ szTemp[0] = szStrA[0];
+ szTemp[0] = 0;
+
+ _tprintf(szFormat, szStrT, szBuffer, lcLocale);
+}
+
+static void MergeLocalPath(TCHAR * szBuffer, const TCHAR * szPart1, const char * szPart2)
+{
+ // Copy directory name
+ while(*szPart1 != 0)
+ *szBuffer++ = *szPart1++;
+
+ // Add separator
+ *szBuffer++ = _T('/');
+
+ // Copy file name
+ while(*szPart2 != 0)
+ *szBuffer++ = *szPart2++;
+
+ // Terminate the string
+ *szBuffer = 0;
+}
+
+int GetFirstDiffer(void * ptr1, void * ptr2, int nSize)
+{
+ char * buff1 = (char *)ptr1;
+ char * buff2 = (char *)ptr2;
+ int nDiffer;
+
+ for(nDiffer = 0; nDiffer < nSize; nDiffer++)
+ {
+ if(*buff1++ != *buff2++)
+ return nDiffer;
+ }
+ return -1;
+}
+
+static void WINAPI CompactCB(void * /* lpParam */, DWORD dwWork, ULONGLONG BytesDone, ULONGLONG TotalBytes)
+{
+ clreol();
+
+ _tprintf(_T("%u of %u "), (DWORD)BytesDone, (DWORD)TotalBytes);
+ switch(dwWork)
+ {
+ case CCB_CHECKING_FILES:
+ _tprintf(_T("Checking files in archive ...\r"));
+ break;
+
+ case CCB_CHECKING_HASH_TABLE:
+ _tprintf(_T("Checking hash table ...\r"));
+ break;
+
+ case CCB_COPYING_NON_MPQ_DATA:
+ _tprintf(_T("Copying non-MPQ data ...\r"));
+ break;
+
+ case CCB_COMPACTING_FILES:
+ _tprintf(_T("Compacting archive ...\r"));
+ break;
+
+ case CCB_CLOSING_ARCHIVE:
+ _tprintf(_T("Closing archive ...\r"));
+ break;
+ }
+}
+
+static void GenerateRandomDataBlock(LPBYTE pbBuffer, DWORD cbBuffer)
+{
+ LPBYTE pbBufferEnd = pbBuffer + cbBuffer;
+ LPBYTE pbPtr = pbBuffer;
+ DWORD cbBytesToPut = 0;
+ BYTE ByteToPut = 0;
+ bool bRandomData = false;
+
+ while(pbPtr < pbBufferEnd)
+ {
+ // If there are no bytes to put, we will generate new byte and length
+ if(cbBytesToPut == 0)
+ {
+ bRandomData = false;
+ switch(rand() % 10)
+ {
+ case 0: // A short sequence of zeros
+ cbBytesToPut = rand() % 0x08;
+ ByteToPut = 0;
+ break;
+
+ case 1: // A long sequence of zeros
+ cbBytesToPut = rand() % 0x80;
+ ByteToPut = 0;
+ break;
+
+ case 2: // A short sequence of non-zeros
+ cbBytesToPut = rand() % 0x08;
+ ByteToPut = (BYTE)(rand() % 0x100);
+ break;
+
+ case 3: // A long sequence of non-zeros
+ cbBytesToPut = rand() % 0x80;
+ ByteToPut = (BYTE)(rand() % 0x100);
+ break;
+
+ case 4: // A short random data
+ cbBytesToPut = rand() % 0x08;
+ bRandomData = true;
+ break;
+
+ case 5: // A long random data
+ cbBytesToPut = rand() % 0x80;
+ bRandomData = true;
+ break;
+
+ default: // A single random byte
+ cbBytesToPut = 1;
+ ByteToPut = (BYTE)(rand() % 0x100);
+ break;
+ }
+ }
+
+ // Generate random byte, if needed
+ if(bRandomData)
+ ByteToPut = (BYTE)(rand() % 0x100);
+
+ // Put next byte to the output buffer
+ *pbPtr++ = ByteToPut;
+ cbBytesToPut--;
+ }
+}
+
+static bool CompareArchivedFiles(const char * szFileName, HANDLE hFile1, HANDLE hFile2, DWORD dwBlockSize)
+{
+ LPBYTE pbBuffer1 = NULL;
+ LPBYTE pbBuffer2 = NULL;
+ DWORD dwRead1; // Number of bytes read (Storm.dll)
+ DWORD dwRead2; // Number of bytes read (StormLib)
+ bool bResult1 = false; // Result from Storm.dll
+ bool bResult2 = false; // Result from StormLib
+ bool bResult = true;
+ int nDiff;
+
+ szFileName = szFileName;
+
+ // Allocate buffers
+ pbBuffer1 = new BYTE[dwBlockSize];
+ pbBuffer2 = new BYTE[dwBlockSize];
+
+ for(;;)
+ {
+ // Read the file's content by both methods and compare the result
+ memset(pbBuffer1, 0, dwBlockSize);
+ memset(pbBuffer2, 0, dwBlockSize);
+ bResult1 = SFileReadFile(hFile1, pbBuffer1, dwBlockSize, &dwRead1, NULL);
+ bResult2 = SFileReadFile(hFile2, pbBuffer2, dwBlockSize, &dwRead2, NULL);
+ if(bResult1 != bResult2)
+ {
+ _tprintf(_T("Different results from SFileReadFile, Mpq1 %u, Mpq2 %u\n"), bResult1, bResult2);
+ bResult = false;
+ break;
+ }
+
+ // Test the number of bytes read
+ if(dwRead1 != dwRead2)
+ {
+ _tprintf(_T("Different bytes read from SFileReadFile, Mpq1 %u, Mpq2 %u\n"), dwRead1, dwRead2);
+ bResult = false;
+ break;
+ }
+
+ // No more bytes ==> OK
+ if(dwRead1 == 0)
+ break;
+
+ // Test the content
+ if((nDiff = GetFirstDiffer(pbBuffer1, pbBuffer2, dwRead1)) != -1)
+ {
+ bResult = false;
+ break;
+ }
+ }
+
+ delete [] pbBuffer2;
+ delete [] pbBuffer1;
+ return bResult;
+}
+
+// Random read version
+static bool CompareArchivedFilesRR(const char * /* szFileName */, HANDLE hFile1, HANDLE hFile2, DWORD dwBlockSize)
+{
+ const char * szPositions[3] = {"FILE_BEGIN ", "FILE_CURRENT", "FILE_END "};
+ LPBYTE pbBuffer1 = NULL;
+ LPBYTE pbBuffer2 = NULL;
+ DWORD dwFileSize1; // File size (Storm.dll)
+ DWORD dwFileSize2; // File size (StormLib)
+ DWORD dwRead1; // Number of bytes read (Storm.dll)
+ DWORD dwRead2; // Number of bytes read (StormLib)
+ bool bResult1 = false; // Result from Storm.dll
+ bool bResult2 = false; // Result from StormLib
+ int nError = ERROR_SUCCESS;
+
+ // Test the file size
+ dwFileSize1 = SFileGetFileSize(hFile1, NULL);
+ dwFileSize2 = SFileGetFileSize(hFile2, NULL);
+ if(dwFileSize1 != dwFileSize2)
+ {
+ _tprintf(_T("Different size from SFileGetFileSize (file1: %u, file2: %u)\n"), dwFileSize1, dwFileSize2);
+ return false;
+ }
+
+ if(dwFileSize1 != 0)
+ {
+ for(int i = 0; i < 10000; i++)
+ {
+ DWORD dwRandom = rand() * rand();
+ DWORD dwMoveMethod = dwRandom % 3;
+ DWORD dwPosition = dwRandom % dwFileSize1;
+ DWORD dwToRead = dwRandom % dwBlockSize;
+
+ // Also test negative seek
+ if(rand() & 1)
+ {
+ int nPosition = (int)dwPosition;
+ dwPosition = (DWORD)(-nPosition);
+ }
+
+ // Allocate buffers
+ pbBuffer1 = new BYTE[dwToRead];
+ pbBuffer2 = new BYTE[dwToRead];
+
+ // Set the file pointer
+ _tprintf(_T("RndRead (%u): pos %8i from %s, size %u ...\r"), i, dwPosition, szPositions[dwMoveMethod], dwToRead);
+ dwRead1 = SFileSetFilePointer(hFile1, dwPosition, NULL, dwMoveMethod);
+ dwRead2 = SFileSetFilePointer(hFile2, dwPosition, NULL, dwMoveMethod);
+ if(dwRead1 != dwRead2)
+ {
+ _tprintf(_T("Difference returned by SFileSetFilePointer (file1: %u, file2: %u)\n"), dwRead1, dwRead2);
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+
+ // Read the file's content by both methods and compare the result
+ bResult1 = SFileReadFile(hFile1, pbBuffer1, dwToRead, &dwRead1, NULL);
+ bResult2 = SFileReadFile(hFile2, pbBuffer2, dwToRead, &dwRead2, NULL);
+ if(bResult1 != bResult2)
+ {
+ _tprintf(_T("Different results from SFileReadFile (file1: %u, file2: %u)\n\n"), bResult1, bResult2);
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+
+ // Test the number of bytes read
+ if(dwRead1 != dwRead2)
+ {
+ _tprintf(_T("Different bytes read from SFileReadFile (file1: %u, file2: %u)\n\n"), dwRead1, dwRead2);
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+
+ // Test the content
+ if(dwRead1 != 0 && memcmp(pbBuffer1, pbBuffer2, dwRead1))
+ {
+ _tprintf(_T("Different data content from SFileReadFile\n"));
+ nError = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
+
+ delete [] pbBuffer2;
+ delete [] pbBuffer1;
+ }
+ }
+ clreol();
+ return (nError == ERROR_SUCCESS) ? true : false;
+}
+
+//-----------------------------------------------------------------------------
+// Opening local file
+
+static int TestOpenLocalFile(const char * szFileName)
+{
+ HANDLE hFile;
+ char szRetrievedName[MAX_PATH];
+
+ if(SFileOpenFileEx(NULL, szFileName, SFILE_OPEN_LOCAL_FILE, &hFile))
+ {
+ SFileGetFileName(hFile, szRetrievedName);
+ SFileCloseFile(hFile);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// Partial file reading
+
+static int TestPartFileRead(const TCHAR * szFileName)
+{
+ ULONGLONG ByteOffset;
+ ULONGLONG FileSize = 0;
+ TFileStream * pStream;
+ BYTE BigBuffer[0x7000];
+ BYTE Buffer[0x100];
+ int nError = ERROR_SUCCESS;
+
+ // Open the partial file
+ pStream = FileStream_OpenFile(szFileName, false);
+ if(pStream == NULL)
+ nError = GetLastError();
+
+ // Get the size of the stream
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!FileStream_GetSize(pStream, FileSize))
+ nError = GetLastError();
+ }
+
+ // Read the last 0x7000 bytes
+ if(nError == ERROR_SUCCESS)
+ {
+ ByteOffset = FileSize - sizeof(BigBuffer);
+ if(!FileStream_Read(pStream, &ByteOffset, BigBuffer, sizeof(BigBuffer)))
+ nError = GetLastError();
+ }
+
+ // Read the last 0x100 bytes
+ if(nError == ERROR_SUCCESS)
+ {
+ ByteOffset = FileSize - sizeof(Buffer);
+ if(!FileStream_Read(pStream, &ByteOffset, Buffer, sizeof(Buffer)))
+ nError = GetLastError();
+ }
+
+ // Read 0x100 bytes from position (FileSize - 0xFF)
+ if(nError == ERROR_SUCCESS)
+ {
+ ByteOffset = FileSize - sizeof(Buffer) + 1;
+ if(!FileStream_Read(pStream, &ByteOffset, Buffer, sizeof(Buffer)))
+ nError = GetLastError();
+ }
+
+ FileStream_Close(pStream);
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Compare PKLIB decompression
+
+BYTE pbCompressed1[] = {0x00, 0x04, 0x00, 0x00, 0x04, 0xF0, 0x1F, 0x7B, 0x01, 0xFF};
+BYTE pbCompressed2[] = {0x00, 0x04, 0x00, 0x00, 0x04, 0xF0, 0x1F, 0x00, 0x00, 0x04, 0xFC, 0x03};
+
+static int ComparePklibCompressions()
+{
+ char Decompressed[0x1000];
+ char Compressed[0x1000];
+ int cbDecompressed = 0x208;
+ int cbCompressed = sizeof(Compressed);
+
+ memset(Decompressed, 0, cbDecompressed);
+ SCompImplode(Compressed, &cbCompressed, Decompressed, cbDecompressed);
+
+ cbDecompressed = sizeof(Decompressed);
+ SCompExplode(Decompressed, &cbDecompressed, Compressed, cbCompressed);
+
+
+ return ERROR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// Compare LZMA decompression
+
+#ifdef PLATFORM_WINDOWS
+typedef void * (*ALLOC_MEMORY)(size_t);
+typedef void (*FREE_MEMORY)(void *);
+typedef int (GIVE_DATA)(void *);
+
+extern "C" int starcraft_decompress_lzma(char * pbInBuffer, int cbInBuffer, char * pbOutBuffer, int cbOutBuffer, int * pcbOutBuffer, ALLOC_MEMORY pfnAllocMemory, FREE_MEMORY pfnFreeMemory);
+extern "C" int starcraft_compress_lzma(char * pbInBuffer, int cbInBuffer, int dummy1, char * pbOutBuffer, int cbOutBuffer, int dummy2, int * pcbOutBuffer, ALLOC_MEMORY pfnAllocMemory, FREE_MEMORY pfnFreeMemory, GIVE_DATA pfnGiveData);
+void Compress_LZMA(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer, int *, int);
+int Decompress_LZMA(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
+
+extern "C" void * operator_new(size_t sz)
+{
+ return malloc(sz);
+}
+
+void * Memory_Allocate(size_t byte_size)
+{
+ return malloc(byte_size);
+}
+
+void Memory_Free(void * address)
+{
+ if(address != NULL)
+ free(address);
+}
+
+int GiveData(void *)
+{
+ return 0;
+}
+
+static int StarcraftCompress_LZMA(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ return starcraft_compress_lzma(pbInBuffer,
+ cbInBuffer,
+ 0,
+ pbOutBuffer,
+ *pcbOutBuffer,
+ 0,
+ pcbOutBuffer,
+ Memory_Allocate,
+ Memory_Free,
+ GiveData);
+}
+
+static int StarcraftDecompress_LZMA(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer)
+{
+ return starcraft_decompress_lzma(pbInBuffer,
+ cbInBuffer,
+ pbOutBuffer,
+ *pcbOutBuffer,
+ pcbOutBuffer,
+ Memory_Allocate,
+ Memory_Free);
+}
+
+static int CompareLzmaCompressions(int nSectorSize)
+{
+ LPBYTE pbCompressed1 = NULL; // Compressed by our code
+ LPBYTE pbCompressed2 = NULL; // Compressed by Blizzard's code
+ LPBYTE pbDecompressed1 = NULL; // Decompressed by our code
+ LPBYTE pbDecompressed2 = NULL; // Decompressed by Blizzard's code
+ LPBYTE pbOriginalData = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate buffers
+ // Must allocate twice blocks due to probable bug in Storm.dll.
+ // Storm.dll corrupts stack when uncompresses data with PKWARE DCL
+ // and no compression occurs.
+ pbDecompressed1 = new BYTE [nSectorSize];
+ pbDecompressed2 = new BYTE [nSectorSize];
+ pbCompressed1 = new BYTE [nSectorSize];
+ pbCompressed2 = new BYTE [nSectorSize];
+ pbOriginalData = new BYTE[nSectorSize];
+ if(!pbDecompressed1 || !pbDecompressed2 || !pbCompressed1 || !pbCompressed2 || !pbOriginalData)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ if(nError == ERROR_SUCCESS)
+ {
+ for(int i = 0; i < 100000; i++)
+ {
+ int nDcmpLength1;
+ int nDcmpLength2;
+ int nCmpLength1;
+ int nCmpLength2;
+ int nDiff;
+
+ clreol();
+ _tprintf(_T("Testing compression of sector %u\r"), i + 1);
+
+ // Generate random data sector
+ GenerateRandomDataBlock(pbOriginalData, nSectorSize);
+
+ // Compress the sector by both methods
+ nCmpLength1 = nCmpLength2 = nSectorSize;
+// Compress_LZMA((char *)pbCompressed1, &nCmpLength1, (char *)pbOriginalData, nSectorSize, 0, 0);
+ StarcraftCompress_LZMA((char *)pbCompressed1, &nCmpLength2, (char *)pbOriginalData, nSectorSize);
+
+__TryToDecompress:
+
+ // Only test decompression when the compression actually succeeded
+ if(nCmpLength1 < nSectorSize)
+ {
+ // Decompress both data
+ nDcmpLength2 = nDcmpLength1 = nSectorSize;
+// Decompress_LZMA((char *)pbDecompressed1, &nDcmpLength1, (char *)pbCompressed1, nCmpLength1);
+ StarcraftDecompress_LZMA((char *)pbDecompressed2, &nDcmpLength2, (char *)pbCompressed1, nCmpLength1);
+
+ // Compare the length of the output data
+ if(nDcmpLength1 != nDcmpLength2)
+ {
+ _tprintf(_T("Difference in compressed blocks lengths (%u vs %u)\n"), nDcmpLength1, nDcmpLength2);
+ goto __TryToDecompress;
+ }
+
+ // Compare the output
+ if((nDiff = GetFirstDiffer(pbDecompressed1, pbDecompressed2, nDcmpLength1)) != -1)
+ {
+ _tprintf(_T("Difference in decompressed blocks (offset 0x%08X)\n"), nDiff);
+ goto __TryToDecompress;
+ }
+
+ // Check for data overflow
+ if(pbDecompressed1[nSectorSize] != 0xFD || pbDecompressed1[nSectorSize] != 0xFD)
+ {
+ _tprintf(_T("Damage after decompressed sector !!!\n"));
+ goto __TryToDecompress;
+ }
+
+ // Compare the decompressed data against original data
+ if((nDiff = GetFirstDiffer(pbDecompressed1, pbOriginalData, nDcmpLength1)) != -1)
+ {
+ _tprintf(_T("Difference between original data and decompressed data (offset 0x%08X)\n"), nDiff);
+ goto __TryToDecompress;
+ }
+ }
+ }
+ }
+
+ // Cleanup
+ if(pbOriginalData != NULL)
+ delete [] pbOriginalData;
+ if(pbCompressed2 != NULL)
+ delete [] pbCompressed2;
+ if(pbCompressed1 != NULL)
+ delete [] pbCompressed1;
+ if(pbDecompressed2 != NULL)
+ delete [] pbDecompressed2;
+ if(pbDecompressed1 != NULL)
+ delete [] pbDecompressed1;
+ clreol();
+ return nError;
+}
+#endif // PLATFORM_WINDOWS
+
+//-----------------------------------------------------------------------------
+// Compression method test
+
+static int TestSectorCompress(int nSectorSize)
+{
+ LPBYTE pbDecompressed = NULL;
+ LPBYTE pbCompressed = NULL;
+ LPBYTE pbOriginal = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Allocate buffers
+ pbDecompressed = new BYTE[nSectorSize];
+ pbCompressed = new BYTE[nSectorSize];
+ pbOriginal = new BYTE[nSectorSize];
+ if(!pbDecompressed || !pbCompressed || !pbOriginal)
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+
+ if(nError == ERROR_SUCCESS)
+ {
+ for(int i = 0; i < 100000; i++)
+ {
+ int nOriginalLength = nSectorSize % (rand() + 1);
+ int nCompressedLength;
+ int nDecompressedLength;
+ int nCmp = MPQ_COMPRESSION_SPARSE | MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_BZIP2 | MPQ_COMPRESSION_PKWARE;
+ int nDiff;
+
+ clreol();
+ _tprintf(_T("Testing compression of sector %u\r"), i + 1);
+
+ // Generate random data sector
+ GenerateRandomDataBlock(pbOriginal, nOriginalLength);
+ if(nOriginalLength == 0x123)
+ nOriginalLength = 0;
+
+__TryAgain:
+
+ // Compress the sector
+ nCompressedLength = nOriginalLength;
+ SCompCompress((char *)pbCompressed, &nCompressedLength, (char *)pbOriginal, nOriginalLength, nCmp, 0, -1);
+// SCompImplode((char *)pbCompressed, &nCompressedLength, (char *)pbOriginal, nOriginalLength);
+
+ // When the method was unable to compress data,
+ // the compressed data must be identical to original data
+ if(nCompressedLength == nOriginalLength)
+ {
+ if((nDiff = GetFirstDiffer(pbCompressed, pbOriginal, nOriginalLength)) != -1)
+ {
+ _tprintf(_T("Compression error: Fail when unable to compress the data (Offset 0x%08X).\n"), nDiff);
+ goto __TryAgain;
+ }
+ }
+
+ // Uncompress the sector
+ nDecompressedLength = nOriginalLength;
+ SCompDecompress((char *)pbDecompressed, &nDecompressedLength, (char *)pbCompressed, nCompressedLength);
+// SCompExplode((char *)pbDecompressed, &nDecompressedLength, (char *)pbCompressed, nCompressedLength);
+
+ // Check the decompressed length against original length
+ if(nDecompressedLength != nOriginalLength)
+ {
+ _tprintf(_T("Length of uncompressed data does not agree with original data length !!!\n"));
+ goto __TryAgain;
+ }
+
+ // Check decompressed block against original block
+ if((nDiff = GetFirstDiffer(pbDecompressed, pbOriginal, nOriginalLength)) != -1)
+ {
+ _tprintf(_T("Decompressed sector does not agree with the original data !!! (Offset 0x%08X)\n"), nDiff);
+ goto __TryAgain;
+ }
+ }
+ }
+
+ // Cleanup
+ delete [] pbOriginal;
+ delete [] pbCompressed;
+ delete [] pbDecompressed;
+ clreol();
+ return nError;
+}
+
+static int TestArchiveOpenAndClose(const TCHAR * szMpqName)
+{
+ const char * szFileName1 = "DBFilesClient\\Item.dbc";
+// const char * szFileName2 = "items\\map\\mapz_deleted.cel";
+ TMPQArchive * ha = NULL;
+ HANDLE hFile1 = NULL;
+// HANDLE hFile2 = NULL;
+ HANDLE hMpq = NULL;
+ int nError = ERROR_SUCCESS;
+
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Opening archive %s ...\n"), szMpqName);
+ if(!SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_ENCRYPTED | BASE_PROVIDER_FILE, &hMpq))
+ nError = GetLastError();
+ ha = (TMPQArchive *)hMpq;
+ }
+/*
+ // Test for TBitArray
+ if(nError == ERROR_SUCCESS && ha->pHetTable != NULL)
+ {
+ TBitArray * pBitArray = ha->pHetTable->pBetIndexes;
+
+ for(ULONG i = 0; i < 0x10000; i++)
+ {
+ BYTE LoadedBits[0x20];
+ BYTE SaveBits[0x40];
+ unsigned int nBitPosition = (i >> 0x08);
+ unsigned int nBitCount = (i & 0xFF);
+
+ memset(LoadedBits, 0, sizeof(LoadedBits));
+ memcpy(SaveBits, pBitArray->Elements, sizeof(SaveBits));
+
+ // Load the index to the BET table
+ pBitArray->GetBits(nBitPosition, nBitCount, LoadedBits, sizeof(LoadedBits));
+
+ // Load the index to the BET table
+ pBitArray->SetBits(nBitPosition, nBitCount, LoadedBits, sizeof(LoadedBits));
+
+ // Verify the bits
+ if(memcmp(SaveBits, pBitArray->Elements, sizeof(SaveBits)))
+ assert(false);
+ }
+ }
+*/
+ // Verify the raw data in the archive
+ if(nError == ERROR_SUCCESS)
+ {
+ // Verify the archive
+ SFileVerifyRawData(hMpq, SFILE_VERIFY_FILE, szFileName1);
+
+ // Try to open a file
+ if(!SFileOpenFileEx(hMpq, szFileName1, SFILE_OPEN_FROM_MPQ, &hFile1))
+ {
+ nError = GetLastError();
+ printf("%s - file not found in the MPQ\n", szFileName1);
+ }
+ }
+
+ // Dummy read from the file
+ if(nError == ERROR_SUCCESS)
+ {
+ DWORD dwBytesRead = 0;
+ BYTE Buffer[0x1000];
+
+ SFileSetFileLocale(hFile1, 0x405);
+ SFileReadFile(hFile1, Buffer, sizeof(Buffer), &dwBytesRead);
+ }
+/*
+ // Verify the MPQ listfile
+ if(nError == ERROR_SUCCESS)
+ {
+ SFileVerifyFile(hMpq, szFileName1, 0xFFFFFFFF);
+ if(!CompareArchivedFilesRR(szFileName1, hFile1, hFile2, 0x100000))
+ nError = ERROR_CAN_NOT_COMPLETE;
+ }
+*/
+ if(hFile1 != NULL)
+ SFileCloseFile(hFile1);
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+ return nError;
+}
+
+static int TestFindFiles(const TCHAR * szMpqName)
+{
+ TMPQFile * hf;
+ HANDLE hFile;
+ HANDLE hMpq = NULL;
+ BYTE Buffer[100];
+ int nError = ERROR_SUCCESS;
+ int nFiles = 0;
+ int nFound = 0;
+
+ // Open the archive
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Opening \"%s\" for finding files ...\n"), szMpqName);
+ if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ nError = GetLastError();
+ }
+
+ // Compact the archive
+ if(nError == ERROR_SUCCESS)
+ {
+ SFILE_FIND_DATA sf;
+ HANDLE hFind;
+ DWORD dwExtraDataSize;
+ bool bFound = true;
+
+ hFind = SFileFindFirstFile(hMpq, "*", &sf, "c:\\Tools32\\ListFiles\\ListFile.txt");
+ while(hFind != NULL && bFound != false)
+ {
+ if(SFileOpenFileEx(hMpq, sf.cFileName, 0, &hFile))
+ {
+ hf = (TMPQFile *)hFile;
+ SFileReadFile(hFile, Buffer, sizeof(Buffer));
+ nFiles++;
+
+ if(sf.dwFileFlags & MPQ_FILE_SECTOR_CRC)
+ {
+ dwExtraDataSize = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount];
+ if(dwExtraDataSize != 0)
+ nFound++;
+ }
+
+ SFileCloseFile(hFile);
+ }
+
+ bFound = SFileFindNextFile(hFind, &sf);
+ }
+ }
+
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+ if(nError == ERROR_SUCCESS)
+ _tprintf(_T("Search complete\n"));
+ return nError;
+}
+
+static int TestMpqCompacting(const TCHAR * szMpqName)
+{
+ HANDLE hMpq = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // Open the archive
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Opening \"%s\" for compacting ...\n"), szMpqName);
+ if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ nError = GetLastError();
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ const char * szFileName = "Shaders\\Effects\\shadowmap.wfx";
+
+ printf("Deleting file %s ...\r", szFileName);
+ if(!SFileRemoveFile(hMpq, szFileName))
+ nError = GetLastError();
+ }
+/*
+ // Compact the archive
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Compacting archive ...\r"));
+ SFileSetCompactCallback(hMpq, CompactCB, NULL);
+ if(!SFileCompactArchive(hMpq, "c:\\Tools32\\ListFiles\\ListFile.txt"))
+ nError = GetLastError();
+ }
+*/
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+ if(nError == ERROR_SUCCESS)
+ _tprintf(_T("Compacting complete (No errors)\n"));
+ return nError;
+}
+
+static int TestCreateArchive(const TCHAR * szMpqName)
+{
+ TFileStream * pStream;
+ const TCHAR * szFileName1 = MAKE_PATH("FileTest.exe");
+ const TCHAR * szFileName2 = MAKE_PATH("ZeroSize.txt");
+ HANDLE hMpq = NULL; // Handle of created archive
+ DWORD dwVerifyResult;
+ DWORD dwFileCount = 0;
+ LCID LocaleIDs[] = {0x000, 0x405, 0x406, 0x407, 0xFFFF};
+ char szMpqFileName[MAX_PATH];
+ int nError = ERROR_SUCCESS;
+ int i;
+
+ // Create the new file
+ _tprintf(_T("Creating %s ...\n"), szMpqName);
+ pStream = FileStream_CreateFile(szMpqName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream == NULL)
+ nError = GetLastError();
+
+ // Write some data
+ if(nError == ERROR_SUCCESS)
+ {
+ ULONGLONG FileSize = 0x100000;
+
+ FileStream_SetSize(pStream, FileSize);
+ FileStream_Close(pStream);
+ }
+
+ // Well, now create the MPQ archive
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileCreateArchive(szMpqName,
+ MPQ_CREATE_ARCHIVE_V4 | MPQ_CREATE_ATTRIBUTES,
+ 17,
+ &hMpq))
+ {
+ nError = GetLastError();
+ }
+ }
+
+ // Add the same file multiple times
+ if(nError == ERROR_SUCCESS)
+ {
+ // Add FileTest.exe
+ for(i = 0; AddFlags[i] != 0xFFFFFFFF; i++)
+ {
+ sprintf(szMpqFileName, "FileTest_%02u.exe", i);
+ PrintfTA(_T("Adding %s as %s ...\n"), szFileName1, szMpqFileName);
+ if(SFileAddFileEx(hMpq, szFileName1, szMpqFileName, AddFlags[i], MPQ_COMPRESSION_ZLIB))
+ {
+ dwVerifyResult = SFileVerifyFile(hMpq, szMpqFileName, MPQ_ATTRIBUTE_CRC32 | MPQ_ATTRIBUTE_MD5);
+ if(dwVerifyResult & (VERIFY_OPEN_ERROR | VERIFY_READ_ERROR | VERIFY_FILE_SECTOR_CRC_ERROR | VERIFY_FILE_CHECKSUM_ERROR | VERIFY_FILE_MD5_ERROR))
+ printf("CRC error on \"%s\"\n", szMpqFileName);
+ dwFileCount++;
+ }
+ else
+ {
+ printf("Failed to add the file \"%s\".\n", szMpqFileName);
+ }
+ }
+
+
+ // Delete a file in the middle of the file table
+ SFileRemoveFile(hMpq, "FileTest_10.exe");
+ SFileAddFileEx(hMpq, szFileName1, "FileTest_xx.exe", MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED, MPQ_COMPRESSION_ZLIB);
+
+ // Try to decrement max file count
+ dwFileCount = SFileGetMaxFileCount(hMpq);
+ SFileSetMaxFileCount(hMpq, dwFileCount - 1);
+
+ // Add ZeroSize.txt (1)
+ sprintf(szMpqFileName, "ZeroSize_1.txt");
+ for(i = 0; LocaleIDs[i] != 0xFFFF; i++)
+ {
+ PrintfTA(_T("Adding %s as %s (locale %04x) ...\n"), szFileName2, szMpqFileName, LocaleIDs[i]);
+ SFileSetLocale(LocaleIDs[i]);
+ if(!SFileAddFileEx(hMpq, szFileName2, szMpqFileName, MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED, MPQ_COMPRESSION_ZLIB))
+ printf("Cannot add the file\n");
+ }
+
+ // Add ZeroSize.txt (1)
+ sprintf(szMpqFileName, "ZeroSize_2.txt");
+ for(int i = 0; LocaleIDs[i] != 0xFFFF; i++)
+ {
+ PrintfTA(_T("Adding %s as %s (locale %04x) ...\n"), szFileName2, szMpqFileName, LocaleIDs[i]);
+ SFileSetLocale(LocaleIDs[i]);
+ if(!SFileAddFileEx(hMpq, szFileName2, szMpqFileName, MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED, MPQ_COMPRESSION_ZLIB))
+ printf("Cannot add the file\n");
+ }
+ }
+
+ // Test rename function
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Testing rename files ...\n"));
+ SFileSetLocale(LANG_NEUTRAL);
+ if(!SFileRenameFile(hMpq, "FileTest_08.exe", "FileTest_08a.exe"))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to rename the file\n"));
+ }
+
+ if(!SFileRenameFile(hMpq, "FileTest_08a.exe", "FileTest_08.exe"))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to rename the file\n"));
+ }
+
+ if(!SFileRenameFile(hMpq, "FileTest_10.exe", "FileTest_10a.exe"))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to rename the file\n"));
+ }
+
+ if(!SFileRenameFile(hMpq, "FileTest_10a.exe", "FileTest_10.exe"))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to rename the file\n"));
+ }
+
+ if(nError == ERROR_SUCCESS)
+ _tprintf(_T("Rename test succeeded.\n\n"));
+ else
+ _tprintf(_T("Rename test failed.\n\n"));
+ }
+
+ // Compact the archive
+// if(nError == ERROR_SUCCESS)
+// SFileCompactArchive(hMpq);
+
+ // Test changing hash table size
+ if(nError == ERROR_SUCCESS)
+ SFileSetMaxFileCount(hMpq, 0x95);
+
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+
+ // Try to reopen the archive
+ if(SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ SFileCloseArchive(hMpq);
+
+ _tprintf(_T("\n"));
+ return nError;
+}
+
+static int TestCreateArchive_PaliRoharBug(const TCHAR * szMpqName)
+{
+ const TCHAR * szFileName = MAKE_PATH("FileTest.exe");
+ HANDLE hMpq = NULL; // Handle of created archive
+ DWORD dwMaxFileCount = 0;
+ DWORD dwMpqFlags = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS;
+ char szMpqFileName[MAX_PATH];
+ int nError = ERROR_SUCCESS;
+ int i;
+
+ _tremove(szMpqName);
+ if(SFileCreateArchive(szMpqName,
+ MPQ_CREATE_ARCHIVE_V4 | MPQ_CREATE_ATTRIBUTES,
+ 1,
+ &hMpq))
+ {
+ // Add the file there
+ SFileAddFileEx(hMpq, szFileName, "FileTest_base.exe", dwMpqFlags, MPQ_COMPRESSION_ZLIB);
+ SFileFlushArchive(hMpq);
+ SFileCloseArchive(hMpq);
+
+ // Add the same file 10 times
+ for(i = 0; i < 10; i++)
+ {
+ if(SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ {
+ dwMaxFileCount = SFileGetMaxFileCount(hMpq) + 1;
+ _tprintf(_T("Increasing max file count to %u ...\n"), dwMaxFileCount);
+ SFileSetMaxFileCount(hMpq, dwMaxFileCount);
+
+ sprintf(szMpqFileName, "FileTest_%02u.exe", dwMaxFileCount);
+ PrintfTA(_T("Adding %s as %s\n"), szFileName, szMpqFileName);
+ if(!SFileAddFileEx(hMpq, szFileName, szMpqFileName, dwMpqFlags, MPQ_COMPRESSION_ZLIB))
+ {
+ printf("Failed to add the file \"%s\".\n", szMpqFileName);
+ break;
+ }
+
+ SFileFlushArchive(hMpq);
+ SFileCompactArchive(hMpq);
+ SFileCloseArchive(hMpq);
+ }
+ }
+ }
+
+ _tprintf(_T("\n"));
+ return nError;
+}
+
+
+static int TestAddFilesToMpq(
+ const TCHAR * szMpqName,
+ ...
+ )
+{
+ const TCHAR * szFileName;
+ const TCHAR * szSrc;
+ char * szTrg;
+ HANDLE hMpq;
+ va_list argList;
+ char szMpqFileName[MAX_PATH];
+ int nError = ERROR_SUCCESS;
+
+ if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ return GetLastError();
+
+ va_start(argList, szMpqName);
+ while((szFileName = va_arg(argList, const TCHAR *)) != NULL)
+ {
+ // Convert the plain name to ANSI
+ szSrc = GetPlainFileNameT(szFileName);
+ szTrg = szMpqFileName;
+ while(*szSrc != 0)
+ *szTrg++ = (char)*szSrc++;
+ *szTrg = 0;
+
+ // Add the file to MPQ
+ if(!SFileAddFileEx(hMpq, szFileName,
+ szMpqFileName,
+ MPQ_FILE_COMPRESS,
+ MPQ_COMPRESSION_ZLIB))
+ {
+ nError = GetLastError();
+ printf("Failed to add the file \"%s\"\n", szFileName);
+ }
+ }
+
+ SFileCloseArchive(hMpq);
+ return nError;
+}
+
+static int TestCreateArchiveFromMemory(const TCHAR * szMpqName)
+{
+#define FILE_SIZE 65535
+
+ HANDLE hFile;
+ HANDLE hMPQ;
+ char* data = new char [FILE_SIZE]; // random memory data
+ char szFileName[100];
+ int i;
+
+ // Create an mpq file for testing
+ if(SFileCreateArchive(szMpqName, MPQ_CREATE_ARCHIVE_V2|MPQ_CREATE_ATTRIBUTES, 0x100000, &hMPQ))
+ {
+ for(i = 0; i < 1000; i++)
+ {
+ sprintf(szFileName, "File%03u.bin", i);
+ printf("Adding file %s\r", szFileName);
+
+ if(SFileCreateFile(hMPQ, szFileName, 0, FILE_SIZE, 0, MPQ_FILE_COMPRESS, &hFile))
+ {
+ SFileWriteFile(hFile, data, FILE_SIZE, MPQ_COMPRESSION_ZLIB);
+ SFileFinishFile(hFile);
+ }
+ }
+ }
+ SFileCloseArchive(hMPQ);
+ delete [] data;
+ return ERROR_SUCCESS;
+}
+
+static int TestFileReadAndWrite(
+ const TCHAR * szMpqName,
+ const char * szFileName)
+{
+ LPBYTE pvFile = NULL;
+ HANDLE hFile = NULL;
+ HANDLE hMpq = NULL;
+ DWORD dwBytesRead;
+ DWORD dwFileSize = 0;
+ int nError = ERROR_SUCCESS;
+
+ if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to open the archive %s (%u).\n"), szMpqName, nError);
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
+ {
+ nError = GetLastError();
+ printf("Failed to open the file %s (%u).\n", szFileName, nError);
+ }
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileGetFileInfo(hFile, SFILE_INFO_FILE_SIZE, &dwFileSize, sizeof(DWORD)))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to get the file size (%u).\n"), nError);
+ }
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ pvFile = new BYTE[dwFileSize];
+ if(pvFile == NULL)
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ printf("Failed to allocate buffer for the file (%u).\n", nError);
+ }
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileReadFile(hFile, pvFile, dwFileSize, &dwBytesRead))
+ {
+ nError = GetLastError();
+ printf("Failed to read file (%u).\n", nError);
+ }
+ }
+
+ if(hFile != NULL)
+ {
+ SFileCloseFile(hFile);
+ hFile = NULL;
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileCreateFile(hMpq, szFileName, 0, dwFileSize, 0, MPQ_FILE_REPLACEEXISTING, &hFile))
+ {
+ nError = GetLastError();
+ printf("Failed to create %s in the archive (%u).\n", szFileName, nError);
+ }
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ if(!SFileWriteFile(hFile, pvFile, dwFileSize, 0))
+ {
+ nError = GetLastError();
+ printf("Failed to write the data to the MPQ (%u).\n", nError);
+ }
+ }
+
+ if(hFile != NULL)
+ {
+ if(!SFileFinishFile(hFile))
+ {
+ nError = GetLastError();
+ printf("Failed to finalize file creation (%u).\n", nError);
+ }
+ }
+
+ if(pvFile != NULL)
+ delete [] pvFile;
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+ return nError;
+}
+
+static int TestSignatureVerify(const TCHAR * szMpqName)
+{
+ HANDLE hMpq;
+
+ if(SFileOpenArchive(szMpqName, 0, 0, &hMpq))
+ {
+ _tprintf(_T("Verifying digital signature in %s:\n"), szMpqName);
+ switch(SFileVerifyArchive(hMpq))
+ {
+ case ERROR_NO_SIGNATURE:
+ _tprintf(_T("No digital signature present.\n"));
+ break;
+
+ case ERROR_VERIFY_FAILED:
+ _tprintf(_T("Failed to verify signature.\n"));
+ break;
+
+ case ERROR_WEAK_SIGNATURE_OK:
+ _tprintf(_T("Weak signature is OK.\n"));
+ break;
+
+ case ERROR_WEAK_SIGNATURE_ERROR:
+ _tprintf(_T("Weak signature mismatch.\n"));
+ break;
+
+ case ERROR_STRONG_SIGNATURE_OK:
+ _tprintf(_T("Strong signature is OK.\n"));
+ break;
+
+ case ERROR_STRONG_SIGNATURE_ERROR:
+ _tprintf(_T("Strong signature mismatch.\n"));
+ break;
+ }
+
+ SFileCloseArchive(hMpq);
+ _tprintf(_T("\n"));
+ }
+
+ return 0;
+}
+
+
+static int TestCreateArchiveCopy(const TCHAR * szMpqName, const TCHAR * szMpqCopyName, const char * szListFile)
+{
+ TFileStream * pStream;
+ TCHAR szLocalFile[MAX_PATH];
+ HANDLE hMpq1 = NULL; // Handle of existing archive
+ HANDLE hMpq2 = NULL; // Handle of created archive
+ DWORD dwHashTableSize = 0;
+ int nError = ERROR_SUCCESS;
+
+ // If no listfile or an empty one, use NULL
+ if(szListFile == NULL || *szListFile == 0)
+ szListFile = NULL;
+
+ // Create the new file
+ pStream = FileStream_CreateFile(szMpqCopyName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream == NULL)
+ nError = GetLastError();
+
+ // Write some data
+ if(nError == ERROR_SUCCESS)
+ {
+ ULONGLONG FileSize = 0x100000;
+
+ FileStream_SetSize(pStream, FileSize);
+ FileStream_Close(pStream);
+ }
+
+ // Open the existing MPQ archive
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Opening %s ...\n"), szMpqName);
+ if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq1))
+ nError = GetLastError();
+ }
+
+ // Well, now create the MPQ archive
+ if(nError == ERROR_SUCCESS)
+ {
+ _tprintf(_T("Creating %s ...\n"), szMpqCopyName);
+ SFileGetFileInfo(hMpq1, SFILE_INFO_HASH_TABLE_SIZE, &dwHashTableSize, 4);
+ if(!SFileCreateArchive(szMpqCopyName, 0, dwHashTableSize, &hMpq2))
+ nError = GetLastError();
+ }
+
+ // Copy all files from one archive to another
+ if(nError == ERROR_SUCCESS)
+ {
+ SFILE_FIND_DATA sf;
+ HANDLE hFind = SFileFindFirstFile(hMpq1, "*", &sf, szListFile);
+ bool bResult = true;
+
+ _tprintf(_T("Copying files ...\n"));
+
+ if(hFind != NULL)
+ {
+ while(bResult)
+ {
+ if(strcmp(sf.cFileName, LISTFILE_NAME) && strcmp(sf.cFileName, ATTRIBUTES_NAME))
+ {
+ SFileSetLocale(sf.lcLocale);
+
+ // Create the local file name
+ MergeLocalPath(szLocalFile, szWorkDir, sf.szPlainName);
+ if(SFileExtractFile(hMpq1, sf.cFileName, szLocalFile))
+ {
+ printf("Extracting %s ... OK\n", sf.cFileName);
+ if(!SFileAddFile(hMpq2, szLocalFile, sf.cFileName, sf.dwFileFlags))
+ {
+ nError = GetLastError();
+ printf("Adding %s ... Failed\n\n", sf.cFileName);
+ _tremove(szLocalFile);
+ break;
+ }
+ else
+ {
+ printf("Adding %s ... OK\n", sf.cFileName);
+ }
+ }
+ else
+ {
+ printf("Extracting %s ... Failed\n", sf.cFileName);
+ }
+
+ // Delete the added file
+ _tremove(szLocalFile);
+ }
+
+ // Find the next file
+ bResult = SFileFindNextFile(hFind, &sf);
+ }
+
+ // Close the search handle
+ SFileFindClose(hFind);
+ printf("\n");
+ }
+ }
+
+ // Close both archives
+ if(hMpq2 != NULL)
+ SFileCloseArchive(hMpq2);
+ if(hMpq1 != NULL)
+ SFileCloseArchive(hMpq1);
+ return nError;
+}
+
+static int TestOpenPatchedArchive(const TCHAR * szMpqName, ...)
+{
+ TFileStream * pStream;
+ HANDLE hFile = NULL;
+ HANDLE hMpq = NULL;
+ va_list argList;
+ const char * szFileName = "World\\Minimaps\\Azeroth\\noLiquid_map20_44.blp";
+ TCHAR szLocFileName[MAX_PATH];
+ LPBYTE pbFullFile = NULL;
+ DWORD dwFileSize;
+ int nError = ERROR_SUCCESS;
+
+ // Open the primary MPQ
+ _tprintf(_T("Opening %s ...\n"), szMpqName);
+ if(!SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq))
+ {
+ nError = GetLastError();
+ _tprintf(_T("Failed to open the archive %s ...\n"), szMpqName);
+ }
+
+ // Add all patches
+ if(nError == ERROR_SUCCESS)
+ {
+ va_start(argList, szMpqName);
+ while((szMpqName = va_arg(argList, const TCHAR *)) != NULL)
+ {
+ _tprintf(_T("Adding patch %s ...\n"), szMpqName);
+ if(!SFileOpenPatchArchive(hMpq, szMpqName, NULL, 0))
+ {
+ nError = GetLastError();
+ printf("Failed to add patch %s ...\n", szMpqName);
+ }
+ }
+ va_end(argList);
+ }
+
+ // Now search all files
+ if(nError == ERROR_SUCCESS)
+ {
+ SFILE_FIND_DATA sf;
+ HANDLE hFind;
+ bool bResult = true;
+
+ hFind = SFileFindFirstFile(hMpq, "World\\Minimaps\\Azeroth\\noLiquid_map20_44.*", &sf, NULL);
+ while(hFind && bResult)
+ {
+ printf("%s\n", sf.cFileName);
+ bResult = SFileFindNextFile(hFind, &sf);
+ }
+ }
+
+ // Now try to open patched version of a file
+ if(nError == ERROR_SUCCESS)
+ {
+ SFileExtractFile(hMpq, szFileName, _T("E:\\noLiquid_map20_44.blp"));
+ }
+
+ // Now try to open patched version of "Achievement.dbc"
+ if(nError == ERROR_SUCCESS)
+ {
+ printf("Opening patched file \"%s\" ...\n", szFileName);
+ SFileVerifyFile(hMpq, szFileName, SFILE_VERIFY_RAW_MD5);
+ if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_PATCHED_FILE, &hFile))
+ {
+ nError = GetLastError();
+ printf("Failed to open patched file \"%s\"\n", szFileName);
+ }
+ }
+
+ // Verify of the patched version is correct
+ if(nError == ERROR_SUCCESS)
+ {
+ TCHAR * szPatchChain = NULL;
+ DWORD cbPatchChain = 0;
+
+ // Get the patch chain
+ SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain);
+ szPatchChain = (TCHAR *)(new BYTE[cbPatchChain]);
+ SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain);
+ delete [] szPatchChain;
+
+ // Get the size of the full patched file
+ dwFileSize = SFileGetFileSize(hFile, NULL);
+ if(dwFileSize != 0)
+ {
+ DWORD dwBytesRead = 0;
+ BYTE TempData[0x100];
+
+ SFileReadFile(hFile, TempData, sizeof(TempData), &dwBytesRead);
+ SFileSetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+
+ // Allocate space for the full file
+ pbFullFile = new BYTE[dwFileSize];
+ if(pbFullFile != NULL)
+ {
+ if(!SFileReadFile(hFile, pbFullFile, dwFileSize))
+ {
+ nError = GetLastError();
+ printf("Failed to read full patched file data \"%s\"\n", szFileName);
+ }
+
+ if(nError == ERROR_SUCCESS)
+ {
+ MergeLocalPath(szLocFileName, MAKE_PATH("Work//"), GetPlainFileNameA(szFileName));
+ pStream = FileStream_CreateFile(szLocFileName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE);
+ if(pStream != NULL)
+ {
+ FileStream_Write(pStream, NULL, pbFullFile, dwFileSize);
+ FileStream_Close(pStream);
+ }
+ }
+
+ delete [] pbFullFile;
+ }
+ }
+ }
+
+ // Close handles
+ if(hFile != NULL)
+ SFileCloseFile(hFile);
+ if(hMpq != NULL)
+ SFileCloseArchive(hMpq);
+ return nError;
+}
+
+static int TestCompareTwoArchives(
+ const TCHAR * szMpqName1,
+ const TCHAR * szMpqName2,
+ const char * szListFile,
+ DWORD dwBlockSize)
+{
+ TMPQArchive * ha1 = NULL;
+ TMPQArchive * ha2 = NULL;
+ HANDLE hMpq1 = NULL; // Handle of the first archive
+ HANDLE hMpq2 = NULL; // Handle of the second archive
+ HANDLE hFile1 = NULL;
+ HANDLE hFile2 = NULL;
+ int nError = ERROR_SUCCESS;
+
+ // If no listfile or an empty one, use NULL
+ if(szListFile == NULL || *szListFile == 0)
+ szListFile = NULL;
+
+ _tprintf(_T("=============== Comparing MPQ archives ===============\n"));
+
+ // Open the first MPQ archive
+ if(nError == ERROR_SUCCESS && szMpqName1 != NULL)
+ {
+ _tprintf(_T("Opening %s ...\n"), szMpqName1);
+ if(!SFileOpenArchive(szMpqName1, 0, 0, &hMpq1))
+ nError = GetLastError();
+ ha1 = (TMPQArchive *)hMpq1;
+ }
+
+ // Open the second MPQ archive
+ if(nError == ERROR_SUCCESS && szMpqName2 != NULL)
+ {
+ _tprintf(_T("Opening %s ...\n"), szMpqName2);
+ if(!SFileOpenArchive(szMpqName2, 0, 0, &hMpq2))
+ nError = GetLastError();
+ ha2 = (TMPQArchive *)hMpq2;
+ }
+
+ // Compare the header
+ if(nError == ERROR_SUCCESS && (ha1 != NULL && ha2 != NULL))
+ {
+ if(ha1->pHeader->dwHeaderSize != ha2->pHeader->dwHeaderSize)
+ printf(" - Header size is different\n");
+ if(ha1->pHeader->wFormatVersion != ha2->pHeader->wFormatVersion)
+ printf(" - Format version is different\n");
+ if(ha1->pHeader->wSectorSize != ha2->pHeader->wSectorSize)
+ printf(" - Sector size is different\n");
+ if(ha1->pHeader->HetTableSize64 != ha2->pHeader->HetTableSize64)
+ printf(" - HET table size is different\n");
+ if(ha1->pHeader->BetTableSize64 != ha2->pHeader->BetTableSize64)
+ printf(" - BET table size is different\n");
+ if(ha1->pHeader->dwHashTableSize != ha2->pHeader->dwHashTableSize)
+ printf(" - Hash table size is different\n");
+ if(ha1->pHeader->dwBlockTableSize != ha2->pHeader->dwBlockTableSize)
+ printf(" - Block table size is different\n");
+ }
+
+ // Find all files in the first archive and compare them
+ if(nError == ERROR_SUCCESS)
+ {
+ SFILE_FIND_DATA sf;
+ TMPQFile * hf1;
+ TMPQFile * hf2;
+ HANDLE hFind = SFileFindFirstFile(hMpq1, "*", &sf, szListFile);
+ bool bResult = true;
+
+ while(hFind != NULL && bResult == true)
+ {
+// printf("%s \r", sf.cFileName);
+ SFileSetLocale(sf.lcLocale);
+
+ // Open the first file
+ if(!SFileOpenFileEx(hMpq1, sf.cFileName, 0, &hFile1))
+ printf("Failed to open the file %s in the first archive\n", sf.cFileName);
+
+ if(!SFileOpenFileEx(hMpq2, sf.cFileName, 0, &hFile2))
+ printf("Failed to open the file %s in the second archive\n", sf.cFileName);
+
+ if(hFile1 != NULL && hFile2 != NULL)
+ {
+ // Get the TMPQFile pointers
+ hf1 = (TMPQFile *)hFile1;
+ hf2 = (TMPQFile *)hFile2;
+
+ // Compare the file sizes
+ if(hf1->pFileEntry->dwFileSize != hf2->pFileEntry->dwFileSize)
+ printf("Different file size: %s (%u x %u)\n", sf.cFileName, hf1->pFileEntry->dwFileSize, hf2->pFileEntry->dwFileSize);
+
+ if(hf1->pFileEntry->dwCmpSize != hf2->pFileEntry->dwCmpSize)
+ printf("Different cmpr size: %s (%u x %u)\n", sf.cFileName, hf1->pFileEntry->dwCmpSize, hf2->pFileEntry->dwCmpSize);
+
+ if(hf1->pFileEntry->dwFlags != hf2->pFileEntry->dwFlags)
+ printf("Different mpq flags: %s (%08X x %08X)\n", sf.cFileName, hf1->pFileEntry->dwFlags, hf2->pFileEntry->dwFlags);
+
+ if(!CompareArchivedFiles(sf.cFileName, hFile1, hFile2, dwBlockSize))
+ printf("Different file data: %s\n", sf.cFileName);
+
+// if(!CompareArchivedFilesRR(sf.cFileName, hFile1, hFile2, dwBlockSize))
+// printf("Different file data: %s\n", sf.cFileName);
+ }
+
+ // Close both files
+ if(hFile2 != NULL)
+ SFileCloseFile(hFile2);
+ if(hFile1 != NULL)
+ SFileCloseFile(hFile1);
+ hFile2 = hFile1 = NULL;
+
+ // Find the next file
+ bResult = SFileFindNextFile(hFind, &sf);
+ }
+
+ // Close the find handle
+ if(hFind != NULL)
+ SFileFindClose(hFind);
+ }
+
+ // Close both archives
+ clreol();
+ printf("================ MPQ compare complete ================\n");
+ if(hMpq2 != NULL)
+ SFileCloseArchive(hMpq2);
+ if(hMpq1 != NULL)
+ SFileCloseArchive(hMpq1);
+ return nError;
+}
+
+//-----------------------------------------------------------------------------
+// Searching all known MPQs
+
+#ifdef _WIN32
+static int TestSearchOneArchive(const TCHAR * szMpqName)
+{
+ SFILE_FIND_DATA sf;
+ HANDLE hFind;
+ HANDLE hMpq;
+ const TCHAR * szExtension;
+ bool bFound = true;
+
+ // Get the file extension
+ szExtension = _tcsrchr(szMpqName, _T('.'));
+ if(szExtension == NULL)
+ return ERROR_SUCCESS;
+
+ // Only search defined extensions
+ if(_tcsicmp(szExtension, _T(".mpq")) && _tcsnicmp(szExtension, _T(".SC2"), 4))
+ return ERROR_SUCCESS;
+
+ _tprintf(_T("Searching %s ...\n"), szMpqName);
+
+ // Try to open the MPQ
+ if(SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq))
+ {
+ hFind = SFileFindFirstFile(hMpq, "*", &sf, NULL);
+ if(hFind != NULL)
+ {
+ while(bFound)
+ {
+ if(sf.dwFileFlags & MPQ_FILE_DELETE_MARKER)
+ _tprintf(_T("Delete marker: %s:%hs\n"), szMpqName, sf.cFileName);
+
+ bFound = SFileFindNextFile(hFind, &sf);
+ }
+ }
+
+ SFileCloseArchive(hMpq);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+static int TestSearchAllArchives(const TCHAR * szSearchMask)
+{
+ WIN32_FIND_DATA wf;
+ LPTSTR szFilePart;
+ HANDLE hFind;
+ TCHAR szFullPath[MAX_PATH];
+ BOOL bFound = TRUE;
+
+ // Initiate search
+ _tcscpy(szFullPath, szSearchMask);
+ szFilePart = _tcschr(szFullPath, _T('*'));
+ assert(szFilePart != NULL);
+
+ // Begin search
+ hFind = FindFirstFile(szSearchMask, &wf);
+ if(hFind != INVALID_HANDLE_VALUE)
+ {
+ while(bFound)
+ {
+ // Eliminate "." and ".."
+ if(wf.cFileName[0] != _T('.'))
+ {
+ // Construct the full path
+ _tcscpy(szFilePart, wf.cFileName);
+
+ // If it a directory?
+ if(wf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ _tcscat(szFullPath, _T("\\*"));
+ TestSearchAllArchives(szFullPath);
+ }
+ else
+ {
+ TestSearchOneArchive(szFullPath);
+ }
+ }
+ bFound = FindNextFile(hFind, &wf);
+ }
+ FindClose(hFind);
+ }
+
+ return ERROR_SUCCESS;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Main
+//
+
+int main(void)
+{
+ int nError = ERROR_SUCCESS;
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif // defined(_MSC_VER) && defined(_DEBUG)
+
+// FileStream_OpenEncrypted(_T("e:\\Multimedia\\MPQs\\2010 - Starcraft II\\Installer UI 2 deDE.MPQE"));
+
+ // Mix the random number generator
+// srand(GetTickCount());
+
+ // Test structure sizes
+// if(nError == ERROR_SUCCESS)
+// nError = TestStructureSizes();
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestOpenLocalFile("C:\\autoexec.bat");
+
+ // Test reading partial file
+// if(nError == ERROR_SUCCESS)
+// nError = TestPartFileRead(MAKE_PATH("2009 - PartialMPQs/patch.MPQ.part"));
+
+// if(nError == ERROR_SUCCESS)
+// nError = ComparePklibCompressions();
+
+ // Test LZMA compression method against the code ripped from Starcraft II
+// if(nError == ERROR_SUCCESS)
+// nError = CompareLzmaCompressions(MPQ_SECTOR_SIZE);
+
+ // Test compression methods
+// if(nError == ERROR_SUCCESS)
+// nError = TestSectorCompress(MPQ_SECTOR_SIZE);
+
+ // Test the archive open and close
+// if(nError == ERROR_SUCCESS)
+// nError = TestArchiveOpenAndClose(_T("d:\\Install\\Blizzard\\Diablo III\\Diablo-III-8370-enGB-Installer\\Installer Tome 1.MPQE"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("2011 - WoW BETA/wow-update-13202.MPQ"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("2002 - Warcraft III/ProtectedMap_HashTable_FakeValid.w3x"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("2010 - Starcraft II/Installer Tome 1 enGB.MPQE"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("1997 - Diablo I/DIABDAT_orig.MPQ"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("2004 - World of Warcraft/SoundCache-enUS.MPQ"));
+// nError = TestArchiveOpenAndClose(MAKE_PATH("smpq.mpq "));
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestFindFiles(MAKE_PATH("2002 - Warcraft III/HumanEd.mpq"));
+
+ // Create a big MPQ archive
+// if(nError == ERROR_SUCCESS)
+// nError = TestCreateArchive_PaliRoharBug(MAKE_PATH("Test.mpq"));
+// nError = TestCreateArchive(MAKE_PATH("Test.mpq"));
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName1);
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName2);
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName3);
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName4);
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName5);
+// nError = TestCreateArchive((const TCHAR*)szUnicodeName6);
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestAddFilesToMpq(MAKE_PATH("wow-update-13202.MPQ"),
+// "c:\\Tools32\\Arj32.exe",
+// "c:\\Tools32\\autoruns.chm",
+// "c:\\Tools32\\CPUEater.exe",
+// "c:\\Tools32\\dumpbin.exe",
+// "c:\\Tools32\\editbin.exe",
+// "c:\\Tools32\\fsg.ini",
+// "c:\\Tools32\\hiew8.ini",
+// "c:\\Tools32\\ida.bat",
+// "c:\\Tools32\\mp3.ini",
+// NULL);
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestCreateArchiveFromMemory(MAKE_PATH("Test-leak.mpq"));
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestFileReadAndWrite(MAKE_PATH("2002 - Warcraft III/(10)DustwallowKeys.w3m"), "war3map.j");
+
+ // Verify the archive signature
+// if(nError == ERROR_SUCCESS)
+// nError = TestSignatureVerify(MAKE_PATH("1998 - Starcraft/BW-1152.exe"));
+// nError = TestSignatureVerify(MAKE_PATH("2002 - Warcraft III/(10)DustwallowKeys.w3m"));
+// nError = TestSignatureVerify(MAKE_PATH("2002 - Warcraft III/War3TFT_121b_English.exe"));
+// nError = TestSignatureVerify(MAKE_PATH("2004 - World of Warcraft/WoW-2.3.3.7799-to-2.4.0.8089-enUS-patch.exe"));
+// nError = TestSignatureVerify(MAKE_PATH("2004 - World of Warcraft/standalone.MPQ"));
+
+ // Compact the archive
+// if(nError == ERROR_SUCCESS)
+// nError = TestMpqCompacting(MAKE_PATH("wow-update-base-14333.MPQ"));
+
+ // Create copy of the archive, appending some bytes before the MPQ header
+// if(nError == ERROR_SUCCESS)
+// nError = TestCreateArchiveCopy(MAKE_PATH("PartialMPQs/interface.MPQ.part"), MAKE_PATH("PartialMPQs/interface-copy.MPQ.part"), NULL);
+
+/*
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = TestOpenPatchedArchive(MAKE_PATH("2011 - WoW 4.x/locale-enGB.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13164.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13205.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13287.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13329.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13596.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-13623.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-13914.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-14007.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-14333.MPQ"),
+ MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-14480.MPQ"),
+ NULL);
+ }
+*/
+
+ if(nError == ERROR_SUCCESS)
+ {
+ nError = TestCompareTwoArchives(MAKE_PATH("Sound-copy.mpq"),
+ MAKE_PATH("Sound.mpq"),
+ NULL,
+ 0x1001);
+ }
+
+
+// if(nError == ERROR_SUCCESS)
+// nError = TestSearchAllArchives(MAKE_PATH("*"));
+
+ return nError;
+}
diff --git a/dep/StormLib/test/x86_ripped_code.asm b/dep/StormLib/test/x86_ripped_code.asm
new file mode 100644
index 00000000000..4b4be328a6c
--- /dev/null
+++ b/dep/StormLib/test/x86_ripped_code.asm
@@ -0,0 +1,1231 @@
+.686P
+.MODEL FLAT
+ASSUME FS: NOTHING
+.CODE
+
+extrn _memset:PROC
+extrn _memcpy:PROC
+extrn _memmove:PROC
+
+;------------------------------------------------------------------------------
+; Structures
+;
+
+;------------------------------------------------------------------------------
+; Functions
+;
+
+_aullrem proc near ; CODE XREF: sub_6CC140+3Ap
+ ; sub_6CC1E0+57p ...
+
+DividendLo = dword ptr 8
+DividendHi = dword ptr 0Ch
+DivisorLo = dword ptr 10h
+DivisorHi = dword ptr 14h
+
+ push ebx
+ mov eax, [esp+DivisorHi]
+ or eax, eax
+ jnz short loc_8F8FE1
+ mov ecx, [esp+DivisorLo]
+ mov eax, [esp+DividendHi]
+ xor edx, edx
+ div ecx
+ mov eax, [esp+DividendLo]
+ div ecx
+ mov eax, edx
+ xor edx, edx
+ jmp short loc_8F9031
+; ---------------------------------------------------------------------------
+
+loc_8F8FE1: ; CODE XREF: _aullrem+7j
+ mov ecx, eax
+ mov ebx, [esp+DivisorLo]
+ mov edx, [esp+DividendHi]
+ mov eax, [esp+DividendLo]
+
+loc_8F8FEF: ; CODE XREF: _aullrem+39j
+ shr ecx, 1
+ rcr ebx, 1
+ shr edx, 1
+ rcr eax, 1
+ or ecx, ecx
+ jnz short loc_8F8FEF
+ div ebx
+ mov ecx, eax
+ mul [esp+DivisorHi]
+ xchg eax, ecx
+ mul [esp+DivisorLo]
+ add edx, ecx
+ jb short loc_8F901A
+ cmp edx, [esp+DividendHi]
+ ja short loc_8F901A
+ jb short loc_8F9022
+ cmp eax, [esp+DividendLo]
+ jbe short loc_8F9022
+
+loc_8F901A: ; CODE XREF: _aullrem+4Aj
+ ; _aullrem+50j
+ sub eax, [esp+DivisorLo]
+ sbb edx, [esp+DivisorHi]
+
+loc_8F9022: ; CODE XREF: _aullrem+52j
+ ; _aullrem+58j
+ sub eax, [esp+DividendLo]
+ sbb edx, [esp+DividendHi]
+ neg edx
+ neg eax
+ sbb edx, 0
+
+loc_8F9031: ; CODE XREF: _aullrem+1Fj
+ pop ebx
+ retn 10h
+_aullrem endp
+
+_aullshr proc near ; CODE XREF: sub_40E2B6+1ECp
+ ; sub_40E2B6+240p ...
+ cmp cl, 40h
+ jnb short loc_414BDA
+ cmp cl, 20h
+ jnb short loc_414BD0
+ shrd eax, edx, cl
+ shr edx, cl
+ retn
+; ---------------------------------------------------------------------------
+
+loc_414BD0: ; CODE XREF: _aullshr+8j
+ mov eax, edx
+ xor edx, edx
+ and cl, 1Fh
+ shr eax, cl
+ retn
+; ---------------------------------------------------------------------------
+
+loc_414BDA: ; CODE XREF: _aullshr+3j
+ xor eax, eax
+ xor edx, edx
+ retn
+_aullshr endp
+
+
+; =============== S U B R O U T I N E =======================================
+
+; Attributes: bp-based frame
+
+SFileDecryptMpqHeader proc near ; CODE XREF: sub_6D00E0+AEp
+ ; sub_6D00E0+D3p
+
+EncryptedDataAligned= dword ptr -88h
+var_48 = dword ptr -48h
+DecryptBuffer = dword ptr -44h
+var_40 = dword ptr -40h
+var_3C = dword ptr -3Ch
+var_38 = dword ptr -38h
+var_34 = dword ptr -34h
+var_30 = dword ptr -30h
+var_2C = dword ptr -2Ch
+var_28 = dword ptr -28h
+var_24 = dword ptr -24h
+var_20 = dword ptr -20h
+var_1C = dword ptr -1Ch
+var_18 = dword ptr -18h
+var_14 = dword ptr -14h
+var_10 = dword ptr -10h
+var_0C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_FFFFFFF8 = dword ptr 0
+arg_FFFFFFFC = dword ptr 4
+arg_0 = dword ptr 8
+
+ push ebp
+ mov ebp, esp
+ sub esp, 88h
+ mov eax, [ecx+8]
+ mov edx, [ecx+14h]
+ push ebx
+ mov ebx, [ecx+10h]
+ mov [ebp+var_0C], eax
+ mov eax, [ebp+arg_0]
+ push esi
+ push edi
+ mov edi, [ecx+0Ch]
+ mov [ebp+DecryptBuffer], ecx
+ mov [ebp+var_10], edx
+ test al, 3
+ jz short loc_6C9F03
+ mov ecx, [eax]
+ mov [ebp+EncryptedDataAligned], ecx
+ mov ecx, [eax+4]
+ mov [ebp+EncryptedDataAligned+4], ecx
+ mov ecx, [eax+8]
+ mov [ebp+EncryptedDataAligned+8], ecx
+ mov ecx, [eax+0Ch]
+ mov [ebp+EncryptedDataAligned+0Ch], ecx
+ mov ecx, [eax+10h]
+ mov [ebp+EncryptedDataAligned+10h], ecx
+ mov ecx, [eax+14h]
+ mov [ebp+EncryptedDataAligned+14h], ecx
+ mov ecx, [eax+18h]
+ mov [ebp+EncryptedDataAligned+18h], ecx
+ mov ecx, [eax+1Ch]
+ mov [ebp+EncryptedDataAligned+1Ch], ecx
+ mov ecx, [eax+20h]
+ mov [ebp+EncryptedDataAligned+20h], ecx
+ mov ecx, [eax+24h]
+ mov [ebp+EncryptedDataAligned+24h], ecx
+ mov ecx, [eax+28h]
+ mov [ebp+EncryptedDataAligned+28h], ecx
+ mov ecx, [eax+2Ch]
+ mov [ebp+EncryptedDataAligned+2Ch], ecx
+ mov ecx, [eax+30h]
+ mov [ebp+EncryptedDataAligned+30h], ecx
+ mov ecx, [eax+34h]
+ mov [ebp+EncryptedDataAligned+34h], ecx
+ mov ecx, [eax+38h]
+ mov eax, [eax+3Ch]
+ mov [ebp+EncryptedDataAligned+3Ch], eax
+ mov [ebp+EncryptedDataAligned+38h], ecx
+ lea eax, [ebp+EncryptedDataAligned]
+
+loc_6C9F03: ; CODE XREF: SFileDecryptMpqHeader+26j
+ mov ecx, [eax]
+ mov [ebp+var_30], ecx
+ mov esi, edi
+ not esi
+ and esi, edx
+ mov edx, ebx
+ and edx, edi
+ or esi, edx
+ add esi, ecx
+ mov ecx, [ebp+var_0C]
+ lea edx, [esi+ecx-28955B88h]
+ mov ecx, [eax+4]
+ rol edx, 7
+ add edx, edi
+ mov [ebp+var_2C], ecx
+ mov ecx, edx
+ not ecx
+ and ecx, ebx
+ mov esi, edi
+ and esi, edx
+ or ecx, esi
+ add ecx, [ebp+var_2C]
+ mov esi, [ebp+var_10]
+ lea esi, [ecx+esi-173848AAh]
+ mov ecx, [eax+8]
+ mov [ebp+var_40], ecx
+ rol esi, 0Ch
+ add esi, edx
+ mov ecx, esi
+ not ecx
+ and ecx, edi
+ mov edi, esi
+ and edi, edx
+ or ecx, edi
+ add ecx, [ebp+var_40]
+ lea edi, [ecx+ebx+242070DBh]
+ mov ecx, [eax+0Ch]
+ ror edi, 0Fh
+ add edi, esi
+ mov [ebp+var_1C], ecx
+ mov ebx, edi
+ not ebx
+ and ebx, edx
+ mov ecx, esi
+ and ecx, edi
+ or ebx, ecx
+ add ebx, [ebp+var_1C]
+ mov ecx, [ebp+DecryptBuffer]
+ mov ecx, [ecx+0Ch]
+ lea ecx, [ebx+ecx-3E423112h]
+ ror ecx, 0Ah
+ add ecx, edi
+ mov [ebp+var_4], edi
+ and edi, ecx
+ mov ebx, ecx
+ not ebx
+ and ebx, esi
+ or ebx, edi
+ mov edi, [eax+10h]
+ add ebx, edi
+ lea edx, [ebx+edx-0A83F051h]
+ rol edx, 7
+ add edx, ecx
+ mov [ebp+arg_0], edx
+ not edx
+ and edx, [ebp+var_4]
+ mov ebx, ecx
+ and ebx, [ebp+arg_0]
+ mov [ebp+var_10], edi
+ mov edi, [eax+14h]
+ or edx, ebx
+ add edx, edi
+ lea esi, [edx+esi+4787C62Ah]
+ mov edx, [eax+18h]
+ mov [ebp+var_34], edi
+ mov edi, [ebp+arg_0]
+ rol esi, 0Ch
+ add esi, edi
+ mov [ebp+var_20], edx
+ mov edx, esi
+ not edx
+ and edx, ecx
+ mov ebx, esi
+ and ebx, edi
+ or edx, ebx
+ add edx, [ebp+var_20]
+ mov ebx, [ebp+var_4]
+ lea edx, [edx+ebx-57CFB9EDh]
+ ror edx, 0Fh
+ add edx, esi
+ mov ebx, edx
+ not ebx
+ and ebx, edi
+ mov edi, esi
+ and edi, edx
+ or ebx, edi
+ mov edi, [eax+1Ch]
+ add ebx, edi
+ lea ecx, [ebx+ecx-2B96AFFh]
+ ror ecx, 0Ah
+ add ecx, edx
+ mov [ebp+var_3C], edi
+ mov edi, [eax+20h]
+ mov [ebp+var_14], edi
+ mov edi, ecx
+ not edi
+ and edi, esi
+ mov ebx, edx
+ and ebx, ecx
+ or edi, ebx
+ add edi, [ebp+var_14]
+ mov ebx, [ebp+arg_0]
+ lea edi, [edi+ebx+698098D8h]
+ mov [ebp+var_8], ecx
+ rol edi, 7
+ add edi, ecx
+ and ecx, edi
+ mov ebx, edi
+ not ebx
+ and ebx, edx
+ or ebx, ecx
+ mov ecx, [eax+24h]
+ add ebx, ecx
+ mov [ebp+var_0C], ecx
+ mov ecx, [eax+28h]
+ lea esi, [ebx+esi-74BB0851h]
+ mov [ebp+var_24], ecx
+ rol esi, 0Ch
+ add esi, edi
+ mov ecx, esi
+ not ecx
+ and ecx, [ebp+var_8]
+ mov ebx, esi
+ and ebx, edi
+ or ecx, ebx
+ add ecx, [ebp+var_24]
+ mov ebx, esi
+ lea edx, [ecx+edx-0A44Fh]
+ mov ecx, [eax+2Ch]
+ ror edx, 0Fh
+ add edx, esi
+ mov [ebp+var_18], ecx
+ and ebx, edx
+ mov ecx, edx
+ not ecx
+ and ecx, edi
+ or ecx, ebx
+ add ecx, [ebp+var_18]
+ mov ebx, [ebp+var_8]
+ lea ecx, [ecx+ebx-76A32842h]
+ ror ecx, 0Ah
+ add ecx, edx
+ mov ebx, ecx
+ not ebx
+ mov [ebp+var_4], edx
+ and edx, ecx
+ and ebx, esi
+ or ebx, edx
+ mov edx, [eax+30h]
+ add ebx, edx
+ mov [ebp+var_38], edx
+ lea edi, [ebx+edi+6B901122h]
+ mov edx, [eax+34h]
+ rol edi, 7
+ add edi, ecx
+ mov [ebp+arg_0], edi
+ not edi
+ and edi, [ebp+var_4]
+ mov ebx, ecx
+ and ebx, [ebp+arg_0]
+ mov [ebp+var_8], edx
+ or edi, ebx
+ add edi, edx
+ mov edx, [eax+38h]
+ mov eax, [eax+3Ch]
+ lea esi, [edi+esi-2678E6Dh]
+ rol esi, 0Ch
+ add esi, [ebp+arg_0]
+ mov [ebp+var_28], edx
+ mov edi, esi
+ not edi
+ mov edx, edi
+ and edx, ecx
+ mov ebx, esi
+ and ebx, [ebp+arg_0]
+ or edx, ebx
+ add edx, [ebp+var_28]
+ mov ebx, [ebp+var_4]
+ lea edx, [edx+ebx-5986BC72h]
+ mov [ebp+var_4], eax
+ ror edx, 0Fh
+ add edx, esi
+ mov ebx, edx
+ not ebx
+ mov [ebp+var_48], ebx
+ and ebx, [ebp+arg_0]
+ mov eax, esi
+ and eax, edx
+ or ebx, eax
+ add ebx, [ebp+var_4]
+ and edi, edx
+ lea ecx, [ebx+ecx+49B40821h]
+ ror ecx, 0Ah
+ add ecx, edx
+ mov eax, esi
+ and eax, ecx
+ or edi, eax
+ add edi, [ebp+var_2C]
+ mov eax, [ebp+arg_0]
+ lea edi, [edi+eax-9E1DA9Eh]
+ mov eax, [ebp+var_48]
+ and eax, ecx
+ rol edi, 5
+ add edi, ecx
+ mov ebx, edx
+ and ebx, edi
+ or eax, ebx
+ add eax, [ebp+var_20]
+ lea esi, [eax+esi-3FBF4CC0h]
+ rol esi, 9
+ add esi, edi
+ mov eax, ecx
+ not eax
+ and eax, edi
+ mov ebx, esi
+ and ebx, ecx
+ or eax, ebx
+ add eax, [ebp+var_18]
+ lea edx, [eax+edx+265E5A51h]
+ rol edx, 0Eh
+ add edx, esi
+ mov eax, edi
+ not eax
+ and eax, esi
+ mov ebx, edx
+ and ebx, edi
+ or eax, ebx
+ add eax, [ebp+var_30]
+ lea ecx, [eax+ecx-16493856h]
+ ror ecx, 0Ch
+ mov eax, esi
+ add ecx, edx
+ not eax
+ and eax, edx
+ mov ebx, esi
+ and ebx, ecx
+ or eax, ebx
+ add eax, [ebp+var_34]
+ lea edi, [eax+edi-29D0EFA3h]
+ rol edi, 5
+ add edi, ecx
+ mov [ebp+arg_0], edi
+ mov eax, edx
+ not eax
+ and eax, ecx
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_24]
+ mov edi, ecx
+ lea esi, [eax+esi+2441453h]
+ mov eax, [ebp+arg_0]
+ not edi
+ and edi, eax
+ rol esi, 9
+ add esi, eax
+ not eax
+ and eax, esi
+ mov ebx, esi
+ and ebx, ecx
+ or edi, ebx
+ add edi, [ebp+var_4]
+ lea edx, [edi+edx-275E197Fh]
+ rol edx, 0Eh
+ add edx, esi
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_10]
+ mov edi, esi
+ lea ecx, [eax+ecx-182C0438h]
+ ror ecx, 0Ch
+ add ecx, edx
+ and edi, ecx
+ mov eax, esi
+ not eax
+ and eax, edx
+ or eax, edi
+ add eax, [ebp+var_0C]
+ mov edi, [ebp+arg_0]
+ lea eax, [eax+edi+21E1CDE6h]
+ rol eax, 5
+ add eax, ecx
+ mov [ebp+arg_0], eax
+ mov eax, edx
+ not eax
+ and eax, ecx
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_28]
+ mov edi, ecx
+ lea esi, [eax+esi-3CC8F82Ah]
+ mov eax, [ebp+arg_0]
+ rol esi, 9
+ add esi, eax
+ not edi
+ and edi, eax
+ mov ebx, esi
+ and ebx, ecx
+ or edi, ebx
+ add edi, [ebp+var_1C]
+ not eax
+ lea edx, [edi+edx-0B2AF279h]
+ rol edx, 0Eh
+ add edx, esi
+ and eax, esi
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_14]
+ lea ecx, [eax+ecx+455A14EDh]
+ ror ecx, 0Ch
+ add ecx, edx
+ mov eax, esi
+ not eax
+ and eax, edx
+ mov edi, esi
+ and edi, ecx
+ or eax, edi
+ add eax, [ebp+var_8]
+ mov edi, [ebp+arg_0]
+ lea eax, [eax+edi-561C16FBh]
+ rol eax, 5
+ add eax, ecx
+ mov [ebp+arg_0], eax
+ mov eax, edx
+ not eax
+ and eax, ecx
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_40]
+ mov edi, ecx
+ lea esi, [eax+esi-3105C08h]
+ mov eax, [ebp+arg_0]
+ not edi
+ and edi, eax
+ rol esi, 9
+ add esi, eax
+ mov ebx, esi
+ and ebx, ecx
+ or edi, ebx
+ add edi, [ebp+var_3C]
+ not eax
+ lea edx, [edi+edx+676F02D9h]
+ and eax, esi
+ rol edx, 0Eh
+ add edx, esi
+ mov edi, edx
+ and edi, [ebp+arg_0]
+ or eax, edi
+ add eax, [ebp+var_38]
+ mov edi, [ebp+arg_0]
+ lea ecx, [eax+ecx-72D5B376h]
+ ror ecx, 0Ch
+ add ecx, edx
+ mov eax, esi
+ xor eax, edx
+ xor eax, ecx
+ add eax, [ebp+var_34]
+ lea eax, [eax+edi-5C6BEh]
+ rol eax, 4
+ add eax, ecx
+ mov edi, edx
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_14]
+ lea esi, [edi+esi-788E097Fh]
+ rol esi, 0Bh
+ add esi, eax
+ mov edi, esi
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_18]
+ lea edx, [edi+edx+6D9D6122h]
+ rol edx, 10h
+ add edx, esi
+ mov edi, esi
+ xor edi, edx
+ mov ebx, edi
+ xor ebx, eax
+ add ebx, [ebp+var_28]
+ lea ecx, [ebx+ecx-21AC7F4h]
+ ror ecx, 9
+ add ecx, edx
+ xor edi, ecx
+ add edi, [ebp+var_2C]
+ lea eax, [edi+eax-5B4115BCh]
+ rol eax, 4
+ mov edi, edx
+ add eax, ecx
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_10]
+ lea esi, [edi+esi+4BDECFA9h]
+ rol esi, 0Bh
+ add esi, eax
+ mov edi, esi
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_3C]
+ lea edx, [edi+edx-944B4A0h]
+ rol edx, 10h
+ add edx, esi
+ mov edi, esi
+ xor edi, edx
+ mov ebx, edi
+ xor ebx, eax
+ add ebx, [ebp+var_24]
+ lea ecx, [ebx+ecx-41404390h]
+ ror ecx, 9
+ add ecx, edx
+ xor edi, ecx
+ add edi, [ebp+var_8]
+ lea eax, [edi+eax+289B7EC6h]
+ rol eax, 4
+ add eax, ecx
+ mov edi, edx
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_30]
+ lea esi, [edi+esi-155ED806h]
+ rol esi, 0Bh
+ add esi, eax
+ mov edi, esi
+ xor edi, ecx
+ xor edi, eax
+ add edi, [ebp+var_1C]
+ lea edi, [edi+edx-2B10CF7Bh]
+ rol edi, 10h
+ add edi, esi
+ mov edx, esi
+ xor edx, edi
+ mov ebx, edx
+ xor ebx, eax
+ add ebx, [ebp+var_20]
+ lea ecx, [ebx+ecx+4881D05h]
+ ror ecx, 9
+ add ecx, edi
+ xor edx, ecx
+ add edx, [ebp+var_0C]
+ lea eax, [edx+eax-262B2FC7h]
+ rol eax, 4
+ add eax, ecx
+ mov edx, edi
+ xor edx, ecx
+ xor edx, eax
+ add edx, [ebp+var_38]
+ lea edx, [edx+esi-1924661Bh]
+ rol edx, 0Bh
+ add edx, eax
+ mov esi, edx
+ xor esi, ecx
+ xor esi, eax
+ add esi, [ebp+var_4]
+ mov ebx, edx
+ lea esi, [esi+edi+1FA27CF8h]
+ mov edi, [ebp+var_40]
+ rol esi, 10h
+ add esi, edx
+ xor ebx, esi
+ xor ebx, eax
+ add ebx, edi
+ lea ecx, [ebx+ecx-3B53A99Bh]
+ ror ecx, 9
+ add ecx, esi
+ mov ebx, edx
+ not ebx
+ or ebx, ecx
+ xor ebx, esi
+ add ebx, [ebp+var_30]
+ lea eax, [ebx+eax-0BD6DDBCh]
+ rol eax, 6
+ add eax, ecx
+ mov ebx, esi
+ not ebx
+ or ebx, eax
+ xor ebx, ecx
+ add ebx, [ebp+var_3C]
+ lea edx, [ebx+edx+432AFF97h]
+ rol edx, 0Ah
+ add edx, eax
+ mov ebx, ecx
+ not ebx
+ or ebx, edx
+ xor ebx, eax
+ add ebx, [ebp+var_28]
+ lea esi, [ebx+esi-546BDC59h]
+ rol esi, 0Fh
+ add esi, edx
+ mov ebx, eax
+ not ebx
+ or ebx, esi
+ xor ebx, edx
+ add ebx, [ebp+var_34]
+ lea ecx, [ebx+ecx-36C5FC7h]
+ ror ecx, 0Bh
+ add ecx, esi
+ mov ebx, edx
+ not ebx
+ or ebx, ecx
+ xor ebx, esi
+ add ebx, [ebp+var_38]
+ lea eax, [ebx+eax+655B59C3h]
+ rol eax, 6
+ add eax, ecx
+ mov ebx, esi
+ not ebx
+ or ebx, eax
+ xor ebx, ecx
+ add ebx, [ebp+var_1C]
+ lea edx, [ebx+edx-70F3336Eh]
+ rol edx, 0Ah
+ add edx, eax
+ mov ebx, ecx
+ not ebx
+ or ebx, edx
+ xor ebx, eax
+ add ebx, [ebp+var_24]
+ lea esi, [ebx+esi-100B83h]
+ rol esi, 0Fh
+ add esi, edx
+ mov ebx, eax
+ not ebx
+ or ebx, esi
+ xor ebx, edx
+ add ebx, [ebp+var_2C]
+ lea ecx, [ebx+ecx-7A7BA22Fh]
+ ror ecx, 0Bh
+ add ecx, esi
+ mov ebx, edx
+ not ebx
+ or ebx, ecx
+ xor ebx, esi
+ add ebx, [ebp+var_14]
+ lea eax, [ebx+eax+6FA87E4Fh]
+ rol eax, 6
+ add eax, ecx
+ mov ebx, esi
+ not ebx
+ or ebx, eax
+ xor ebx, ecx
+ add ebx, [ebp+var_4]
+ lea edx, [ebx+edx-1D31920h]
+ rol edx, 0Ah
+ add edx, eax
+ mov ebx, ecx
+ not ebx
+ or ebx, edx
+ xor ebx, eax
+ add ebx, [ebp+var_20]
+ lea esi, [ebx+esi-5CFEBCECh]
+ rol esi, 0Fh
+ mov ebx, eax
+ add esi, edx
+ not ebx
+ or ebx, esi
+ xor ebx, edx
+ add ebx, [ebp+var_8]
+ lea ecx, [ebx+ecx+4E0811A1h]
+ ror ecx, 0Bh
+ add ecx, esi
+ mov ebx, edx
+ not ebx
+ or ebx, ecx
+ xor ebx, esi
+ add ebx, [ebp+var_10]
+ lea eax, [ebx+eax-8AC817Eh]
+ rol eax, 6
+ add eax, ecx
+ mov ebx, esi
+ not ebx
+ or ebx, eax
+ xor ebx, ecx
+ add ebx, [ebp+var_18]
+ lea edx, [ebx+edx-42C50DCBh]
+ rol edx, 0Ah
+ add edx, eax
+ mov ebx, ecx
+ not ebx
+ or ebx, edx
+ xor ebx, eax
+ add ebx, edi
+ lea esi, [ebx+esi+2AD7D2BBh]
+ mov edi, eax
+ not edi
+ rol esi, 0Fh
+ add esi, edx
+ or edi, esi
+ xor edi, edx
+ add edi, [ebp+var_0C]
+ lea edi, [edi+ecx-14792C6Fh]
+ mov ecx, [ebp+DecryptBuffer]
+ mov ebx, [ecx+8]
+ add ebx, eax
+ mov eax, [ecx+10h]
+ ror edi, 0Bh
+ add edi, [ecx+0Ch]
+ add eax, esi
+ add edi, esi
+ mov [ecx+10h], eax
+ mov eax, [ecx+14h]
+ mov [ecx+0Ch], edi
+ pop edi
+ add eax, edx
+ pop esi
+ mov [ecx+8], ebx
+ mov [ecx+14h], eax
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ retn 4
+SFileDecryptMpqHeader endp
+
+; ---------------------------------------------------------------------------
+
+; ---------------------------------------------------------------------------
+
+sub_6D00E0 proc near ; CODE XREF: sub_6D0210+59p
+ ; sub_6D0210+66p ...
+
+var_10 = dword ptr -10h
+pbMpqHeader = dword ptr -4
+pMpqHeader = dword ptr 8
+dwSize = dword ptr 0Ch
+
+ push ebp
+ mov ebp, esp
+ push ecx
+ mov eax, [ebp+pMpqHeader] ; EAX = MPQ Header
+ push ebx
+ mov ebx, [ebp+dwSize] ; EBX - size of MPQ Header
+ push esi
+ push edi
+ mov esi, ecx ; ESI - decryption buffer (6 DWORDs)
+ mov edi, [esi]
+ shr edi, 3
+ and edi, 3Fh
+ mov [ebp+pbMpqHeader], eax
+ lea ecx, ds:0[ebx*8] ; ECX = sizeof header * 8
+ test ebx, ebx
+ jbe loc_6D01F8
+ add [esi], ecx
+ mov edx, ebx ; EDX = size of header
+ shr edx, 1Dh
+ add [esi+4], edx
+ mov edx, [esi+4]
+ cmp [esi], ecx
+ jnb short loc_6D011E
+ inc edx
+ mov [esi+4], edx
+
+loc_6D011E: ; CODE XREF: sub_6D00E0+38j
+ test edi, edi
+ jz short loc_6D0196
+ lea eax, [edi+ebx]
+ cmp eax, 40h
+ jbe short loc_6D0136
+ mov eax, 40h
+ sub eax, edi
+ mov [ebp+dwSize], eax
+ jmp short loc_6D013B
+; ---------------------------------------------------------------------------
+
+loc_6D0136: ; CODE XREF: sub_6D00E0+48j
+ mov [ebp+dwSize], ebx
+ mov eax, ebx
+
+loc_6D013B: ; CODE XREF: sub_6D00E0+54j
+ mov edx, [ebp+pMpqHeader]
+ add edx, eax
+ lea ecx, [edi+esi+18h]
+ mov [ebp+pbMpqHeader], edx
+ cmp ecx, edx
+ jnb short loc_6D0163
+ lea edx, [ecx+eax]
+ mov ecx, [ebp+pMpqHeader]
+ cmp edx, ecx
+ jbe short loc_6D0166
+ push eax
+ push ecx
+ lea eax, [edi+esi+18h]
+ push eax
+ call _memmove
+ jmp short loc_6D0172
+; ---------------------------------------------------------------------------
+
+loc_6D0163: ; CODE XREF: sub_6D00E0+69j
+ mov ecx, [ebp+pMpqHeader]
+
+loc_6D0166: ; CODE XREF: sub_6D00E0+73j
+ push eax
+ push ecx
+ lea eax, [edi+esi+18h]
+ push eax
+ call _memcpy
+
+loc_6D0172: ; CODE XREF: sub_6D00E0+81j
+ mov eax, [ebp+dwSize]
+ lea ecx, [eax+edi]
+ add esp, 0Ch
+ cmp ecx, 40h
+ jl short loc_6D01F8
+ mov edx, [ebp+pbMpqHeader]
+ sub ebx, eax
+ lea eax, [esi+18h]
+ push eax
+ mov ecx, esi
+ mov [ebp+pbMpqHeader], edx
+ call SFileDecryptMpqHeader
+ mov eax, [ebp+pbMpqHeader]
+
+loc_6D0196: ; CODE XREF: sub_6D00E0+40j
+ cmp ebx, 40h
+ jl short loc_6D01C4
+ mov edi, ebx
+ shr edi, 6
+ mov ecx, edi
+ neg ecx
+ shl ecx, 6
+ add ebx, ecx
+ lea esp, [esp+0]
+
+loc_6D01B0: ; CODE XREF: sub_6D00E0+E2j
+ push eax
+ mov ecx, esi
+ call SFileDecryptMpqHeader
+ add [ebp+pbMpqHeader], 40h
+ sub edi, 1
+ mov eax, [ebp+pbMpqHeader]
+ jnz short loc_6D01B0
+
+loc_6D01C4: ; CODE XREF: sub_6D00E0+B9j
+ test ebx, ebx
+ jz short loc_6D01F8
+ add esi, 18h
+ lea edx, [ebx+eax]
+ cmp esi, edx
+ jnb short loc_6D01ED
+ lea ecx, [esi+ebx]
+ cmp ecx, eax
+ jbe short loc_6D01ED
+ push ebx
+ push eax
+ push esi
+ call _memmove
+ add esp, 0Ch
+ pop edi
+ pop esi
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_6D01ED: ; CODE XREF: sub_6D00E0+F0j
+ ; sub_6D00E0+F7j
+ push ebx
+ push eax
+ push esi
+ call _memcpy
+ add esp, 0Ch
+
+loc_6D01F8: ; CODE XREF: sub_6D00E0+23j
+ ; sub_6D00E0+9Ej ...
+ pop edi
+ pop esi
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ retn 8
+sub_6D00E0 endp
+
+aA_1: ; DATA XREF: sub_6249D0+68o
+ ; sub_6D0210+4Fo ...
+ dw 80h, 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+ db 0
+
+sub_6D0210 proc near ; CODE XREF: SFileVerifyMpqHeaderMD5+42p
+ ; sub_6D2D60+A9p ...
+
+var_8 = byte ptr -8
+var_6 = byte ptr -6
+var_5 = byte ptr -5
+var_4 = byte ptr -4
+var_3 = byte ptr -3
+var_2 = byte ptr -2
+var_1 = byte ptr -1
+arg_0 = dword ptr 8
+
+ push ebp
+ mov ebp, esp
+ sub esp, 8
+ push esi
+ mov esi, ecx ; Source address
+ mov eax, [esi]
+ mov ecx, eax
+ shr ecx, 8
+ mov [ebp-7], cl
+ mov ecx, eax
+ shr ecx, 18h
+ mov [ebp+var_5], cl
+ mov ecx, [esi+4]
+ mov edx, eax
+ shr edx, 10h
+ mov [ebp+var_6], dl
+ mov edx, ecx
+ mov [ebp+var_4], cl
+ shr edx, 8
+ mov [ebp+var_3], dl
+ mov edx, ecx
+ shr ecx, 18h
+ mov [ebp+var_1], cl
+ mov [ebp+var_8], al
+ shr eax, 3
+ mov ecx, 0FFFFFFF7h
+ sub ecx, eax
+ and ecx, 3Fh
+ push edi
+ inc ecx
+ push ecx
+ shr edx, 10h
+ push offset aA_1 ; ""
+ mov ecx, esi
+ mov [ebp+var_2], dl
+ call sub_6D00E0
+ push 8
+ lea edx, [ebp+var_8]
+ push edx
+ mov ecx, esi
+ call sub_6D00E0
+ mov edi, [ebp+arg_0]
+ xor eax, eax
+
+loc_6D0280: ; CODE XREF: sub_6D0210+8Ej
+ mov ecx, eax
+ and ecx, 3
+ add ecx, ecx
+ mov edx, eax
+ sar edx, 2
+ mov edx, [esi+edx*4+8]
+ add ecx, ecx
+ add ecx, ecx
+ shr edx, cl
+ inc eax
+ cmp eax, 10h
+ mov [eax+edi-1], dl
+ jl short loc_6D0280
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ retn 4
+sub_6D0210 endp
+
+
+sub_6CEBE0 proc near ; CODE XREF: sub_4A72D0+49p
+ ; SFileVerifyMpqHeaderMD5+51p ...
+
+var_4 = dword ptr -4
+arg_0 = dword ptr 8
+
+ push ebp
+ mov ebp, esp
+ mov edx, [ebp+arg_0]
+ mov eax, 10h
+ push esi
+ lea esp, [esp+0]
+
+loc_6CEBF0: ; CODE XREF: sub_6CEBE0+22j
+ mov esi, [ecx]
+ cmp esi, [edx]
+ jnz short loc_6CEC14
+ sub eax, 4
+ add edx, 4
+ add ecx, 4
+ cmp eax, 4
+ jnb short loc_6CEBF0
+ xor eax, eax
+ xor edx, edx
+ test eax, eax
+ setz dl
+ mov al, dl
+ pop esi
+ pop ebp
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_6CEC14: ; CODE XREF: sub_6CEBE0+14j
+ movzx eax, byte ptr [ecx]
+ movzx esi, byte ptr [edx]
+ sub eax, esi
+ jnz short loc_6CEC40
+ movzx eax, byte ptr [ecx+1]
+ movzx esi, byte ptr [edx+1]
+ sub eax, esi
+ jnz short loc_6CEC40
+ movzx eax, byte ptr [ecx+2]
+ movzx esi, byte ptr [edx+2]
+ sub eax, esi
+ jnz short loc_6CEC40
+ movzx eax, byte ptr [ecx+3]
+ movzx ecx, byte ptr [edx+3]
+ sub eax, ecx
+
+loc_6CEC40: ; CODE XREF: sub_6CEBE0+3Cj
+ ; sub_6CEBE0+48j ...
+ sar eax, 1Fh
+ or eax, 1
+ xor edx, edx
+ test eax, eax
+ setz dl
+ mov al, dl
+ pop esi
+ pop ebp
+ retn 4
+sub_6CEBE0 endp
+
+SFileVerifyMpqHeaderMD5 proc near ; CODE XREF: SFileVerifyMpqHeader+6Bp
+
+var_68 = dword ptr -68h
+var_64 = dword ptr -64h
+var_60 = dword ptr -60h
+var_5C = dword ptr -5Ch
+var_58 = dword ptr -58h
+var_54 = dword ptr -54h
+var_10 = dword ptr -10h
+
+ push ebp
+ mov ebp, esp
+ sub esp, 68h
+ push esi
+ mov esi, eax ; ESI = pointer to MPQ Header
+ xor eax, eax
+ push 0C0h
+ push esi
+ lea ecx, [ebp+var_68]
+ mov [ebp+var_64], eax
+ mov [ebp+var_68], eax
+ mov [ebp+var_60], 67452301h
+ mov [ebp+var_5C], 0EFCDAB89h
+ mov [ebp+var_58], 98BADCFEh
+ mov [ebp+var_54], 10325476h
+ call sub_6D00E0
+ lea eax, [ebp+var_10]
+ push eax
+ lea ecx, [ebp+var_68]
+ call sub_6D0210
+ add esi, 0C0h
+ push esi
+ lea ecx, [ebp+var_10]
+ call sub_6CEBE0
+ pop esi
+ mov esp, ebp
+ pop ebp
+ retn
+SFileVerifyMpqHeaderMD5 endp
+
+
+_wow_SFileVerifyMpqHeaderMD5 proc
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ call SFileVerifyMpqHeaderMD5
+ mov esp, ebp
+ pop ebp
+ retn
+_wow_SFileVerifyMpqHeaderMD5 endp
+
+END
diff --git a/dep/StormLib/test/x86_starcraft_lzma.asm b/dep/StormLib/test/x86_starcraft_lzma.asm
new file mode 100644
index 00000000000..bb13200b432
--- /dev/null
+++ b/dep/StormLib/test/x86_starcraft_lzma.asm
@@ -0,0 +1,11066 @@
+;
+; LZMA compression code ripped from Starctaft II BEta
+; Used while StormLib's LZMA implementation was tested against Starcraft compression
+; Not used in StormLib.
+;
+
+.686P
+.MODEL FLAT
+ASSUME FS: NOTHING
+
+.DATA
+
+;---------------------------------------------------------------------------
+; Data
+
+byte_4CB248 db 0, 0Bh, 0Bh, 0Bh ; indirect table for switch statement
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 1, 2, 3, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 4, 5, 6, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 7, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 8, 9, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Bh, 0Bh, 0Bh, 0Bh
+ db 0Ah
+ align 10h
+
+dword_544960 dd 0BB40E64Eh ; DATA XREF: sub_401C72+B
+dword_553598 dd ? ; DATA XREF: sub_4CB8A0+9
+
+off_50CD3C dd offset sub_4A0605 ; DATA XREF: sub_4A05F7+1o
+ ; .data:off_52A004o ...
+dword_50CD40 dd 0E06D7363h ; DATA XREF: _CxxThrowException(x,x)+Eo
+ dd 1
+ dd 0
+ dd 0
+ dd 3
+ dd 19930520h
+ dd 0
+ dd 0
+
+; ---------------------------------------------------------------------------
+
+off_546E20 dd offset sub_4CDD70 ; DATA XREF: sub_4D0270:loc_4D0324o
+off_546E24 dd offset sub_4CDD90 ; DATA XREF: sub_4CF810+53r
+off_546E28 dd offset off_50CD3C ; DATA XREF: .rdata:off_51B888o
+ dd 0
+ db '.?AUISequentialInStream@@',0
+ db 0
+ db 0
+off_546E4C dd offset off_50CD3C ; DATA XREF: .rdata:off_51B8C0o
+ dd 0
+ db '.?AUISequentialOutStream@@',0
+ db 0
+off_546E70 dd offset off_50CD3C ; DATA XREF: .rdata:off_51B8F8o
+ dd 0
+ db '.?AUICompressCoder@@',0
+ db 0
+ db 0
+ db 0
+off_546E90 dd offset off_50CD3C ; DATA XREF: .rdata:off_51B944o
+ dd 0
+ db '.?AUICompressSetOutStream@@',0
+off_546EB4 dd offset off_50CD3C ; DATA XREF: .rdata:0051B96Co
+ dd 0
+ db '.?AUICompressSetCoderProperties@@',0
+ db 0
+ db 0
+off_546EE0 dd offset off_50CD3C ; DATA XREF: .rdata:0051B9B8o
+ dd 0
+ db '.?AUICompressWriteCoderProperties@@',0
+ dd offset off_50CD3C
+ dd 0
+ db '.?AUCSystemException@@',0
+ db 0
+ dd offset off_50CD3C
+ dd 0
+ db '.?AUCOutBufferException@@',0
+ db 0
+ db 0
+off_546F50 dd offset off_50CD3C ; DATA XREF: .rdata:0051BA04o
+ dd 0
+ db '.?AVCInStreamMemory@@',0
+ db 0
+ db 0
+off_546F70 dd offset off_50CD3C ; DATA XREF: .rdata:off_51BA4Co
+ dd 0
+ db '.?AVCMyUnknownImp@@',0
+off_546F8C dd offset off_50CD3C ; DATA XREF: .rdata:0051BAA8o
+ dd 0
+ db '.?AVCOutStreamMemory@@',0
+ db 0
+off_546FAC dd offset off_50CD3C ; DATA XREF: .rdata:0051BAFCo
+ dd 0
+ db '.?AVCEncoder@NLZMA@NCompress@@',0
+ db 0
+off_546FD4 dd offset off_50CD3C ; DATA XREF: .rdata:off_51BBECo
+ dd 0
+ db '.?AVCBaseState@NLZMA@NCompress@@',0
+ db 0
+ db 0
+ db 0
+
+; ---------------------------------------------------------------------------
+
+dword_51B960 dd 0 ; DATA XREF: .rdata:00517A64o
+ dd 0
+ dd 0
+ dd offset off_546EB4
+ dd 0 ; offset dword_51B974
+
+dword_51B9AC dd 0 ; DATA XREF: .rdata:00517A78o
+ dd 0
+ dd 0
+ dd offset off_546EE0
+ dd 0 ;offset dword_51B9C0
+
+dword_51B9F8 dd 0 ; DATA XREF: .rdata:00517A8Co
+ dd 0
+ dd 0
+ dd offset off_546F50
+ dd 0 ; offset dword_51BA0C
+
+dword_51BA9C dd 0 ; DATA XREF: .rdata:00517AA0o
+ dd 0
+ dd 0
+ dd offset off_546F8C
+ dd 0 ; offset dword_51BAB0
+
+dword_51BAF0 dd 0 ; DATA XREF: .rdata:00517AF8o
+ dd 0
+ dd 0
+ dd offset off_546FAC
+ dd 0 ; offset dword_51BB04
+
+dword_51BC58 dd 0 ; DATA XREF: .rdata:00517AE0o
+ dd 4
+ dd 0
+ dd offset off_546FAC
+ dd 0 ; offset dword_51BB04
+
+dword_51BC6C dd 0 ; DATA XREF: .rdata:00517ACCo
+ dd 8
+ dd 0
+ dd offset off_546FAC
+ dd 0 ; offset dword_51BB04
+
+dword_51BC80 dd 0 ; DATA XREF: .rdata:00517AB8o
+ dd 0Ch
+ dd 0
+ dd offset off_546FAC
+ dd 0 ; offset dword_51BB04
+
+; ---------------------------------------------------------------------------
+
+dword_512730 dd 0 ; DATA XREF: sub_48DB4D+B9o
+dword_512734 dd 0 ; DATA XREF: CCmdTarget::GetInterface(void const *)+2Dr
+dword_512738 dd 0C0h ; DATA XREF: CCmdTarget::GetInterface(void const *)+38r
+dword_51273C dd 46000000h ; DATA XREF: CCmdTarget::GetInterface(void const *)+43r
+
+dword_5535A0 dd ? ; DATA XREF: sub_4CF900:loc_4CF94Co
+dword_5535A4 dd ? ; DATA XREF: .text:004DAF37w
+dword_5535A8 dd ? ; DATA XREF: .text:004DAF3Cw
+dword_5535AC dd ? ; DATA XREF: .text:004DAF41w
+
+dword_5535B0 dd ? ; DATA XREF: sub_4CF900+5Eo
+dword_5535B4 dd ? ; DATA XREF: .text:004DAF17w
+dword_5535B8 dd ? ; DATA XREF: .text:004DAF1Cw
+dword_5535BC dd ? ; DATA XREF: .text:004DAF21w
+
+dword_5535C0 dd ? ; DATA XREF: sub_4CF900:loc_4CF98Fo
+dword_5535C4 dd ? ; DATA XREF: .text:004DAEF7w
+dword_5535C8 dd ? ; DATA XREF: .text:004DAEFCw
+dword_5535CC dd ? ; DATA XREF: .text:004DAF01w
+
+
+dword_526DD0 dd 0 ; DATA XREF: .text:loc_4CF6CBo
+ dd 0
+ dd 0
+ dd 0 ; offset dword_526DE0
+
+kLiteralNextStates db 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5
+kMatchNextStates db 7, 7, 7, 7, 7, 7, 7, 0Ah, 0Ah, 0Ah, 0Ah, 0Ah
+kRepNextStates db 8, 8, 8, 8, 8, 8, 8, 0Bh, 0Bh, 0Bh, 0Bh, 0Bh
+kShortRepNextStates db 9, 9, 9, 9, 9, 9, 9, 0Bh, 0Bh, 0Bh, 0Bh, 0Bh
+
+dword_550998 dd 200h dup(?)
+dword_551198 dd 800h dup(?)
+dword_553198 dd 100h dup(?)
+
+ICompressSetOutStream_vftable dd offset __purecall ; DATA XREF: NCompress_NLZMA_CEncoder_CEncoder+2o
+ dd offset __purecall
+ dd offset __purecall
+ dd offset __purecall
+ dd offset __purecall
+ dd offset dword_51B960
+ICompressSetCoderProperties_vftable dd offset __purecall ; DATA XREF: NCompress_NLZMA_CEncoder_CEncoder+9o
+ dd offset __purecall
+ dd offset __purecall
+ dd offset __purecall
+ dd offset dword_51B9AC
+ICompressWriteCoderProperties_vftable dd offset __purecall ; DATA XREF: NCompress_NLZMA_CEncoder_CEncoder+10o
+ dd offset __purecall
+ dd offset __purecall
+ dd offset __purecall
+ dd offset dword_51B9F8
+off_517A90 dd offset Interface1_QueryInterface
+ dd offset Interface1_AddRef
+ dd offset Interface1_Release
+ dd offset sub_4CCB20
+ dd offset dword_51BA9C
+off_517AA4 dd offset Interface1_QueryInterface ; DATA XREF: sub_4CF610+Eo
+ dd offset Interface1_AddRef
+ dd offset Interface2_Release
+ dd offset sub_4CCB90
+ dd offset sub_4CF590
+ dd offset dword_51BC80
+NCompress_NLZMA_CEncoder_vftable_ICompressWriteCoderProperties dd offset sub_4CFA50 ; DATA XREF: sub_4CF810+3Do
+ dd offset sub_4CFA10
+ dd offset sub_4CFA70
+ dd offset sub_4CDDB0
+ dd offset dword_51BC6C
+NCompress_NLZMA_CEncoder_vftable_ICompressSetCoderProperties dd offset ICompressSetCoderProperties_QueryInterface ; DATA XREF: sub_4CF810+36o
+ dd offset ICompressSetCoderProperties_AddRef
+ dd offset ICompressSetCoderProperties_Release
+ dd offset ICompressSetCoderProperties_SetCoderProperties
+ dd offset dword_51BC58
+NCompress_NLZMA_CEncoder_vftable_ICompressSetOutStream dd offset sub_4CFA20 ; DATA XREF: sub_4CF810+2Fo
+ dd offset sub_4CFA80
+ dd offset sub_4CFA40
+ dd offset sub_4CFA90
+ dd offset sub_4CDE70
+ dd offset dword_51BAF0
+NCompress_NLZMA_CEncoder_vftable dd offset sub_4CF900 ; DATA XREF: sub_4CF810+29o
+ dd offset sub_4CF9D0
+ dd offset sub_4CF9E0
+ dd offset CEncoder_Code
+ dd offset sub_4D0250
+
+.CODE
+
+extrn _operator_new:PROC
+extrn __allshr: PROC
+extrn _free: PROC
+extrn _memcmp: PROC
+extrn _memcpy: PROC
+extrn _memset: PROC
+extrn ___report_gsfailure: PROC
+extrn __purecall: PROC
+VirtualAlloc PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
+VirtualFree PROTO STDCALL :DWORD,:DWORD,:DWORD
+
+; ---------------------------------------------------------------------------
+
+; void __cdecl j__free(void *Memory)
+; 004843B8
+j__free proc near ; CODE XREF: sub_401048+16p
+ ; .text:004010CFp ...
+ jmp _free
+j__free endp
+
+
+; ---------------------------------------------------------------------------
+
+; int __cdecl unknown_libname_324(void *Buf1, void *Buf2)
+unknown_libname_324 proc near
+; sub_48B7BA
+
+Buf1 = dword ptr 4
+Buf2 = dword ptr 8
+
+ push 10h ; Size
+ push [esp+4+Buf2] ; Buf2
+ push [esp+8+Buf1] ; Buf1
+ call _memcmp
+ add esp, 0Ch
+ neg eax
+ sbb eax, eax
+ inc eax
+ retn
+unknown_libname_324 endp
+
+; ---------------------------------------------------------------------------
+
+sub_4A05F7 proc near ; CODE XREF: sub_4A0605+3p
+ push ecx
+ mov dword ptr [ecx], offset off_50CD3C
+ call sub_4A98B8
+ pop ecx
+ retn
+sub_4A05F7 endp
+
+; ---------------------------------------------------------------------------
+
+; int __thiscall sub_4A0605(void *Memory, char)
+sub_4A0605 proc near ; DATA XREF: .rdata:off_50CD3Co
+
+arg_0 = byte ptr 4
+
+ push esi
+ mov esi, ecx
+ call sub_4A05F7
+ test [esp+4+arg_0], 1
+ jz short loc_4A061B
+ push esi ; Memory
+ call j__free
+ pop ecx
+
+loc_4A061B: ; CODE XREF: sub_4A0605+Dj
+ mov eax, esi
+ pop esi
+ retn 4
+sub_4A0605 endp
+
+; ---------------------------------------------------------------------------
+
+sub_4A0686 proc near ; CODE XREF: sub_401C72+49p
+ ; sub_40222F+15Cp ...
+ cmp ecx, dword_544960
+ jnz short loc_4A0690
+ retn
+loc_4A0690: ; CODE XREF: sub_4A0686+6j
+ jmp ___report_gsfailure
+sub_4A0686 endp
+
+; ---------------------------------------------------------------------------
+
+sub_4A98B8 proc near ; CODE XREF: sub_4A05F7+7p
+
+ int 3
+ retn
+sub_4A98B8 endp
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CAEC0 proc near ; CODE XREF: CEncoder_GetOptimum+514p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push esi
+ push edi
+ mov edi, [esp+8+arg_4]
+ lea eax, [edi-2]
+ cmp eax, 4
+ mov esi, ecx
+ jb short loc_4CAED5
+ mov eax, 3
+
+loc_4CAED5: ; CODE XREF: sub_4CAEC0+Ej
+ mov edx, [esp+8+arg_0]
+ cmp edx, 80h
+ jnb short loc_4CAEEF
+ shl eax, 7
+ add eax, edx
+ mov ecx, [esi+eax*4+33314h]
+ jmp short loc_4CAF25
+; ---------------------------------------------------------------------------
+
+loc_4CAEEF: ; CODE XREF: sub_4CAEC0+1Fj
+ mov ecx, 7FFFFh
+ sub ecx, edx
+ sar ecx, 1Fh
+ push ebx
+ and ecx, 0Ch
+ add ecx, 6
+ mov ebx, edx
+ shr ebx, cl
+ shl eax, 5
+ add eax, ecx
+ and edx, 0Fh
+ movzx ebx, byte ptr dword_551198[ebx]
+ lea eax, [ebx+eax*2]
+ mov ecx, [esi+eax*4+32F14h]
+ add ecx, [esi+edx*4+33B14h]
+ pop ebx
+
+loc_4CAF25: ; CODE XREF: sub_4CAEC0+2Dj
+ mov edx, [esp+8+arg_8]
+ imul edx, 110h
+ add edx, edi
+ mov eax, [esi+edx*4+295B8h]
+ pop edi
+ add eax, ecx
+ pop esi
+ retn 0Ch
+sub_4CAEC0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CAF40: ; CODE XREF: .text:004DAED5j
+ push ecx
+ push ebx
+ push ebp
+ push esi
+ mov ebp, 2
+ mov bl, 2
+ push edi
+ mov byte ptr dword_551198, 0
+ mov byte ptr dword_551198+1, 1
+ mov [esp+10h], bl
+ mov edi, ebp
+
+loc_4CAF60: ; CODE XREF: .text:004CAF96j
+ mov ecx, edi
+ shr ecx, 1
+ sub ecx, 1
+ mov esi, 1
+ shl esi, cl
+ test esi, esi
+ jbe short loc_4CAF89
+ mov ecx, [esp+10h]
+ push esi
+ lea eax, dword_551198[ebp]
+ push ecx
+ push eax
+ call _memset
+ add esp, 0Ch
+ add ebp, esi
+
+loc_4CAF89: ; CODE XREF: .text:004CAF70j
+ add bl, 1
+ add edi, 1
+ cmp bl, 1Ah
+ mov [esp+10h], bl
+ jb short loc_4CAF60
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CAFA0 proc near ; CODE XREF: sub_4CAFC0+90p
+
+arg_0 = dword ptr 4
+
+ mov eax, [esp+arg_0]
+ lea ecx, [eax-61h]
+ cmp cx, 19h
+ ja short locret_4CAFB2
+ add eax, 0FFE0h
+
+locret_4CAFB2: ; CODE XREF: sub_4CAFA0+Bj
+ retn
+sub_4CAFA0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CAFC0 proc near ; CODE XREF: ICompressSetCoderProperties_SetCoderProperties+A5p
+ movzx ecx, word ptr [eax]
+ lea edx, [ecx-61h]
+ cmp dx, 19h
+ ja short loc_4CAFD2
+ add ecx, 0FFE0h
+
+loc_4CAFD2: ; CODE XREF: sub_4CAFC0+Aj
+ add eax, 2
+ cmp cx, 48h
+ jnz short loc_4CB01B
+ movzx ecx, word ptr [eax]
+ lea edx, [ecx-61h]
+ cmp dx, 19h
+ ja short loc_4CAFED
+ add ecx, 0FFE0h
+
+loc_4CAFED: ; CODE XREF: sub_4CAFC0+25j
+ add eax, 2
+ cmp cx, 43h
+ jz short loc_4CAFF9
+
+loc_4CAFF6: ; CODE XREF: sub_4CAFC0+44j
+ ; sub_4CAFC0+4Bj ...
+ xor eax, eax
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CAFF9: ; CODE XREF: sub_4CAFC0+34j
+ movzx ecx, word ptr [eax]
+ sub ecx, 30h
+ lea edx, [ecx-4]
+ test edx, edx
+ ja short loc_4CAFF6
+ cmp word ptr [eax+2], 0
+ jnz short loc_4CAFF6
+ mov dword ptr [ebx], 0
+ mov [edi], ecx
+ mov eax, 1
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CB01B: ; CODE XREF: sub_4CAFC0+19j
+ cmp cx, 42h
+ jnz short loc_4CAFF6
+ movzx ecx, word ptr [eax]
+ lea edx, [ecx-61h]
+ cmp dx, 19h
+ ja short loc_4CB033
+ add ecx, 0FFE0h
+
+loc_4CB033: ; CODE XREF: sub_4CAFC0+6Bj
+ add eax, 2
+ cmp cx, 54h
+ jnz short loc_4CAFF6
+ push esi
+ movzx esi, word ptr [eax]
+ sub esi, 30h
+ lea ecx, [esi-2]
+ cmp ecx, 2
+ ja short loc_4CB06C
+ movzx eax, word ptr [eax+2]
+ push eax
+ call sub_4CAFA0
+ add esp, 4
+ test ax, ax
+ jnz short loc_4CB06C
+ mov dword ptr [ebx], 1
+ mov [edi], esi
+ mov eax, 1
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CB06C: ; CODE XREF: sub_4CAFC0+89j
+ ; sub_4CAFC0+9Bj
+ xor eax, eax
+ pop esi
+ retn
+sub_4CAFC0 endp
+
+
+ICompressSetCoderProperties_SetCoderProperties proc near ; DATA XREF: .rdata:00517ADCo
+
+var_4 = dword ptr -4
+pThis = dword ptr 4
+propIDs = dword ptr 8
+properties = dword ptr 0Ch
+numProperties = dword ptr 10h
+
+ push ecx
+ push ebx
+ push ebp
+ xor edx, edx
+ cmp [esp+0Ch+numProperties], edx
+ push esi
+ push edi
+ mov [esp+14h+var_4], edx
+ jbe loc_4CB20D
+ mov esi, [esp+14h+properties]
+ mov ebp, [esp+14h+pThis]
+ lea ecx, [ecx+0]
+
+loc_4CB090: ; CODE XREF: sub_4CB070+197j
+ mov eax, [esp+14h+propIDs]
+ mov eax, [eax+edx*4]
+ add eax, 0FFFFFC00h
+ cmp eax, 90h ; switch 145 cases
+ ja loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ movzx ecx, ds:byte_4CB248[eax]
+ jmp ds:off_4CB218[ecx*4] ; switch jump
+
+loc_4CB0B5: ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 80
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ lea ecx, [eax-5]
+ cmp ecx, 10Ch
+ ja short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov [ebp+32EF0h], eax
+ jmp loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB0D4: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 82
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ mov [ebp+33B88h], eax
+ jmp loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB0E8: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 112
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ cmp dword ptr [esi+8], 0
+ setz cl
+ mov [ebp+32EECh], cl
+ jmp loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB100: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 8 ; jumptable 004CB0AE case 81
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ lea edi, [ebp+0C4h]
+ lea ebx, [ebp+0CCh]
+ call sub_4CAFC0
+ test eax, eax
+ jz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov edx, [esp+14h+var_4]
+ jmp loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB127: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 0Bh ; jumptable 004CB0AE case 128
+ jz loc_4CB1F9
+
+loc_4CB131: ; CODE XREF: sub_4CB070+31j
+ ; sub_4CB070+3Ej ...
+ pop edi ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ pop esi
+ pop ebp
+ mov eax, 80070057h
+ pop ebx
+ pop ecx
+ retn 10h
+; ---------------------------------------------------------------------------
+
+loc_4CB13E: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 129
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ jmp loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB149: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 0
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ lea ecx, [eax-1]
+ cmp ecx, 3FFFFFFFh
+ ja short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov [ebp+33B64h], eax
+ xor ecx, ecx
+
+loc_4CB165: ; CODE XREF: sub_4CB070+106j
+ mov edi, 1
+ shl edi, cl
+ cmp eax, edi
+ jbe short loc_4CB178
+ add ecx, 1
+ cmp ecx, 1Eh
+ jb short loc_4CB165
+
+loc_4CB178: ; CODE XREF: sub_4CB070+FEj
+ lea eax, [ecx+ecx]
+ mov [ebp+33B50h], eax
+ jmp short loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB183: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 64
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov ecx, [esi+8]
+ cmp ecx, 4
+ ja short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, 1
+ shl eax, cl
+ mov [ebp+33B54h], ecx
+ sub eax, 1
+ mov [ebp+33B58h], eax
+ jmp short loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB1A9: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 66
+ jnz short loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ cmp eax, 4
+ ja loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov [ebp+33B5Ch], eax
+ jmp short loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB1C3: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 13h ; jumptable 004CB0AE case 65
+ jnz loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov eax, [esi+8]
+ cmp eax, 8
+ ja loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ mov [ebp+33B60h], eax
+ jmp short loc_4CB1F9
+; ---------------------------------------------------------------------------
+
+loc_4CB1E1: ; CODE XREF: sub_4CB070+3Ej
+ ; DATA XREF: .text:off_4CB218o
+ cmp word ptr [esi], 0Bh ; jumptable 004CB0AE case 144
+ jnz loc_4CB131 ; default
+ ; jumptable 004CB0AE cases 1-63,67-79,83-111,113-127,130-143
+ cmp word ptr [esi+8], 0FFFFh
+ setz cl
+ mov [ebp+33B8Ch], cl
+
+loc_4CB1F9: ; CODE XREF: sub_4CB070+5Fj
+ ; sub_4CB070+73j ...
+ add edx, 1
+ add esi, 10h
+ cmp edx, [esp+14h+numProperties]
+ mov [esp+14h+var_4], edx
+ jb loc_4CB090
+
+loc_4CB20D: ; CODE XREF: sub_4CB070+Fj
+ pop edi
+ pop esi
+ pop ebp
+ xor eax, eax
+ pop ebx
+ pop ecx
+ retn 10h
+
+off_4CB218 dd offset loc_4CB149, offset loc_4CB183, offset loc_4CB1C3
+ dd offset loc_4CB1A9, offset loc_4CB0B5, offset loc_4CB100 ; jump table for switch statement
+ dd offset loc_4CB0D4, offset loc_4CB0E8, offset loc_4CB127
+ dd offset loc_4CB13E, offset loc_4CB1E1, offset loc_4CB131
+
+ICompressSetCoderProperties_SetCoderProperties endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CB2E0 proc near ; CODE XREF: CEncoder_GetOptimum+1199p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_4]
+ lea eax, [esi+esi*4]
+ lea edx, [ecx+eax*8]
+ mov [ecx+32F08h], esi
+ mov eax, [edx+100h]
+ mov ebx, [edx+104h]
+ push edi
+
+loc_4CB300: ; CODE XREF: sub_4CB2E0+A6j
+ lea edx, [esi+esi*4]
+ cmp byte ptr [ecx+edx*8+0F1h], 0
+ lea edi, [ecx+edx*8]
+ jz short loc_4CB359
+ lea edx, [eax+eax*4+1Eh]
+ lea edx, [ecx+edx*8]
+ mov dword ptr [edx+14h], 0FFFFFFFFh
+ mov byte ptr [edx+1], 0
+ lea edx, [eax+eax*4]
+ lea edx, [ecx+edx*8]
+ lea ebp, [eax-1]
+ mov [edx+100h], ebp
+ cmp byte ptr [edi+0F2h], 0
+ jz short loc_4CB359
+ mov byte ptr [edx+0C9h], 0
+ mov ebp, [edi+0F4h]
+ mov [edx+0D8h], ebp
+ mov edi, [edi+0F8h]
+ mov [edx+0DCh], edi
+
+loc_4CB359: ; CODE XREF: sub_4CB2E0+2Ej
+ ; sub_4CB2E0+58j
+ lea edx, [eax+eax*4]
+ add edx, edx
+ add edx, edx
+ add edx, edx
+ mov edi, eax
+ test edi, edi
+ mov eax, [edx+ecx+100h]
+ mov ebp, ebx
+ mov ebx, [edx+ecx+104h]
+ mov [edx+ecx+100h], esi
+ mov [edx+ecx+104h], ebp
+ mov esi, edi
+ jnz loc_4CB300
+ mov eax, [ecx+104h]
+ mov edx, [esp+10h+arg_0]
+ pop edi
+ pop esi
+ mov [edx], eax
+ mov eax, [ecx+100h]
+ pop ebp
+ mov [ecx+32F0Ch], eax
+ pop ebx
+ retn 8
+sub_4CB2E0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CB3B0 proc near ; CODE XREF: CEncoder_GetOptimumFast+2Dp
+ ; CEncoder_GetOptimumFast+28Fp ...
+
+arg_0 = dword ptr 4
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, ecx
+ mov ecx, [esi+80h]
+ mov edx, [esi+78h]
+ lea eax, [esi+32660h]
+ push eax
+ push ecx
+ xor ebx, ebx
+ call edx
+ mov ebp, [esp+14h+arg_0]
+ add esp, 8
+ test eax, eax
+ mov [ebp+0], eax
+ jbe short loc_4CB446
+ mov ebx, [esi+eax*4+32658h]
+ cmp ebx, [esi+32EF8h]
+ jnz short loc_4CB446
+ mov eax, [esi+80h]
+ mov ecx, [esi+70h]
+ push edi
+ push eax
+ call ecx
+ mov edx, [esi+80h]
+ mov edi, eax
+ mov eax, [esi+74h]
+ push edx
+ add edi, 1
+ call eax
+ mov ecx, [ebp+0]
+ mov ecx, [esi+ecx*4+3265Ch]
+ add esp, 8
+ sub eax, 1
+ add ecx, 1
+ cmp edi, 111h
+ jbe short loc_4CB425
+ mov edi, 111h
+
+loc_4CB425: ; CODE XREF: sub_4CB3B0+6Ej
+ mov edx, eax
+ sub edx, ecx
+ cmp ebx, edi
+ jnb short loc_4CB445
+ mov ebp, edx
+ lea ecx, [eax+ebx]
+ sub ebp, eax
+
+loc_4CB434: ; CODE XREF: sub_4CB3B0+93j
+ mov dl, [ecx]
+ cmp dl, [ecx+ebp]
+ jnz short loc_4CB445
+ add ebx, 1
+ add ecx, 1
+ cmp ebx, edi
+ jb short loc_4CB434
+
+loc_4CB445: ; CODE XREF: sub_4CB3B0+7Bj
+ ; sub_4CB3B0+89j
+ pop edi
+
+loc_4CB446: ; CODE XREF: sub_4CB3B0+26j
+ ; sub_4CB3B0+35j
+ add dword ptr [esi+32F04h], 1
+ pop esi
+ pop ebp
+ mov eax, ebx
+ pop ebx
+ retn 4
+sub_4CB3B0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_GetOptimumFast proc near ; CODE XREF: CEncoder_CodeOneBlock+1F4p
+
+var_28 = dword ptr -28h
+var_24 = dword ptr -24h
+var_20 = dword ptr -20h
+var_1C = dword ptr -1Ch
+var_18 = dword ptr -18h
+var_14 = dword ptr -14h
+var_10 = dword ptr -10h
+arg_0 = dword ptr 4
+
+ sub esp, 28h
+ push ebx
+ push esi
+ push edi
+ mov edi, ecx
+ mov eax, [edi+80h]
+ mov ecx, [edi+70h]
+ push eax
+ call ecx
+ add esp, 4
+ cmp byte ptr [edi+32F10h], 0
+ mov esi, eax
+ mov [esp+34h+var_24], esi
+ jnz short loc_4CB498
+ lea edx, [esp+34h+var_20]
+ push edx
+ mov ecx, edi
+ call sub_4CB3B0
+ mov ebx, [esp+34h+var_20]
+ jmp short loc_4CB4AF
+; ---------------------------------------------------------------------------
+
+loc_4CB498: ; CODE XREF: CEncoder_GetOptimumFast+24j
+ mov ebx, [edi+32F00h]
+ mov eax, [edi+32EFCh]
+ mov [esp+34h+var_20], ebx
+ mov byte ptr [edi+32F10h], 0
+
+loc_4CB4AF: ; CODE XREF: CEncoder_GetOptimumFast+36j
+ mov ecx, [edi+80h]
+ mov edx, [edi+74h]
+ push ecx
+ mov [esp+38h+var_28], eax
+ call edx
+ add esp, 4
+ sub eax, 1
+ cmp esi, 111h
+ jbe loc_4CB55E
+ mov [esp+34h+var_24], 111h
+
+loc_4CB4D9: ; CODE XREF: CEncoder_GetOptimumFast+101j
+ push ebp
+ xor ebp, ebp
+ lea ecx, [edi+14h]
+ mov [esp+38h+var_18], ebp
+ mov [esp+38h+var_14], ebp
+ mov [esp+38h+var_1C], ecx
+ jmp short loc_4CB4F0
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CB4F0: ; CODE XREF: CEncoder_GetOptimumFast+8Bj
+ ; CEncoder_GetOptimumFast+132j
+ mov edx, [esp+38h+var_1C]
+ mov ecx, eax
+ sub ecx, [edx]
+ mov dl, [eax]
+ sub ecx, 1
+ cmp dl, [ecx]
+ jnz short loc_4CB57F
+ mov dl, [eax+1]
+ cmp dl, [ecx+1]
+ jnz short loc_4CB57F
+ mov esi, 2
+ cmp [esp+38h+var_24], esi
+ jbe short loc_4CB537
+ lea edx, [eax+2]
+ sub ecx, eax
+ lea esp, [esp+0]
+
+loc_4CB520: ; CODE XREF: CEncoder_GetOptimumFast+D1j
+ mov bl, [edx]
+ cmp bl, [ecx+edx]
+ jnz short loc_4CB533
+ add esi, 1
+ add edx, 1
+ cmp esi, [esp+38h+var_24]
+ jb short loc_4CB520
+
+loc_4CB533: ; CODE XREF: CEncoder_GetOptimumFast+C5j
+ mov ebx, [esp+38h+var_20]
+
+loc_4CB537: ; CODE XREF: CEncoder_GetOptimumFast+B2j
+ cmp esi, [edi+32EF8h]
+ jnb short loc_4CB5B9
+ mov edx, [esp+38h+var_14]
+ lea ecx, ds:0[ebp*4]
+ mov [esp+ecx+38h+var_10], esi
+ cmp esi, [esp+edx+38h+var_10]
+ jbe short loc_4CB587
+ mov [esp+38h+var_18], ebp
+ mov [esp+38h+var_14], ecx
+ jmp short loc_4CB587
+; ---------------------------------------------------------------------------
+
+loc_4CB55E: ; CODE XREF: CEncoder_GetOptimumFast+6Bj
+ cmp esi, 2
+ jnb loc_4CB4D9
+ mov eax, [esp+34h+arg_0]
+ pop edi
+ pop esi
+ mov dword ptr [eax], 0FFFFFFFFh
+ mov eax, 1
+ pop ebx
+ add esp, 28h
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_4CB57F: ; CODE XREF: CEncoder_GetOptimumFast+9Fj
+ ; CEncoder_GetOptimumFast+A7j
+ mov [esp+ebp*4+38h+var_10], 0
+
+loc_4CB587: ; CODE XREF: CEncoder_GetOptimumFast+F2j
+ ; CEncoder_GetOptimumFast+FCj
+ add [esp+38h+var_1C], 4
+ add ebp, 1
+ cmp ebp, 4
+ jb loc_4CB4F0
+ mov esi, [esp+38h+var_28]
+ cmp esi, [edi+32EF8h]
+ jb short loc_4CB5EC
+ mov eax, [edi+ebx*4+3265Ch]
+ mov ecx, [esp+38h+arg_0]
+ add eax, 4
+ mov [ecx], eax
+ jmp loc_4CB69A
+; ---------------------------------------------------------------------------
+
+loc_4CB5B9: ; CODE XREF: CEncoder_GetOptimumFast+DDj
+ mov eax, [esp+38h+arg_0]
+ mov [eax], ebp
+ lea eax, [esi-1]
+ test eax, eax
+ jz loc_4CB82E
+ mov ecx, [edi+80h]
+ mov edx, [edi+7Ch]
+ add [edi+32F04h], eax
+ push eax
+ push ecx
+ call edx
+ add esp, 8
+ pop ebp
+ pop edi
+ mov eax, esi
+ pop esi
+ pop ebx
+ add esp, 28h
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_4CB5EC: ; CODE XREF: CEncoder_GetOptimumFast+142j
+ xor ebp, ebp
+ cmp esi, 2
+ mov [esp+38h+var_20], ebp
+ jb short loc_4CB65A
+ cmp ebx, 2
+ mov ecx, [edi+ebx*4+3265Ch]
+ mov [esp+38h+var_20], ecx
+ jbe short loc_4CB63F
+ lea eax, [edi+ebx*4+32654h]
+ mov edi, edi
+
+loc_4CB610: ; CODE XREF: CEncoder_GetOptimumFast+1DDj
+ mov edx, [eax-4]
+ add edx, 1
+ cmp esi, edx
+ jnz short loc_4CB63F
+ mov ecx, [esp+38h+var_20]
+ shr ecx, 7
+ cmp ecx, [eax]
+ jbe short loc_4CB63F
+ mov edx, [eax-4]
+ mov ecx, [eax]
+ sub eax, 8
+ sub ebx, 2
+ cmp ebx, 2
+ mov [esp+38h+var_28], edx
+ mov [esp+38h+var_20], ecx
+ mov esi, edx
+ ja short loc_4CB610
+
+loc_4CB63F: ; CODE XREF: CEncoder_GetOptimumFast+1A5j
+ ; CEncoder_GetOptimumFast+1B8j ...
+ cmp esi, 2
+ jnz short loc_4CB656
+ cmp [esp+38h+var_20], 80h
+ jb short loc_4CB656
+ mov [esp+38h+var_28], 1
+
+loc_4CB656: ; CODE XREF: CEncoder_GetOptimumFast+1E2j
+ ; CEncoder_GetOptimumFast+1ECj
+ mov ebp, [esp+38h+var_20]
+
+loc_4CB65A: ; CODE XREF: CEncoder_GetOptimumFast+195j
+ mov edx, [esp+38h+var_18]
+ mov esi, [esp+edx*4+38h+var_10]
+ cmp esi, 2
+ mov ebx, [esp+38h+var_28]
+ jb short loc_4CB6C7
+ lea eax, [esi+1]
+ cmp eax, ebx
+ jnb short loc_4CB690
+ lea ecx, [esi+2]
+ cmp ecx, ebx
+ jb short loc_4CB681
+ cmp ebp, 200h
+ ja short loc_4CB690
+
+loc_4CB681: ; CODE XREF: CEncoder_GetOptimumFast+217j
+ lea edx, [esi+3]
+ cmp edx, ebx
+ jb short loc_4CB6C7
+ cmp ebp, 8000h
+ jbe short loc_4CB6C7
+
+loc_4CB690: ; CODE XREF: CEncoder_GetOptimumFast+210j
+ ; CEncoder_GetOptimumFast+21Fj
+ mov eax, [esp+38h+arg_0]
+ mov ecx, [esp+38h+var_18]
+ mov [eax], ecx
+
+loc_4CB69A: ; CODE XREF: CEncoder_GetOptimumFast+154j
+ lea eax, [esi-1]
+ test eax, eax
+ jz loc_4CB82E
+ mov edx, [edi+80h]
+ add [edi+32F04h], eax
+ push eax
+ mov eax, [edi+7Ch]
+ push edx
+ call eax
+ add esp, 8
+ pop ebp
+ pop edi
+ mov eax, esi
+ pop esi
+ pop ebx
+ add esp, 28h
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_4CB6C7: ; CODE XREF: CEncoder_GetOptimumFast+209j
+ ; CEncoder_GetOptimumFast+226j ...
+ cmp ebx, 2
+ jb short loc_4CB73E
+ cmp [esp+38h+var_24], 2
+ jbe short loc_4CB73E
+ mov ecx, [edi+80h]
+ mov edx, [edi+70h]
+ push ecx
+ call edx
+ add esp, 4
+ lea esi, [edi+32F00h]
+ push esi
+ mov ecx, edi
+ mov [esp+3Ch+var_24], eax
+ call sub_4CB3B0
+ cmp eax, 2
+ mov [edi+32EFCh], eax
+ jb short loc_4CB757
+ cmp eax, ebx
+ mov ecx, [esi]
+ mov edx, [edi+ecx*4+3265Ch]
+ jb short loc_4CB710
+ cmp edx, ebp
+ jb short loc_4CB737
+
+loc_4CB710: ; CODE XREF: CEncoder_GetOptimumFast+2AAj
+ lea ecx, [ebx+1]
+ cmp eax, ecx
+ jnz short loc_4CB722
+ mov esi, edx
+ shr esi, 7
+ cmp esi, ebp
+ jbe short loc_4CB737
+ cmp eax, ecx
+
+loc_4CB722: ; CODE XREF: CEncoder_GetOptimumFast+2B5j
+ ja short loc_4CB737
+ add eax, 1
+ cmp eax, ebx
+ jb short loc_4CB757
+ cmp ebx, 3
+ jb short loc_4CB757
+ shr ebp, 7
+ cmp ebp, edx
+ jbe short loc_4CB757
+
+loc_4CB737: ; CODE XREF: CEncoder_GetOptimumFast+2AEj
+ ; CEncoder_GetOptimumFast+2BEj ...
+ mov byte ptr [edi+32F10h], 1
+
+loc_4CB73E: ; CODE XREF: CEncoder_GetOptimumFast+26Aj
+ ; CEncoder_GetOptimumFast+271j
+ mov edx, [esp+38h+arg_0]
+ pop ebp
+ pop edi
+ pop esi
+ mov dword ptr [edx], 0FFFFFFFFh
+ mov eax, 1
+ pop ebx
+ add esp, 28h
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_4CB757: ; CODE XREF: CEncoder_GetOptimumFast+29Dj
+ ; CEncoder_GetOptimumFast+2C9j ...
+ mov eax, [edi+80h]
+ mov ecx, [edi+74h]
+ push eax
+ call ecx
+ lea ecx, [edi+14h]
+ add esp, 4
+ sub eax, 1
+ mov [esp+38h+var_18], 0
+ mov ebx, ecx
+
+loc_4CB776: ; CODE XREF: CEncoder_GetOptimumFast+39Aj
+ mov dl, [eax+1]
+ mov ecx, eax
+ sub ecx, [ebx]
+ sub ecx, 1
+ cmp dl, [ecx+1]
+ jnz short loc_4CB7DD
+ mov dl, [eax+2]
+ cmp dl, [ecx+2]
+ lea ebp, [eax+2]
+ jnz short loc_4CB7DD
+ mov esi, 2
+ cmp [esp+38h+var_24], esi
+ jbe short loc_4CB7B4
+ mov edx, ebp
+ mov ebp, ecx
+ sub ebp, eax
+
+loc_4CB7A1: ; CODE XREF: CEncoder_GetOptimumFast+352j
+ mov cl, [edx]
+ cmp cl, [edx+ebp]
+ jnz short loc_4CB7B4
+ add esi, 1
+ add edx, 1
+ cmp esi, [esp+38h+var_24]
+ jb short loc_4CB7A1
+
+loc_4CB7B4: ; CODE XREF: CEncoder_GetOptimumFast+339j
+ ; CEncoder_GetOptimumFast+346j
+ add esi, 1
+ cmp esi, [esp+38h+var_28]
+ jb short loc_4CB7E9
+ mov eax, [esp+38h+arg_0]
+ pop ebp
+ mov byte ptr [edi+32F10h], 1
+ pop edi
+ pop esi
+ mov dword ptr [eax], 0FFFFFFFFh
+ mov eax, 1
+ pop ebx
+ add esp, 28h
+ retn 4
+; ---------------------------------------------------------------------------
+
+loc_4CB7DD: ; CODE XREF: CEncoder_GetOptimumFast+323j
+ ; CEncoder_GetOptimumFast+32Ej
+ mov edx, [esp+38h+var_18]
+ mov [esp+edx*4+38h+var_10], 0
+
+loc_4CB7E9: ; CODE XREF: CEncoder_GetOptimumFast+35Bj
+ mov ecx, [esp+38h+var_18]
+ add ecx, 1
+ add ebx, 4
+ cmp ecx, 4
+ mov [esp+38h+var_18], ecx
+ jb loc_4CB776
+ mov esi, [esp+38h+var_28]
+ mov ecx, [esp+38h+var_20]
+ mov edx, [esp+38h+arg_0]
+ add ecx, 4
+ lea eax, [esi-2]
+ test eax, eax
+ mov [edx], ecx
+ jz short loc_4CB82E
+ add [edi+32F04h], eax
+ mov ecx, [edi+7Ch]
+ push eax
+ mov eax, [edi+80h]
+ push eax
+ call ecx
+ add esp, 8
+
+loc_4CB82E: ; CODE XREF: CEncoder_GetOptimumFast+164j
+ ; CEncoder_GetOptimumFast+23Fj ...
+ pop ebp
+ pop edi
+ mov eax, esi
+ pop esi
+ pop ebx
+ add esp, 28h
+ retn 4
+CEncoder_GetOptimumFast endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CB8A0 proc near ; CODE XREF: sub_4CD940+37p
+
+arg_0 = dword ptr 4
+
+ push edi
+ mov edi, [esp+4+arg_0]
+ test edi, edi
+ jz short loc_4CB8EB
+ mov eax, dword_553598
+ test eax, eax
+ jnz short loc_4CB8DD
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ test eax, eax
+ jz short loc_4CB8D6
+ mov dword ptr [eax], 0
+ mov dword ptr [eax+4], 0
+ mov dword ptr [eax+8], 0
+ jmp short loc_4CB8D8
+; ---------------------------------------------------------------------------
+
+loc_4CB8D6: ; CODE XREF: sub_4CB8A0+1Ej
+ xor eax, eax
+
+loc_4CB8D8: ; CODE XREF: sub_4CB8A0+34j
+ mov dword_553598, eax
+
+loc_4CB8DD: ; CODE XREF: sub_4CB8A0+10j
+ mov eax, [eax]
+ test eax, eax
+ jz short loc_4CB8EB
+ push edi
+ call eax
+ add esp, 4
+ pop edi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CB8EB: ; CODE XREF: sub_4CB8A0+7j
+ ; sub_4CB8A0+41j
+ xor eax, eax
+ pop edi
+ retn
+sub_4CB8A0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CB8F0 proc near ; CODE XREF: sub_4CBA60+85p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ push edi
+ mov edi, [esi+44h]
+ add edi, [esi+40h]
+ add edi, [esp+8+arg_4]
+ cmp dword ptr [esi+4Ch], 0
+ jz short loc_4CB911
+ mov [esi+3Ch], edi
+ pop edi
+ mov eax, 1
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CB911: ; CODE XREF: sub_4CB8F0+14j
+ mov eax, [esi+30h]
+ test eax, eax
+ jz short loc_4CB91D
+ cmp [esi+3Ch], edi
+ jz short loc_4CB93E
+
+loc_4CB91D: ; CODE XREF: sub_4CB8F0+26j
+ push ebx
+ mov ebx, [esp+0Ch+arg_8]
+ push eax
+ mov eax, [ebx+4]
+ call eax
+ mov dword ptr [esi+30h], 0
+ mov [esi+3Ch], edi
+ mov ecx, [ebx]
+ push edi
+ call ecx
+ add esp, 8
+ mov [esi+30h], eax
+ pop ebx
+
+loc_4CB93E: ; CODE XREF: sub_4CB8F0+2Bj
+ xor eax, eax
+ cmp [esi+30h], eax
+ pop edi
+ setnz al
+ pop esi
+ retn
+sub_4CB8F0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CB950: ; DATA XREF: sub_4CCAA0+1Co
+ mov eax, [esp+4]
+ mov eax, [eax]
+ retn
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CB960: ; DATA XREF: sub_4CCAA0+Eo
+ mov eax, [esp+4]
+ mov ecx, [eax]
+ mov edx, [esp+8]
+ mov al, [edx+ecx]
+ retn
+; ---------------------------------------------------------------------------
+ align 10h
+loc_4CB970: ; DATA XREF: sub_4CCAA0+15o
+ mov ecx, [esp+4]
+
+; =============== S U B R O U T I N E =======================================
+
+; Attributes: library function
+
+; public: int __thiscall CRect::Height(void)const
+?Height@CRect@@QBEHXZ proc near
+ mov eax, [ecx+0Ch]
+ sub eax, [ecx+4]
+ retn
+?Height@CRect@@QBEHXZ endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CB980 proc near ; CODE XREF: sub_4CBC80+46p
+ ; sub_4CBD50+61p
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ cmp dword ptr [esi+38h], 0
+ jnz short loc_4CB9F0
+ cmp dword ptr [esi+68h], 0
+ jnz short loc_4CB9F0
+ mov eax, [esi]
+ sub eax, [esi+4]
+ mov ecx, [esi+30h]
+ add eax, [esi+0Ch]
+ sub ecx, eax
+ add ecx, [esi+3Ch]
+ jz short loc_4CB9F0
+ push edi
+
+loc_4CB9A4: ; CODE XREF: sub_4CB980+63j
+ mov edx, [esi+34h]
+ lea edi, [esp+8+arg_0]
+ push edi
+ push ecx
+ push eax
+ mov eax, [edx]
+ push edx
+ call eax
+ add esp, 10h
+ test eax, eax
+ mov [esi+68h], eax
+ jnz short loc_4CB9EF
+ mov eax, [esp+8+arg_0]
+ test eax, eax
+ jz short loc_4CB9E8
+ add [esi+0Ch], eax
+ mov eax, [esi+0Ch]
+ sub eax, [esi+4]
+ cmp eax, [esi+44h]
+ ja short loc_4CB9EF
+ mov eax, [esi]
+ sub eax, [esi+4]
+ mov ecx, [esi+30h]
+ add eax, [esi+0Ch]
+ sub ecx, eax
+ add ecx, [esi+3Ch]
+ jnz short loc_4CB9A4
+ pop edi
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CB9E8: ; CODE XREF: sub_4CB980+43j
+ mov dword ptr [esi+38h], 1
+
+loc_4CB9EF: ; CODE XREF: sub_4CB980+3Bj
+ ; sub_4CB980+51j
+ pop edi
+
+loc_4CB9F0: ; CODE XREF: sub_4CB980+9j
+ ; sub_4CB980+Fj ...
+ pop esi
+ retn
+sub_4CB980 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBA00 proc near ; CODE XREF: sub_4CBD50+58p
+
+arg_0 = dword ptr 4
+
+ push ebx
+ push ebp
+ push esi
+ push edi
+ mov edi, [esp+10h+arg_0]
+ mov esi, [edi+0Ch]
+ mov eax, [edi+40h]
+ sub esi, [edi+4]
+ mov ebx, [edi]
+ mov ebp, [edi+30h]
+ add esi, eax
+ sub ebx, eax
+ mov eax, dword_553598
+ test eax, eax
+ jnz short loc_4CBA44
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ xor ecx, ecx
+ add esp, 4
+ cmp eax, ecx
+ jz short loc_4CBA3D
+ mov [eax], ecx
+ mov [eax+4], ecx
+ mov [eax+8], ecx
+ jmp short loc_4CBA3F
+; ---------------------------------------------------------------------------
+
+loc_4CBA3D: ; CODE XREF: sub_4CBA00+31j
+ xor eax, eax
+
+loc_4CBA3F: ; CODE XREF: sub_4CBA00+3Bj
+ mov dword_553598, eax
+
+loc_4CBA44: ; CODE XREF: sub_4CBA00+21j
+ mov eax, [eax+8]
+ test eax, eax
+ jz short loc_4CBA53
+ push esi
+ push ebx
+ push ebp
+ call eax
+ add esp, 0Ch
+
+loc_4CBA53: ; CODE XREF: sub_4CBA00+49j
+ mov eax, [edi+30h]
+ add eax, [edi+40h]
+ mov [edi], eax
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn
+sub_4CBA00 endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBA60 proc near ; CODE XREF: sub_4D0270+D2p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+arg_10 = dword ptr 14h
+arg_14 = dword ptr 18h
+
+ push ebx
+ push esi
+ push edi
+ mov edi, [esp+0Ch+arg_4]
+ cmp edi, 0C0000000h
+ jbe short loc_4CBAA2
+ mov esi, [esp+0Ch+arg_0]
+ mov eax, [esi+20h]
+ mov edi, [esp+0Ch+arg_14]
+ mov ecx, [edi+4]
+ push eax
+ call ecx
+ xor ebx, ebx
+ add esp, 4
+ cmp [esi+4Ch], ebx
+ mov [esi+20h], ebx
+ jnz short loc_4CBA9C
+ mov edx, [esi+30h]
+ mov eax, [edi+4]
+ push edx
+ call eax
+ add esp, 4
+ mov [esi+30h], ebx
+
+loc_4CBA9C: ; CODE XREF: sub_4CBA60+2Bj
+ pop edi
+ pop esi
+ xor eax, eax
+ pop ebx
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CBAA2: ; CODE XREF: sub_4CBA60+Dj
+ mov eax, edi
+ shr eax, 1
+ cmp edi, 80000000h
+ jbe short loc_4CBAB3
+ mov eax, edi
+ shr eax, 2
+
+loc_4CBAB3: ; CODE XREF: sub_4CBA60+4Cj
+ mov ecx, [esp+0Ch+arg_8]
+ mov esi, [esp+0Ch+arg_0]
+ mov ebx, [esp+0Ch+arg_C]
+ lea edx, [edi+ecx+1]
+ push ebp
+ mov [esi+40h], edx
+ mov edx, [esp+10h+arg_10]
+ add ecx, ebx
+ lea ebp, [ebx+edx]
+ add ecx, edx
+ mov [esi+44h], ebp
+ mov ebp, [esp+10h+arg_14]
+ shr ecx, 1
+ push ebp
+ lea eax, [ecx+eax+80000h]
+ push eax
+ push esi
+ call sub_4CB8F0
+ add esp, 0Ch
+ test eax, eax
+ jz loc_4CBBEA
+ mov edx, [esi+48h]
+ mov [esi+1Ch], ebx
+ xor ebx, ebx
+ cmp edx, 2
+ lea ebp, [edi+1]
+ mov [esi+5Ch], ebx
+ jnz short loc_4CBB0F
+ mov eax, 0FFFFh
+ jmp short loc_4CBB49
+; ---------------------------------------------------------------------------
+
+loc_4CBB0F: ; CODE XREF: sub_4CBA60+A6j
+ lea ecx, [edi-1]
+ mov eax, ecx
+ shr eax, 1
+ or ecx, eax
+ mov eax, ecx
+ shr eax, 2
+ or ecx, eax
+ mov eax, ecx
+ shr eax, 4
+ or ecx, eax
+ mov eax, ecx
+ or eax, 1FFFE00h
+ shr eax, 8
+ or eax, ecx
+ shr eax, 1
+ cmp eax, 1000000h
+ jbe short loc_4CBB49
+ cmp edx, 3
+ jnz short loc_4CBB47
+ mov eax, 0FFFFFFh
+ jmp short loc_4CBB49
+; ---------------------------------------------------------------------------
+
+loc_4CBB47: ; CODE XREF: sub_4CBA60+DEj
+ shr eax, 1
+
+loc_4CBB49: ; CODE XREF: sub_4CBA60+ADj
+ ; sub_4CBA60+D9j ...
+ mov [esi+28h], eax
+ add eax, 1
+ cmp edx, 2
+ jbe short loc_4CBB5B
+ mov dword ptr [esi+5Ch], 400h
+
+loc_4CBB5B: ; CODE XREF: sub_4CBA60+F2j
+ cmp edx, 3
+ jbe short loc_4CBB67
+ add dword ptr [esi+5Ch], 10000h
+
+loc_4CBB67: ; CODE XREF: sub_4CBA60+FEj
+ cmp edx, 4
+ jbe short loc_4CBB73
+ add dword ptr [esi+5Ch], 100000h
+
+loc_4CBB73: ; CODE XREF: sub_4CBA60+10Aj
+ mov ecx, [esi+60h]
+ mov edx, [esi+5Ch]
+ add ecx, [esi+64h]
+ add eax, edx
+ cmp [esi+50h], ebx
+ mov [esi+58h], edi
+ mov [esi+60h], eax
+ mov [esi+18h], ebp
+ lea edx, [ebp+ebp+0]
+ jnz short loc_4CBB92
+ mov edx, ebp
+
+loc_4CBB92: ; CODE XREF: sub_4CBA60+12Ej
+ lea edi, [eax+edx]
+ mov eax, [esi+20h]
+ cmp eax, ebx
+ mov [esi+64h], edx
+ jz short loc_4CBBA3
+ cmp ecx, edi
+ jz short loc_4CBBE0
+
+loc_4CBBA3: ; CODE XREF: sub_4CBA60+13Dj
+ mov ebp, [esp+10h+arg_14]
+ push eax
+ mov eax, [ebp+4]
+ call eax
+ lea eax, ds:0[edi*4]
+ mov ecx, eax
+ shr ecx, 2
+ add esp, 4
+ cmp ecx, edi
+ mov [esi+20h], ebx
+ jz short loc_4CBBC7
+ xor eax, eax
+ jmp short loc_4CBBD0
+; ---------------------------------------------------------------------------
+
+loc_4CBBC7: ; CODE XREF: sub_4CBA60+161j
+ mov edx, [ebp+0]
+ push eax
+ call edx
+ add esp, 4
+
+loc_4CBBD0: ; CODE XREF: sub_4CBA60+165j
+ cmp eax, ebx
+ mov [esi+20h], eax
+ jz short loc_4CBBEC
+ mov ecx, [esi+60h]
+ lea edx, [eax+ecx*4]
+ mov [esi+24h], edx
+
+loc_4CBBE0: ; CODE XREF: sub_4CBA60+141j
+ pop ebp
+ pop edi
+ pop esi
+ mov eax, 1
+ pop ebx
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CBBEA: ; CODE XREF: sub_4CBA60+8Fj
+ xor ebx, ebx
+
+loc_4CBBEC: ; CODE XREF: sub_4CBA60+175j
+ mov eax, [esi+20h]
+ mov ecx, [ebp+4]
+ push eax
+ call ecx
+ add esp, 4
+ cmp [esi+4Ch], ebx
+ mov [esi+20h], ebx
+ jnz short loc_4CBC0F
+ mov edx, [esi+30h]
+ mov eax, [ebp+4]
+ push edx
+ call eax
+ add esp, 4
+ mov [esi+30h], ebx
+
+loc_4CBC0F: ; CODE XREF: sub_4CBA60+19Ej
+ pop ebp
+ pop edi
+ pop esi
+ xor eax, eax
+ pop ebx
+ retn
+sub_4CBA60 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBC20 proc near ; CODE XREF: sub_4CBD50+79p
+
+arg_0 = dword ptr 4
+
+ mov eax, [esp+arg_0]
+ mov edx, [eax+18h]
+ sub edx, [eax+14h]
+ push ebx
+ mov ebx, [eax+4]
+ or ecx, 0FFFFFFFFh
+ sub ecx, ebx
+ cmp edx, ecx
+ push esi
+ jnb short loc_4CBC3A
+ mov ecx, edx
+
+loc_4CBC3A: ; CODE XREF: sub_4CBC20+16j
+ mov esi, [eax+0Ch]
+ sub esi, ebx
+ push edi
+ mov edi, [eax+44h]
+ mov edx, esi
+ cmp edx, edi
+ ja short loc_4CBC54
+ test edx, edx
+ jbe short loc_4CBC56
+ mov edx, 1
+ jmp short loc_4CBC56
+; ---------------------------------------------------------------------------
+
+loc_4CBC54: ; CODE XREF: sub_4CBC20+27j
+ sub edx, edi
+
+loc_4CBC56: ; CODE XREF: sub_4CBC20+2Bj
+ ; sub_4CBC20+32j
+ cmp edx, ecx
+ pop edi
+ jnb short loc_4CBC5D
+ mov ecx, edx
+
+loc_4CBC5D: ; CODE XREF: sub_4CBC20+39j
+ mov edx, [eax+1Ch]
+ cmp esi, edx
+ jbe short loc_4CBC66
+ mov esi, edx
+
+loc_4CBC66: ; CODE XREF: sub_4CBC20+42j
+ add ebx, ecx
+ mov [eax+10h], esi
+ pop esi
+ mov [eax+8], ebx
+ pop ebx
+ retn
+sub_4CBC20 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBC80 proc near ; DATA XREF: sub_4CCAA0+8o
+
+arg_0 = dword ptr 4
+
+ push ebx
+ push esi
+ mov esi, [esp+8+arg_0]
+ xor eax, eax
+ cmp [esi+60h], eax
+ jbe short loc_4CBCA2
+ lea ecx, [ecx+0]
+
+loc_4CBC90: ; CODE XREF: sub_4CBC80+20j
+ mov ecx, [esi+20h]
+ mov dword ptr [ecx+eax*4], 0
+ add eax, 1
+ cmp eax, [esi+60h]
+ jb short loc_4CBC90
+
+loc_4CBCA2: ; CODE XREF: sub_4CBC80+Bj
+ mov eax, [esi+18h]
+ mov edx, [esi+30h]
+ push esi
+ mov dword ptr [esi+14h], 0
+ mov [esi], edx
+ mov [esi+0Ch], eax
+ mov [esi+4], eax
+ mov dword ptr [esi+68h], 0
+ mov dword ptr [esi+38h], 0
+ call sub_4CB980
+ mov eax, [esi+18h]
+ mov ebx, [esi+4]
+ sub eax, [esi+14h]
+ or ecx, 0FFFFFFFFh
+ sub ecx, ebx
+ add esp, 4
+ cmp eax, ecx
+ jnb short loc_4CBCE2
+ mov ecx, eax
+
+loc_4CBCE2: ; CODE XREF: sub_4CBC80+5Ej
+ mov edx, [esi+0Ch]
+ sub edx, ebx
+ push edi
+ mov edi, [esi+44h]
+ mov eax, edx
+ cmp eax, edi
+ ja short loc_4CBCFC
+ test eax, eax
+ jbe short loc_4CBCFE
+ mov eax, 1
+ jmp short loc_4CBCFE
+; ---------------------------------------------------------------------------
+
+loc_4CBCFC: ; CODE XREF: sub_4CBC80+6Fj
+ sub eax, edi
+
+loc_4CBCFE: ; CODE XREF: sub_4CBC80+73j
+ ; sub_4CBC80+7Aj
+ cmp eax, ecx
+ pop edi
+ jnb short loc_4CBD05
+ mov ecx, eax
+
+loc_4CBD05: ; CODE XREF: sub_4CBC80+81j
+ mov eax, edx
+ mov edx, [esi+1Ch]
+ cmp eax, edx
+ jbe short loc_4CBD10
+ mov eax, edx
+
+loc_4CBD10: ; CODE XREF: sub_4CBC80+8Cj
+ add ebx, ecx
+ mov [esi+8], ebx
+ mov [esi+10h], eax
+ pop esi
+ pop ebx
+ retn
+sub_4CBC80 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CBD20 proc near ; CODE XREF: sub_4CBD50+26p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push edi
+ mov edi, [esp+4+arg_8]
+ xor eax, eax
+ test edi, edi
+ jbe short loc_4CBD4C
+ mov edx, [esp+4+arg_4]
+ push esi
+ mov esi, [esp+8+arg_0]
+
+loc_4CBD34: ; CODE XREF: sub_4CBD20+29j
+ mov ecx, [edx+eax*4]
+ cmp ecx, esi
+ ja short loc_4CBD3F
+ xor ecx, ecx
+ jmp short loc_4CBD41
+; ---------------------------------------------------------------------------
+
+loc_4CBD3F: ; CODE XREF: sub_4CBD20+19j
+ sub ecx, esi
+
+loc_4CBD41: ; CODE XREF: sub_4CBD20+1Dj
+ mov [edx+eax*4], ecx
+ add eax, 1
+ cmp eax, edi
+ jb short loc_4CBD34
+ pop esi
+
+loc_4CBD4C: ; CODE XREF: sub_4CBD20+9j
+ pop edi
+ retn
+sub_4CBD20 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBD50 proc near ; CODE XREF: .text:004CC1A1p
+ ; .text:004CC20Ap ...
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ cmp dword ptr [esi+4], 0FFFFFFFFh
+ jnz short loc_4CBD88
+ mov eax, [esi+64h]
+ add eax, [esi+60h]
+ mov ecx, [esi+20h]
+ push edi
+ mov edi, 0FFFFFFFEh
+ sub edi, [esi+58h]
+ push eax
+ push ecx
+ and edi, 0FFFFFC00h
+ push edi
+ call sub_4CBD20
+ sub [esi+8], edi
+ sub [esi+4], edi
+ add esp, 0Ch
+ sub [esi+0Ch], edi
+ pop edi
+
+loc_4CBD88: ; CODE XREF: sub_4CBD50+9j
+ cmp dword ptr [esi+38h], 0
+ jnz short loc_4CBDB9
+ mov edx, [esi+0Ch]
+ sub edx, [esi+4]
+ mov eax, [esi+44h]
+ cmp eax, edx
+ jnz short loc_4CBDB9
+ mov ecx, [esi+3Ch]
+ add ecx, [esi+30h]
+ sub ecx, [esi]
+ cmp ecx, eax
+ ja short loc_4CBDB0
+ push esi
+ call sub_4CBA00
+ add esp, 4
+
+loc_4CBDB0: ; CODE XREF: sub_4CBD50+55j
+ push esi
+ call sub_4CB980
+ add esp, 4
+
+loc_4CBDB9: ; CODE XREF: sub_4CBD50+3Cj
+ ; sub_4CBD50+49j
+ mov edx, [esi+14h]
+ cmp edx, [esi+18h]
+ jnz short loc_4CBDC8
+ mov dword ptr [esi+14h], 0
+
+loc_4CBDC8: ; CODE XREF: sub_4CBD50+6Fj
+ push esi
+ call sub_4CBC20
+ add esp, 4
+ pop esi
+ retn
+sub_4CBD50 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBDE0 proc near ; CODE XREF: sub_4CC5C0+1B7p
+
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+arg_10 = dword ptr 14h
+arg_14 = dword ptr 18h
+arg_18 = dword ptr 1Ch
+arg_1C = dword ptr 20h
+arg_20 = dword ptr 24h
+arg_24 = dword ptr 28h
+
+ push ecx
+ mov edx, [esp+4+arg_4]
+ mov ecx, [esp+4+arg_10]
+ mov eax, [esp+4+arg_14]
+ push ebx
+ mov [ecx+eax*4], edx
+ mov ecx, [esp+8+arg_8]
+ push ebp
+ push esi
+ sub ecx, edx
+ cmp [esp+10h+arg_1C], 0
+ push edi
+ jz loc_4CBEAC
+ mov ebp, [esp+14h+arg_C]
+ mov ebx, [esp+14h+arg_24]
+ jmp short loc_4CBE14
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CBE10: ; CODE XREF: sub_4CBDE0+C6j
+ mov eax, [esp+14h+arg_14]
+
+loc_4CBE14: ; CODE XREF: sub_4CBDE0+2Dj
+ mov esi, [esp+14h+arg_18]
+ sub [esp+14h+arg_1C], 1
+ cmp ecx, esi
+ jnb loc_4CBEAC
+ mov edx, ebp
+ sub edx, ecx
+ cmp eax, ecx
+ sbb edi, edi
+ and edi, esi
+ sub edi, ecx
+ add edi, eax
+ mov eax, [esp+14h+arg_10]
+ mov eax, [eax+edi*4]
+ mov [esp+14h+arg_4], eax
+ mov al, [edx+ebx]
+ cmp al, [ebx+ebp]
+ jnz short loc_4CBE99
+ mov al, [edx]
+ cmp al, [ebp+0]
+ jnz short loc_4CBE99
+ mov eax, [esp+14h+arg_0]
+ mov esi, 1
+ cmp eax, esi
+ jz short loc_4CBE7A
+ sub edx, ebp
+ lea edi, [ebp+1]
+ mov [esp+14h+var_4], edx
+ jmp short loc_4CBE69
+; ---------------------------------------------------------------------------
+
+loc_4CBE65: ; CODE XREF: sub_4CBDE0+98j
+ mov edx, [esp+14h+var_4]
+
+loc_4CBE69: ; CODE XREF: sub_4CBDE0+83j
+ mov dl, [edx+edi]
+ cmp dl, [edi]
+ jnz short loc_4CBE7A
+ add esi, 1
+ add edi, 1
+ cmp esi, eax
+ jnz short loc_4CBE65
+
+loc_4CBE7A: ; CODE XREF: sub_4CBDE0+78j
+ ; sub_4CBDE0+8Ej
+ cmp ebx, esi
+ jnb short loc_4CBE99
+ mov edx, [esp+14h+arg_20]
+ mov [edx], esi
+ add edx, 4
+ add ecx, 0FFFFFFFFh
+ mov [edx], ecx
+ add edx, 4
+ cmp esi, eax
+ mov ebx, esi
+ mov [esp+14h+arg_20], edx
+ jz short loc_4CBEB6
+
+loc_4CBE99: ; CODE XREF: sub_4CBDE0+64j
+ ; sub_4CBDE0+6Bj ...
+ mov ecx, [esp+14h+arg_8]
+ sub ecx, [esp+14h+arg_4]
+ cmp [esp+14h+arg_1C], 0
+ jnz loc_4CBE10
+
+loc_4CBEAC: ; CODE XREF: sub_4CBDE0+1Fj
+ ; sub_4CBDE0+3Fj
+ mov eax, [esp+14h+arg_20]
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CBEB6: ; CODE XREF: sub_4CBDE0+B7j
+ pop edi
+ pop esi
+ pop ebp
+ mov eax, edx
+ pop ebx
+ pop ecx
+ retn
+sub_4CBDE0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CBEC0 proc near ; CODE XREF: .text:004CC1E7p
+ ; sub_4CC220+14Ep ...
+
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+arg_10 = dword ptr 14h
+arg_14 = dword ptr 18h
+arg_18 = dword ptr 1Ch
+arg_1C = dword ptr 20h
+arg_20 = dword ptr 24h
+arg_24 = dword ptr 28h
+
+ sub esp, 10h
+ mov eax, [esp+10h+arg_10]
+ mov edx, [esp+10h+arg_8]
+ sub edx, [esp+10h+arg_4]
+ push ebx
+ push ebp
+ push esi
+ push edi
+ mov edi, [esp+20h+arg_14]
+ lea eax, [eax+edi*8]
+ lea ecx, [eax+4]
+ mov [esp+20h+var_C], ecx
+ xor ecx, ecx
+ xor ebx, ebx
+ cmp [esp+20h+arg_1C], ecx
+ mov ebp, eax
+ mov [esp+20h+var_10], ebp
+ mov [esp+20h+var_8], ecx
+ mov [esp+20h+var_4], ebx
+ jnz short loc_4CBF24
+
+loc_4CBEF9: ; CODE XREF: sub_4CBEC0+6Fj
+ ; sub_4CBEC0+151j
+ mov edx, [esp+20h+var_C]
+ mov eax, [esp+20h+arg_20]
+ pop edi
+ pop esi
+ mov dword ptr [ebp+0], 0
+ pop ebp
+ mov dword ptr [edx], 0
+ pop ebx
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+ jmp short loc_4CBF20
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CBF20: ; CODE XREF: sub_4CBEC0+56j
+ ; sub_4CBEC0+14Bj
+ mov edi, [esp+20h+arg_14]
+
+loc_4CBF24: ; CODE XREF: sub_4CBEC0+37j
+ mov eax, [esp+20h+arg_18]
+ sub [esp+20h+arg_1C], 1
+ cmp edx, eax
+ jnb short loc_4CBEF9
+ cmp edi, edx
+ sbb esi, esi
+ and esi, eax
+ mov eax, [esp+20h+arg_10]
+ sub esi, edx
+ add esi, edi
+ lea eax, [eax+esi*8]
+ mov esi, [esp+20h+arg_C]
+ sub esi, edx
+ cmp ecx, ebx
+ jb short loc_4CBF4E
+ mov ecx, ebx
+
+loc_4CBF4E: ; CODE XREF: sub_4CBEC0+8Aj
+ mov bl, [ecx+esi]
+ mov edi, [esp+20h+arg_C]
+ cmp bl, [ecx+edi]
+ jnz short loc_4CBFB8
+ add ecx, 1
+ cmp ecx, [esp+20h+arg_0]
+ jz short loc_4CBF93
+ mov bl, [ecx+esi]
+ cmp bl, [ecx+edi]
+ jnz short loc_4CBF93
+ add ecx, 1
+ cmp ecx, [esp+20h+arg_0]
+ jz short loc_4CBF93
+ mov ebx, edi
+ mov ebp, esi
+ lea edi, [ecx+ebx]
+ sub ebp, ebx
+ lea ecx, [ecx+0]
+
+loc_4CBF80: ; CODE XREF: sub_4CBEC0+D1j
+ mov bl, [edi+ebp]
+ cmp bl, [edi]
+ jnz short loc_4CBF93
+ add ecx, 1
+ add edi, 1
+ cmp ecx, [esp+20h+arg_0]
+ jnz short loc_4CBF80
+
+loc_4CBF93: ; CODE XREF: sub_4CBEC0+A1j
+ ; sub_4CBEC0+A9j ...
+ cmp [esp+20h+arg_24], ecx
+ jnb short loc_4CBFB8
+ mov edi, [esp+20h+arg_20]
+ mov [edi], ecx
+ add edi, 4
+ add edx, 0FFFFFFFFh
+ mov [edi], edx
+ add edi, 4
+ cmp ecx, [esp+20h+arg_0]
+ mov [esp+20h+arg_24], ecx
+ mov [esp+20h+arg_20], edi
+ jz short loc_4CC016
+
+loc_4CBFB8: ; CODE XREF: sub_4CBEC0+98j
+ ; sub_4CBEC0+D7j
+ mov dl, [ecx+esi]
+ mov esi, [esp+20h+arg_C]
+ cmp dl, [ecx+esi]
+ mov edx, [esp+20h+arg_4]
+ jnb short loc_4CBFE4
+ mov esi, [esp+20h+var_10]
+ lea ebp, [eax+4]
+ mov ebx, ecx
+ mov ecx, [esp+20h+var_8]
+ mov [esi], edx
+ mov eax, [ebp+0]
+ mov [esp+20h+var_10], ebp
+ mov [esp+20h+var_4], ebx
+ jmp short loc_4CBFFC
+; ---------------------------------------------------------------------------
+
+loc_4CBFE4: ; CODE XREF: sub_4CBEC0+106j
+ mov esi, [esp+20h+var_C]
+ mov ebp, [esp+20h+var_10]
+ mov ebx, [esp+20h+var_4]
+ mov [esi], edx
+ mov [esp+20h+var_C], eax
+ mov eax, [eax]
+ mov [esp+20h+var_8], ecx
+
+loc_4CBFFC: ; CODE XREF: sub_4CBEC0+122j
+ mov edx, [esp+20h+arg_8]
+ sub edx, eax
+ cmp [esp+20h+arg_1C], 0
+ mov [esp+20h+arg_4], eax
+ jnz loc_4CBF20
+ jmp loc_4CBEF9
+; ---------------------------------------------------------------------------
+
+loc_4CC016: ; CODE XREF: sub_4CBEC0+F6j
+ mov ecx, [eax]
+ mov edx, [esp+20h+var_10]
+ mov [edx], ecx
+ mov eax, [eax+4]
+ mov ecx, [esp+20h+var_C]
+ mov [ecx], eax
+ mov eax, edi
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ add esp, 10h
+ retn
+sub_4CBEC0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CC040 proc near ; CODE XREF: sub_4CC220+F8p
+ ; sub_4CC3B0+173p ...
+
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+arg_10 = dword ptr 14h
+arg_14 = dword ptr 18h
+arg_18 = dword ptr 1Ch
+arg_1C = dword ptr 20h
+
+ sub esp, 10h
+ mov eax, [esp+10h+arg_10]
+ mov edx, [esp+10h+arg_4]
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+1Ch+arg_14]
+ lea eax, [eax+esi*8]
+ lea ecx, [eax+4]
+ push edi
+ mov edi, eax
+ mov eax, [esp+20h+arg_8]
+ xor ebx, ebx
+ xor ebp, ebp
+ sub eax, edx
+ cmp [esp+20h+arg_1C], ebx
+ mov [esp+20h+var_C], ecx
+ mov [esp+20h+var_10], edi
+ mov [esp+20h+var_8], ebx
+ mov [esp+20h+var_4], ebp
+ jz loc_4CC159
+ nop
+
+loc_4CC080: ; CODE XREF: sub_4CC040+114j
+ sub [esp+20h+arg_1C], 1
+ cmp eax, [esp+20h+arg_18]
+ jnb loc_4CC159
+ cmp esi, eax
+ sbb ecx, ecx
+ and ecx, [esp+20h+arg_18]
+ sub ecx, eax
+ add ecx, esi
+ mov esi, [esp+20h+arg_10]
+ lea edi, [esi+ecx*8]
+ mov ecx, [esp+20h+arg_C]
+ sub ecx, eax
+ cmp ebx, ebp
+ mov eax, ebx
+ jb short loc_4CC0B0
+ mov eax, ebp
+
+loc_4CC0B0: ; CODE XREF: sub_4CC040+6Cj
+ mov bl, [eax+ecx]
+ mov esi, [esp+20h+arg_C]
+ cmp bl, [eax+esi]
+ jnz short loc_4CC102
+ add eax, 1
+ cmp eax, [esp+20h+arg_0]
+ jz short loc_4CC0E3
+ mov ebx, esi
+ mov ebp, ecx
+ lea esi, [eax+ebx]
+ sub ebp, ebx
+ mov edi, edi
+
+loc_4CC0D0: ; CODE XREF: sub_4CC040+A1j
+ mov bl, [esi+ebp]
+ cmp bl, [esi]
+ jnz short loc_4CC0FC
+ add eax, 1
+ add esi, 1
+ cmp eax, [esp+20h+arg_0]
+ jnz short loc_4CC0D0
+
+loc_4CC0E3: ; CODE XREF: sub_4CC040+83j
+ ; sub_4CC040+C0j
+ mov edx, [edi]
+ mov eax, [esp+20h+var_10]
+ mov [eax], edx
+ mov ecx, [edi+4]
+ mov edx, [esp+20h+var_C]
+ pop edi
+ pop esi
+ pop ebp
+ mov [edx], ecx
+ pop ebx
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC0FC: ; CODE XREF: sub_4CC040+95j
+ cmp eax, [esp+20h+arg_0]
+ jz short loc_4CC0E3
+
+loc_4CC102: ; CODE XREF: sub_4CC040+7Aj
+ mov cl, [eax+ecx]
+ mov esi, [esp+20h+arg_C]
+ cmp cl, [eax+esi]
+ jnb short loc_4CC129
+ mov ecx, [esp+20h+var_10]
+ mov ebx, [esp+20h+var_8]
+ add edi, 4
+ mov ebp, eax
+ mov [ecx], edx
+ mov edx, [edi]
+ mov [esp+20h+var_10], edi
+ mov [esp+20h+var_4], ebp
+ jmp short loc_4CC143
+; ---------------------------------------------------------------------------
+
+loc_4CC129: ; CODE XREF: sub_4CC040+CCj
+ mov ecx, [esp+20h+var_C]
+ mov ebp, [esp+20h+var_4]
+ mov [ecx], edx
+ mov edx, [edi]
+ mov ebx, eax
+ mov [esp+20h+var_C], edi
+ mov edi, [esp+20h+var_10]
+ mov [esp+20h+var_8], ebx
+
+loc_4CC143: ; CODE XREF: sub_4CC040+E7j
+ mov eax, [esp+20h+arg_8]
+ sub eax, edx
+ cmp [esp+20h+arg_1C], 0
+ jz short loc_4CC159
+ mov esi, [esp+20h+arg_14]
+ jmp loc_4CC080
+; ---------------------------------------------------------------------------
+
+loc_4CC159: ; CODE XREF: sub_4CC040+39j
+ ; sub_4CC040+49j ...
+ mov eax, [esp+20h+var_C]
+ mov dword ptr [edi], 0
+ pop edi
+ pop esi
+ pop ebp
+ mov dword ptr [eax], 0
+ pop ebx
+ add esp, 10h
+ retn
+sub_4CC040 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CC180: ; DATA XREF: sub_4CCAA0+40o
+ push esi
+ mov esi, [esp+8]
+ mov edx, [esi+10h]
+ cmp edx, 2
+ jnb short loc_4CC1AD
+ add dword ptr [esi+4], 1
+ mov eax, [esi+4]
+ add dword ptr [esi+14h], 1
+ add dword ptr [esi], 1
+ cmp eax, [esi+8]
+ jnz short loc_4CC1A9
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC1A9: ; CODE XREF: .text:004CC19Ej
+ xor eax, eax
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC1AD: ; CODE XREF: .text:004CC18Bj
+ mov eax, [esi]
+ xor ecx, ecx
+ mov ch, [eax+1]
+ push ebx
+ mov ebx, [esp+10h]
+ push edi
+ mov edi, [esi+4]
+ push 1
+ push ebx
+ mov cl, [eax]
+ mov eax, ecx
+ mov ecx, [esi+20h]
+ lea eax, [ecx+eax*4]
+ mov ecx, [eax]
+ mov [eax], edi
+ mov eax, [esi+2Ch]
+ push eax
+ mov eax, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push eax
+ mov eax, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push eax
+ mov eax, [esi+4]
+ push eax
+ push ecx
+ push edx
+ call sub_4CBEC0
+ add dword ptr [esi+4], 1
+ add dword ptr [esi+14h], 1
+ add dword ptr [esi], 1
+ mov edi, eax
+ mov eax, [esi+4]
+ sub edi, ebx
+ add esp, 28h
+ sar edi, 2
+ cmp eax, [esi+8]
+ jnz short loc_4CC212
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC212: ; CODE XREF: .text:004CC207j
+ mov eax, edi
+ pop edi
+ pop ebx
+ pop esi
+ retn
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC220 proc near ; DATA XREF: sub_4CCAA0+54o
+
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ sub esp, 8
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ mov eax, [esi+10h]
+ cmp eax, 3
+ mov [esp+0Ch+arg_0], eax
+ jnb short loc_4CC259
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ cmp eax, [esi+8]
+ jnz short loc_4CC252
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC252: ; CODE XREF: sub_4CC220+27j
+ xor eax, eax
+ pop esi
+ add esp, 8
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC259: ; CODE XREF: sub_4CC220+12j
+ push ebx
+ mov ebx, [esi+20h]
+ push ebp
+ xor edx, edx
+ push edi
+ mov edi, [esi]
+ mov dh, [edi+2]
+ movzx ecx, byte ptr [edi]
+ movzx eax, byte ptr [edi+1]
+ xor eax, dword_553198[ecx*4]
+ xor edx, eax
+ and edx, [esi+28h]
+ mov ecx, eax
+ mov ebp, [ebx+edx*4+1000h]
+ mov eax, [esi+4]
+ and ecx, 3FFh
+ sub eax, [ebx+ecx*4]
+ mov [esp+18h+var_8], ebp
+ mov ebp, [esi+4]
+ mov [ebx+edx*4+1000h], ebp
+ mov ebx, [esi+20h]
+ mov edx, [ebx+edx*4+1000h]
+ mov [ebx+ecx*4], edx
+ mov ebx, [esp+18h+arg_4]
+ xor ebp, ebp
+ cmp eax, [esi+18h]
+ mov ecx, 2
+ jnb loc_4CC348
+ mov edx, edi
+ sub edx, eax
+ mov [esp+18h+var_4], edx
+ mov dl, [edx]
+ cmp dl, [edi]
+ jnz short loc_4CC348
+ mov edx, [esp+18h+arg_0]
+ cmp edx, ecx
+ jz short loc_4CC2EA
+
+loc_4CC2D3: ; CODE XREF: sub_4CC220+C4j
+ mov ebx, [esp+18h+var_4]
+ mov bl, [ebx+ecx]
+ cmp bl, [ecx+edi]
+ jnz short loc_4CC2E6
+ add ecx, 1
+ cmp ecx, edx
+ jnz short loc_4CC2D3
+
+loc_4CC2E6: ; CODE XREF: sub_4CC220+BDj
+ mov ebx, [esp+18h+arg_4]
+
+loc_4CC2EA: ; CODE XREF: sub_4CC220+B1j
+ add eax, 0FFFFFFFFh
+ cmp ecx, edx
+ mov [ebx], ecx
+ mov [ebx+4], eax
+ mov ebp, 2
+ jnz short loc_4CC34C
+ mov eax, [esi+2Ch]
+ mov ecx, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push ecx
+ mov ecx, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push ecx
+ mov ecx, [esi+4]
+ push eax
+ mov eax, [esp+2Ch+var_8]
+ push ecx
+ push eax
+ push edx
+ call sub_4CC040
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ add esp, 20h
+ cmp eax, [esi+8]
+ jnz short loc_4CC33E
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC33E: ; CODE XREF: sub_4CC220+113j
+ pop edi
+ mov eax, ebp
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 8
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC348: ; CODE XREF: sub_4CC220+97j
+ ; sub_4CC220+A9j
+ mov edx, [esp+18h+arg_0]
+
+loc_4CC34C: ; CODE XREF: sub_4CC220+D9j
+ mov eax, [esi+2Ch]
+ push ecx
+ lea ecx, [ebx+ebp*4]
+ push ecx
+ mov ecx, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push ecx
+ mov ecx, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push ecx
+ mov ecx, [esi+4]
+ push eax
+ mov eax, [esp+34h+var_8]
+ push ecx
+ push eax
+ push edx
+ call sub_4CBEC0
+ mov edi, eax
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ sub edi, ebx
+ add esp, 28h
+ sar edi, 2
+ cmp eax, [esi+8]
+ jnz short loc_4CC39B
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC39B: ; CODE XREF: sub_4CC220+170j
+ mov eax, edi
+ pop edi
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 8
+ retn
+sub_4CC220 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC3B0 proc near ; DATA XREF: sub_4CCAA0:loc_4CCB03o
+
+var_10 = dword ptr -10h
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ sub esp, 10h
+ push esi
+ mov esi, [esp+14h+arg_0]
+ mov eax, [esi+10h]
+ cmp eax, 4
+ mov [esp+14h+arg_0], eax
+ jnb short loc_4CC3E9
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ cmp eax, [esi+8]
+ jnz short loc_4CC3E2
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC3E2: ; CODE XREF: sub_4CC3B0+27j
+ xor eax, eax
+ pop esi
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC3E9: ; CODE XREF: sub_4CC3B0+12j
+ push ebx
+ push ebp
+ push edi
+ mov edi, [esi]
+ movzx eax, byte ptr [edi]
+ movzx edx, byte ptr [edi+1]
+ xor edx, dword_553198[eax*4]
+ movzx eax, byte ptr [edi+2]
+ movzx ebp, byte ptr [edi+3]
+ mov ecx, eax
+ add eax, eax
+ add eax, eax
+ add eax, eax
+ xor eax, dword_553198[ebp*4]
+ mov ebp, [esi+4]
+ shl eax, 5
+ shl ecx, 8
+ xor eax, edx
+ and eax, [esi+28h]
+ xor ecx, edx
+ mov ebx, edx
+ mov edx, [esi+20h]
+ and ebx, 3FFh
+ sub ebp, [edx+ebx*4]
+ and ecx, 0FFFFh
+ mov [esp+20h+var_4], ebp
+ mov ebp, [esi+4]
+ sub ebp, [edx+ecx*4+1000h]
+ mov [esp+20h+var_10], ebp
+ mov ebp, [edx+eax*4+41000h]
+ mov [esp+20h+var_8], ebp
+ mov ebp, [esi+4]
+ mov [edx+eax*4+41000h], ebp
+ mov edx, [esi+20h]
+ mov eax, [edx+eax*4+41000h]
+ mov [edx+ecx*4+1000h], eax
+ mov eax, [esi+20h]
+ mov ecx, [eax+ecx*4+1000h]
+ mov [eax+ebx*4], ecx
+ mov ecx, [esp+20h+var_4]
+ mov ebx, [esp+20h+arg_4]
+ xor ebp, ebp
+ cmp ecx, [esi+18h]
+ mov eax, 1
+ jnb short loc_4CC4A9
+ mov edx, edi
+ sub edx, ecx
+ mov dl, [edx]
+ cmp dl, [edi]
+ jnz short loc_4CC4A9
+ mov eax, 2
+ lea edx, [ecx-1]
+ mov [ebx], eax
+ mov [ebx+4], edx
+ mov ebp, eax
+
+loc_4CC4A9: ; CODE XREF: sub_4CC3B0+DEj
+ ; sub_4CC3B0+E8j
+ mov edx, [esp+20h+var_10]
+ cmp ecx, edx
+ jz short loc_4CC4D5
+ cmp edx, [esi+18h]
+ jnb short loc_4CC4D5
+ mov edx, edi
+ sub edx, [esp+20h+var_10]
+ mov dl, [edx]
+ cmp dl, [edi]
+ jnz short loc_4CC4D5
+ mov ecx, [esp+20h+var_10]
+ lea edx, [ecx-1]
+ mov [ebx+ebp*4+4], edx
+ mov eax, 3
+ add ebp, 2
+
+loc_4CC4D5: ; CODE XREF: sub_4CC3B0+FFj
+ ; sub_4CC3B0+104j ...
+ test ebp, ebp
+ mov edx, [esp+20h+arg_0]
+ jz short loc_4CC553
+ cmp eax, edx
+ jz short loc_4CC4FE
+ mov edx, eax
+ sub edx, ecx
+ add edx, edi
+
+loc_4CC4E7: ; CODE XREF: sub_4CC3B0+148j
+ mov cl, [edx]
+ cmp cl, [eax+edi]
+ jnz short loc_4CC4FA
+ add eax, 1
+ add edx, 1
+ cmp eax, [esp+20h+arg_0]
+ jnz short loc_4CC4E7
+
+loc_4CC4FA: ; CODE XREF: sub_4CC3B0+13Cj
+ mov edx, [esp+20h+arg_0]
+
+loc_4CC4FE: ; CODE XREF: sub_4CC3B0+12Fj
+ cmp eax, edx
+ mov [ebx+ebp*4-8], eax
+ jnz short loc_4CC553
+ mov eax, [esi+2Ch]
+ mov ecx, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push ecx
+ mov ecx, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push ecx
+ mov ecx, [esi+4]
+ push eax
+ mov eax, [esp+34h+var_8]
+ push ecx
+ push eax
+ push edx
+ call sub_4CC040
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ add esp, 20h
+ cmp eax, [esi+8]
+ jnz short loc_4CC549
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC549: ; CODE XREF: sub_4CC3B0+18Ej
+ pop edi
+ mov eax, ebp
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC553: ; CODE XREF: sub_4CC3B0+12Bj
+ ; sub_4CC3B0+154j
+ cmp eax, 3
+ jnb short loc_4CC55D
+ mov eax, 3
+
+loc_4CC55D: ; CODE XREF: sub_4CC3B0+1A6j
+ push eax
+ mov eax, [esi+2Ch]
+ lea ecx, [ebx+ebp*4]
+ push ecx
+ mov ecx, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push ecx
+ mov ecx, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push ecx
+ mov ecx, [esi+4]
+ push eax
+ mov eax, [esp+3Ch+var_8]
+ push ecx
+ push eax
+ push edx
+ call sub_4CBEC0
+ mov edi, eax
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ sub edi, ebx
+ add esp, 28h
+ sar edi, 2
+ cmp eax, [esi+8]
+ jnz short loc_4CC5AC
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC5AC: ; CODE XREF: sub_4CC3B0+1F1j
+ mov eax, edi
+ pop edi
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 10h
+ retn
+sub_4CC3B0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC5C0 proc near ; DATA XREF: sub_4CCAA0+29o
+
+var_10 = dword ptr -10h
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ sub esp, 10h
+ push esi
+ mov esi, [esp+14h+arg_0]
+ mov eax, [esi+10h]
+ cmp eax, 4
+ mov [esp+14h+arg_0], eax
+ jnb short loc_4CC5F9
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ cmp eax, [esi+8]
+ jnz short loc_4CC5F2
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC5F2: ; CODE XREF: sub_4CC5C0+27j
+ xor eax, eax
+ pop esi
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC5F9: ; CODE XREF: sub_4CC5C0+12j
+ push ebx
+ push ebp
+ push edi
+ mov edi, [esi]
+ movzx eax, byte ptr [edi]
+ movzx edx, byte ptr [edi+1]
+ xor edx, dword_553198[eax*4]
+ movzx eax, byte ptr [edi+2]
+ movzx ebp, byte ptr [edi+3]
+ mov ecx, eax
+ add eax, eax
+ add eax, eax
+ add eax, eax
+ xor eax, dword_553198[ebp*4]
+ mov ebp, [esi+4]
+ shl eax, 5
+ shl ecx, 8
+ xor eax, edx
+ and eax, [esi+28h]
+ xor ecx, edx
+ mov ebx, edx
+ mov edx, [esi+20h]
+ and ebx, 3FFh
+ sub ebp, [edx+ebx*4]
+ and ecx, 0FFFFh
+ mov [esp+20h+var_4], ebp
+ mov ebp, [esi+4]
+ sub ebp, [edx+ecx*4+1000h]
+ mov [esp+20h+var_10], ebp
+ mov ebp, [edx+eax*4+41000h]
+ mov [esp+20h+var_8], ebp
+ mov ebp, [esi+4]
+ mov [edx+eax*4+41000h], ebp
+ mov edx, [esi+20h]
+ mov eax, [edx+eax*4+41000h]
+ mov [edx+ecx*4+1000h], eax
+ mov eax, [esi+20h]
+ mov ecx, [eax+ecx*4+1000h]
+ mov [eax+ebx*4], ecx
+ mov ecx, [esp+20h+var_4]
+ mov ebx, [esp+20h+arg_4]
+ xor ebp, ebp
+ cmp ecx, [esi+18h]
+ mov eax, 1
+ jnb short loc_4CC6B9
+ mov edx, edi
+ sub edx, ecx
+ mov dl, [edx]
+ cmp dl, [edi]
+ jnz short loc_4CC6B9
+ mov eax, 2
+ lea edx, [ecx-1]
+ mov [ebx], eax
+ mov [ebx+4], edx
+ mov ebp, eax
+
+loc_4CC6B9: ; CODE XREF: sub_4CC5C0+DEj
+ ; sub_4CC5C0+E8j
+ mov edx, [esp+20h+var_10]
+ cmp ecx, edx
+ jz short loc_4CC6E5
+ cmp edx, [esi+18h]
+ jnb short loc_4CC6E5
+ mov edx, edi
+ sub edx, [esp+20h+var_10]
+ mov dl, [edx]
+ cmp dl, [edi]
+ jnz short loc_4CC6E5
+ mov ecx, [esp+20h+var_10]
+ lea edx, [ecx-1]
+ mov [ebx+ebp*4+4], edx
+ mov eax, 3
+ add ebp, 2
+
+loc_4CC6E5: ; CODE XREF: sub_4CC5C0+FFj
+ ; sub_4CC5C0+104j ...
+ test ebp, ebp
+ jz short loc_4CC747
+ cmp eax, [esp+20h+arg_0]
+ jz short loc_4CC708
+ mov edx, eax
+ sub edx, ecx
+ add edx, edi
+
+loc_4CC6F5: ; CODE XREF: sub_4CC5C0+146j
+ mov cl, [edx]
+ cmp cl, [eax+edi]
+ jnz short loc_4CC708
+ add eax, 1
+ add edx, 1
+ cmp eax, [esp+20h+arg_0]
+ jnz short loc_4CC6F5
+
+loc_4CC708: ; CODE XREF: sub_4CC5C0+12Dj
+ ; sub_4CC5C0+13Aj
+ cmp eax, [esp+20h+arg_0]
+ mov [ebx+ebp*4-8], eax
+ jnz short loc_4CC747
+ mov edx, [esi+14h]
+ mov eax, [esi+24h]
+ mov ecx, [esp+20h+var_8]
+ mov [eax+edx*4], ecx
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ cmp eax, [esi+8]
+ jnz short loc_4CC73D
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC73D: ; CODE XREF: sub_4CC5C0+172j
+ pop edi
+ mov eax, ebp
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 10h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CC747: ; CODE XREF: sub_4CC5C0+127j
+ ; sub_4CC5C0+150j
+ cmp eax, 3
+ jnb short loc_4CC751
+ mov eax, 3
+
+loc_4CC751: ; CODE XREF: sub_4CC5C0+18Aj
+ mov ecx, [esi+18h]
+ push eax
+ mov eax, [esi+2Ch]
+ lea edx, [ebx+ebp*4]
+ push edx
+ mov edx, [esi+14h]
+ push eax
+ mov eax, [esi+24h]
+ push ecx
+ mov ecx, [esi]
+ push edx
+ mov edx, [esi+4]
+ push eax
+ mov eax, [esp+38h+var_8]
+ push ecx
+ mov ecx, [esp+3Ch+arg_0]
+ push edx
+ push eax
+ push ecx
+ call sub_4CBDE0
+ mov edi, eax
+ mov eax, 1
+ add [esi+14h], eax
+ add [esi], eax
+ add [esi+4], eax
+ mov eax, [esi+4]
+ sub edi, ebx
+ add esp, 28h
+ sar edi, 2
+ cmp eax, [esi+8]
+ jnz short loc_4CC7A4
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC7A4: ; CODE XREF: sub_4CC5C0+1D9j
+ mov eax, edi
+ pop edi
+ pop ebp
+ pop ebx
+ pop esi
+ add esp, 10h
+ retn
+sub_4CC5C0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC7B0 proc near ; DATA XREF: sub_4CCAA0+47o
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ mov ebp, [esp+8+arg_4]
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov edi, 1
+
+loc_4CC7C1: ; CODE XREF: sub_4CC7B0+6Dj
+ mov edx, [esi+10h]
+ cmp edx, 2
+ jb short loc_4CC802
+ mov eax, [esi]
+ mov ebx, [esi+4]
+ xor ecx, ecx
+ mov ch, [eax+1]
+ mov cl, [eax]
+ mov eax, ecx
+ mov ecx, [esi+20h]
+ lea eax, [ecx+eax*4]
+ mov ecx, [eax]
+ mov [eax], ebx
+ mov eax, [esi+2Ch]
+ push eax
+ mov eax, [esi+18h]
+ push eax
+ mov eax, [esi+14h]
+ push eax
+ mov eax, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push eax
+ mov eax, [esi+4]
+ push eax
+ push ecx
+ push edx
+ call sub_4CC040
+ add esp, 20h
+
+loc_4CC802: ; CODE XREF: sub_4CC7B0+17j
+ add [esi+4], edi
+ mov eax, [esi+4]
+ add [esi+14h], edi
+ add [esi], edi
+ cmp eax, [esi+8]
+ jnz short loc_4CC81B
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC81B: ; CODE XREF: sub_4CC7B0+60j
+ sub ebp, edi
+ jnz short loc_4CC7C1
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn
+sub_4CC7B0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC830 proc near ; DATA XREF: sub_4CCAA0+5Bo
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov edi, 1
+ lea ecx, [ecx+0]
+
+loc_4CC840: ; CODE XREF: sub_4CC830+9Fj
+ mov ebp, [esi+10h]
+ cmp ebp, 3
+ jb short loc_4CC8B2
+ mov ecx, [esi]
+ movzx edx, byte ptr [ecx]
+ movzx eax, byte ptr [ecx+1]
+ xor eax, dword_553198[edx*4]
+ mov ebx, [esi+4]
+ xor edx, edx
+ mov dh, [ecx+2]
+ xor edx, eax
+ and edx, [esi+28h]
+ and eax, 3FFh
+ mov ecx, edx
+ mov edx, [esi+20h]
+ mov edi, [edx+ecx*4+1000h]
+ lea edx, [edx+ecx*4+1000h]
+ mov [edx], ebx
+ mov edx, [esi+20h]
+ mov ecx, [edx+ecx*4+1000h]
+ mov [edx+eax*4], ecx
+ mov edx, [esi+2Ch]
+ mov eax, [esi+18h]
+ mov ecx, [esi+14h]
+ push edx
+ mov edx, [esi+24h]
+ push eax
+ mov eax, [esi]
+ push ecx
+ mov ecx, [esi+4]
+ push edx
+ push eax
+ push ecx
+ push edi
+ push ebp
+ call sub_4CC040
+ add esp, 20h
+ mov edi, 1
+
+loc_4CC8B2: ; CODE XREF: sub_4CC830+16j
+ add [esi+4], edi
+ mov eax, [esi+4]
+ add [esi+14h], edi
+ add [esi], edi
+ cmp eax, [esi+8]
+ jnz short loc_4CC8CB
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC8CB: ; CODE XREF: sub_4CC830+90j
+ sub [esp+10h+arg_4], edi
+ jnz loc_4CC840
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn
+sub_4CC830 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC8E0 proc near ; DATA XREF: sub_4CCAA0+6Ao
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov edi, 1
+ lea ecx, [ecx+0]
+
+loc_4CC8F0: ; CODE XREF: sub_4CC8E0+D6j
+ mov eax, [esi+10h]
+ cmp eax, 4
+ mov [esp+10h+arg_0], eax
+ jb loc_4CC999
+ mov eax, [esi]
+ movzx edi, byte ptr [eax+2]
+ movzx edx, byte ptr [eax]
+ movzx ebx, byte ptr [eax+3]
+ movzx ecx, byte ptr [eax+1]
+ xor ecx, dword_553198[edx*4]
+ mov ebp, [esi+4]
+ lea eax, ds:0[edi*8]
+ xor eax, dword_553198[ebx*4]
+ mov edx, edi
+ mov edi, [esi+20h]
+ shl eax, 5
+ xor eax, ecx
+ and eax, [esi+28h]
+ shl edx, 8
+ mov ebx, [edi+eax*4+41000h]
+ xor edx, ecx
+ and edx, 0FFFFh
+ mov [edi+edx*4+1000h], ebp
+ mov edi, [esi+20h]
+ mov edx, [edi+edx*4+1000h]
+ and ecx, 3FFh
+ mov [edi+ecx*4], edx
+ mov ecx, [esi+20h]
+ mov edx, [esi+4]
+ mov [ecx+eax*4+41000h], edx
+ mov eax, [esi+2Ch]
+ mov ecx, [esi+18h]
+ mov edx, [esi+14h]
+ push eax
+ mov eax, [esi+24h]
+ push ecx
+ mov ecx, [esi]
+ push edx
+ mov edx, [esi+4]
+ push eax
+ mov eax, [esp+20h+arg_0]
+ push ecx
+ push edx
+ push ebx
+ push eax
+ call sub_4CC040
+ add esp, 20h
+ mov edi, 1
+
+loc_4CC999: ; CODE XREF: sub_4CC8E0+1Aj
+ add [esi+4], edi
+ mov eax, [esi+4]
+ add [esi+14h], edi
+ add [esi], edi
+ cmp eax, [esi+8]
+ jnz short loc_4CC9B2
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CC9B2: ; CODE XREF: sub_4CC8E0+C7j
+ sub [esp+10h+arg_4], edi
+ jnz loc_4CC8F0
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn
+sub_4CC8E0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CC9D0 proc near ; DATA XREF: sub_4CCAA0+30o
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov edi, 1
+ lea ecx, [ecx+0]
+
+loc_4CC9E0: ; CODE XREF: sub_4CC9D0+BAj
+ cmp dword ptr [esi+10h], 4
+ jb loc_4CCA6D
+ mov eax, [esi]
+ movzx edi, byte ptr [eax+2]
+ movzx edx, byte ptr [eax]
+ movzx ebx, byte ptr [eax+3]
+ movzx ecx, byte ptr [eax+1]
+ xor ecx, dword_553198[edx*4]
+ mov ebp, [esi+4]
+ lea eax, ds:0[edi*8]
+ xor eax, dword_553198[ebx*4]
+ mov edx, edi
+ mov edi, [esi+20h]
+ shl eax, 5
+ xor eax, ecx
+ and eax, [esi+28h]
+ mov ebx, [edi+eax*4+41000h]
+ lea edi, [edi+eax*4+41000h]
+ mov [edi], ebp
+ mov edi, [esi+20h]
+ mov eax, [edi+eax*4+41000h]
+ shl edx, 8
+ xor edx, ecx
+ and edx, 0FFFFh
+ mov [edi+edx*4+1000h], eax
+ mov eax, [esi+20h]
+ mov edx, [eax+edx*4+1000h]
+ and ecx, 3FFh
+ mov [eax+ecx*4], edx
+ mov eax, [esi+14h]
+ mov ecx, [esi+24h]
+ mov [ecx+eax*4], ebx
+ mov edi, 1
+
+loc_4CCA6D: ; CODE XREF: sub_4CC9D0+14j
+ add [esi+4], edi
+ mov eax, [esi+4]
+ add [esi+14h], edi
+ add [esi], edi
+ cmp eax, [esi+8]
+ jnz short loc_4CCA86
+ push esi
+ call sub_4CBD50
+ add esp, 4
+
+loc_4CCA86: ; CODE XREF: sub_4CC9D0+ABj
+ sub [esp+10h+arg_4], edi
+ jnz loc_4CC9E0
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn
+sub_4CC9D0 endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CCAA0 proc near ; CODE XREF: sub_4D0270+F3p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ mov eax, [esp+arg_4]
+ mov ecx, [esp+arg_0]
+ mov dword ptr [eax], offset sub_4CBC80
+ mov dword ptr [eax+4], offset loc_4CB960
+ mov dword ptr [eax+8], offset loc_4CB970
+ mov dword ptr [eax+0Ch], offset loc_4CB950
+ cmp dword ptr [ecx+50h], 0
+ jnz short loc_4CCAD8
+ mov dword ptr [eax+10h], offset sub_4CC5C0
+ mov dword ptr [eax+14h], offset sub_4CC9D0
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCAD8: ; CODE XREF: sub_4CCAA0+27j
+ mov ecx, [ecx+48h]
+ cmp ecx, 2
+ jnz short loc_4CCAEF
+ mov dword ptr [eax+10h], offset loc_4CC180
+ mov dword ptr [eax+14h], offset sub_4CC7B0
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCAEF: ; CODE XREF: sub_4CCAA0+3Ej
+ cmp ecx, 3
+ jnz short loc_4CCB03
+ mov dword ptr [eax+10h], offset sub_4CC220
+ mov dword ptr [eax+14h], offset sub_4CC830
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCB03: ; CODE XREF: sub_4CCAA0+52j
+ mov dword ptr [eax+10h], offset sub_4CC3B0
+ mov dword ptr [eax+14h], offset sub_4CC8E0
+ retn
+sub_4CCAA0 endp
+
+; ---------------------------------------------------------------------------
+
+Interface1_AddRef proc near ; DATA XREF: .rdata:00517A94o
+;sub_4CCB80
+
+arg_0 = dword ptr 4
+ mov eax, [esp+arg_0]
+ add dword ptr [eax+4], 1
+ mov eax, [eax+4]
+ retn 4
+Interface1_AddRef endp
+
+; ---------------------------------------------------------------------------
+
+sub_4CCB20 proc near ; DATA XREF: .rdata:00517A9Co
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ mov ecx, [esi+10h]
+ sub ecx, [esi+18h]
+ mov eax, [esi+14h]
+ sbb eax, [esi+1Ch]
+ xor edx, edx
+ cmp edx, eax
+ push edi
+ mov edi, [esp+8+arg_8]
+ jb short loc_4CCB48
+ ja short loc_4CCB42
+ cmp edi, ecx
+ jbe short loc_4CCB48
+
+loc_4CCB42: ; CODE XREF: sub_4CCB20+1Cj
+ mov edi, [esi+10h]
+ sub edi, [esi+18h]
+
+loc_4CCB48: ; CODE XREF: sub_4CCB20+1Aj
+ ; sub_4CCB20+20j
+ mov eax, [esp+8+arg_C]
+ test eax, eax
+ jz short loc_4CCB52
+ mov [eax], edi
+
+loc_4CCB52: ; CODE XREF: sub_4CCB20+2Ej
+ test edi, edi
+ jz short loc_4CCB72
+ mov eax, [esi+8]
+ add eax, [esi+18h]
+ mov ecx, [esp+8+arg_4]
+ push edi ; size_t
+ push eax ; void *
+ push ecx ; void *
+ call _memcpy ; Microsoft VisualC 2-8/net runtime
+ add esp, 0Ch
+ add [esi+18h], edi
+ adc dword ptr [esi+1Ch], 0
+
+loc_4CCB72: ; CODE XREF: sub_4CCB20+34j
+ pop edi
+ xor eax, eax
+ pop esi
+ retn 10h
+sub_4CCB20 endp
+
+; ---------------------------------------------------------------------------
+
+sub_4CCB90 proc near ; DATA XREF: .rdata:00517AB0o
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+
+ push ebx
+ mov ebx, [esp+4+arg_8]
+ push esi
+ mov esi, [esp+8+arg_0]
+ mov ecx, [esi+10h]
+ mov eax, [esi+14h]
+ push edi
+ xor edi, edi
+ sub ecx, [esi+18h]
+ sbb eax, [esi+1Ch]
+ cmp edi, eax
+ jb short loc_4CCBC2
+ ja short loc_4CCBB3
+ cmp ebx, ecx
+ jbe short loc_4CCBC2
+
+loc_4CCBB3: ; CODE XREF: sub_4CCB90+1Dj
+ pop edi
+ mov byte ptr [esi+20h], 1
+ pop esi
+ mov eax, 80004005h
+ pop ebx
+ retn 10h
+
+loc_4CCBC2: ; CODE XREF: sub_4CCB90+1Bj
+ ; sub_4CCB90+21j
+ mov ecx, [esi+8]
+ mov eax, [esp+0Ch+arg_4]
+ add ecx, [esi+18h]
+ push ebx ; size_t
+ push eax ; void *
+ push ecx ; void *
+ call _memcpy ; Microsoft VisualC 2-8/net runtime
+ mov eax, [esp+18h+arg_C]
+ add esp, 0Ch
+ add [esi+18h], ebx
+ adc [esi+1Ch], edi
+ test eax, eax
+ jz short loc_4CCBE7
+ mov [eax], ebx
+
+loc_4CCBE7: ; CODE XREF: sub_4CCB90+53j
+ pop edi
+ pop esi
+ xor eax, eax
+ pop ebx
+ retn 10h
+sub_4CCB90 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; ---------------------------------------------------------------------------
+
+LzmaProps_Decode proc near ; CODE XREF: Decompress_lzma_internal+35p
+;sub_4CCBF0
+
+propsRes = dword ptr 4
+propsData = dword ptr 8
+propsSize = dword ptr 0Ch
+
+ cmp [esp+propsSize], 5 ; LZMA_PROPS_SIZE
+ jge short loc_4CCBFD
+
+loc_4CCBF7: ; CODE XREF: LzmaProps_Decode+16j
+ mov eax, 1
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCBFD: ; CODE XREF: LzmaProps_Decode+5j
+ mov eax, [esp+propsData]
+ mov cl, [eax]
+ cmp cl, 0E1h ; 9 * 5 * 5
+ jnb short loc_4CCBF7
+ cmp cl, 2Dh
+ push edi
+ mov edi, [esp+4+propsRes]
+ mov dword ptr [edi+8], 0
+ jb short loc_4CCC40
+ push esi
+ movzx esi, cl
+ mov eax, 6C16C16Dh
+ mul esi
+ mov eax, esi
+ sub eax, edx
+ shr eax, 1
+ add eax, edx
+ shr eax, 5
+ movzx eax, al
+ mov edx, eax
+ pop esi
+
+loc_4CCC35: ; CODE XREF: LzmaProps_Decode+4Bj
+ add cl, 0D3h
+ sub eax, 1
+ jnz short loc_4CCC35
+ mov [edi+8], edx
+
+loc_4CCC40: ; CODE XREF: LzmaProps_Decode+27j
+ cmp cl, 9
+ mov dword ptr [edi+4], 0
+ jb short loc_4CCC6B
+ movzx edx, cl
+ mov eax, 38E38E39h
+ mul edx
+ shr edx, 1
+ movzx eax, dl
+ mov edx, eax
+ lea ecx, [ecx+0]
+
+loc_4CCC60: ; CODE XREF: LzmaProps_Decode+76j
+ add cl, 0F7h
+ sub eax, 1
+ jnz short loc_4CCC60
+ mov [edi+4], edx
+
+loc_4CCC6B: ; CODE XREF: LzmaProps_Decode+5Aj
+ movzx eax, cl
+ mov [edi], eax
+ xor eax, eax
+ pop edi
+ retn
+LzmaProps_Decode endp
+
+sub_4CCC80 proc near ; CODE XREF: Decompress_lzma_internal+97p
+
+var_3C = dword ptr -3Ch
+var_38 = dword ptr -38h
+var_34 = dword ptr -34h
+var_30 = dword ptr -30h
+var_2C = dword ptr -2Ch
+var_28 = dword ptr -28h
+var_24 = dword ptr -24h
+var_20 = dword ptr -20h
+var_1C = dword ptr -1Ch
+var_18 = dword ptr -18h
+var_14 = dword ptr -14h
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+arg_10 = dword ptr 14h
+arg_14 = dword ptr 18h
+arg_18 = dword ptr 1Ch
+
+ sub esp, 3Ch
+ mov eax, [esp+3Ch+arg_0]
+ mov ecx, [eax+8]
+ push ebx
+ push ebp
+ mov ebp, 1
+ mov edx, ebp
+ shl edx, cl
+ mov ecx, [eax+4]
+ xor ebx, ebx
+ push esi
+ sub edx, ebp
+ mov [esp+48h+var_C], edx
+ mov edx, ebp
+ shl edx, cl
+ mov ecx, [esp+48h+arg_C]
+ push edi
+ mov edi, [eax+0Ch]
+ sub edx, ebp
+ mov [esp+4Ch+var_8], edx
+ mov edx, [eax]
+ mov [ecx], ebx
+ mov ecx, [esp+4Ch+arg_18]
+ mov [ecx], ebx
+ mov ecx, [eax+4]
+ add ecx, edx
+ mov eax, 300h
+ shl eax, cl
+ mov [esp+4Ch+var_20], edi
+ mov [esp+4Ch+var_2C], ebx
+ mov byte ptr [esp+4Ch+arg_0], bl
+ add eax, 736h
+ mov [esp+4Ch+var_14], edx
+ mov [esp+4Ch+var_34], ebx
+ mov [esp+4Ch+var_38], ebp
+ mov [esp+4Ch+var_24], ebp
+ mov [esp+4Ch+var_28], ebp
+ mov [esp+4Ch+var_18], ebp
+ jz short loc_4CCD04
+ mov ecx, eax
+ shr ecx, 1
+ mov eax, 4000400h
+ rep stosd
+ adc ecx, ecx
+ rep stosw
+
+loc_4CCD04: ; CODE XREF: sub_4CCC80+72j
+ mov edx, [esp+4Ch+arg_8]
+ mov ecx, [esp+4Ch+arg_4]
+ lea edi, [ecx+edx]
+ xor esi, esi
+ or eax, 0FFFFFFFFh
+ mov [esp+4Ch+var_3C], edi
+ xor edx, edx
+ lea ebx, [ebx+0]
+
+loc_4CCD20: ; CODE XREF: sub_4CCC80+BCj
+ cmp ecx, edi
+ jz loc_4CCF0B
+ movzx ebp, byte ptr [ecx]
+ shl esi, 8
+ or esi, ebp
+ mov ebp, 1
+ add edx, ebp
+ add ecx, ebp
+ cmp edx, 5
+ jl short loc_4CCD20
+ cmp [esp+4Ch+arg_14], ebx
+ mov [esp+4Ch+arg_8], ecx
+ jbe loc_4CCFCD
+ lea esp, [esp+0]
+
+loc_4CCD50: ; CODE XREF: sub_4CCC80+32Dj
+ mov edx, [esp+4Ch+var_34]
+ mov ecx, [esp+4Ch+var_C]
+ and ecx, [esp+4Ch+var_2C]
+ mov edi, [esp+4Ch+var_20]
+ mov ebx, edx
+ shl ebx, 4
+ add ebx, ecx
+ cmp eax, 1000000h
+ lea ebx, [edi+ebx*2]
+ mov [esp+4Ch+var_1C], ecx
+ mov [esp+4Ch+var_30], ebx
+ jnb short loc_4CCD99
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebp, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebp
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CCD99: ; CODE XREF: sub_4CCC80+F7j
+ movzx ebx, word ptr [ebx]
+ movzx ebp, bx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb loc_4CCFF4
+ mov edi, [esp+4Ch+var_30]
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ mov ebp, [esp+4Ch+var_8]
+ sar ecx, 5
+ add ecx, ebx
+ movzx ebx, byte ptr [esp+4Ch+arg_0]
+ mov [edi], cx
+ mov edi, [esp+4Ch+var_2C]
+ mov ecx, 8
+ sub cl, byte ptr [esp+4Ch+var_14]
+ and ebp, edi
+ shr ebx, cl
+ mov ecx, [esp+4Ch+var_14]
+ shl ebp, cl
+ mov ecx, [esp+4Ch+var_20]
+ mov edx, 1
+ add ebx, ebp
+ imul ebx, 600h
+ cmp [esp+4Ch+var_34], 7
+ lea ebp, [ebx+ecx+0E6Ch]
+ mov [esp+4Ch+var_30], ebp
+ jl loc_4CCEB0
+ sub edi, [esp+4Ch+var_38]
+ mov ecx, [esp+4Ch+arg_10]
+ movzx ebx, byte ptr [edi+ecx]
+ jmp short loc_4CCE20
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CCE20: ; CODE XREF: sub_4CCC80+197j
+ ; sub_4CCC80+2C6j
+ add ebx, ebx
+ mov [esp+4Ch+var_10], ebx
+ and ebx, 100h
+ cmp eax, 1000000h
+ lea ecx, [ebx+edx]
+ lea ebp, [ebp+ecx*2+200h]
+ mov [esp+4Ch+arg_0], ebp
+ jnb short loc_4CCE61
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx edi, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, edi
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CCE61: ; CODE XREF: sub_4CCC80+1BFj
+ movzx edi, word ptr [ebp+0]
+ movzx ebp, di
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb loc_4CCF15
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ sar ecx, 5
+ add ecx, edi
+ mov edi, [esp+4Ch+arg_0]
+ add edx, edx
+ test ebx, ebx
+ mov [edi], cx
+ jz loc_4CCF36
+
+loc_4CCE97: ; CODE XREF: sub_4CCC80+2B0j
+ cmp edx, 100h
+ jge loc_4CCF70
+ mov ebp, [esp+4Ch+var_30]
+ jmp short loc_4CCEB0
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CCEB0: ; CODE XREF: sub_4CCC80+185j
+ ; sub_4CCC80+227j ...
+ cmp eax, 1000000h
+ lea ecx, [edx+edx]
+ mov [esp+4Ch+arg_0], ecx
+ jnb short loc_4CCEDE
+ mov edi, [esp+4Ch+arg_8]
+ cmp edi, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebx, byte ptr [edi]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebx
+ add edi, 1
+ mov [esp+4Ch+arg_8], edi
+
+loc_4CCEDE: ; CODE XREF: sub_4CCC80+23Cj
+ movzx edi, word ptr [ecx+ebp]
+ movzx ebx, di
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebx
+ cmp esi, ecx
+ jnb short loc_4CCF4B
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebx
+ sar ecx, 5
+ add ecx, edi
+ mov edi, [esp+4Ch+arg_0]
+ mov [edi+ebp], cx
+ add edx, edx
+ jmp short loc_4CCF64
+; ---------------------------------------------------------------------------
+
+loc_4CCF0B: ; CODE XREF: sub_4CCC80+A2j
+ pop edi
+ pop esi
+ mov eax, ebp
+ pop ebp
+ pop ebx
+ add esp, 3Ch
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCF15: ; CODE XREF: sub_4CCC80+1F2j
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, di
+ shr cx, 5
+ sub di, cx
+ test ebx, ebx
+ mov ecx, [esp+4Ch+arg_0]
+ mov [ecx], di
+ lea edx, [edx+edx+1]
+ jz loc_4CCE97
+
+loc_4CCF36: ; CODE XREF: sub_4CCC80+211j
+ cmp edx, 100h
+ jge short loc_4CCF70
+ mov ebp, [esp+4Ch+var_30]
+ mov ebx, [esp+4Ch+var_10]
+ jmp loc_4CCE20
+; ---------------------------------------------------------------------------
+
+loc_4CCF4B: ; CODE XREF: sub_4CCC80+26Fj
+ mov dx, di
+ shr dx, 5
+ sub di, dx
+ mov edx, [esp+4Ch+arg_0]
+ sub eax, ecx
+ sub esi, ecx
+ mov [edx+ebp], di
+ add edx, 1
+
+loc_4CCF64: ; CODE XREF: sub_4CCC80+289j
+ cmp edx, 100h
+ jl loc_4CCEB0
+
+loc_4CCF70: ; CODE XREF: sub_4CCC80+21Dj
+ ; sub_4CCC80+2BCj
+ mov ecx, [esp+4Ch+var_2C]
+ mov edi, [esp+4Ch+arg_10]
+ mov [ecx+edi], dl
+ add ecx, 1
+ mov [esp+4Ch+var_2C], ecx
+ mov ecx, [esp+4Ch+var_34]
+ cmp ecx, 4
+ mov byte ptr [esp+4Ch+arg_0], dl
+ jge short loc_4CCF99
+ mov [esp+4Ch+var_34], 0
+ jmp short loc_4CCFA5
+; ---------------------------------------------------------------------------
+
+loc_4CCF99: ; CODE XREF: sub_4CCC80+30Dj
+ cmp ecx, 0Ah
+ jge short loc_4CCFEF
+ sub ecx, 3
+
+loc_4CCFA1: ; CODE XREF: sub_4CCC80+372j
+ mov [esp+4Ch+var_34], ecx
+
+loc_4CCFA5: ; CODE XREF: sub_4CCC80+317j
+ ; sub_4CCC80+530j ...
+ mov ecx, [esp+4Ch+var_2C]
+ cmp ecx, [esp+4Ch+arg_14]
+ jb loc_4CCD50
+
+loc_4CCFB3: ; CODE XREF: sub_4CCC80+A13j
+ ; sub_4CCC80+A5Aj
+ cmp eax, 1000000h
+ jnb short loc_4CCFCD
+ mov edx, [esp+4Ch+arg_8]
+ cmp edx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ add [esp+4Ch+arg_8], 1
+
+loc_4CCFCD: ; CODE XREF: sub_4CCC80+C6j
+ ; sub_4CCC80+338j
+ mov eax, [esp+4Ch+arg_8]
+ sub eax, [esp+4Ch+arg_4]
+ mov ecx, [esp+4Ch+arg_C]
+ mov edx, [esp+4Ch+var_2C]
+ pop edi
+ mov [ecx], eax
+ mov eax, [esp+48h+arg_18]
+ pop esi
+ pop ebp
+ mov [eax], edx
+ xor eax, eax
+ pop ebx
+ add esp, 3Ch
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CCFEF: ; CODE XREF: sub_4CCC80+31Cj
+ sub ecx, 6
+ jmp short loc_4CCFA1
+; ---------------------------------------------------------------------------
+
+loc_4CCFF4: ; CODE XREF: sub_4CCC80+129j
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, bx
+ shr cx, 5
+ sub bx, cx
+ cmp eax, 1000000h
+ mov ecx, [esp+4Ch+var_30]
+ mov [ecx], bx
+ jnb short loc_4CD030
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebx, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebx
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CD030: ; CODE XREF: sub_4CCC80+38Ej
+ movzx ebx, word ptr [edi+edx*2+180h]
+ movzx ebp, bx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb short loc_4CD096
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ sar ecx, 5
+ add ecx, ebx
+ mov [edi+edx*2+180h], cx
+ mov ecx, [esp+4Ch+var_28]
+ mov ebp, [esp+4Ch+var_1C]
+ mov [esp+4Ch+var_18], ecx
+ mov ecx, [esp+4Ch+var_24]
+ mov [esp+4Ch+var_28], ecx
+ mov ecx, [esp+4Ch+var_38]
+ mov [esp+4Ch+var_24], ecx
+ xor ecx, ecx
+ cmp edx, 7
+ setl cl
+ sub ecx, 1
+ and ecx, 3
+ mov [esp+4Ch+var_34], ecx
+ lea ecx, [edi+664h]
+ jmp loc_4CD30B
+; ---------------------------------------------------------------------------
+
+loc_4CD096: ; CODE XREF: sub_4CCC80+3C5j
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, bx
+ shr cx, 5
+ sub bx, cx
+ cmp eax, 1000000h
+ mov [edi+edx*2+180h], bx
+ jnb short loc_4CD0D3
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebx, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebx
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CD0D3: ; CODE XREF: sub_4CCC80+431j
+ movzx ebx, word ptr [edi+edx*2+198h]
+ movzx ebp, bx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ mov [esp+4Ch+arg_0], ebx
+ jnb loc_4CD1D3
+ mov ebx, 800h
+ sub ebx, ebp
+ mov ebp, [esp+4Ch+var_1C]
+ sar ebx, 5
+ add ebx, [esp+4Ch+arg_0]
+ mov eax, ecx
+ mov [edi+edx*2+198h], bx
+ lea ebx, [edx+0Fh]
+ shl ebx, 4
+ add ebx, ebp
+ cmp ecx, 1000000h
+ lea ebx, [edi+ebx*2]
+ mov [esp+4Ch+var_30], ebx
+ jnb short loc_4CD147
+ mov ebx, [esp+4Ch+arg_8]
+ cmp ebx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ shl ecx, 8
+ mov eax, ecx
+ movzx ecx, byte ptr [ebx]
+ shl esi, 8
+ or esi, ecx
+ add ebx, 1
+ mov [esp+4Ch+arg_8], ebx
+
+loc_4CD147: ; CODE XREF: sub_4CCC80+4A3j
+ mov ecx, [esp+4Ch+var_30]
+ movzx ecx, word ptr [ecx]
+ mov [esp+4Ch+arg_0], ecx
+ movzx ebx, cx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebx
+ cmp esi, ecx
+ jnb short loc_4CD1B5
+ mov edi, [esp+4Ch+var_30]
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebx
+ sar ecx, 5
+ add ecx, [esp+4Ch+arg_0]
+ mov [edi], cx
+ mov edi, [esp+4Ch+var_2C]
+ test edi, edi
+ jz loc_4CD6E2
+ xor ecx, ecx
+ cmp edx, 7
+ mov edx, [esp+4Ch+arg_10]
+ setnl cl
+ lea ecx, [ecx+ecx+9]
+ mov [esp+4Ch+var_34], ecx
+ mov ecx, edi
+ sub ecx, [esp+4Ch+var_38]
+ add edi, 1
+ mov cl, [ecx+edx]
+ mov [edi+edx-1], cl
+ mov byte ptr [esp+4Ch+arg_0], cl
+ mov [esp+4Ch+var_2C], edi
+ jmp loc_4CCFA5
+; ---------------------------------------------------------------------------
+
+loc_4CD1B5: ; CODE XREF: sub_4CCC80+4DFj
+ sub eax, ecx
+ sub esi, ecx
+ mov ecx, [esp+4Ch+arg_0]
+ mov bx, cx
+ shr bx, 5
+ sub cx, bx
+ mov ebx, [esp+4Ch+var_30]
+ mov [ebx], cx
+ jmp loc_4CD2F0
+; ---------------------------------------------------------------------------
+
+loc_4CD1D3: ; CODE XREF: sub_4CCC80+46Cj
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, bx
+ shr cx, 5
+ sub bx, cx
+ cmp eax, 1000000h
+ mov [edi+edx*2+198h], bx
+ jnb short loc_4CD210
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebx, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebx
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CD210: ; CODE XREF: sub_4CCC80+56Ej
+ movzx ebx, word ptr [edi+edx*2+1B0h]
+ movzx ebp, bx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb short loc_4CD246
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ sar ecx, 5
+ add ecx, ebx
+ mov [edi+edx*2+1B0h], cx
+ mov ecx, [esp+4Ch+var_24]
+ jmp loc_4CD2E0
+; ---------------------------------------------------------------------------
+
+loc_4CD246: ; CODE XREF: sub_4CCC80+5A5j
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, bx
+ shr cx, 5
+ sub bx, cx
+ cmp eax, 1000000h
+ mov [edi+edx*2+1B0h], bx
+ jnb short loc_4CD283
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebx, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebx
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CD283: ; CODE XREF: sub_4CCC80+5E1j
+ movzx ebx, word ptr [edi+edx*2+1C8h]
+ movzx ebp, bx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb short loc_4CD2B6
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ sar ecx, 5
+ add ecx, ebx
+ mov [edi+edx*2+1C8h], cx
+ mov ecx, [esp+4Ch+var_28]
+ jmp short loc_4CD2D8
+; ---------------------------------------------------------------------------
+
+loc_4CD2B6: ; CODE XREF: sub_4CCC80+618j
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, bx
+ shr cx, 5
+ sub bx, cx
+ mov ecx, [esp+4Ch+var_18]
+ mov [edi+edx*2+1C8h], bx
+ mov ebx, [esp+4Ch+var_28]
+ mov [esp+4Ch+var_18], ebx
+
+loc_4CD2D8: ; CODE XREF: sub_4CCC80+634j
+ mov ebx, [esp+4Ch+var_24]
+ mov [esp+4Ch+var_28], ebx
+
+loc_4CD2E0: ; CODE XREF: sub_4CCC80+5C1j
+ mov ebx, [esp+4Ch+var_38]
+ mov ebp, [esp+4Ch+var_1C]
+ mov [esp+4Ch+var_24], ebx
+ mov [esp+4Ch+var_38], ecx
+
+loc_4CD2F0: ; CODE XREF: sub_4CCC80+54Ej
+ xor ecx, ecx
+ cmp edx, 7
+ setnl cl
+ sub ecx, 1
+ and ecx, 0FFFFFFFDh
+ add ecx, 0Bh
+ mov [esp+4Ch+var_34], ecx
+ lea ecx, [edi+0A68h]
+
+loc_4CD30B: ; CODE XREF: sub_4CCC80+411j
+ cmp eax, 1000000h
+ jnb short loc_4CD332
+ mov edx, [esp+4Ch+arg_8]
+ cmp edx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx edi, byte ptr [edx]
+ shl esi, 8
+ shl eax, 8
+ or esi, edi
+ add edx, 1
+ mov [esp+4Ch+arg_8], edx
+
+loc_4CD332: ; CODE XREF: sub_4CCC80+690j
+ movzx edi, word ptr [ecx]
+ movzx ebx, di
+ mov edx, eax
+ shr edx, 0Bh
+ imul edx, ebx
+ cmp esi, edx
+ jnb short loc_4CD36E
+ mov eax, edx
+ mov edx, 800h
+ sub edx, ebx
+ sar edx, 5
+ add edx, edi
+ mov [ecx], dx
+ shl ebp, 4
+ lea ecx, [ecx+ebp+4]
+ mov [esp+4Ch+var_1C], 0
+ mov edx, 3
+ jmp loc_4CD409
+; ---------------------------------------------------------------------------
+
+loc_4CD36E: ; CODE XREF: sub_4CCC80+6C2j
+ sub eax, edx
+ sub esi, edx
+ mov dx, di
+ shr dx, 5
+ sub di, dx
+ cmp eax, 1000000h
+ mov [ecx], di
+ jnb short loc_4CD3A6
+ mov edx, [esp+4Ch+arg_8]
+ cmp edx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx edi, byte ptr [edx]
+ shl esi, 8
+ shl eax, 8
+ or esi, edi
+ add edx, 1
+ mov [esp+4Ch+arg_8], edx
+
+loc_4CD3A6: ; CODE XREF: sub_4CCC80+704j
+ movzx edx, word ptr [ecx+2]
+ movzx ebx, dx
+ mov edi, eax
+ shr edi, 0Bh
+ imul edi, ebx
+ cmp esi, edi
+ jnb short loc_4CD3E4
+ mov eax, edi
+ mov edi, 800h
+ sub edi, ebx
+ sar edi, 5
+ add edi, edx
+ shl ebp, 4
+ mov [ecx+2], di
+ lea ecx, [ecx+ebp+104h]
+ mov [esp+4Ch+var_1C], 8
+ mov edx, 3
+ jmp short loc_4CD409
+; ---------------------------------------------------------------------------
+
+loc_4CD3E4: ; CODE XREF: sub_4CCC80+737j
+ sub eax, edi
+ sub esi, edi
+ mov di, dx
+ shr di, 5
+ sub dx, di
+ mov [ecx+2], dx
+ add ecx, 204h
+ mov [esp+4Ch+var_1C], 10h
+ mov edx, 8
+
+loc_4CD409: ; CODE XREF: sub_4CCC80+6E9j
+ ; sub_4CCC80+762j
+ mov [esp+4Ch+arg_0], edx
+ mov [esp+4Ch+var_10], edx
+ mov ebx, 1
+ jmp short loc_4CD420
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CD420: ; CODE XREF: sub_4CCC80+796j
+ ; sub_4CCC80+819j
+ cmp eax, 1000000h
+ mov edx, [esp+4Ch+arg_8]
+ lea edi, [ebx+ebx]
+ mov [esp+4Ch+var_30], edi
+ jnb short loc_4CD44E
+ cmp edx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebp, byte ptr [edx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebp
+ add edx, 1
+ mov [esp+4Ch+arg_8], edx
+
+loc_4CD44E: ; CODE XREF: sub_4CCC80+7B0j
+ movzx edi, word ptr [edi+ecx]
+ movzx ebp, di
+ mov edx, eax
+ shr edx, 0Bh
+ imul edx, ebp
+ cmp esi, edx
+ jnb short loc_4CD47B
+ mov eax, edx
+ mov edx, 800h
+ sub edx, ebp
+ sar edx, 5
+ add edx, edi
+ mov edi, [esp+4Ch+var_30]
+ mov [edi+ecx], dx
+ add ebx, ebx
+ jmp short loc_4CD494
+; ---------------------------------------------------------------------------
+
+loc_4CD47B: ; CODE XREF: sub_4CCC80+7DFj
+ mov ebx, [esp+4Ch+var_30]
+ sub eax, edx
+ sub esi, edx
+ mov dx, di
+ shr dx, 5
+ sub di, dx
+ mov [ebx+ecx], di
+ add ebx, 1
+
+loc_4CD494: ; CODE XREF: sub_4CCC80+7F9j
+ sub [esp+4Ch+var_10], 1
+ jnz short loc_4CD420
+ mov ecx, [esp+4Ch+arg_0]
+ mov edx, 1
+ shl edx, cl
+ mov ecx, [esp+4Ch+var_1C]
+ sub ecx, edx
+ add ebx, ecx
+ cmp [esp+4Ch+var_34], 4
+ mov [esp+4Ch+var_4], ebx
+ jge loc_4CD69D
+ add [esp+4Ch+var_34], 7
+ cmp ebx, 4
+ jl short loc_4CD4CC
+ mov ebx, 3
+
+loc_4CD4CC: ; CODE XREF: sub_4CCC80+845j
+ mov ecx, [esp+4Ch+var_20]
+ shl ebx, 7
+ lea ecx, [ebx+ecx+360h]
+ mov [esp+4Ch+var_30], ecx
+ mov [esp+4Ch+arg_0], 6
+ mov edi, 1
+ jmp short loc_4CD4F0
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CD4F0: ; CODE XREF: sub_4CCC80+86Bj
+ ; sub_4CCC80+8E3j
+ cmp eax, 1000000h
+ mov edx, [esp+4Ch+arg_8]
+ lea ebx, [edi+edi]
+ jnb short loc_4CD51A
+ cmp edx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx ebp, byte ptr [edx]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebp
+ add edx, 1
+ mov [esp+4Ch+arg_8], edx
+
+loc_4CD51A: ; CODE XREF: sub_4CCC80+87Cj
+ movzx edx, word ptr [ebx+ecx]
+ movzx ebp, dx
+ mov ecx, eax
+ shr ecx, 0Bh
+ imul ecx, ebp
+ cmp esi, ecx
+ jnb short loc_4CD545
+ mov eax, ecx
+ mov ecx, 800h
+ sub ecx, ebp
+ sar ecx, 5
+ add ecx, edx
+ mov [esp+4Ch+var_10], ecx
+ mov edx, ecx
+ add edi, edi
+ jmp short loc_4CD556
+; ---------------------------------------------------------------------------
+
+loc_4CD545: ; CODE XREF: sub_4CCC80+8ABj
+ sub eax, ecx
+ sub esi, ecx
+ mov cx, dx
+ shr cx, 5
+ sub dx, cx
+ lea edi, [ebx+1]
+
+loc_4CD556: ; CODE XREF: sub_4CCC80+8C3j
+ sub [esp+4Ch+arg_0], 1
+ mov ecx, [esp+4Ch+var_30]
+ mov [ebx+ecx], dx
+ jnz short loc_4CD4F0
+ sub edi, 40h
+ cmp edi, 4
+ jl loc_4CD68A
+ mov ebx, 1
+ mov ecx, edi
+ mov edx, edi
+ sar ecx, 1
+ and edx, ebx
+ sub ecx, ebx
+ or edx, 2
+ cmp edi, 0Eh
+ mov [esp+4Ch+var_30], ecx
+ jge short loc_4CD5A1
+ shl edx, cl
+ mov ecx, [esp+4Ch+var_20]
+ mov [esp+4Ch+var_38], edx
+ sub edx, edi
+ lea ebp, [ecx+edx*2+55Eh]
+ jmp short loc_4CD5F3
+; ---------------------------------------------------------------------------
+
+loc_4CD5A1: ; CODE XREF: sub_4CCC80+90Aj
+ mov edi, [esp+4Ch+arg_8]
+ sub ecx, 4
+
+loc_4CD5A8: ; CODE XREF: sub_4CCC80+958j
+ cmp eax, 1000000h
+ jnb short loc_4CD5CA
+ cmp edi, [esp+4Ch+var_3C]
+ jz loc_4CD6EF
+ movzx ebp, byte ptr [edi]
+ shl esi, 8
+ shl eax, 8
+ or esi, ebp
+ add edi, ebx
+ mov [esp+4Ch+arg_8], edi
+
+loc_4CD5CA: ; CODE XREF: sub_4CCC80+92Dj
+ shr eax, 1
+ add edx, edx
+ cmp esi, eax
+ jb short loc_4CD5D6
+ sub esi, eax
+ or edx, ebx
+
+loc_4CD5D6: ; CODE XREF: sub_4CCC80+950j
+ sub ecx, ebx
+ jnz short loc_4CD5A8
+ mov ebp, [esp+4Ch+var_20]
+ add ebp, 644h
+ shl edx, 4
+ mov [esp+4Ch+var_38], edx
+ mov [esp+4Ch+var_30], 4
+
+loc_4CD5F3: ; CODE XREF: sub_4CCC80+91Fj
+ mov [esp+4Ch+var_1C], ebx
+ mov [esp+4Ch+arg_0], ebx
+ jmp short loc_4CD600
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CD600: ; CODE XREF: sub_4CCC80+97Bj
+ ; sub_4CCC80+A02j
+ mov ebx, [esp+4Ch+arg_0]
+ add ebx, ebx
+ cmp eax, 1000000h
+ jnb short loc_4CD62D
+ mov ecx, [esp+4Ch+arg_8]
+ cmp ecx, [esp+4Ch+var_3C]
+ jz loc_4CD6E2
+ movzx edx, byte ptr [ecx]
+ shl esi, 8
+ shl eax, 8
+ or esi, edx
+ add ecx, 1
+ mov [esp+4Ch+arg_8], ecx
+
+loc_4CD62D: ; CODE XREF: sub_4CCC80+98Bj
+ movzx edi, word ptr [ebx+ebp]
+ movzx ecx, di
+ mov edx, eax
+ shr edx, 0Bh
+ imul edx, ecx
+ cmp esi, edx
+ jnb short loc_4CD658
+ mov eax, edx
+ mov edx, 800h
+ sub edx, ecx
+ sar edx, 5
+ add edx, edi
+ shl [esp+4Ch+arg_0], 1
+ mov [ebx+ebp], dx
+ jmp short loc_4CD679
+; ---------------------------------------------------------------------------
+
+loc_4CD658: ; CODE XREF: sub_4CCC80+9BEj
+ mov cx, di
+ shr cx, 5
+ sub di, cx
+ sub eax, edx
+ sub esi, edx
+ mov edx, [esp+4Ch+var_1C]
+ mov [ebx+ebp], di
+ add ebx, 1
+ or [esp+4Ch+var_38], edx
+ mov [esp+4Ch+arg_0], ebx
+
+loc_4CD679: ; CODE XREF: sub_4CCC80+9D6j
+ shl [esp+4Ch+var_1C], 1
+ sub [esp+4Ch+var_30], 1
+ jnz loc_4CD600
+ jmp short loc_4CD68E
+; ---------------------------------------------------------------------------
+
+loc_4CD68A: ; CODE XREF: sub_4CCC80+8EBj
+ mov [esp+4Ch+var_38], edi
+
+loc_4CD68E: ; CODE XREF: sub_4CCC80+A08j
+ add [esp+4Ch+var_38], 1
+ jz loc_4CCFB3
+ mov ebx, [esp+4Ch+var_4]
+
+loc_4CD69D: ; CODE XREF: sub_4CCC80+837j
+ mov ebp, [esp+4Ch+var_2C]
+ mov ecx, [esp+4Ch+var_38]
+ add ebx, 2
+ cmp ecx, ebp
+ ja short loc_4CD6E2
+ mov edi, ebp
+ sub edi, ecx
+ add edi, [esp+4Ch+arg_10]
+
+loc_4CD6B4: ; CODE XREF: sub_4CCC80+A60j
+ mov cl, [edi]
+ mov edx, [esp+4Ch+arg_10]
+ sub ebx, 1
+ mov [edx+ebp], cl
+ add ebp, 1
+ add edi, 1
+ test ebx, ebx
+ mov byte ptr [esp+4Ch+arg_0], cl
+ mov [esp+4Ch+var_2C], ebp
+ jz loc_4CCFA5
+ cmp ebp, [esp+4Ch+arg_14]
+ jnb loc_4CCFB3
+ jmp short loc_4CD6B4
+; ---------------------------------------------------------------------------
+
+loc_4CD6E2: ; CODE XREF: sub_4CCC80+101j
+ ; sub_4CCC80+1C9j ...
+ pop edi
+ pop esi
+ pop ebp
+ mov eax, 1
+ pop ebx
+ add esp, 3Ch
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CD6EF: ; CODE XREF: sub_4CCC80+933j
+ pop edi
+ pop esi
+ pop ebp
+ mov eax, ebx
+ pop ebx
+ add esp, 3Ch
+ retn
+sub_4CCC80 endp
+
+_starcraft_decompress_lzma PROC
+;sub_4CD700
+
+var_14 = byte ptr -14h
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_4 = dword ptr -4
+pbInBuffer = dword ptr 4
+cbInBuffer = dword ptr 8
+pbOutBuffer = dword ptr 0Ch
+cbOutBuffer = dword ptr 10h
+pcbOutBuffer = dword ptr 14h
+pfnAllocateMemory= dword ptr 18h
+pfnFreeMemory = dword ptr 1Ch
+
+ sub esp, 14h
+ push ebx
+ mov ebx, [esp+18h+cbInBuffer]
+ cmp ebx, 0Eh ; LZMA_PROPS_SIZE + 8
+ jnb short loc_4CD714
+ xor al, al
+ pop ebx
+ add esp, 14h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CD714: ; CODE XREF: Decompress_lzma_internal+Bj
+ push ebp
+ mov ebp, [esp+1Ch+pcbOutBuffer]
+ push edi
+ mov edi, [esp+20h+pbInBuffer]
+ mov dword ptr [ebp+0], 0
+ cmp byte ptr [edi], 0
+ jnz short loc_4CD741
+ push 5
+ lea eax, [edi+1]
+ push eax
+ lea ecx, [esp+28h+var_10]
+ push ecx
+ call LzmaProps_Decode
+ add esp, 0Ch
+ test eax, eax
+ jz short loc_4CD74A
+
+loc_4CD741: ; CODE XREF: Decompress_lzma_internal+28j
+ pop edi
+ pop ebp
+ xor al, al
+ pop ebx
+ add esp, 14h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CD74A: ; CODE XREF: Decompress_lzma_internal+3Fj
+ mov edx, [esp+20h+var_10]
+ mov eax, [esp+20h+var_C]
+ lea ecx, [eax+edx]
+ mov edx, 300h
+ shl edx, cl
+ push esi
+ lea eax, [edx+edx+0E6Ch]
+ push eax
+ call [esp+28h+pfnAllocateMemory]
+ mov esi, eax
+ add esp, 4
+ test esi, esi
+ mov [esp+24h+var_4], esi
+ jz short loc_4CD7AA
+ mov edx, [esp+24h+cbOutBuffer]
+ mov eax, [esp+24h+pbOutBuffer]
+ lea ecx, [esp+24h+cbInBuffer]
+ push ecx ; cbInBuffer
+ push edx ; cbOutBuffer
+ push eax ; pbOutBuffer
+ lea ecx, [esp+30h+var_14]
+ push ecx ; &var_14
+ add ebx, 0FFFFFFF2h
+ push ebx ; cbInBuffer - LZMA86_HEADER_SIZE
+ add edi, 0Eh
+ lea edx, [esp+38h+var_10]
+ push edi ; pbInBuffer + LZMA86_HEADER_SIZE
+ push edx ; dest
+ call sub_4CCC80
+ push esi
+ mov edi, eax
+ call [esp+44h+pfnFreeMemory]
+ add esp, 20h
+ test edi, edi
+ jz short loc_4CD7B4
+
+loc_4CD7AA: ; CODE XREF: Decompress_lzma_internal+74j
+ pop esi
+ pop edi
+ pop ebp
+ xor al, al
+ pop ebx
+ add esp, 14h
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CD7B4: ; CODE XREF: Decompress_lzma_internal+A8j
+ mov eax, [esp+24h+cbInBuffer]
+ pop esi
+ pop edi
+ mov [ebp+0], eax
+ pop ebp
+ mov al, 1
+ pop ebx
+ add esp, 14h
+ retn
+_starcraft_decompress_lzma ENDP
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD7D0 proc near ; CODE XREF: sub_4CDC00+74p
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ or esi, 8
+ xor eax, eax
+ cmp esi, 1
+ jz short loc_4CD806
+ push edi
+
+loc_4CD7E0: ; CODE XREF: sub_4CD7D0+33j
+ mov edx, esi
+ shr esi, 1
+ mov edi, [ecx+esi*4]
+ and edx, 1
+ sub edi, edx
+ neg edx
+ xor edi, edx
+ shr edi, 2
+ and edi, 1FFh
+ add eax, dword_550998[edi*4]
+ cmp esi, 1
+ jnz short loc_4CD7E0
+ pop edi
+
+loc_4CD806: ; CODE XREF: sub_4CD7D0+Dj
+ pop esi
+ retn 4
+sub_4CD7D0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD810 proc near ; CODE XREF: CEncoder_FillAlignPrices+17p
+
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+
+ push ecx
+ push ebx
+ push ebp
+ push esi
+ xor eax, eax
+ push edi
+ mov edi, [esp+14h+arg_0]
+ mov [esp+14h+var_4], ecx
+ lea esi, [eax+1]
+ lea ebx, [eax+4]
+
+loc_4CD825: ; CODE XREF: sub_4CD810+42j
+ mov ecx, [esp+14h+var_4]
+ mov ecx, [ecx+esi*4]
+ mov edx, edi
+ and edx, 1
+ sub ecx, edx
+ mov ebp, edx
+ neg ebp
+ xor ecx, ebp
+ shr ecx, 2
+ and ecx, 1FFh
+ add eax, dword_550998[ecx*4]
+ add esi, esi
+ shr edi, 1
+ or esi, edx
+ sub ebx, 1
+ jnz short loc_4CD825
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn 4
+sub_4CD810 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD860 proc near ; CODE XREF: CEncoder_FillDistancesPrices+6Bp
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push edi
+ mov edi, [esp+4+arg_4]
+ xor eax, eax
+ test edi, edi
+ lea edx, [eax+1]
+ jz short loc_4CD8A7
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+10h+arg_8]
+
+loc_4CD875: ; CODE XREF: sub_4CD860+42j
+ mov ebx, [esp+10h+arg_0]
+ mov ebx, [ebx+edx*4]
+ mov ecx, esi
+ and ecx, 1
+ sub ebx, ecx
+ mov ebp, ecx
+ neg ebp
+ xor ebx, ebp
+ shr ebx, 2
+ and ebx, 1FFh
+ add eax, dword_550998[ebx*4]
+ add edx, edx
+ shr esi, 1
+ or edx, ecx
+ sub edi, 1
+ jnz short loc_4CD875
+ pop esi
+ pop ebp
+ pop ebx
+
+loc_4CD8A7: ; CODE XREF: sub_4CD860+Cj
+ pop edi
+ retn
+sub_4CD860 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD8B0 proc near ; CODE XREF: CEncoder_CodeOneBlock+7B8p
+ mov eax, [ecx+24h]
+ mov edx, [ecx+1Ch]
+ push ebx
+ push esi
+ mov esi, [ecx+30h]
+ xor ebx, ebx
+ push edi
+ mov edi, [ecx+34h]
+ sub esi, eax
+ sbb edi, ebx
+ add esi, edx
+ adc edi, ebx
+ cmp eax, edx
+ jbe short loc_4CD8D4
+ mov eax, [ecx+28h]
+ add esi, eax
+ adc edi, ebx
+
+loc_4CD8D4: ; CODE XREF: sub_4CD8B0+1Bj
+ mov eax, [ecx]
+ xor edx, edx
+ add eax, esi
+ adc edx, edi
+ pop edi
+ add eax, 4
+ pop esi
+ adc edx, ebx
+ pop ebx
+ retn
+sub_4CD8B0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD8F0 proc near ; CODE XREF: sub_4CD940+21p
+ ; .text:loc_4CF730j ...
+ mov eax, dword_553598
+ test eax, eax
+ push esi
+ mov esi, ecx
+ push edi
+ mov edi, [esi]
+ jnz short loc_4CD92A
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ test eax, eax
+ jz short loc_4CD923
+ mov dword ptr [eax], 0
+ mov dword ptr [eax+4], 0
+ mov dword ptr [eax+8], 0
+ jmp short loc_4CD925
+; ---------------------------------------------------------------------------
+
+loc_4CD923: ; CODE XREF: sub_4CD8F0+1Bj
+ xor eax, eax
+
+loc_4CD925: ; CODE XREF: sub_4CD8F0+31j
+ mov dword_553598, eax
+
+loc_4CD92A: ; CODE XREF: sub_4CD8F0+Dj
+ mov eax, [eax+4]
+ test eax, eax
+ jz short loc_4CD937
+ push edi
+ call eax
+ add esp, 4
+
+loc_4CD937: ; CODE XREF: sub_4CD8F0+3Fj
+ pop edi
+ mov dword ptr [esi], 0
+ pop esi
+ retn
+sub_4CD8F0 endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CD940 proc near ; CODE XREF: sub_4D0270+74p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ mov ebx, [esp+4+arg_4]
+ push esi
+ mov esi, ecx
+ cmp dword ptr [esi], 0
+ push edi
+ mov edi, [esp+0Ch+arg_0]
+ jz short loc_4CD95F
+ mov eax, [esi+8]
+ add eax, [esi+4]
+ lea ecx, [edi+ebx]
+ cmp ecx, eax
+ jz short loc_4CD981
+
+loc_4CD95F: ; CODE XREF: sub_4CD940+10j
+ mov ecx, esi
+ call sub_4CD8F0
+ lea ecx, [edi+ebx]
+ mov edx, 1
+ shl edx, cl
+ imul edx, 0C00h
+ push edx
+ call sub_4CB8A0
+ add esp, 4
+ mov [esi], eax
+
+loc_4CD981: ; CODE XREF: sub_4CD940+1Dj
+ mov ecx, edi
+ mov eax, 1
+ shl eax, cl
+ mov [esi+8], edi
+ pop edi
+ mov [esi+4], ebx
+ sub eax, 1
+ mov [esi+0Ch], eax
+ xor eax, eax
+ cmp [esi], eax
+ pop esi
+ setnz al
+ pop ebx
+ retn 8
+sub_4CD940 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CD9B0 proc near ; CODE XREF: CEncoder_GetOptimum+436p
+ ; CEncoder_GetOptimum+AE1p
+
+arg_0 = dword ptr 4
+arg_4 = byte ptr 8
+arg_8 = dword ptr 0Ch
+
+ mov edx, [esp+arg_0]
+ test edx, edx
+ push esi
+ jnz short loc_4CD9F2
+ movzx eax, [esp+4+arg_4]
+ mov edx, eax
+ shl edx, 4
+ add edx, [esp+4+arg_8]
+ mov esi, 800h
+ sub esi, [ecx+edx*4+284B0h]
+ mov ecx, [ecx+eax*4+28420h]
+ shr esi, 2
+ mov eax, dword_550998[esi*4]
+ shr ecx, 2
+ add eax, dword_550998[ecx*4]
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CD9F2: ; CODE XREF: sub_4CD9B0+7j
+ movzx esi, [esp+4+arg_4]
+ mov eax, 800h
+ sub eax, [ecx+esi*4+28420h]
+ shr eax, 2
+ cmp edx, 1
+ mov eax, dword_550998[eax*4]
+ jnz short loc_4CDA27
+ mov ecx, [ecx+esi*4+28450h]
+ shr ecx, 2
+ add eax, dword_550998[ecx*4]
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CDA27: ; CODE XREF: sub_4CD9B0+60j
+ push edi
+ add edx, 0FFFFFFFEh
+ mov edi, 800h
+ sub edi, [ecx+esi*4+28450h]
+ mov ecx, [ecx+esi*4+28480h]
+ sub ecx, edx
+ neg edx
+ xor ecx, edx
+ shr edi, 2
+ mov edx, dword_550998[edi*4]
+ shr ecx, 2
+ and ecx, 1FFh
+ add edx, dword_550998[ecx*4]
+ pop edi
+ add eax, edx
+ pop esi
+ retn 0Ch
+sub_4CD9B0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CDA70 proc near ; CODE XREF: CEncoder_CodeReal+10Cp
+ ; CEncoder_CodeReal+134p ...
+ push esi
+ mov esi, [ecx]
+ cmp dword ptr [esi+80h], 0
+ jz short loc_4CDA8C
+ cmp byte ptr [esi+33B95h], 0
+ jz short loc_4CDA8C
+ mov byte ptr [esi+33B95h], 0
+
+loc_4CDA8C: ; CODE XREF: sub_4CDA70+Aj
+ ; sub_4CDA70+13j
+ mov eax, [esi+33B8Ch]
+ test eax, eax
+ jz short loc_4CDAA8
+ mov ecx, [eax]
+ mov edx, [ecx+8]
+ push eax
+ call edx
+ mov dword ptr [esi+33B8Ch], 0
+
+loc_4CDAA8: ; CODE XREF: sub_4CDA70+24j
+ mov ecx, [esi+4]
+ mov edx, [ecx+10h]
+ lea eax, [esi+4]
+ push eax
+ call edx
+ pop esi
+ retn
+sub_4CDA70 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CDAC0 proc near ; CODE XREF: CEncoder_GetOptimum+2C4p
+ ; CEncoder_GetOptimum+7ACp ...
+
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = byte ptr 8
+arg_8 = byte ptr 0Ch
+
+ push ecx
+ push ebx
+ push ebp
+ xor ebp, ebp
+ cmp byte ptr [esp+0Ch+arg_0], 0
+ push esi
+ mov eax, ecx
+ push edi
+ mov [esp+14h+var_4], eax
+ lea edi, [ebp+1]
+ lea ebx, [ebp+8]
+ jz short loc_4CDB3B
+ movzx ecx, [esp+14h+arg_8]
+ mov [esp+14h+arg_0], ecx
+
+loc_4CDAE3: ; CODE XREF: sub_4CDAC0+71j
+ movzx esi, [esp+14h+arg_4]
+ mov edx, [esp+14h+arg_0]
+ sub ebx, 1
+ movzx ecx, bl
+ shr esi, cl
+ shr edx, cl
+ and esi, 1
+ mov ecx, esi
+ shl ecx, 8
+ add ecx, edi
+ mov eax, [eax+ecx*4+400h]
+ and edx, 1
+ sub eax, edx
+ mov ecx, edx
+ neg ecx
+ xor eax, ecx
+ shr eax, 2
+ and eax, 1FFh
+ add ebp, dword_550998[eax*4]
+ add edi, edi
+ or edi, edx
+ cmp esi, edx
+ jnz short loc_4CDB33
+ test ebx, ebx
+ jz short loc_4CDB75
+ mov eax, [esp+14h+var_4]
+ jmp short loc_4CDAE3
+; ---------------------------------------------------------------------------
+
+loc_4CDB33: ; CODE XREF: sub_4CDAC0+67j
+ test ebx, ebx
+ jz short loc_4CDB75
+ mov eax, [esp+14h+var_4]
+
+loc_4CDB3B: ; CODE XREF: sub_4CDAC0+18j
+ movzx edx, [esp+14h+arg_8]
+ mov [esp+14h+arg_0], edx
+
+loc_4CDB44: ; CODE XREF: sub_4CDAC0+B3j
+ mov edx, [esp+14h+arg_0]
+ sub ebx, 1
+ mov cl, bl
+ shr edx, cl
+ mov ecx, [eax+edi*4]
+ add edi, edi
+ and edx, 1
+ sub ecx, edx
+ mov esi, edx
+ neg esi
+ xor ecx, esi
+ shr ecx, 2
+ and ecx, 1FFh
+ add ebp, dword_550998[ecx*4]
+ or edi, edx
+ test ebx, ebx
+ jnz short loc_4CDB44
+
+loc_4CDB75: ; CODE XREF: sub_4CDAC0+6Bj
+ ; sub_4CDAC0+75j
+ pop edi
+ pop esi
+ mov eax, ebp
+ pop ebp
+ pop ebx
+ pop ecx
+ retn 0Ch
+sub_4CDAC0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CDB80 proc near ; CODE XREF: sub_4CDEA0+11Ep
+ ; sub_4CDEA0+137p
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ test esi, esi
+ mov edx, 400h
+ push edi
+ mov [ecx], edx
+ mov [ecx+4], edx
+ jbe short loc_4CDBE6
+ lea eax, [ecx+20Ch]
+ lea ebx, [ebx+0]
+
+loc_4CDBA0: ; CODE XREF: sub_4CDB80+64j
+ mov [eax-200h], edx
+ mov [eax-1FCh], edx
+ mov [eax-1F8h], edx
+ mov [eax-1F4h], edx
+ mov [eax-1F0h], edx
+ mov [eax-1ECh], edx
+ mov [eax-1E8h], edx
+ mov [eax], edx
+ mov [eax+4], edx
+ mov [eax+8], edx
+ mov [eax+0Ch], edx
+ mov [eax+10h], edx
+ mov [eax+14h], edx
+ mov [eax+18h], edx
+ add eax, 20h
+ sub esi, 1
+ jnz short loc_4CDBA0
+
+loc_4CDBE6: ; CODE XREF: sub_4CDB80+12j
+ lea edi, [ecx+40Ch]
+ mov ecx, 0FFh
+ mov eax, edx
+ rep stosd
+ pop edi
+ pop esi
+ retn 4
+sub_4CDB80 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CDC00 proc near ; CODE XREF: sub_4CF740+22p
+ ; sub_4CF780+2Bp
+
+var_C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ sub esp, 0Ch
+ push ebx
+ push ebp
+ push esi
+ push edi
+ mov edi, ecx
+ mov eax, [edi]
+ mov ebx, [esp+1Ch+arg_0]
+ mov ecx, eax
+ shr ecx, 2
+ mov edx, dword_550998[ecx*4]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 2
+ mov eax, dword_550998[ecx*4]
+ mov ecx, [edi+4]
+ mov [esp+1Ch+var_C], edx
+ mov edx, ecx
+ shr edx, 2
+ mov ebp, dword_550998[edx*4]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 2
+ mov ecx, dword_550998[edx*4]
+ add ebp, eax
+ add ecx, eax
+ mov [esp+1Ch+var_8], ebp
+ mov [esp+1Ch+var_4], ecx
+ xor esi, esi
+ mov edi, edi
+
+loc_4CDC60: ; CODE XREF: sub_4CDC00+8Aj
+ cmp esi, [esp+1Ch+arg_4]
+ jnb loc_4CDD62
+ mov eax, ebx
+ shl eax, 5
+ push esi
+ lea ecx, [eax+edi+8]
+ call sub_4CD7D0
+ add eax, [esp+1Ch+var_C]
+ mov ecx, [esp+1Ch+arg_8]
+ mov [ecx+esi*4], eax
+ add esi, 1
+ cmp esi, 8
+ jb short loc_4CDC60
+ cmp esi, 10h
+ jnb short loc_4CDD00
+ lea ecx, [esi-8]
+ mov [esp+1Ch+arg_0], ecx
+ jmp short loc_4CDCA0
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CDCA0: ; CODE XREF: sub_4CDC00+98j
+ ; sub_4CDC00+FEj
+ cmp esi, [esp+1Ch+arg_4]
+ jnb loc_4CDD62
+ or ecx, 8
+ xor edx, edx
+ cmp ecx, 1
+ jz short loc_4CDCE4
+
+loc_4CDCB4: ; CODE XREF: sub_4CDC00+DEj
+ mov eax, ecx
+ shr ecx, 1
+ and eax, 1
+ lea ebp, [ecx+ebx*8]
+ mov ebp, [edi+ebp*4+208h]
+ sub ebp, eax
+ neg eax
+ xor ebp, eax
+ shr ebp, 2
+ and ebp, 1FFh
+ add edx, dword_550998[ebp*4]
+ cmp ecx, 1
+ jnz short loc_4CDCB4
+ mov ebp, [esp+1Ch+var_8]
+
+loc_4CDCE4: ; CODE XREF: sub_4CDC00+B2j
+ mov eax, [esp+1Ch+arg_8]
+ mov ecx, [esp+1Ch+arg_0]
+ add edx, ebp
+ mov [eax+esi*4], edx
+ add esi, 1
+ add ecx, 1
+ cmp esi, 10h
+ mov [esp+1Ch+arg_0], ecx
+ jb short loc_4CDCA0
+
+loc_4CDD00: ; CODE XREF: sub_4CDC00+8Fj
+ cmp esi, [esp+1Ch+arg_4]
+ jnb short loc_4CDD62
+ lea ebx, [esi-10h]
+ lea esp, [esp+0]
+
+loc_4CDD10: ; CODE XREF: sub_4CDC00+160j
+ mov ecx, ebx
+ or ecx, 100h
+ xor edx, edx
+ cmp ecx, 1
+ jz short loc_4CDD49
+ nop
+
+loc_4CDD20: ; CODE XREF: sub_4CDC00+147j
+ mov eax, ecx
+ shr ecx, 1
+ mov ebp, [edi+ecx*4+408h]
+ and eax, 1
+ sub ebp, eax
+ neg eax
+ xor ebp, eax
+ shr ebp, 2
+ and ebp, 1FFh
+ add edx, dword_550998[ebp*4]
+ cmp ecx, 1
+ jnz short loc_4CDD20
+
+loc_4CDD49: ; CODE XREF: sub_4CDC00+11Dj
+ mov ecx, [esp+1Ch+var_4]
+ mov eax, [esp+1Ch+arg_8]
+ add edx, ecx
+ mov [eax+esi*4], edx
+ add esi, 1
+ add ebx, 1
+ cmp esi, [esp+1Ch+arg_4]
+ jb short loc_4CDD10
+
+loc_4CDD62: ; CODE XREF: sub_4CDC00+64j
+ ; sub_4CDC00+A4j ...
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ add esp, 0Ch
+ retn 0Ch
+sub_4CDC00 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+; int __cdecl sub_4CDD70(SIZE_T dwSize)
+sub_4CDD70 proc near ; DATA XREF: .data:off_546E20o
+
+dwSize = dword ptr 4
+
+ mov eax, [esp+dwSize]
+ test eax, eax
+ jnz short loc_4CDD79
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4CDD79: ; CODE XREF: sub_4CDD70+6j
+ push 4 ; flProtect
+ push 1000h ; flAllocationType
+ push eax ; dwSize
+ push 0 ; lpAddress
+ call ds:VirtualAlloc
+ retn
+sub_4CDD70 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+; int __cdecl sub_4CDD90(void * lpAddress)
+sub_4CDD90 proc near ; CODE XREF: sub_4CF810+53p
+ ; sub_4CF810+73p
+ ; DATA XREF: ...
+
+lpAddress = dword ptr 4
+
+ mov eax, [esp+lpAddress]
+ test eax, eax
+ jz short locret_4CDDA6
+ push 8000h ; dwFreeType
+ push 0 ; dwSize
+ push eax ; lpAddress
+ call ds:VirtualFree
+
+locret_4CDDA6: ; CODE XREF: sub_4CDD90+6j
+ retn
+sub_4CDD90 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CDDB0 proc near ; DATA XREF: .rdata:00517AC8o
+
+var_10 = dword ptr -10h
+var_C = byte ptr -0Ch
+var_B = byte ptr -0Bh
+var_A = byte ptr -0Ah
+var_9 = byte ptr -9
+var_8 = byte ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ sub esp, 10h
+ mov eax, dword_544960
+ xor eax, esp
+ mov [esp+10h+var_4], eax
+ mov ecx, [esp+10h+arg_0]
+ mov al, [ecx+33B50h]
+ mov dl, 5
+ imul dl
+ add al, [ecx+33B58h]
+ mov dl, 9
+ imul dl
+ add al, [ecx+33B5Ch]
+ push ebp
+ mov ebp, [esp+14h+arg_4]
+ mov [esp+14h+var_C], al
+ mov eax, [ecx+33B60h]
+ mov ecx, eax
+ mov edx, eax
+ push esi
+ shr ecx, 8
+ shr edx, 10h
+ mov [esp+18h+var_B], al
+ shr eax, 18h
+ push edi
+ mov [esp+1Ch+var_A], cl
+ mov [esp+1Ch+var_9], dl
+ mov [esp+1Ch+var_8], al
+ mov esi, 5
+ lea edi, [esp+1Ch+var_C]
+
+loc_4CDE13: ; CODE XREF: sub_4CDDB0+85j
+ mov eax, [ebp+0]
+ mov edx, [eax+0Ch]
+ lea ecx, [esp+1Ch+var_10]
+ push ecx
+ push esi
+ push edi
+ push ebp
+ call edx
+ mov ecx, [esp+1Ch+var_10]
+ add edi, ecx
+ sub esi, ecx
+ test eax, eax
+ jnz short loc_4CDE37
+ test ecx, ecx
+ jz short loc_4CDE4B
+ test esi, esi
+ jnz short loc_4CDE13
+
+loc_4CDE37: ; CODE XREF: sub_4CDDB0+7Dj
+ pop edi
+ pop esi
+ pop ebp
+ mov ecx, [esp+10h+var_4]
+ xor ecx, esp
+ call sub_4A0686
+ add esp, 10h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CDE4B: ; CODE XREF: sub_4CDDB0+81j
+ mov ecx, [esp+1Ch+var_4]
+ pop edi
+ pop esi
+ pop ebp
+ xor ecx, esp
+ mov eax, 80004005h
+ call sub_4A0686
+ add esp, 10h
+ retn 8
+sub_4CDDB0 endp
+
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CDE70 proc near ; DATA XREF: .rdata:00517AF4o
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, [esp+4+arg_0]
+ mov eax, [esi+50h]
+ test eax, eax
+ jz short loc_4CDE8B
+ mov ecx, [eax]
+ mov edx, [ecx+8]
+ push eax
+ call edx
+ mov dword ptr [esi+50h], 0
+
+loc_4CDE8B: ; CODE XREF: sub_4CDE70+Aj
+ xor eax, eax
+ pop esi
+ retn 4
+sub_4CDE70 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CDEA0 proc near ; CODE XREF: CEncoder_SetStreams+3Cp
+
+var_4 = dword ptr -4
+
+ push ecx
+ push ebx
+ xor ebx, ebx
+ push ebp
+ push esi
+ mov esi, ecx
+ mov byte ptr [esi+10h], 0
+ mov byte ptr [esi+11h], 0
+ mov [esi+14h], ebx
+ mov [esi+18h], ebx
+ mov [esi+1Ch], ebx
+ mov [esi+20h], ebx
+ mov eax, [esi+50h]
+ mov [esi+4Ch], ebx
+ mov [esi+48h], eax
+ mov [esi+44h], ebx
+ mov [esi+58h], ebx
+ mov [esi+5Ch], ebx
+ mov [esi+64h], bl
+ push edi
+ mov [esi+30h], ebx
+ mov [esi+34h], ebx
+ mov dword ptr [esi+38h], 0FFFFFFFFh
+ mov dword ptr [esi+28h], 1
+ mov [esi+2Ch], bl
+ lea ecx, [esi+28420h]
+ lea edi, [esi+284B0h]
+ mov [esp+14h+var_4], 0Ch
+ mov ebp, 400h
+
+loc_4CDF02: ; CODE XREF: sub_4CDEA0+9Cj
+ xor edx, edx
+ mov eax, edi
+ jmp short loc_4CDF10
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CDF10: ; CODE XREF: sub_4CDEA0+66j
+ ; sub_4CDEA0+84j
+ mov [eax-3C0h], ebp
+ mov [eax], ebp
+ add edx, 1
+ add eax, 4
+ cmp edx, [esi+33B60h]
+ jbe short loc_4CDF10
+ mov [ecx-30h], ebp
+ mov [ecx], ebp
+ mov [ecx+30h], ebp
+ mov [ecx+60h], ebp
+ add ecx, 4
+ add edi, 40h
+ sub [esp+14h+var_4], 1
+ jnz short loc_4CDF02
+ mov ecx, [esi+32658h]
+ add ecx, [esi+32654h]
+ mov eax, 1
+ shl eax, cl
+ cmp eax, ebx
+ jbe short loc_4CDF7C
+ xor edx, edx
+ mov ebx, eax
+ lea esp, [esp+0]
+
+loc_4CDF60: ; CODE XREF: sub_4CDEA0+DAj
+ mov edi, [esi+32650h]
+ add edi, edx
+ mov ecx, 300h
+ mov eax, ebp
+ add edx, 0C00h
+ sub ebx, 1
+ rep stosd
+ jnz short loc_4CDF60
+
+loc_4CDF7C: ; CODE XREF: sub_4CDEA0+B3j
+ lea edx, [esi+287B4h]
+ mov ebx, 4
+
+loc_4CDF87: ; CODE XREF: sub_4CDEA0+FBj
+ mov edi, edx
+ mov ecx, 3Fh
+ mov eax, ebp
+ add edx, 100h
+ sub ebx, 1
+ rep stosd
+ jnz short loc_4CDF87
+ lea edi, [esi+28BB0h]
+ mov ecx, 72h
+ rep stosd
+ mov ecx, [esi+33B5Ch]
+ mov edx, 1
+ shl edx, cl
+ lea ecx, [esi+28DB8h]
+ push edx
+ call sub_4CDB80
+ mov ecx, [esi+33B5Ch]
+ mov eax, 1
+ shl eax, cl
+ lea ecx, [esi+2DA04h]
+ push eax
+ call sub_4CDB80
+ mov eax, ebp
+ mov [esi+28D7Ch], eax
+ mov [esi+28D80h], eax
+ mov [esi+28D84h], eax
+ mov [esi+28D88h], eax
+ mov [esi+28D8Ch], eax
+ mov [esi+28D90h], eax
+ mov [esi+28D94h], eax
+ mov [esi+28D98h], eax
+ mov [esi+28D9Ch], eax
+ mov [esi+28DA0h], eax
+ mov [esi+28DA4h], eax
+ mov [esi+28DA8h], eax
+ mov [esi+28DACh], eax
+ mov [esi+28DB0h], eax
+ mov [esi+28DB4h], eax
+ xor eax, eax
+ pop edi
+ mov [esi+32F10h], bl
+ mov [esi+32F08h], eax
+ mov [esi+32F0Ch], eax
+ mov [esi+32F04h], eax
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn
+sub_4CDEA0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CF450 proc near ; CODE XREF: .text:004CF692p
+ ; CEncoder_Flush+42p
+
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+
+ sub esp, 8
+ push esi
+ mov esi, ecx
+ mov eax, [esi+0Ch]
+ push edi
+ mov edi, [esi+4]
+ cmp eax, edi
+ jb short loc_4CF464
+ mov edi, [esi+10h]
+
+loc_4CF464: ; CODE XREF: sub_4CF450+Fj
+ push ebp
+ mov ebp, [esi+20h]
+ xor edx, edx
+ sub edi, eax
+ cmp ebp, edx
+ mov [esp+14h+var_4], edx
+ jz short loc_4CF4BA
+ push ebx
+ mov ebx, [esi]
+ add ebx, eax
+ mov eax, dword_553598
+ cmp eax, edx
+ jnz short loc_4CF4A5
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ xor ecx, ecx
+ add esp, 4
+ cmp eax, ecx
+ jz short loc_4CF49C
+ mov [eax], ecx
+ mov [eax+4], ecx
+ mov [eax+8], ecx
+ jmp short loc_4CF49E
+; ---------------------------------------------------------------------------
+
+loc_4CF49C: ; CODE XREF: sub_4CF450+40j
+ xor eax, eax
+
+loc_4CF49E: ; CODE XREF: sub_4CF450+4Aj
+ mov dword_553598, eax
+ xor edx, edx
+
+loc_4CF4A5: ; CODE XREF: sub_4CF450+30j
+ mov eax, [eax+8]
+ cmp eax, edx
+ jz short loc_4CF4B6
+ push edi
+ push ebx
+ push ebp
+ call eax
+ add esp, 0Ch
+ xor edx, edx
+
+loc_4CF4B6: ; CODE XREF: sub_4CF450+5Aj
+ add [esi+20h], edi
+ pop ebx
+
+loc_4CF4BA: ; CODE XREF: sub_4CF450+22j
+ mov eax, [esi+14h]
+ cmp eax, edx
+ pop ebp
+ jz short loc_4CF4E4
+ mov [esp+10h+var_8], edx
+ mov ecx, [eax]
+ lea edx, [esp+10h+var_8]
+ push edx
+ mov edx, [esi]
+ add edx, [esi+0Ch]
+ push edi
+ push edx
+ push eax
+ mov eax, [ecx+0Ch]
+ call eax
+ mov edi, [esp+10h+var_8]
+ mov [esp+10h+var_4], eax
+ xor edx, edx
+
+loc_4CF4E4: ; CODE XREF: sub_4CF450+70j
+ add [esi+0Ch], edi
+ mov ecx, [esi+0Ch]
+ mov eax, [esi+10h]
+ cmp ecx, eax
+ jnz short loc_4CF4F4
+ mov [esi+0Ch], edx
+
+loc_4CF4F4: ; CODE XREF: sub_4CF450+9Fj
+ cmp [esi+4], eax
+ jnz short loc_4CF500
+ mov byte ptr [esi+24h], 1
+ mov [esi+4], edx
+
+loc_4CF500: ; CODE XREF: sub_4CF450+A7j
+ mov ecx, [esi+0Ch]
+ cmp ecx, [esi+4]
+ jbe short loc_4CF50A
+ mov eax, ecx
+
+loc_4CF50A: ; CODE XREF: sub_4CF450+B6j
+ add [esi+18h], edi
+ mov [esi+8], eax
+ mov eax, [esp+10h+var_4]
+ adc [esi+1Ch], edx
+ pop edi
+ pop esi
+ add esp, 8
+ retn
+sub_4CF450 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+
+; ---------------------------------------------------------------------------
+
+; int __stdcall Interface1_QueryInterface(int, void *Buf1, int)
+Interface1_QueryInterface proc near ; DATA XREF: .rdata:off_517A90o
+; sub_4CF520
+
+arg_0 = dword ptr 4
+Buf1 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ mov eax, [esp+Buf1]
+ push offset dword_512730 ; Buf2
+ push eax ; Buf1
+ call unknown_libname_324 ; MFC 3.1/4.0/4.2/8.0 32bit
+ add esp, 8
+ test eax, eax
+ jz short loc_4CF54D
+ mov eax, [esp+arg_0]
+ mov ecx, [esp+arg_8]
+ mov [ecx], eax
+ mov edx, [eax]
+ push eax
+ mov eax, [edx+4]
+ call eax
+ xor eax, eax
+ retn 0Ch
+loc_4CF54D: ; CODE XREF: Interface1_QueryInterface+14j
+ mov eax, 80004002h
+ retn 0Ch
+Interface1_QueryInterface endp
+
+; ---------------------------------------------------------------------------
+
+; int __stdcall Interface1_Release(void *pUnknown)
+Interface1_Release proc near ; DATA XREF: .rdata:00517A98o
+
+pUnknown = dword ptr 4
+
+ mov ecx, [esp+pUnknown]
+ add dword ptr [ecx+4], 0FFFFFFFFh
+ mov eax, [ecx+4]
+ jnz short locret_4CF585
+ push ecx ; Memory
+ mov dword ptr [ecx], offset off_517A90
+ mov dword ptr [ecx+8], 0
+ call j__free
+ add esp, 4
+ xor eax, eax
+
+locret_4CF585: ; CODE XREF: Interface1_Release+Bj
+ retn 4
+Interface1_Release endp
+
+; ---------------------------------------------------------------------------
+
+sub_4CF590 proc near ; DATA XREF: .rdata:00517AB4o
+
+arg_0 = dword ptr 4
+arg_4 = byte ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+
+ mov eax, [esp+arg_0]
+ mov edx, [eax+10h]
+ sub edx, [eax+18h]
+ mov ecx, [eax+14h]
+ sbb ecx, [eax+1Ch]
+ push ebx
+ mov ebx, [esp+4+arg_8]
+ push edi
+ mov edi, [esp+8+arg_C]
+ cmp edi, ecx
+ jb short loc_4CF5C2
+ ja short loc_4CF5B4
+ cmp ebx, edx
+ jbe short loc_4CF5C2
+
+loc_4CF5B4: ; CODE XREF: sub_4CF590+1Ej
+ pop edi
+ mov byte ptr [eax+20h], 1
+ mov eax, 80004005h
+ pop ebx
+ retn 10h
+; ---------------------------------------------------------------------------
+
+loc_4CF5C2: ; CODE XREF: sub_4CF590+1Cj
+ ; sub_4CF590+22j
+ push esi
+ xor esi, esi
+ xor ecx, ecx
+ test edi, edi
+ jb short loc_4CF5FA
+ ja short loc_4CF5D1
+ test ebx, ebx
+ jbe short loc_4CF5FA
+
+loc_4CF5D1: ; CODE XREF: sub_4CF590+3Bj
+ mov dl, [esp+0Ch+arg_4]
+ push ebp
+
+loc_4CF5D6: ; CODE XREF: sub_4CF590+5Fj
+ ; sub_4CF590+67j
+ mov ebp, [eax+18h]
+ mov ebx, [eax+8]
+ mov [ebx+ebp], dl
+ add dword ptr [eax+18h], 1
+ adc dword ptr [eax+1Ch], 0
+ add esi, 1
+ adc ecx, 0
+ cmp ecx, edi
+ jb short loc_4CF5D6
+ ja short loc_4CF5F9
+ cmp esi, [esp+10h+arg_8]
+ jb short loc_4CF5D6
+
+loc_4CF5F9: ; CODE XREF: sub_4CF590+61j
+ pop ebp
+
+loc_4CF5FA: ; CODE XREF: sub_4CF590+39j
+ ; sub_4CF590+3Fj
+ pop esi
+ pop edi
+ xor eax, eax
+ pop ebx
+ retn 10h
+sub_4CF590 endp
+
+; =============== S U B R O U T I N E =======================================
+
+; int __stdcall Interface2_Release(void *pUnknown)
+Interface2_Release proc near ; DATA XREF: .rdata:00517AACo
+; sub_4CF610
+
+pUnknown = dword ptr 4
+
+ mov ecx, [esp+pUnknown]
+ add dword ptr [ecx+4], 0FFFFFFFFh
+ mov eax, [ecx+4]
+ jnz short locret_4CF635
+ push ecx ; Memory
+ mov dword ptr [ecx], offset off_517AA4
+ mov dword ptr [ecx+8], 0
+ call j__free
+ add esp, 4
+ xor eax, eax
+
+locret_4CF635: ; CODE XREF: Interface2_Release+Bj
+ retn 4
+Interface2_Release endp
+
+; =============== S U B R O U T I N E =======================================
+
+loc_4CF640: ; CODE XREF: sub_4CF6E0+39p
+ ; sub_4CFAC0+57p ...
+ push ecx
+ push ebx
+ push esi
+ push edi
+ mov edi, ecx
+ mov esi, [edi+8]
+ cmp esi, 0FF000000h
+ jb short loc_4CF661
+ mov edx, [edi+0Ch]
+ mov eax, esi
+ mov cl, 20h
+ call __allshr ; Microsoft VisualC 2-8/net runtime
+ test eax, eax
+ jz short loc_4CF6B6
+
+loc_4CF661: ; CODE XREF: .text:004CF64Fj
+ mov bl, [edi+4]
+ lea esi, [edi+18h]
+
+loc_4CF667: ; CODE XREF: .text:004CF6A9j
+ mov eax, [edi+8]
+ mov edx, [edi+0Ch]
+ mov cl, 20h
+ call __allshr ; Microsoft VisualC 2-8/net runtime
+ mov ecx, [esi+4]
+ mov edx, [esi]
+ add al, bl
+ mov [ecx+edx], al
+ add dword ptr [esi+4], 1
+ mov eax, [esi+4]
+ cmp eax, [esi+8]
+ jnz short loc_4CF6A3
+ cmp [esi+0Ch], eax
+ jz short loc_4CF6A3
+ nop
+
+loc_4CF690: ; CODE XREF: .text:004CF6A1j
+ mov ecx, esi
+ call sub_4CF450
+ test eax, eax
+ jnz short loc_4CF6CB
+ mov eax, [esi+0Ch]
+ cmp eax, [esi+4]
+ jnz short loc_4CF690
+
+loc_4CF6A3: ; CODE XREF: .text:004CF688j
+ ; .text:004CF68Dj
+ or bl, 0FFh
+ add dword ptr [edi], 0FFFFFFFFh
+ jnz short loc_4CF667
+ mov esi, [edi+8]
+ mov edx, esi
+ shr edx, 18h
+ mov [edi+4], dl
+
+loc_4CF6B6: ; CODE XREF: .text:004CF65Fj
+ add dword ptr [edi], 1
+ shl esi, 8
+ mov [edi+8], esi
+ mov dword ptr [edi+0Ch], 0
+ pop edi
+ pop esi
+ pop ebx
+ pop ecx
+ retn
+
+; ---------------------------------------------------------------------------
+
+loc_4CF6CB: ; CODE XREF: .text:004CF699j
+ push offset dword_526DD0
+ lea ecx, [esp+10h]
+ push ecx
+ mov [esp+14h], eax
+ int 3
+; call __CxxThrowException@8 ; _CxxThrowException(x,x)
+; ---------------------------------------------------------------------------
+
+ db 2 dup(0CCh)
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CF6E0 proc near ; CODE XREF: sub_4D0770+FBp
+ ; CEncoder_CodeOneBlock+6C5p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push esi
+ push edi
+ mov edi, [esp+8+arg_4]
+ add edi, 0FFFFFFFFh
+ mov esi, ecx
+ js short loc_4CF724
+ push ebp
+ mov ebp, [esp+0Ch+arg_0]
+
+loc_4CF6F2: ; CODE XREF: sub_4CF6E0+41j
+ shr dword ptr [esi+10h], 1
+ mov eax, [esi+10h]
+ mov edx, ebp
+ mov ecx, edi
+ shr edx, cl
+ test dl, 1
+ jz short loc_4CF70A
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+
+loc_4CF70A: ; CODE XREF: sub_4CF6E0+21j
+ cmp eax, 1000000h
+ jnb short loc_4CF71E
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4CF71E: ; CODE XREF: sub_4CF6E0+2Fj
+ sub edi, 1
+ jns short loc_4CF6F2
+ pop ebp
+
+loc_4CF724: ; CODE XREF: sub_4CF6E0+Bj
+ pop edi
+ pop esi
+ retn 8
+sub_4CF6E0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CF740 proc near ; CODE XREF: sub_4D0770+DFp
+ ; CEncoder_CodeOneBlock+58Ap ...
+
+arg_0 = dword ptr 4
+
+ push esi
+ push edi
+ mov edi, [esp+8+arg_0]
+ mov eax, edi
+ imul eax, 440h
+ mov esi, ecx
+ mov edx, [esi+4C08h]
+ lea ecx, [eax+esi+808h]
+ push ecx
+ push edx
+ push edi
+ mov ecx, esi
+ call sub_4CDC00
+ mov eax, [esi+4C08h]
+ mov [esi+edi*4+4C0Ch], eax
+ pop edi
+ pop esi
+ retn 4
+sub_4CF740 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CF780 proc near ; CODE XREF: CEncoder_SetStreams+7Ep
+ ; CEncoder_SetStreams+A6p
+
+arg_0 = dword ptr 4
+
+ push esi
+ push edi
+ xor edi, edi
+ cmp [esp+8+arg_0], edi
+ mov esi, ecx
+ jbe short loc_4CF7CC
+ push ebx
+ push ebp
+ lea ebx, [esi+4C0Ch]
+ lea ebp, [esi+808h]
+ lea ebx, [ebx+0]
+
+loc_4CF7A0: ; CODE XREF: sub_4CF780+48j
+ mov eax, [esi+4C08h]
+ push ebp
+ push eax
+ push edi
+ mov ecx, esi
+ call sub_4CDC00
+ mov ecx, [esi+4C08h]
+ mov [ebx], ecx
+ add edi, 1
+ add ebx, 4
+ add ebp, 440h
+ cmp edi, [esp+10h+arg_0]
+ jb short loc_4CF7A0
+ pop ebp
+ pop ebx
+
+loc_4CF7CC: ; CODE XREF: sub_4CF780+Aj
+ pop edi
+ pop esi
+ retn 4
+sub_4CF780 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+CEncoder_GetOptimum proc near ; CODE XREF: CEncoder_CodeOneBlock+201p
+
+var_7D = byte ptr -7Dh
+var_7C = dword ptr -7Ch
+var_78 = dword ptr -78h
+var_74 = dword ptr -74h
+var_70 = dword ptr -70h
+var_6C = dword ptr -6Ch
+var_68 = dword ptr -68h
+var_64 = dword ptr -64h
+var_60 = dword ptr -60h
+var_5C = dword ptr -5Ch
+var_58 = dword ptr -58h
+var_54 = dword ptr -54h
+var_50 = dword ptr -50h
+var_4C = dword ptr -4Ch
+var_48 = dword ptr -48h
+var_44 = dword ptr -44h
+var_40 = dword ptr -40h
+var_3C = dword ptr -3Ch
+var_38 = dword ptr -38h
+var_34 = dword ptr -34h
+var_30 = dword ptr -30h
+var_2C = dword ptr -2Ch
+var_28 = dword ptr -28h
+var_24 = dword ptr -24h
+var_20 = dword ptr -20h
+var_1C = dword ptr -1Ch
+var_18 = dword ptr -18h
+var_14 = dword ptr -14h
+var_10 = dword ptr -10h
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ sub esp, 80h
+ push ebp
+ mov ebp, ecx
+ mov edx, [ebp+32F0Ch]
+ cmp [ebp+32F08h], edx
+ push esi
+ jz short loc_4CE0A5
+ mov esi, [esp+88h+arg_4]
+ lea eax, [edx+edx*4+1Eh]
+ lea ecx, [ebp+eax*8+0]
+ mov eax, [ecx+10h]
+ sub eax, edx
+ mov edx, [ecx+14h]
+ mov [esi], edx
+ mov ecx, [ecx+10h]
+ pop esi
+ mov [ebp+32F0Ch], ecx
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE0A5: ; CODE XREF: CEncoder_GetOptimum+16j
+ mov edx, [ebp+80h]
+ mov eax, [ebp+70h]
+ push ebx
+ xor esi, esi
+ push edx
+ mov [ebp+32F08h], esi
+ mov [ebp+32F0Ch], esi
+ call eax
+ add esp, 4
+ cmp byte ptr [ebp+32F10h], 0
+ mov ebx, eax
+ mov [esp+8Ch+var_60], eax
+ jnz short loc_4CE0E4
+ lea ecx, [esp+8Ch+var_70]
+ push ecx
+ mov ecx, ebp
+ call sub_4CB3B0
+ mov [esp+8Ch+var_68], eax
+ jmp short loc_4CE0FF
+; ---------------------------------------------------------------------------
+
+loc_4CE0E4: ; CODE XREF: CEncoder_GetOptimum+70j
+ mov edx, [ebp+32EFCh]
+ mov eax, [ebp+32F00h]
+ mov [esp+8Ch+var_68], edx
+ mov [esp+8Ch+var_70], eax
+ mov byte ptr [ebp+32F10h], 0
+
+loc_4CE0FF: ; CODE XREF: CEncoder_GetOptimum+82j
+ mov ecx, [ebp+80h]
+ mov edx, [ebp+74h]
+ push edi
+ push ecx
+ call edx
+ mov edi, eax
+ add esp, 4
+ sub edi, 1
+ cmp ebx, 2
+ jnb short loc_4CE138
+ mov eax, [esp+90h+arg_4]
+ pop edi
+ pop ebx
+ pop esi
+ mov dword ptr [eax], 0FFFFFFFFh
+ mov eax, 1
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE138: ; CODE XREF: CEncoder_GetOptimum+B7j
+ cmp ebx, 111h
+ jbe short loc_4CE149
+ mov ebx, 111h
+ mov [esp+90h+var_60], ebx
+
+loc_4CE149: ; CODE XREF: CEncoder_GetOptimum+DEj
+ lea ecx, [ebp+14h]
+ mov [esp+90h+var_50], esi
+ mov [esp+90h+var_64], esi
+ xor edx, edx
+ mov [esp+90h+var_4C], esi
+ mov [esp+90h+var_6C], ecx
+ mov edi, edi
+
+loc_4CE160: ; CODE XREF: CEncoder_GetOptimum+180j
+ mov eax, [esp+90h+var_6C]
+ mov eax, [eax]
+ mov ecx, edi
+ sub ecx, eax
+ mov [esp+edx+90h+var_20], eax
+ mov al, [edi]
+ sub ecx, 1
+ cmp al, [ecx]
+ jnz short loc_4CE1C9
+ mov al, [edi+1]
+ cmp al, [ecx+1]
+ jnz short loc_4CE1C9
+ mov eax, 2
+ cmp ebx, eax
+ jbe short loc_4CE1A7
+ lea esi, [edi+2]
+ sub ecx, edi
+ lea ecx, [ecx+0]
+
+loc_4CE190: ; CODE XREF: CEncoder_GetOptimum+143j
+ mov bl, [esi]
+ cmp bl, [ecx+esi]
+ mov ebx, [esp+90h+var_60]
+ jnz short loc_4CE1A5
+ add eax, 1
+ add esi, 1
+ cmp eax, ebx
+ jb short loc_4CE190
+
+loc_4CE1A5: ; CODE XREF: CEncoder_GetOptimum+139j
+ xor esi, esi
+
+loc_4CE1A7: ; CODE XREF: CEncoder_GetOptimum+126j
+ mov ecx, [esp+90h+var_4C]
+ mov [esp+edx+90h+var_10], eax
+ cmp eax, [esp+ecx+90h+var_10]
+ jbe short loc_4CE1D0
+ mov eax, [esp+90h+var_64]
+ mov [esp+90h+var_50], eax
+ mov [esp+90h+var_4C], edx
+ jmp short loc_4CE1D0
+; ---------------------------------------------------------------------------
+
+loc_4CE1C9: ; CODE XREF: CEncoder_GetOptimum+115j
+ ; CEncoder_GetOptimum+11Dj
+ mov [esp+edx+90h+var_10], esi
+
+loc_4CE1D0: ; CODE XREF: CEncoder_GetOptimum+159j
+ ; CEncoder_GetOptimum+167j
+ add [esp+90h+var_64], 1
+ add [esp+90h+var_6C], 4
+ add edx, 4
+ cmp edx, 10h
+ jb loc_4CE160
+ mov ecx, [esp+90h+var_50]
+ mov ebx, [esp+ecx*4+90h+var_10]
+ mov eax, [ebp+32EF8h]
+ cmp ebx, eax
+ mov [esp+90h+var_40], ebx
+ jb short loc_4CE234
+ mov edx, [esp+90h+arg_4]
+ lea eax, [ebx-1]
+ cmp eax, esi
+ mov [edx], ecx
+ jz short loc_4CE225
+ add [ebp+32F04h], eax
+ mov ecx, [ebp+7Ch]
+ push eax
+ mov eax, [ebp+80h]
+ push eax
+ call ecx
+ add esp, 8
+
+loc_4CE225: ; CODE XREF: CEncoder_GetOptimum+1ADj
+ pop edi
+ mov eax, ebx
+ pop ebx
+ pop esi
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE234: ; CODE XREF: CEncoder_GetOptimum+19Dj
+ mov esi, [esp+90h+var_68]
+ cmp esi, eax
+ jb short loc_4CE27F
+ mov edx, [esp+90h+var_70]
+ mov eax, [ebp+edx*4+3265Ch]
+ mov ecx, [esp+90h+arg_4]
+ add eax, 4
+ mov [ecx], eax
+ lea eax, [esi-1]
+ test eax, eax
+ jz short loc_4CE270
+ mov edx, [ebp+80h]
+ add [ebp+32F04h], eax
+ push eax
+ mov eax, [ebp+7Ch]
+ push edx
+ call eax
+ add esp, 8
+
+loc_4CE270: ; CODE XREF: CEncoder_GetOptimum+1F8j
+ pop edi
+ pop ebx
+ mov eax, esi
+ pop esi
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE27F: ; CODE XREF: CEncoder_GetOptimum+1DAj
+ mov al, [edi]
+ mov esi, [esp+90h+var_20]
+ sub edi, esi
+ cmp [esp+90h+var_68], 2
+ mov cl, [edi-1]
+ mov byte ptr [esp+90h+var_4C], al
+ mov byte ptr [esp+90h+var_50], cl
+ jnb short loc_4CE2C1
+ cmp al, cl
+ jz short loc_4CE2C1
+ cmp ebx, 2
+ jnb short loc_4CE2C1
+ mov ecx, [esp+90h+arg_4]
+ pop edi
+ pop ebx
+ pop esi
+ mov dword ptr [ecx], 0FFFFFFFFh
+ mov eax, 1
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE2C1: ; CODE XREF: CEncoder_GetOptimum+237j
+ ; CEncoder_GetOptimum+23Bj ...
+ mov edx, [esp+90h+var_4C]
+ mov bl, [ebp+10h]
+ mov edi, [ebp+33B60h]
+ and edi, [esp+90h+arg_0]
+ mov ecx, [esp+90h+var_50]
+ push edx
+ cmp bl, 7
+ setnb dl
+ push ecx
+ mov [ebp+0F0h], bl
+ mov eax, [ebp+32654h]
+ mov ecx, 8
+ sub cl, al
+ push edx
+ movzx edx, byte ptr [ebp+11h]
+ shr edx, cl
+ mov ecx, [ebp+3265Ch]
+ and ecx, [esp+9Ch+arg_0]
+ mov [esp+9Ch+var_3C], ecx
+ mov ecx, eax
+ mov eax, [esp+9Ch+var_3C]
+ shl eax, cl
+ add edx, eax
+ imul edx, 0C00h
+ add edx, [ebp+32650h]
+ mov ecx, edx
+ call sub_4CDAC0
+ movzx ecx, bl
+ shl ecx, 4
+ add ecx, edi
+ mov edx, [ebp+ecx*4+280F0h]
+ shr edx, 2
+ add eax, dword_550998[edx*4]
+ mov ebx, 800h
+ mov [ebp+124h], eax
+ mov dword ptr [ebp+12Ch], 0FFFFFFFFh
+ mov byte ptr [ebp+119h], 0
+ mov cl, [ebp+10h]
+ movzx eax, cl
+ mov edx, eax
+ shl edx, 4
+ add edx, edi
+ sub ebx, [ebp+edx*4+280F0h]
+ mov edx, 800h
+ sub edx, [ebp+eax*4+283F0h]
+ mov al, byte ptr [esp+90h+var_4C]
+ shr edx, 2
+ mov edx, dword_550998[edx*4]
+ shr ebx, 2
+ mov ebx, dword_550998[ebx*4]
+ add edx, ebx
+ cmp byte ptr [esp+90h+var_50], al
+ mov [esp+90h+var_44], ebx
+ mov [esp+90h+var_3C], edx
+ jnz short loc_4CE3F3
+ movzx eax, cl
+ mov ebx, [ebp+eax*4+28420h]
+ mov ecx, eax
+ shl ecx, 4
+ add ecx, edi
+ mov ecx, [ebp+ecx*4+284B0h]
+ shr ecx, 2
+ mov eax, dword_550998[ecx*4]
+ shr ebx, 2
+ add eax, dword_550998[ebx*4]
+ add eax, edx
+ cmp eax, [ebp+124h]
+ jnb short loc_4CE3F3
+ mov [ebp+124h], eax
+ mov dword ptr [ebp+12Ch], 0
+ mov byte ptr [ebp+119h], 0
+
+loc_4CE3F3: ; CODE XREF: CEncoder_GetOptimum+344j
+ ; CEncoder_GetOptimum+37Aj
+ mov eax, [esp+90h+var_68]
+ mov ecx, [esp+90h+var_40]
+ cmp eax, ecx
+ jb short loc_4CE405
+ mov [esp+90h+var_7C], eax
+ jmp short loc_4CE40B
+; ---------------------------------------------------------------------------
+
+loc_4CE405: ; CODE XREF: CEncoder_GetOptimum+39Dj
+ mov [esp+90h+var_7C], ecx
+ mov eax, ecx
+
+loc_4CE40B: ; CODE XREF: CEncoder_GetOptimum+3A3j
+ cmp eax, 2
+ jnb short loc_4CE431
+ mov edx, [ebp+12Ch]
+ mov eax, [esp+90h+arg_4]
+ pop edi
+ pop ebx
+ pop esi
+ mov [eax], edx
+ mov eax, 1
+ pop ebp
+ add esp, 80h
+ retn 8
+; ---------------------------------------------------------------------------
+
+loc_4CE431: ; CODE XREF: CEncoder_GetOptimum+3AEj
+ mov ecx, [esp+90h+var_1C]
+ mov edx, [esp+90h+var_18]
+ xor ebx, ebx
+ mov [ebp+128h], ebx
+ mov [ebp+10Ch], ecx
+ mov ecx, [esp+90h+var_14]
+ mov [ebp+110h], edx
+ lea edx, [eax+eax*4]
+ mov [ebp+114h], ecx
+ mov [ebp+108h], esi
+ lea ecx, [ebp+edx*8+0FCh]
+ jmp short loc_4CE470
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CE470: ; CODE XREF: CEncoder_GetOptimum+407j
+ ; CEncoder_GetOptimum+41Fj
+ mov dword ptr [ecx], 0FFFFFFFh
+ sub eax, 1
+ sub ecx, 28h
+ cmp eax, 2
+ jnb short loc_4CE470
+
+loc_4CE481: ; CODE XREF: CEncoder_GetOptimum+48Ej
+ mov esi, [esp+ebx*4+90h+var_10]
+ cmp esi, 2
+ jb short loc_4CE4E8
+ movzx eax, byte ptr [ebp+10h]
+ push edi
+ push eax
+ push ebx
+ mov ecx, ebp
+ call sub_4CD9B0
+ add eax, [esp+90h+var_3C]
+ mov ecx, edi
+ imul ecx, 110h
+ add ecx, esi
+ mov [esp+90h+var_40], eax
+ lea edx, [esi+esi*4]
+ lea eax, [ebp+ecx*4+2E204h]
+ lea ecx, [ebp+edx*8+0FCh]
+ mov edi, edi
+
+loc_4CE4C0: ; CODE XREF: CEncoder_GetOptimum+486j
+ mov edx, [eax]
+ add edx, [esp+90h+var_40]
+ cmp edx, [ecx]
+ jnb short loc_4CE4DA
+ mov [ecx], edx
+ mov dword ptr [ecx+4], 0
+ mov [ecx+8], ebx
+ mov byte ptr [ecx-0Bh], 0
+
+loc_4CE4DA: ; CODE XREF: CEncoder_GetOptimum+468j
+ sub esi, 1
+ sub eax, 4
+ sub ecx, 28h
+ cmp esi, 2
+ jnb short loc_4CE4C0
+
+loc_4CE4E8: ; CODE XREF: CEncoder_GetOptimum+42Bj
+ add ebx, 1
+ cmp ebx, 4
+ jb short loc_4CE481
+ movzx eax, byte ptr [ebp+10h]
+ mov ecx, [ebp+eax*4+283F0h]
+ shr ecx, 2
+ mov eax, dword_550998[ecx*4]
+ add eax, [esp+90h+var_44]
+ mov [esp+90h+var_3C], eax
+ mov eax, [esp+90h+var_10]
+ cmp eax, 2
+ lea ebx, [eax+1]
+ jnb short loc_4CE521
+ mov ebx, 2
+
+loc_4CE521: ; CODE XREF: CEncoder_GetOptimum+4BAj
+ cmp ebx, [esp+90h+var_68]
+ ja loc_4CE5BA
+ xor eax, eax
+ cmp ebx, [ebp+32660h]
+ mov [esp+90h+var_60], eax
+ jbe short loc_4CE550
+ lea esp, [esp+0]
+
+loc_4CE540: ; CODE XREF: CEncoder_GetOptimum+4EAj
+ add eax, 2
+ cmp ebx, [ebp+eax*4+32660h]
+ ja short loc_4CE540
+ mov [esp+90h+var_60], eax
+
+loc_4CE550: ; CODE XREF: CEncoder_GetOptimum+4D7j
+ lea edx, [ebx+ebx*4]
+ lea esi, [ebp+edx*8+0FCh]
+ lea ebx, [ebx+0]
+
+loc_4CE560: ; CODE XREF: CEncoder_GetOptimum+558j
+ mov eax, [esp+90h+var_60]
+ mov eax, [ebp+eax*4+32664h]
+ push edi
+ push ebx
+ push eax
+ mov ecx, ebp
+ mov [esp+9Ch+var_40], eax
+ call sub_4CAEC0
+ add eax, [esp+90h+var_3C]
+ cmp eax, [esi]
+ jnb short loc_4CE598
+ mov ecx, [esp+90h+var_40]
+ add ecx, 4
+ mov [esi], eax
+ mov dword ptr [esi+4], 0
+ mov [esi+8], ecx
+ mov byte ptr [esi-0Bh], 0
+
+loc_4CE598: ; CODE XREF: CEncoder_GetOptimum+51Fj
+ mov eax, [esp+90h+var_60]
+ cmp ebx, [ebp+eax*4+32660h]
+ jnz short loc_4CE5B2
+ add eax, 2
+ cmp eax, [esp+90h+var_70]
+ mov [esp+90h+var_60], eax
+ jz short loc_4CE5BA
+
+loc_4CE5B2: ; CODE XREF: CEncoder_GetOptimum+543j
+ add ebx, 1
+ add esi, 28h
+ jmp short loc_4CE560
+; ---------------------------------------------------------------------------
+
+loc_4CE5BA: ; CODE XREF: CEncoder_GetOptimum+4C5j
+ ; CEncoder_GetOptimum+550j
+ mov eax, 1
+ cmp [esp+90h+var_7C], eax
+ mov [esp+90h+var_78], eax
+ jz loc_4CF1D0
+ mov esi, eax
+ jmp short loc_4CE5D5
+; ---------------------------------------------------------------------------
+
+loc_4CE5D1: ; CODE XREF: CEncoder_GetOptimum+116Aj
+ mov esi, [esp+90h+var_78]
+
+loc_4CE5D5: ; CODE XREF: CEncoder_GetOptimum+56Fj
+ mov edx, [ebp+80h]
+ mov eax, [ebp+70h]
+ push edx
+ call eax
+ add esp, 4
+ lea ecx, [esp+90h+var_4C]
+ push ecx
+ mov ecx, ebp
+ mov [esp+94h+var_60], eax
+ call sub_4CB3B0
+ cmp eax, [ebp+32EF8h]
+ mov [esp+90h+var_28], eax
+ jnb loc_4CF1D7
+ add [esp+90h+arg_0], 1
+ lea edx, [esi+esi*4+1Eh]
+ mov bl, [ebp+edx*8+1]
+ test bl, bl
+ lea eax, [ebp+edx*8+0]
+ mov edx, [eax+10h]
+ jz short loc_4CE673
+ sub edx, 1
+ cmp byte ptr [eax+2], 0
+ jz short loc_4CE660
+ mov ecx, [eax+4]
+ add ecx, 6
+ cmp dword ptr [eax+8], 4
+ lea ecx, [ecx+ecx*4]
+ mov cl, [ebp+ecx*8+0]
+ movzx ecx, cl
+ jnb short loc_4CE64F
+ mov cl, ds:kRepNextStates[ecx]
+ movzx ecx, cl
+ mov cl, ds:kLiteralNextStates[ecx]
+ jmp short loc_4CE67B
+; ---------------------------------------------------------------------------
+
+loc_4CE64F: ; CODE XREF: CEncoder_GetOptimum+5DCj
+ mov cl, ds:kMatchNextStates[ecx]
+ movzx ecx, cl
+ mov cl, ds:kLiteralNextStates[ecx]
+ jmp short loc_4CE67B
+; ---------------------------------------------------------------------------
+
+loc_4CE660: ; CODE XREF: CEncoder_GetOptimum+5C6j
+ lea ecx, [edx+edx*4+1Eh]
+ mov cl, [ebp+ecx*8+0]
+ movzx ecx, cl
+ mov cl, ds:kLiteralNextStates[ecx]
+ jmp short loc_4CE67B
+; ---------------------------------------------------------------------------
+
+loc_4CE673: ; CODE XREF: CEncoder_GetOptimum+5BDj
+ lea ecx, [edx+edx*4+1Eh]
+ mov cl, [ebp+ecx*8+0]
+
+loc_4CE67B: ; CODE XREF: CEncoder_GetOptimum+5EDj
+ ; CEncoder_GetOptimum+5FEj ...
+ add esi, 0FFFFFFFFh
+ cmp edx, esi
+ jnz short loc_4CE6AC
+ cmp dword ptr [eax+14h], 0
+ jnz short loc_4CE69A
+ movzx edx, cl
+ mov bl, ds:kShortRepNextStates[edx]
+ mov byte ptr [esp+90h+var_64], bl
+ jmp loc_4CE754
+; ---------------------------------------------------------------------------
+
+loc_4CE69A: ; CODE XREF: CEncoder_GetOptimum+626j
+ movzx ecx, cl
+ mov bl, ds:kLiteralNextStates[ecx]
+ mov byte ptr [esp+90h+var_64], bl
+ jmp loc_4CE754
+; ---------------------------------------------------------------------------
+
+loc_4CE6AC: ; CODE XREF: CEncoder_GetOptimum+620j
+ test bl, bl
+ jz short loc_4CE6CB
+ cmp byte ptr [eax+2], 0
+ jz short loc_4CE6CB
+ mov edi, [eax+8]
+ mov edx, [eax+4]
+ movzx ecx, cl
+ mov bl, ds:kRepNextStates[ecx]
+ mov [esp+90h+var_68], edi
+ jmp short loc_4CE6EA
+; ---------------------------------------------------------------------------
+
+loc_4CE6CB: ; CODE XREF: CEncoder_GetOptimum+64Ej
+ ; CEncoder_GetOptimum+654j
+ mov esi, [eax+14h]
+ cmp esi, 4
+ mov [esp+90h+var_68], esi
+ movzx ecx, cl
+ mov edi, esi
+ jnb short loc_4CE6E4
+ mov bl, ds:kRepNextStates[ecx]
+ jmp short loc_4CE6EA
+; ---------------------------------------------------------------------------
+
+loc_4CE6E4: ; CODE XREF: CEncoder_GetOptimum+67Aj
+ mov bl, ds:kMatchNextStates[ecx]
+
+loc_4CE6EA: ; CODE XREF: CEncoder_GetOptimum+669j
+ ; CEncoder_GetOptimum+682j
+ cmp edi, 4
+ lea edx, [edx+edx*4+1Eh]
+ mov byte ptr [esp+90h+var_64], bl
+ lea edx, [ebp+edx*8+0]
+ jnb short loc_4CE738
+ mov ecx, [edx+edi*4+18h]
+ mov esi, 1
+ cmp edi, esi
+ mov [esp+90h+var_20], ecx
+ jb short loc_4CE723
+ mov ecx, edi
+ lea esi, [edx+18h]
+ lea edi, [esp+90h+var_1C]
+ rep movsd
+ mov esi, [esp+90h+var_68]
+ add esi, 1
+ cmp esi, 4
+ jnb short loc_4CE754
+
+loc_4CE723: ; CODE XREF: CEncoder_GetOptimum+6AAj
+ lea edx, [edx+esi*4+18h]
+ mov ecx, 4
+ lea edi, [esp+esi*4+90h+var_20]
+ sub ecx, esi
+ mov esi, edx
+ rep movsd
+ jmp short loc_4CE754
+; ---------------------------------------------------------------------------
+
+loc_4CE738: ; CODE XREF: CEncoder_GetOptimum+699j
+ mov ecx, [edx+18h]
+ mov [esp+90h+var_1C], ecx
+ mov ecx, [edx+1Ch]
+ mov edx, [edx+20h]
+ add edi, 0FFFFFFFCh
+ mov [esp+90h+var_20], edi
+ mov [esp+90h+var_18], ecx
+ mov [esp+90h+var_14], edx
+
+loc_4CE754: ; CODE XREF: CEncoder_GetOptimum+635j
+ ; CEncoder_GetOptimum+647j ...
+ mov ecx, [esp+90h+var_1C]
+ mov edx, [esp+90h+var_18]
+ mov edi, [esp+90h+var_20]
+ mov [eax], bl
+ mov [eax+1Ch], ecx
+ mov ecx, [esp+90h+var_14]
+ mov [eax+18h], edi
+ mov [eax+20h], edx
+ mov [eax+24h], ecx
+ mov esi, [eax+0Ch]
+ mov edx, [ebp+80h]
+ mov eax, [ebp+74h]
+ push edx
+ mov [esp+94h+var_3C], esi
+ call eax
+ movzx ecx, byte ptr [eax-1]
+ sub eax, 1
+ mov edx, eax
+ mov byte ptr [esp+94h+var_5C], cl
+ sub edx, edi
+ movzx ecx, byte ptr [edx-1]
+ lea edi, [edx-1]
+ mov edx, [ebp+32654h]
+ mov byte ptr [esp+94h+var_58], cl
+ mov ecx, [ebp+33B60h]
+ and ecx, [esp+94h+arg_0]
+ mov [esp+94h+var_40], edi
+ movzx edi, bl
+ mov [esp+94h+var_54], ecx
+ mov [esp+94h+var_68], edi
+ add esp, 4
+ shl edi, 4
+ add edi, ecx
+ mov ecx, [esp+90h+var_5C]
+ push ecx
+ mov ecx, [esp+94h+var_58]
+ push ecx
+ cmp bl, 7
+ mov ebx, [ebp+3265Ch]
+ setnb cl
+ and ebx, [esp+98h+arg_0]
+ mov [esp+98h+var_74], eax
+ movzx eax, byte ptr [eax-1]
+ push ecx
+ mov ecx, 8
+ sub cl, dl
+ shr eax, cl
+ mov ecx, edx
+ shl ebx, cl
+ add eax, ebx
+ imul eax, 0C00h
+ add eax, [ebp+32650h]
+ mov ecx, eax
+ call sub_4CDAC0
+ mov ecx, [ebp+edi*4+280F0h]
+ shr ecx, 2
+ add eax, dword_550998[ecx*4]
+ mov ecx, [esp+90h+var_78]
+ add eax, esi
+ lea edx, [ecx+ecx*4+23h]
+ cmp eax, [ebp+edx*8+0Ch]
+ lea esi, [ebp+edx*8+0]
+ mov [esp+90h+var_7D], 0
+ jnb short loc_4CE851
+ mov [esi+0Ch], eax
+ mov [esi+10h], ecx
+ mov dword ptr [esi+14h], 0FFFFFFFFh
+ mov byte ptr [esi+1], 0
+ mov [esp+90h+var_7D], 1
+
+loc_4CE851: ; CODE XREF: CEncoder_GetOptimum+7D9j
+ mov ebx, [esp+90h+var_68]
+ mov edx, 800h
+ sub edx, [ebp+edi*4+280F0h]
+ shr edx, 2
+ mov ecx, dword_550998[edx*4]
+ add ecx, [esp+90h+var_3C]
+ mov edx, 800h
+ sub edx, [ebp+ebx*4+283F0h]
+ mov ebx, [esp+90h+var_78]
+ shr edx, 2
+ mov edx, dword_550998[edx*4]
+ add edx, ecx
+ mov [esp+90h+var_24], ecx
+ mov cl, byte ptr [esp+90h+var_58]
+ cmp cl, byte ptr [esp+90h+var_5C]
+ mov [esp+90h+var_38], edx
+ jnz short loc_4CE8EB
+ cmp [esi+10h], ebx
+ jnb short loc_4CE8A8
+ cmp dword ptr [esi+14h], 0
+ jz short loc_4CE8EB
+
+loc_4CE8A8: ; CODE XREF: CEncoder_GetOptimum+840j
+ mov ecx, [esp+90h+var_68]
+ mov ecx, [ebp+ecx*4+28420h]
+ mov edi, [ebp+edi*4+284B0h]
+ shr ecx, 2
+ mov ecx, dword_550998[ecx*4]
+ shr edi, 2
+ add ecx, dword_550998[edi*4]
+ add ecx, edx
+ cmp ecx, [esi+0Ch]
+ ja short loc_4CE8EB
+ mov [esi+0Ch], ecx
+ mov [esi+10h], ebx
+ mov dword ptr [esi+14h], 0
+ mov byte ptr [esi+1], 0
+ mov [esp+90h+var_7D], 1
+
+loc_4CE8EB: ; CODE XREF: CEncoder_GetOptimum+83Bj
+ ; CEncoder_GetOptimum+846j ...
+ mov edx, [esp+90h+var_60]
+ mov ecx, 0FFFh
+ sub ecx, ebx
+ cmp ecx, edx
+ jnb short loc_4CE900
+ mov edx, ecx
+ mov [esp+90h+var_60], edx
+
+loc_4CE900: ; CODE XREF: CEncoder_GetOptimum+898j
+ cmp edx, 2
+ mov ebx, edx
+ mov [esp+90h+var_6C], ebx
+ jb loc_4CF1BB
+ mov esi, [ebp+32EF8h]
+ mov edi, [esp+90h+var_60]
+ cmp edi, esi
+ jbe short loc_4CE923
+ mov ebx, esi
+ mov [esp+90h+var_6C], esi
+
+loc_4CE923: ; CODE XREF: CEncoder_GetOptimum+8BBj
+ cmp [esp+90h+var_7D], 0
+ jnz loc_4CEA90
+ mov dl, byte ptr [esp+90h+var_5C]
+ cmp byte ptr [esp+90h+var_58], dl
+ jz loc_4CEA90
+ lea ecx, [esi+1]
+ cmp edi, ecx
+ jb short loc_4CE945
+ mov edi, ecx
+
+loc_4CE945: ; CODE XREF: CEncoder_GetOptimum+8E1j
+ mov esi, 1
+ cmp edi, esi
+ jbe short loc_4CE975
+ mov ebx, [esp+90h+var_74]
+ mov edx, [esp+90h+var_40]
+ lea ecx, [ebx+1]
+ sub edx, ebx
+ jmp short loc_4CE960
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CE960: ; CODE XREF: CEncoder_GetOptimum+8FBj
+ ; CEncoder_GetOptimum+90Fj
+ mov bl, [ecx]
+ cmp bl, [edx+ecx]
+ jnz short loc_4CE971
+ add esi, 1
+ add ecx, 1
+ cmp esi, edi
+ jb short loc_4CE960
+
+loc_4CE971: ; CODE XREF: CEncoder_GetOptimum+905j
+ mov ebx, [esp+90h+var_6C]
+
+loc_4CE975: ; CODE XREF: CEncoder_GetOptimum+8ECj
+ add esi, 0FFFFFFFFh
+ cmp esi, 2
+ mov [esp+90h+var_50], esi
+ jb loc_4CEA90
+ mov ecx, [esp+90h+var_68]
+ mov dl, ds:kLiteralNextStates[ecx]
+ mov ecx, [esp+90h+arg_0]
+ movzx ebx, dl
+ add ecx, 1
+ and ecx, [ebp+33B60h]
+ mov edx, ebx
+ shl edx, 4
+ lea esi, [edx+ecx]
+ mov edx, 800h
+ sub edx, [ebp+ebx*4+283F0h]
+ mov edi, 800h
+ sub edi, [ebp+esi*4+280F0h]
+ shr edx, 2
+ mov edx, dword_550998[edx*4]
+ shr edi, 2
+ add edx, dword_550998[edi*4]
+ mov edi, [esp+90h+var_78]
+ add edx, eax
+ mov eax, [esp+90h+var_50]
+ lea edi, [eax+edi+1]
+ mov eax, [esp+90h+var_7C]
+ cmp eax, edi
+ mov [esp+90h+var_40], esi
+ jnb short loc_4CEA22
+ mov esi, [esp+90h+var_7C]
+ lea eax, [eax+eax*4]
+ lea eax, [ebp+eax*8+0FCh]
+ mov [esp+90h+var_3C], eax
+ mov eax, edi
+ sub eax, esi
+ add esi, eax
+ mov [esp+90h+var_7C], esi
+ mov esi, [esp+90h+var_3C]
+
+loc_4CEA10: ; CODE XREF: CEncoder_GetOptimum+9BCj
+ add esi, 28h
+ sub eax, 1
+ mov dword ptr [esi], 0FFFFFFFh
+ jnz short loc_4CEA10
+ mov esi, [esp+90h+var_40]
+
+loc_4CEA22: ; CODE XREF: CEncoder_GetOptimum+98Ej
+ imul ecx, 110h
+ add ecx, [esp+90h+var_50]
+ mov eax, 800h
+ sub eax, [ebp+esi*4+284B0h]
+ mov esi, [ebp+ebx*4+28420h]
+ mov ebx, [esp+90h+var_6C]
+ shr eax, 2
+ mov eax, dword_550998[eax*4]
+ shr esi, 2
+ add eax, dword_550998[esi*4]
+ mov esi, [esp+90h+var_7C]
+ add eax, [ebp+ecx*4+2E204h]
+ lea ecx, [edi+edi*4+1Eh]
+ add eax, edx
+ cmp eax, [ebp+ecx*8+0Ch]
+ lea ecx, [ebp+ecx*8+0]
+ jnb short loc_4CEA94
+ mov edx, [esp+90h+var_78]
+ add edx, 1
+ mov [ecx+0Ch], eax
+ mov [ecx+10h], edx
+ mov dword ptr [ecx+14h], 0
+ mov byte ptr [ecx+1], 1
+ mov byte ptr [ecx+2], 0
+ jmp short loc_4CEA94
+; ---------------------------------------------------------------------------
+
+loc_4CEA90: ; CODE XREF: CEncoder_GetOptimum+8C8j
+ ; CEncoder_GetOptimum+8D6j ...
+ mov esi, [esp+90h+var_7C]
+
+loc_4CEA94: ; CODE XREF: CEncoder_GetOptimum+A10j
+ ; CEncoder_GetOptimum+A2Ej
+ mov [esp+90h+var_70], 0
+ mov ecx, [esp+90h+var_70]
+ mov [esp+90h+var_40], 2
+ jmp short loc_4CEAB8
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CEAB0: ; CODE XREF: CEncoder_GetOptimum+D63j
+ mov ebx, [esp+90h+var_6C]
+ mov esi, [esp+90h+var_7C]
+
+loc_4CEAB8: ; CODE XREF: CEncoder_GetOptimum+A48j
+ mov edx, [esp+90h+var_74]
+ mov eax, edx
+ sub eax, [esp+ecx*4+90h+var_20]
+ mov cl, [edx]
+ sub eax, 1
+ cmp cl, [eax]
+ mov [esp+90h+var_48], eax
+ jnz loc_4CEDB5
+ mov cl, [edx+1]
+ cmp cl, [eax+1]
+ jnz loc_4CEDB5
+ mov edi, 2
+ cmp ebx, edi
+ jbe short loc_4CEB01
+ lea ecx, [edx+2]
+ sub eax, edx
+ lea ecx, [ecx+0]
+
+loc_4CEAF0: ; CODE XREF: CEncoder_GetOptimum+A9Fj
+ mov dl, [ecx]
+ cmp dl, [eax+ecx]
+ jnz short loc_4CEB01
+ add edi, 1
+ add ecx, 1
+ cmp edi, ebx
+ jb short loc_4CEAF0
+
+loc_4CEB01: ; CODE XREF: CEncoder_GetOptimum+A86j
+ ; CEncoder_GetOptimum+A95j
+ mov eax, [esp+90h+var_78]
+ lea ebx, [edi+eax]
+ cmp esi, ebx
+ jnb short loc_4CEB2E
+ mov eax, ebx
+ lea ecx, [esi+esi*4]
+ sub eax, esi
+ add esi, eax
+ lea ecx, [ebp+ecx*8+0FCh]
+ mov [esp+90h+var_7C], esi
+
+loc_4CEB20: ; CODE XREF: CEncoder_GetOptimum+ACCj
+ add ecx, 28h
+ sub eax, 1
+ mov dword ptr [ecx], 0FFFFFFFh
+ jnz short loc_4CEB20
+
+loc_4CEB2E: ; CODE XREF: CEncoder_GetOptimum+AAAj
+ mov edx, [esp+90h+var_54]
+ mov eax, [esp+90h+var_64]
+ mov ecx, [esp+90h+var_70]
+ push edx
+ push eax
+ push ecx
+ mov ecx, ebp
+ mov esi, edi
+ call sub_4CD9B0
+ add eax, [esp+90h+var_38]
+ mov ecx, [esp+90h+var_54]
+ imul ecx, 110h
+ lea edx, [edi+ecx]
+ mov [esp+90h+var_34], ecx
+ lea ecx, [ebp+edx*4+2E204h]
+ mov [esp+90h+var_50], ecx
+ lea edx, [ebx+ebx*4]
+ mov ebx, [esp+90h+var_50]
+ mov [esp+90h+var_2C], eax
+ lea ecx, [ebp+edx*8+0FCh]
+
+loc_4CEB78: ; CODE XREF: CEncoder_GetOptimum+B40j
+ mov edx, [ebx]
+ add edx, eax
+ cmp edx, [ecx]
+ jnb short loc_4CEB94
+ mov [ecx], edx
+ mov edx, [esp+90h+var_78]
+ mov [ecx+4], edx
+ mov edx, [esp+90h+var_70]
+ mov [ecx+8], edx
+ mov byte ptr [ecx-0Bh], 0
+
+loc_4CEB94: ; CODE XREF: CEncoder_GetOptimum+B1Ej
+ sub edi, 1
+ sub ebx, 4
+ sub ecx, 28h
+ cmp edi, 2
+ jnb short loc_4CEB78
+ cmp [esp+90h+var_70], 0
+ jnz short loc_4CEBB0
+ lea eax, [esi+1]
+ mov [esp+90h+var_40], eax
+
+loc_4CEBB0: ; CODE XREF: CEncoder_GetOptimum+B47j
+ mov ecx, [ebp+32EF8h]
+ mov edx, [esp+90h+var_60]
+ lea eax, [esi+1]
+ add ecx, eax
+ cmp edx, ecx
+ jnb short loc_4CEBC5
+ mov ecx, edx
+
+loc_4CEBC5: ; CODE XREF: CEncoder_GetOptimum+B61j
+ cmp eax, ecx
+ jnb short loc_4CEBE7
+ mov ebx, [esp+90h+var_74]
+ mov edi, [esp+90h+var_48]
+ lea edx, [eax+ebx]
+ sub edi, ebx
+
+loc_4CEBD6: ; CODE XREF: CEncoder_GetOptimum+B85j
+ mov bl, [edx]
+ cmp bl, [edx+edi]
+ jnz short loc_4CEBE7
+ add eax, 1
+ add edx, 1
+ cmp eax, ecx
+ jb short loc_4CEBD6
+
+loc_4CEBE7: ; CODE XREF: CEncoder_GetOptimum+B67j
+ ; CEncoder_GetOptimum+B7Bj
+ or ecx, 0FFFFFFFFh
+ sub ecx, esi
+ add eax, ecx
+ cmp eax, 2
+ mov [esp+90h+var_44], eax
+ jb loc_4CEDB5
+ mov edx, [esp+90h+var_68]
+ mov cl, ds:kRepNextStates[edx]
+ mov eax, [ebp+33B60h]
+ mov edi, [esp+90h+arg_0]
+ movzx ecx, cl
+ mov ebx, eax
+ lea edx, [esi+edi]
+ and ebx, edx
+ mov edx, ecx
+ mov cl, ds:kLiteralNextStates[ecx]
+ shl edx, 4
+ add ebx, edx
+ mov edx, [ebp+ebx*4+280F0h]
+ movzx ebx, cl
+ shr edx, 2
+ mov edx, dword_550998[edx*4]
+ mov [esp+90h+var_30], edx
+ lea edi, [esi+edi+1]
+ and edi, eax
+ mov eax, [ebp+32654h]
+ mov ecx, ebx
+ shl ecx, 4
+ add ecx, edi
+ mov [esp+90h+var_50], ecx
+ mov ecx, [esp+90h+var_74]
+ movzx edx, byte ptr [esi+ecx]
+ push edx
+ mov edx, [esp+94h+var_48]
+ movzx edx, byte ptr [esi+edx]
+ push edx
+ movzx edx, byte ptr [ecx+esi-1]
+ mov ecx, 8
+ sub cl, al
+ shr edx, cl
+ mov ecx, [esp+98h+arg_0]
+ lea eax, [esi+ecx]
+ mov ecx, [ebp+3265Ch]
+ and ecx, eax
+ mov eax, ecx
+ mov ecx, [ebp+32654h]
+ shl eax, cl
+ push 1
+ add edx, eax
+ imul edx, 0C00h
+ add edx, [ebp+32650h]
+ mov ecx, edx
+ call sub_4CDAC0
+ mov ecx, [esp+90h+var_50]
+ mov edx, 800h
+ sub edx, [ebp+ecx*4+280F0h]
+ mov ecx, [esp+90h+var_34]
+ shr edx, 2
+ add eax, dword_550998[edx*4]
+ mov edx, 800h
+ sub edx, [ebp+ebx*4+283F0h]
+ shr edx, 2
+ add eax, dword_550998[edx*4]
+ lea edx, [esi+ecx]
+ add eax, [ebp+edx*4+2E204h]
+ mov ecx, [esp+90h+var_44]
+ add eax, [esp+90h+var_30]
+ mov edx, [esp+90h+var_78]
+ add eax, [esp+90h+var_2C]
+ add ecx, esi
+ lea ecx, [ecx+edx+1]
+ cmp [esp+90h+var_7C], ecx
+ mov [esp+90h+var_30], ecx
+ jnb short loc_4CED3E
+ mov edx, [esp+90h+var_7C]
+ lea edx, [edx+edx*4]
+ lea edx, [ebp+edx*8+0FCh]
+ mov [esp+90h+var_2C], edx
+ mov edx, [esp+90h+var_7C]
+ sub ecx, edx
+ add edx, ecx
+ mov [esp+90h+var_7C], edx
+ mov edx, [esp+90h+var_2C]
+ jmp short loc_4CED30
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CED30: ; CODE XREF: CEncoder_GetOptimum+CCBj
+ ; CEncoder_GetOptimum+CDCj
+ add edx, 28h
+ sub ecx, 1
+ mov dword ptr [edx], 0FFFFFFFh
+ jnz short loc_4CED30
+
+loc_4CED3E: ; CODE XREF: CEncoder_GetOptimum+CA7j
+ mov edx, [esp+90h+var_50]
+ imul edi, 110h
+ add edi, [esp+90h+var_44]
+ mov ecx, 800h
+ sub ecx, [ebp+edx*4+284B0h]
+ mov edx, [ebp+ebx*4+28420h]
+ shr ecx, 2
+ mov ecx, dword_550998[ecx*4]
+ shr edx, 2
+ add ecx, dword_550998[edx*4]
+ add ecx, [ebp+edi*4+2E204h]
+ add ecx, eax
+ mov eax, [esp+90h+var_30]
+ lea eax, [eax+eax*4+1Eh]
+ cmp ecx, [ebp+eax*8+0Ch]
+ lea eax, [ebp+eax*8+0]
+ jnb short loc_4CEDB5
+ mov [eax+0Ch], ecx
+ mov ecx, [esp+90h+var_78]
+ lea edx, [esi+ecx+1]
+ mov [eax+4], ecx
+ mov ecx, [esp+90h+var_70]
+ mov [eax+10h], edx
+ mov dword ptr [eax+14h], 0
+ mov byte ptr [eax+1], 1
+ mov byte ptr [eax+2], 1
+ mov [eax+8], ecx
+
+loc_4CEDB5: ; CODE XREF: CEncoder_GetOptimum+A6Dj
+ ; CEncoder_GetOptimum+A79j ...
+ mov ecx, [esp+90h+var_70]
+ add ecx, 1
+ cmp ecx, 4
+ mov [esp+90h+var_70], ecx
+ jb loc_4CEAB0
+ mov edx, [esp+90h+var_28]
+ mov ecx, [esp+90h+var_6C]
+ cmp edx, ecx
+ jbe short loc_4CEDFB
+ xor eax, eax
+ cmp ecx, [ebp+32660h]
+ mov edx, ecx
+ jbe short loc_4CEDED
+
+loc_4CEDE1: ; CODE XREF: CEncoder_GetOptimum+D8Bj
+ add eax, 2
+ cmp ecx, [ebp+eax*4+32660h]
+ ja short loc_4CEDE1
+
+loc_4CEDED: ; CODE XREF: CEncoder_GetOptimum+D7Fj
+ mov [ebp+eax*4+32660h], ecx
+ add eax, 2
+ mov [esp+90h+var_4C], eax
+
+loc_4CEDFB: ; CODE XREF: CEncoder_GetOptimum+D73j
+ mov esi, [esp+90h+var_40]
+ cmp edx, esi
+ jb loc_4CF1BB
+ mov eax, [esp+90h+var_68]
+ mov ecx, [ebp+eax*4+283F0h]
+ shr ecx, 2
+ mov eax, dword_550998[ecx*4]
+ add eax, [esp+90h+var_24]
+ mov ecx, [esp+90h+var_7C]
+ mov [esp+90h+var_40], eax
+ mov eax, [esp+90h+var_78]
+ add eax, edx
+ cmp ecx, eax
+ jnb short loc_4CEE52
+ lea edx, [ecx+ecx*4]
+ sub eax, ecx
+ add ecx, eax
+ lea edx, [ebp+edx*8+0FCh]
+ mov [esp+90h+var_7C], ecx
+
+loc_4CEE44: ; CODE XREF: CEncoder_GetOptimum+DF0j
+ add edx, 28h
+ sub eax, 1
+ mov dword ptr [edx], 0FFFFFFFh
+ jnz short loc_4CEE44
+
+loc_4CEE52: ; CODE XREF: CEncoder_GetOptimum+DD0j
+ xor eax, eax
+ cmp esi, [ebp+32660h]
+ mov [esp+90h+var_70], eax
+ jbe short loc_4CEE70
+
+loc_4CEE60: ; CODE XREF: CEncoder_GetOptimum+E0Aj
+ add eax, 2
+ cmp esi, [ebp+eax*4+32660h]
+ ja short loc_4CEE60
+ mov [esp+90h+var_70], eax
+
+loc_4CEE70: ; CODE XREF: CEncoder_GetOptimum+DFEj
+ lea ebx, ds:0[eax*4]
+ mov edx, [ebx+ebp+32664h]
+ mov ecx, 7FFFFh
+ sub ecx, edx
+ sar ecx, 1Fh
+ and ecx, 0Ch
+ add ecx, 6
+ mov eax, edx
+ shr eax, cl
+ mov [esp+90h+var_6C], edx
+ lea edi, [esi+1]
+ movzx eax, byte ptr dword_551198[eax]
+ lea ecx, [eax+ecx*2]
+ mov eax, [esp+90h+var_54]
+ imul eax, 110h
+ add eax, esi
+ lea eax, [ebp+eax*4+295B8h]
+ mov [esp+90h+var_3C], ecx
+ mov ecx, [esp+90h+var_78]
+ mov [esp+90h+var_54], eax
+ lea eax, [esi+ecx]
+ lea eax, [eax+eax*4]
+ lea ecx, [ebp+eax*8+0FCh]
+ mov [esp+90h+var_50], ecx
+
+loc_4CEED3: ; CODE XREF: CEncoder_GetOptimum+1156j
+ lea eax, [edi-3]
+ cmp eax, 4
+ jb short loc_4CEEE0
+ mov eax, 3
+
+loc_4CEEE0: ; CODE XREF: CEncoder_GetOptimum+E79j
+ cmp edx, 80h
+ jnb short loc_4CEEF6
+ shl eax, 7
+ add eax, edx
+ mov eax, [ebp+eax*4+33314h]
+ jmp short loc_4CEF10
+; ---------------------------------------------------------------------------
+
+loc_4CEEF6: ; CODE XREF: CEncoder_GetOptimum+E86j
+ shl eax, 6
+ add eax, [esp+90h+var_3C]
+ mov esi, edx
+ mov eax, [ebp+eax*4+32F14h]
+ and esi, 0Fh
+ add eax, [ebp+esi*4+33B14h]
+
+loc_4CEF10: ; CODE XREF: CEncoder_GetOptimum+E94j
+ add eax, [esp+90h+var_40]
+ mov esi, [esp+90h+var_54]
+ add eax, [esi]
+ cmp eax, [ecx]
+ mov [esp+90h+var_2C], eax
+ jnb short loc_4CEF35
+ mov [ecx], eax
+ mov eax, [esp+90h+var_78]
+ add edx, 4
+ mov [ecx+4], eax
+ mov [ecx+8], edx
+ mov byte ptr [ecx-0Bh], 0
+
+loc_4CEF35: ; CODE XREF: CEncoder_GetOptimum+EC0j
+ lea eax, [edi-1]
+ cmp eax, [ebx+ebp+32660h]
+ jnz loc_4CF1A1
+ mov ebx, [esp+90h+var_74]
+ mov eax, [ebp+32EF8h]
+ mov esi, [esp+90h+var_60]
+ mov edx, ebx
+ sub edx, [esp+90h+var_6C]
+ add eax, edi
+ sub edx, 1
+ cmp esi, eax
+ mov ecx, edi
+ jnb short loc_4CEF6C
+ mov eax, esi
+ mov [esp+90h+var_44], esi
+ jmp short loc_4CEF70
+; ---------------------------------------------------------------------------
+
+loc_4CEF6C: ; CODE XREF: CEncoder_GetOptimum+F02j
+ mov [esp+90h+var_44], eax
+
+loc_4CEF70: ; CODE XREF: CEncoder_GetOptimum+F0Aj
+ cmp edi, eax
+ jnb short loc_4CEF93
+ lea esi, [edi+edx]
+ sub ebx, edx
+ lea esp, [esp+0]
+
+loc_4CEF80: ; CODE XREF: CEncoder_GetOptimum+F31j
+ mov al, [ebx+esi]
+ cmp al, [esi]
+ jnz short loc_4CEF93
+ add ecx, 1
+ add esi, 1
+ cmp ecx, [esp+90h+var_44]
+ jb short loc_4CEF80
+
+loc_4CEF93: ; CODE XREF: CEncoder_GetOptimum+F12j
+ ; CEncoder_GetOptimum+F25j
+ or esi, 0FFFFFFFFh
+ lea eax, [edi-1]
+ sub esi, eax
+ add ecx, esi
+ cmp ecx, 2
+ mov [esp+90h+var_48], ecx
+ jb loc_4CF157
+ mov ecx, [esp+90h+var_68]
+ mov bl, ds:kMatchNextStates[ecx]
+ mov ecx, [ebp+33B60h]
+ mov eax, [esp+90h+arg_0]
+ lea esi, [edi+eax-1]
+ mov eax, ecx
+ and eax, esi
+ movzx esi, bl
+ movzx edx, byte ptr [edi+edx-1]
+ mov ebx, esi
+ shl ebx, 4
+ add ebx, eax
+ mov ebx, [ebp+ebx*4+280F0h]
+ shr ebx, 2
+ mov ebx, dword_550998[ebx*4]
+ mov [esp+90h+var_28], ebx
+ mov bl, ds:kLiteralNextStates[esi]
+ lea esi, [eax+1]
+ mov eax, [ebp+32654h]
+ and esi, ecx
+ movzx ebx, bl
+ mov ecx, ebx
+ shl ecx, 4
+ add ecx, esi
+ mov [esp+90h+var_44], ecx
+ mov ecx, [esp+90h+var_74]
+ movzx ecx, byte ptr [ecx+edi-1]
+ push ecx
+ mov ecx, [esp+94h+var_74]
+ push edx
+ movzx edx, byte ptr [edi+ecx-2]
+ mov ecx, 8
+ sub cl, al
+ shr edx, cl
+ mov ecx, [esp+98h+arg_0]
+ lea eax, [edi+ecx-1]
+ mov ecx, [ebp+3265Ch]
+ and ecx, eax
+ mov eax, ecx
+ mov ecx, [ebp+32654h]
+ shl eax, cl
+ push 1
+ add edx, eax
+ imul edx, 0C00h
+ add edx, [ebp+32650h]
+ mov ecx, edx
+ call sub_4CDAC0
+ mov edx, 800h
+ sub edx, [ebp+ebx*4+283F0h]
+ mov ecx, 800h
+ shr edx, 2
+ add eax, dword_550998[edx*4]
+ mov edx, [esp+90h+var_44]
+ sub ecx, [ebp+edx*4+280F0h]
+ mov edx, [esp+90h+var_78]
+ shr ecx, 2
+ add eax, dword_550998[ecx*4]
+ mov ecx, [esp+90h+var_48]
+ add eax, [esp+90h+var_28]
+ add ecx, edx
+ add eax, [esp+90h+var_2C]
+ add ecx, edi
+ cmp [esp+90h+var_7C], ecx
+ mov [esp+90h+var_28], ecx
+ jnb short loc_4CF0DE
+ mov edx, [esp+90h+var_7C]
+ lea edx, [edx+edx*4]
+ lea edx, [ebp+edx*8+0FCh]
+ mov [esp+90h+var_24], edx
+ mov edx, [esp+90h+var_7C]
+ sub ecx, edx
+ add edx, ecx
+ mov [esp+90h+var_7C], edx
+ mov edx, [esp+90h+var_24]
+ lea ecx, [ecx+0]
+
+loc_4CF0D0: ; CODE XREF: CEncoder_GetOptimum+107Cj
+ add edx, 28h
+ sub ecx, 1
+ mov dword ptr [edx], 0FFFFFFFh
+ jnz short loc_4CF0D0
+
+loc_4CF0DE: ; CODE XREF: CEncoder_GetOptimum+1049j
+ mov edx, [esp+90h+var_44]
+ imul esi, 110h
+ add esi, [esp+90h+var_48]
+ mov ecx, 800h
+ sub ecx, [ebp+edx*4+284B0h]
+ mov edx, [ebp+ebx*4+28420h]
+ shr ecx, 2
+ mov ecx, dword_550998[ecx*4]
+ shr edx, 2
+ add ecx, dword_550998[edx*4]
+ add ecx, [ebp+esi*4+2E204h]
+ add ecx, eax
+ mov eax, [esp+90h+var_28]
+ lea eax, [eax+eax*4+1Eh]
+ cmp ecx, [ebp+eax*8+0Ch]
+ lea eax, [ebp+eax*8+0]
+ jnb short loc_4CF157
+ mov [eax+0Ch], ecx
+ mov ecx, [esp+90h+var_78]
+ lea edx, [ecx+edi]
+ mov [eax+4], ecx
+ mov ecx, [esp+90h+var_6C]
+ add ecx, 4
+ mov [eax+10h], edx
+ mov dword ptr [eax+14h], 0
+ mov byte ptr [eax+1], 1
+ mov byte ptr [eax+2], 1
+ mov [eax+8], ecx
+
+loc_4CF157: ; CODE XREF: CEncoder_GetOptimum+F44j
+ ; CEncoder_GetOptimum+10CCj
+ mov eax, [esp+90h+var_70]
+ add eax, 2
+ cmp eax, [esp+90h+var_4C]
+ mov [esp+90h+var_70], eax
+ jz short loc_4CF1BB
+ lea ebx, ds:0[eax*4]
+ mov eax, [ebx+ebp+32664h]
+ cmp eax, 80h
+ mov [esp+90h+var_6C], eax
+ jb short loc_4CF1A1
+ mov ecx, 7FFFFh
+ sub ecx, eax
+ sar ecx, 1Fh
+ and ecx, 0Ch
+ add ecx, 6
+ shr eax, cl
+ movzx edx, byte ptr dword_551198[eax]
+ lea eax, [edx+ecx*2]
+ mov [esp+90h+var_3C], eax
+
+loc_4CF1A1: ; CODE XREF: CEncoder_GetOptimum+EDFj
+ ; CEncoder_GetOptimum+111Fj
+ add [esp+90h+var_50], 28h
+ add [esp+90h+var_54], 4
+ mov ecx, [esp+90h+var_50]
+ mov edx, [esp+90h+var_6C]
+ add edi, 1
+ jmp loc_4CEED3
+; ---------------------------------------------------------------------------
+
+loc_4CF1BB: ; CODE XREF: CEncoder_GetOptimum+8A9j
+ ; CEncoder_GetOptimum+DA1j ...
+ mov eax, [esp+90h+var_78]
+ add eax, 1
+ cmp eax, [esp+90h+var_7C]
+ mov [esp+90h+var_78], eax
+ jnz loc_4CE5D1
+
+loc_4CF1D0: ; CODE XREF: CEncoder_GetOptimum+567j
+ mov ecx, [esp+90h+var_78]
+ push ecx
+ jmp short loc_4CF1EF
+; ---------------------------------------------------------------------------
+
+loc_4CF1D7: ; CODE XREF: CEncoder_GetOptimum+59Ej
+ mov ecx, [esp+90h+var_4C]
+ mov [ebp+32F00h], ecx
+ mov [ebp+32EFCh], eax
+ mov byte ptr [ebp+32F10h], 1
+ push esi
+
+loc_4CF1EF: ; CODE XREF: CEncoder_GetOptimum+1175j
+ mov edx, [esp+94h+arg_4]
+ push edx
+ mov ecx, ebp
+ call sub_4CB2E0
+ pop edi
+ pop ebx
+ pop esi
+ pop ebp
+ add esp, 80h
+ retn 8
+CEncoder_GetOptimum endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CF210: ; DATA XREF: CEncoder_CodeOneBlock+44o
+ mov edx, [esp+10h]
+ mov eax, [esp+4]
+ mov eax, [eax+4]
+ mov ecx, [eax]
+ push edx
+ mov edx, [esp+10h]
+ push edx
+ mov edx, [esp+10h]
+ push edx
+ push eax
+ mov eax, [ecx+0Ch]
+ call eax
+ retn
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_FillDistancesPrices proc near ; CODE XREF: CEncoder_SetStreams+4Fp
+ ; CEncoder_CodeOneBlock+751p
+
+var_20C = dword ptr -20Ch
+var_208 = dword ptr -208h
+var_204 = dword ptr -204h
+var_200 = dword ptr -200h
+
+ sub esp, 20Ch
+ push ebx
+ push ebp
+ push esi
+ push edi
+ mov ebx, ecx
+ mov esi, 4
+
+loc_4CF241: ; CODE XREF: CEncoder_FillDistancesPrices+80j
+ cmp esi, 2000h
+ jnb short loc_4CF252
+ movzx edx, byte ptr dword_551198[esi]
+ jmp short loc_4CF27A
+; ---------------------------------------------------------------------------
+
+loc_4CF252: ; CODE XREF: CEncoder_FillDistancesPrices+17j
+ cmp esi, 2000000h
+ jnb short loc_4CF26B
+ mov eax, esi
+ shr eax, 0Ch
+ movzx edx, byte ptr dword_551198[eax]
+ add edx, 18h
+ jmp short loc_4CF27A
+; ---------------------------------------------------------------------------
+
+loc_4CF26B: ; CODE XREF: CEncoder_FillDistancesPrices+28j
+ mov ecx, esi
+ shr ecx, 18h
+ movzx edx, byte ptr dword_551198[ecx]
+ add edx, 30h
+
+loc_4CF27A: ; CODE XREF: CEncoder_FillDistancesPrices+20j
+ ; CEncoder_FillDistancesPrices+39j
+ mov ecx, edx
+ mov eax, edx
+ and eax, 1
+ shr ecx, 1
+ sub ecx, 1
+ or eax, 2
+ shl eax, cl
+ mov edi, esi
+ sub edi, eax
+ push edi
+ sub eax, edx
+ push ecx
+ lea edx, [ebx+eax*4+28BACh]
+ push edx
+ call sub_4CD860
+ mov [esp+esi*4+228h+var_200], eax
+ add esi, 1
+ add esp, 0Ch
+ cmp esi, 80h
+ jb short loc_4CF241
+ lea ebp, [esp+21Ch+var_200]
+ sub ebp, ebx
+ lea esi, [ebx+3331Ch]
+ sub ebp, 33314h
+ lea edx, [ebx+32F14h]
+ mov [esp+21Ch+var_20C], esi
+ mov [esp+21Ch+var_208], ebp
+ mov [esp+21Ch+var_204], 4
+ jmp short loc_4CF2E4
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CF2E0: ; CODE XREF: CEncoder_FillDistancesPrices+1BDj
+ mov esi, [esp+21Ch+var_20C]
+
+loc_4CF2E4: ; CODE XREF: CEncoder_FillDistancesPrices+AAj
+ xor edi, edi
+ cmp [ebx+33B58h], edi
+ jbe short loc_4CF33F
+ mov edi, edi
+
+loc_4CF2F0: ; CODE XREF: CEncoder_FillDistancesPrices+109j
+ mov ecx, edi
+ or ecx, 40h
+ xor esi, esi
+ cmp ecx, 1
+ jz short loc_4CF32D
+ lea esp, [esp+0]
+
+loc_4CF300: ; CODE XREF: CEncoder_FillDistancesPrices+F7j
+ mov eax, ecx
+ shr ecx, 1
+ mov ebp, [edx+ecx*4-0A764h]
+ and eax, 1
+ sub ebp, eax
+ neg eax
+ xor ebp, eax
+ shr ebp, 2
+ and ebp, 1FFh
+ add esi, dword_550998[ebp*4]
+ cmp ecx, 1
+ jnz short loc_4CF300
+ mov ebp, [esp+21Ch+var_208]
+
+loc_4CF32D: ; CODE XREF: CEncoder_FillDistancesPrices+CAj
+ mov [edx+edi*4], esi
+ add edi, 1
+ cmp edi, [ebx+33B58h]
+ jb short loc_4CF2F0
+ mov esi, [esp+21Ch+var_20C]
+
+loc_4CF33F: ; CODE XREF: CEncoder_FillDistancesPrices+BCj
+ mov eax, 0Eh
+ cmp [ebx+33B58h], eax
+ jbe short loc_4CF368
+ lea esp, [esp+0]
+
+loc_4CF350: ; CODE XREF: CEncoder_FillDistancesPrices+136j
+ mov ecx, eax
+ shr ecx, 1
+ sub ecx, 5
+ shl ecx, 6
+ add [edx+eax*4], ecx
+ add eax, 1
+ cmp eax, [ebx+33B58h]
+ jb short loc_4CF350
+
+loc_4CF368: ; CODE XREF: CEncoder_FillDistancesPrices+11Aj
+ mov eax, [edx]
+ mov [esi-8], eax
+ mov ecx, [edx+4]
+ mov [esi-4], ecx
+ mov eax, [edx+8]
+ mov [esi], eax
+ mov ecx, [edx+0Ch]
+ mov [esi+4], ecx
+ mov eax, 4
+ add esi, 8
+
+loc_4CF386: ; CODE XREF: CEncoder_FillDistancesPrices+19Ej
+ cmp eax, 2000h
+ jnb short loc_4CF396
+ movzx ecx, byte ptr dword_551198[eax]
+ jmp short loc_4CF3BB
+; ---------------------------------------------------------------------------
+
+loc_4CF396: ; CODE XREF: CEncoder_FillDistancesPrices+15Bj
+ cmp eax, 2000000h
+ mov ecx, eax
+ jnb short loc_4CF3AE
+ shr ecx, 0Ch
+ movzx ecx, byte ptr dword_551198[ecx]
+ add ecx, 18h
+ jmp short loc_4CF3BB
+; ---------------------------------------------------------------------------
+
+loc_4CF3AE: ; CODE XREF: CEncoder_FillDistancesPrices+16Dj
+ shr ecx, 18h
+ movzx ecx, byte ptr dword_551198[ecx]
+ add ecx, 30h
+
+loc_4CF3BB: ; CODE XREF: CEncoder_FillDistancesPrices+164j
+ ; CEncoder_FillDistancesPrices+17Cj
+ mov ecx, [edx+ecx*4]
+ add ecx, [esi+ebp]
+ add eax, 1
+ mov [esi], ecx
+ add esi, 4
+ cmp eax, 80h
+ jb short loc_4CF386
+ add [esp+21Ch+var_20C], 200h
+ sub ebp, 200h
+ add edx, 100h
+ sub [esp+21Ch+var_204], 1
+ mov [esp+21Ch+var_208], ebp
+ jnz loc_4CF2E0
+ pop edi
+ pop esi
+ pop ebp
+ mov dword ptr [ebx+33B70h], 0
+ pop ebx
+ add esp, 20Ch
+ retn
+CEncoder_FillDistancesPrices endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_FillAlignPrices proc near ; CODE XREF: CEncoder_SetStreams+56p
+ ; CEncoder_CodeOneBlock+761p
+ push ebx
+ push ebp
+ push esi
+ mov ebp, ecx
+ push edi
+ xor esi, esi
+ lea ebx, [ebp+28D78h]
+ lea edi, [ebp+33B14h]
+
+loc_4CF424: ; CODE XREF: CEncoder_FillAlignPrices+27j
+ push esi
+ mov ecx, ebx
+ call sub_4CD810
+ mov [edi], eax
+ add esi, 1
+ add edi, 4
+ cmp esi, 10h
+ jb short loc_4CF424
+ pop edi
+ pop esi
+ mov dword ptr [ebp+33B54h], 0
+ pop ebp
+ pop ebx
+ retn
+CEncoder_FillAlignPrices endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CF810 proc near ; CODE XREF: sub_4D0250+3p
+
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_4 = dword ptr -4
+
+ push 0FFFFFFFFh
+ push offset loc_4DA0C9
+ mov eax, dword ptr fs:[0]
+ push eax
+ push ecx
+ push ebx
+ push esi
+ mov eax, dword_544960
+ xor eax, esp
+ push eax
+ lea eax, [esp+1Ch+var_C]
+ mov dword ptr fs:[0], eax
+ mov esi, ecx
+ mov [esp+1Ch+var_10], esi
+ mov dword ptr [esi], offset NCompress_NLZMA_CEncoder_vftable
+ mov dword ptr [esi+4], offset NCompress_NLZMA_CEncoder_vftable_ICompressSetOutStream
+ mov dword ptr [esi+8], offset NCompress_NLZMA_CEncoder_vftable_ICompressSetCoderProperties
+ mov dword ptr [esi+0Ch], offset NCompress_NLZMA_CEncoder_vftable_ICompressWriteCoderProperties
+ mov eax, [esi+0A4h]
+ push eax ; lpAddress
+ mov [esp+20h+var_4], 1
+ call off_546E24
+ xor ebx, ebx
+ add esp, 4
+ cmp [esi+0D0h], ebx
+ mov [esi+0A4h], ebx
+ jnz short loc_4CF892
+ mov ecx, [esi+0B4h]
+ push ecx ; lpAddress
+ call off_546E24
+ add esp, 4
+ mov [esi+0B4h], ebx
+
+loc_4CF892: ; CODE XREF: sub_4CF810+6Aj
+ mov eax, [esi+33B8Ch]
+ cmp eax, ebx
+ jz short loc_4CF8A4
+ mov edx, [eax]
+ push eax
+ mov eax, [edx+8]
+ call eax
+
+loc_4CF8A4: ; CODE XREF: sub_4CF810+8Aj
+ lea ecx, [esi+32650h]
+ mov byte ptr [esp+1Ch+var_4], bl
+ call sub_4CD8F0
+ mov eax, [esi+40h]
+ cmp eax, ebx
+ mov [esp+1Ch+var_4], 0FFFFFFFFh
+ jz short loc_4CF8CF
+ push 8000h ; dwFreeType
+ push ebx ; dwSize
+ push eax ; lpAddress
+ call ds:VirtualFree
+
+loc_4CF8CF: ; CODE XREF: sub_4CF810+B0j
+ mov [esi+40h], ebx
+ mov esi, [esi+54h]
+ cmp esi, ebx
+ jz short loc_4CF8E1
+ mov ecx, [esi]
+ mov edx, [ecx+8]
+ push esi
+ call edx
+
+loc_4CF8E1: ; CODE XREF: sub_4CF810+C7j
+ mov ecx, [esp+1Ch+var_C]
+ mov dword ptr fs:[0], ecx
+ pop ecx
+ pop esi
+ pop ebx
+ add esp, 10h
+ retn
+sub_4CF810 endp
+
+; =============== S U B R O U T I N E =======================================
+
+; int __stdcall sub_4CF900(int, void *Buf1, int)
+sub_4CF900 proc near ; CODE XREF: sub_4CFA20+5j
+ ; ICompressSetCoderProperties_QueryInterface+5j ...
+
+arg_0 = dword ptr 4
+Buf1 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push esi
+ mov esi, [esp+4+Buf1]
+ push offset dword_512730 ; Buf2
+ push esi ; Buf1
+ call unknown_libname_324 ; MFC 3.1/4.0/4.2/8.0 32bit
+ add esp, 8
+ test eax, eax
+ jz short loc_4CF94C
+
+loc_4CF917: ; CODE XREF: sub_4CF900+5Cj
+ mov eax, [esp+4+arg_0]
+ test eax, eax
+ jz short loc_4CF936
+ mov edx, [esp+4+arg_8]
+ lea ecx, [eax+4]
+ mov [edx], ecx
+ mov ecx, [eax]
+ mov edx, [ecx+4]
+ push eax
+ call edx
+ xor eax, eax
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CF936: ; CODE XREF: sub_4CF900+1Dj
+ ; sub_4CF900+76j ...
+ mov edx, [esp+4+arg_8]
+ xor ecx, ecx
+ mov [edx], ecx
+ mov ecx, [eax]
+ mov edx, [ecx+4]
+ push eax
+ call edx
+ xor eax, eax
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CF94C: ; CODE XREF: sub_4CF900+15j
+ push offset dword_5535A0 ; Buf2
+ push esi ; Buf1
+ call unknown_libname_324 ; MFC 3.1/4.0/4.2/8.0 32bit
+ add esp, 8
+ test eax, eax
+ jnz short loc_4CF917
+ push offset dword_5535B0 ; Buf2
+ push esi ; Buf1
+ call unknown_libname_324 ; MFC 3.1/4.0/4.2/8.0 32bit
+ add esp, 8
+ test eax, eax
+ jz short loc_4CF98F
+ mov eax, [esp+4+arg_0]
+ test eax, eax
+ jz short loc_4CF936
+ mov edx, [esp+4+arg_8]
+ lea ecx, [eax+8]
+ mov [edx], ecx
+ mov ecx, [eax]
+ mov edx, [ecx+4]
+ push eax
+ call edx
+ xor eax, eax
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CF98F: ; CODE XREF: sub_4CF900+6Ej
+ push offset dword_5535C0 ; Buf2
+ push esi ; Buf1
+ call unknown_libname_324 ; MFC 3.1/4.0/4.2/8.0 32bit
+ add esp, 8
+ test eax, eax
+ jz short loc_4CF9C0
+ mov eax, [esp+4+arg_0]
+ test eax, eax
+ jz short loc_4CF936
+ mov edx, [esp+4+arg_8]
+ lea ecx, [eax+0Ch]
+ mov [edx], ecx
+ mov ecx, [eax]
+ mov edx, [ecx+4]
+ push eax
+ call edx
+ xor eax, eax
+ pop esi
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CF9C0: ; CODE XREF: sub_4CF900+9Fj
+ mov eax, 80004002h
+ pop esi
+ retn 0Ch
+sub_4CF900 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CF9D0 proc near ; CODE XREF: ICompressSetCoderProperties_AddRef+5j
+ ; sub_4CFA10+5j ...
+
+arg_0 = dword ptr 4
+
+ mov eax, [esp+arg_0]
+ add dword ptr [eax+24h], 1
+ mov eax, [eax+24h]
+ retn 4
+sub_4CF9D0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CF9E0 proc near ; CODE XREF: sub_4CFA40+5j
+ ; ICompressSetCoderProperties_Release+5j ...
+
+arg_0 = dword ptr 4
+
+ mov ecx, [esp+arg_0]
+ add dword ptr [ecx+24h], 0FFFFFFFFh
+ mov eax, [ecx+24h]
+ jnz short locret_4CF9F8
+ mov eax, [ecx]
+ mov edx, [eax+10h]
+ push 1
+ call edx
+ xor eax, eax
+
+locret_4CF9F8: ; CODE XREF: sub_4CF9E0+Bj
+ retn 4
+sub_4CF9E0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+ICompressSetCoderProperties_AddRef proc near ; DATA XREF: .rdata:00517AD4o
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 8
+ jmp sub_4CF9D0
+ICompressSetCoderProperties_AddRef endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA10 proc near ; DATA XREF: .rdata:00517AC0o
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 0Ch
+ jmp sub_4CF9D0
+sub_4CFA10 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA20 proc near ; DATA XREF: .rdata:NCompress_NLZMA_CEncoder_vftable_ICompressSetOutStreamo
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 4
+ jmp sub_4CF900
+sub_4CFA20 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+ICompressSetCoderProperties_QueryInterface proc near ; DATA XREF: .rdata:NCompress_NLZMA_CEncoder_vftable_ICompressSetCoderPropertieso
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 8
+ jmp sub_4CF900
+ICompressSetCoderProperties_QueryInterface endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA40 proc near ; DATA XREF: .rdata:00517AECo
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 4
+ jmp sub_4CF9E0
+sub_4CFA40 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA50 proc near ; DATA XREF: .rdata:NCompress_NLZMA_CEncoder_vftable_ICompressWriteCoderPropertieso
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ sub [esp+arg_0], 0Ch
+ jmp sub_4CF900
+sub_4CFA50 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+ICompressSetCoderProperties_Release proc near ; DATA XREF: .rdata:00517AD8o
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 8
+ jmp sub_4CF9E0
+ICompressSetCoderProperties_Release endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA70 proc near ; DATA XREF: .rdata:00517AC4o
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 0Ch
+ jmp sub_4CF9E0
+sub_4CFA70 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA80 proc near ; DATA XREF: .rdata:00517AE8o
+
+arg_0 = dword ptr 4
+
+ sub [esp+arg_0], 4
+ jmp sub_4CF9D0
+sub_4CFA80 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFA90 proc near ; DATA XREF: .rdata:00517AF0o
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push esi
+ mov esi, [esp+4+arg_4]
+ test esi, esi
+ push edi
+ mov edi, [esp+8+arg_0]
+ jz short loc_4CFAA6
+ mov eax, [esi]
+ mov ecx, [eax+4]
+ push esi
+ call ecx
+
+loc_4CFAA6: ; CODE XREF: sub_4CFA90+Cj
+ mov eax, [edi+50h]
+ test eax, eax
+ jz short loc_4CFAB5
+ mov edx, [eax]
+ push eax
+ mov eax, [edx+8]
+ call eax
+
+loc_4CFAB5: ; CODE XREF: sub_4CFA90+1Bj
+ mov [edi+50h], esi
+ pop edi
+ xor eax, eax
+ pop esi
+ retn 8
+sub_4CFA90 endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4CFAC0 proc near ; CODE XREF: CEncoder_CodeOneBlock+42Ap
+ ; CEncoder_CodeOneBlock+517p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ mov eax, [esp+arg_0]
+ push esi
+ mov esi, [eax+10h]
+ mov edx, esi
+ shr edx, 0Bh
+ imul edx, [ecx]
+ cmp [esp+4+arg_4], 0
+ jnz short loc_4CFAEC
+ mov [eax+10h], edx
+ mov edx, [ecx]
+ mov esi, 800h
+ sub esi, edx
+ shr esi, 5
+ add esi, edx
+ mov [ecx], esi
+ jmp short loc_4CFB03
+; ---------------------------------------------------------------------------
+
+loc_4CFAEC: ; CODE XREF: sub_4CFAC0+15j
+ add [eax+8], edx
+ adc dword ptr [eax+0Ch], 0
+ sub esi, edx
+ mov [eax+10h], esi
+ mov edx, [ecx]
+ mov esi, edx
+ shr esi, 5
+ sub edx, esi
+ mov [ecx], edx
+
+loc_4CFB03: ; CODE XREF: sub_4CFAC0+2Aj
+ mov ecx, [eax+10h]
+ cmp ecx, 1000000h
+ pop esi
+ jnb short locret_4CFB1C
+ shl ecx, 8
+ mov [eax+10h], ecx
+ mov ecx, eax
+ call loc_4CF640
+
+locret_4CFB1C: ; CODE XREF: sub_4CFAC0+4Dj
+ retn 8
+sub_4CFAC0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFB20 proc near ; CODE XREF: sub_4D0020+52p
+ ; sub_4D0020+E4p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov ebp, ecx
+ mov ebx, 1
+ mov edx, 3
+
+loc_4CFB34: ; CODE XREF: sub_4CFB20+8Cj
+ mov edi, [esp+10h+arg_4]
+ sub edx, 1
+ mov ecx, edx
+ shr edi, cl
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+ebx*4+0]
+ and edi, 1
+ test edi, edi
+ mov [esp+10h+arg_0], edx
+ jnz short loc_4CFB70
+ mov [esi+10h], eax
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+ebx*4+0], ecx
+ jmp short loc_4CFB8B
+; ---------------------------------------------------------------------------
+
+loc_4CFB70: ; CODE XREF: sub_4CFB20+35j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [ebp+ebx*4+0], eax
+
+loc_4CFB8B: ; CODE XREF: sub_4CFB20+4Ej
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFBA6
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+ mov edx, [esp+10h+arg_0]
+
+loc_4CFBA6: ; CODE XREF: sub_4CFB20+73j
+ add ebx, ebx
+ or ebx, edi
+ test edx, edx
+ jnz short loc_4CFB34
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn 8
+sub_4CFB20 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFBC0 proc near ; CODE XREF: sub_4D0020+136p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov ebp, ecx
+ mov ebx, 1
+ mov edx, 8
+
+loc_4CFBD4: ; CODE XREF: sub_4CFBC0+8Cj
+ mov edi, [esp+10h+arg_4]
+ sub edx, 1
+ mov ecx, edx
+ shr edi, cl
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+ebx*4+0]
+ and edi, 1
+ test edi, edi
+ mov [esp+10h+arg_0], edx
+ jnz short loc_4CFC10
+ mov [esi+10h], eax
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+ebx*4+0], ecx
+ jmp short loc_4CFC2B
+; ---------------------------------------------------------------------------
+
+loc_4CFC10: ; CODE XREF: sub_4CFBC0+35j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [ebp+ebx*4+0], eax
+
+loc_4CFC2B: ; CODE XREF: sub_4CFBC0+4Ej
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFC46
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+ mov edx, [esp+10h+arg_0]
+
+loc_4CFC46: ; CODE XREF: sub_4CFBC0+73j
+ add ebx, ebx
+ or ebx, edi
+ test edx, edx
+ jnz short loc_4CFBD4
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn 8
+sub_4CFBC0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFC60 proc near ; CODE XREF: sub_4D0770+EDp
+ ; CEncoder_CodeOneBlock+67Cp
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov ebp, ecx
+ mov ebx, 1
+ mov edx, 6
+
+loc_4CFC74: ; CODE XREF: sub_4CFC60+8Cj
+ mov edi, [esp+10h+arg_4]
+ sub edx, 1
+ mov ecx, edx
+ shr edi, cl
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+ebx*4+0]
+ and edi, 1
+ test edi, edi
+ mov [esp+10h+arg_0], edx
+ jnz short loc_4CFCB0
+ mov [esi+10h], eax
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+ebx*4+0], ecx
+ jmp short loc_4CFCCB
+; ---------------------------------------------------------------------------
+
+loc_4CFCB0: ; CODE XREF: sub_4CFC60+35j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [ebp+ebx*4+0], eax
+
+loc_4CFCCB: ; CODE XREF: sub_4CFC60+4Ej
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFCE6
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+ mov edx, [esp+10h+arg_0]
+
+loc_4CFCE6: ; CODE XREF: sub_4CFC60+73j
+ add ebx, ebx
+ or ebx, edi
+ test edx, edx
+ jnz short loc_4CFC74
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn 8
+sub_4CFC60 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFD00 proc near ; CODE XREF: sub_4D0770+109p
+ ; CEncoder_CodeOneBlock+6D5p
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov ebp, ecx
+ mov edi, 1
+ mov [esp+10h+arg_0], 4
+
+loc_4CFD17: ; CODE XREF: sub_4CFD00+87j
+ mov ecx, [esi+10h]
+ mov ebx, [esp+10h+arg_4]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+edi*4+0]
+ and ebx, 1
+ test ebx, ebx
+ jnz short loc_4CFD48
+ mov [esi+10h], eax
+ mov eax, [ebp+edi*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+edi*4+0], ecx
+ jmp short loc_4CFD63
+; ---------------------------------------------------------------------------
+
+loc_4CFD48: ; CODE XREF: sub_4CFD00+2Dj
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+edi*4+0]
+ mov edx, eax
+ shr edx, 5
+ sub eax, edx
+ mov [ebp+edi*4+0], eax
+
+loc_4CFD63: ; CODE XREF: sub_4CFD00+46j
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFD7A
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4CFD7A: ; CODE XREF: sub_4CFD00+6Bj
+ shr [esp+10h+arg_4], 1
+ add edi, edi
+ or edi, ebx
+ sub [esp+10h+arg_0], 1
+ jnz short loc_4CFD17
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn 8
+sub_4CFD00 endp
+
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFD90 proc near ; CODE XREF: CEncoder_CodeOneBlock+6AFp
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+arg_C = dword ptr 10h
+
+ mov eax, [esp+arg_8]
+ test eax, eax
+ push edi
+ mov edi, 1
+ jle loc_4CFE26
+ push ebx
+ push ebp
+ mov ebp, [esp+0Ch+arg_0]
+ push esi
+ mov esi, [esp+10h+arg_4]
+ mov [esp+10h+arg_8], eax
+
+loc_4CFDB1: ; CODE XREF: sub_4CFD90+91j
+ mov ecx, [esi+10h]
+ mov ebx, [esp+10h+arg_C]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+edi*4+0]
+ and ebx, 1
+ test ebx, ebx
+ jnz short loc_4CFDE2
+ mov [esi+10h], eax
+ mov eax, [ebp+edi*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+edi*4+0], ecx
+ jmp short loc_4CFDFD
+; ---------------------------------------------------------------------------
+
+loc_4CFDE2: ; CODE XREF: sub_4CFD90+37j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+edi*4+0]
+ mov edx, eax
+ shr edx, 5
+ sub eax, edx
+ mov [ebp+edi*4+0], eax
+
+loc_4CFDFD: ; CODE XREF: sub_4CFD90+50j
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFE14
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4CFE14: ; CODE XREF: sub_4CFD90+75j
+ shr [esp+10h+arg_C], 1
+ add edi, edi
+ or edi, ebx
+ sub [esp+10h+arg_8], 1
+ jnz short loc_4CFDB1
+ pop esi
+ pop ebp
+ pop ebx
+
+loc_4CFE26: ; CODE XREF: sub_4CFD90+Cj
+ pop edi
+ retn
+sub_4CFD90 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+
+; =============== S U B R O U T I N E =======================================
+
+
+sub_4CFE30 proc near ; CODE XREF: CEncoder_CodeOneBlock+190p
+ ; CEncoder_CodeOneBlock+2CCp
+
+arg_0 = dword ptr 4
+arg_4 = byte ptr 8
+
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+0Ch+arg_0]
+ push edi
+ mov ebx, ecx
+ mov ebp, 1
+ mov edx, 8
+
+loc_4CFE44: ; CODE XREF: sub_4CFE30+88j
+ movzx edi, [esp+10h+arg_4]
+ sub edx, 1
+ mov cl, dl
+ shr edi, cl
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebx+ebp*4]
+ and edi, 1
+ test edi, edi
+ mov [esp+10h+arg_0], edx
+ jnz short loc_4CFE7E
+ mov [esi+10h], eax
+ mov eax, [ebx+ebp*4]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebx+ebp*4], ecx
+ jmp short loc_4CFE97
+; ---------------------------------------------------------------------------
+
+loc_4CFE7E: ; CODE XREF: sub_4CFE30+35j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebx+ebp*4]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [ebx+ebp*4], eax
+
+loc_4CFE97: ; CODE XREF: sub_4CFE30+4Cj
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFEB2
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+ mov edx, [esp+10h+arg_0]
+
+loc_4CFEB2: ; CODE XREF: sub_4CFE30+6Fj
+ add ebp, ebp
+ or ebp, edi
+ test edx, edx
+ jnz short loc_4CFE44
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ retn 8
+sub_4CFE30 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4CFED0 proc near ; CODE XREF: CEncoder_CodeOneBlock+300p
+
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = byte ptr 8
+arg_8 = byte ptr 0Ch
+
+ push ecx
+ push ebx
+ push ebp
+ push esi
+ mov esi, [esp+10h+arg_0]
+ push edi
+ mov [esp+14h+var_4], ecx
+ mov ebx, 1
+ mov edx, 8
+ jmp short loc_4CFEF0
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4CFEF0: ; CODE XREF: sub_4CFED0+17j
+ ; sub_4CFED0+ADj
+ movzx ebp, [esp+14h+arg_4]
+ movzx edi, [esp+14h+arg_8]
+ sub edx, 1
+ movzx ecx, dl
+ shr ebp, cl
+ shr edi, cl
+ mov ecx, [esp+14h+var_4]
+ mov [esp+14h+arg_0], edx
+ mov edx, [esi+10h]
+ and ebp, 1
+ lea eax, [ebp+1]
+ shl eax, 8
+ add eax, ebx
+ lea ecx, [ecx+eax*4]
+ mov eax, edx
+ shr eax, 0Bh
+ imul eax, [ecx]
+ and edi, 1
+ test edi, edi
+ jnz short loc_4CFF41
+ mov [esi+10h], eax
+ mov eax, [ecx]
+ mov edx, 800h
+ sub edx, eax
+ shr edx, 5
+ add edx, eax
+ mov [ecx], edx
+ jmp short loc_4CFF58
+; ---------------------------------------------------------------------------
+
+loc_4CFF41: ; CODE XREF: sub_4CFED0+5Aj
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub edx, eax
+ mov [esi+10h], edx
+ mov eax, [ecx]
+ mov edx, eax
+ shr edx, 5
+ sub eax, edx
+ mov [ecx], eax
+
+loc_4CFF58: ; CODE XREF: sub_4CFED0+6Fj
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4CFF6F
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4CFF6F: ; CODE XREF: sub_4CFED0+90j
+ mov edx, [esp+14h+arg_0]
+ add ebx, ebx
+ or ebx, edi
+ cmp ebp, edi
+ jnz short loc_4CFF8B
+ test edx, edx
+ jnz loc_4CFEF0
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4CFF8B: ; CODE XREF: sub_4CFED0+A9j
+ test edx, edx
+ jz loc_4D0012
+
+loc_4CFF93: ; CODE XREF: sub_4CFED0+140j
+ movzx edi, [esp+14h+arg_8]
+ mov ebp, [esp+14h+var_4]
+ sub edx, 1
+ mov cl, dl
+ shr edi, cl
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [ebp+ebx*4+0]
+ and edi, 1
+ test edi, edi
+ mov [esp+14h+arg_0], edx
+ jnz short loc_4CFFD4
+ mov [esi+10h], eax
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [ebp+ebx*4+0], ecx
+ jmp short loc_4CFFEF
+; ---------------------------------------------------------------------------
+
+loc_4CFFD4: ; CODE XREF: sub_4CFED0+E9j
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [ebp+ebx*4+0]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [ebp+ebx*4+0], eax
+
+loc_4CFFEF: ; CODE XREF: sub_4CFED0+102j
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D000A
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+ mov edx, [esp+14h+arg_0]
+
+loc_4D000A: ; CODE XREF: sub_4CFED0+127j
+ add ebx, ebx
+ or ebx, edi
+ test edx, edx
+ jnz short loc_4CFF93
+
+loc_4D0012: ; CODE XREF: sub_4CFED0+BDj
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ pop ecx
+ retn 0Ch
+sub_4CFED0 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4D0020 proc near ; CODE XREF: sub_4D0770+C6p
+ ; CEncoder_CodeOneBlock+56Dp ...
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ push ebp
+ mov ebp, [esp+4+arg_4]
+ cmp ebp, 8
+ push esi
+ mov esi, [esp+8+arg_0]
+ push edi
+ mov edi, ecx
+ jnb short loc_4D007D
+ mov eax, [esi+10h]
+ shr eax, 0Bh
+ imul eax, [edi]
+ mov [esi+10h], eax
+ mov eax, [edi]
+ mov ecx, 800h
+ sub ecx, eax
+
+loc_4D0047: ; DATA XREF: .rdata:0050C3BCo
+ shr ecx, 5
+ add ecx, eax
+ mov [edi], ecx
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0065
+ shl eax, 8
+
+loc_4D005B: ; DATA XREF: .rdata:005064B0o
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D0065: ; CODE XREF: sub_4D0020+36j
+ mov edx, [esp+0Ch+arg_8]
+ push ebp
+ shl edx, 5
+ push esi
+ lea ecx, [edx+edi+8]
+ call sub_4CFB20
+ pop edi
+ pop esi
+ pop ebp
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4D007D: ; CODE XREF: sub_4D0020+10j
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [edi]
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [edi]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edi], eax
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D00B6
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D00B6: ; CODE XREF: sub_4D0020+87j
+ cmp ebp, 10h
+ jnb short loc_4D010F
+ mov edx, [esi+10h]
+ shr edx, 0Bh
+ imul edx, [edi+4]
+ mov [esi+10h], edx
+ mov eax, [edi+4]
+ mov ecx, 800h
+ sub ecx, eax
+ shr ecx, 5
+ add ecx, eax
+ mov [edi+4], ecx
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D00F1
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D00F1: ; CODE XREF: sub_4D0020+C2j
+ mov edx, [esp+0Ch+arg_8]
+ add ebp, 0FFFFFFF8h
+ push ebp
+ shl edx, 5
+ push esi
+ lea ecx, [edx+edi+208h]
+ call sub_4CFB20
+ pop edi
+ pop esi
+ pop ebp
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4D010F: ; CODE XREF: sub_4D0020+99j
+ mov ecx, [esi+10h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [edi+4]
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [edi+4]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edi+4], eax
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D014B
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D014B: ; CODE XREF: sub_4D0020+11Cj
+ add ebp, 0FFFFFFF0h
+ push ebp
+ push esi
+ lea ecx, [edi+408h]
+ call sub_4CFBC0
+ pop edi
+ pop esi
+ pop ebp
+ retn 0Ch
+sub_4D0020 endp
+
+; =============== S U B R O U T I N E =======================================
+
+NCompress_NLZMA_CEncoder_CEncoder proc near ; CODE XREF: Compress_lzma_internal+149p
+ mov eax, ecx
+ mov dword ptr [eax+4], offset ICompressSetOutStream_vftable
+ mov dword ptr [eax+8], offset ICompressSetCoderProperties_vftable
+ mov dword ptr [eax+0Ch], offset ICompressWriteCoderProperties_vftable
+ xor ecx, ecx
+ mov [eax+24h], ecx
+ mov dword ptr [eax], offset NCompress_NLZMA_CEncoder_vftable
+ mov dword ptr [eax+4], offset NCompress_NLZMA_CEncoder_vftable_ICompressSetOutStream
+ mov dword ptr [eax+8], offset NCompress_NLZMA_CEncoder_vftable_ICompressSetCoderProperties
+ mov dword ptr [eax+0Ch], offset NCompress_NLZMA_CEncoder_vftable_ICompressWriteCoderProperties
+ mov [eax+40h], ecx
+ mov [eax+44h], ecx
+ mov [eax+54h], ecx
+ mov [eax+60h], ecx
+ mov [eax+32650h], ecx
+ mov dword ptr [eax+32EF8h], 20h
+ mov dword ptr [eax+33B58h], 2Ch
+ mov dword ptr [eax+33B5Ch], 2
+ mov [eax+33B64h], ecx
+ mov dword ptr [eax+33B6Ch], 00400000h
+ mov edx, 3
+ mov [eax+33B60h], edx
+ mov [eax+33B68h], edx
+ mov [eax+33B8Ch], ecx
+ mov [eax+33B90h], ecx
+ mov [eax+33B94h], cl
+ mov [eax+0B4h], ecx
+ mov [eax+0A4h], ecx
+ mov dword ptr [eax+0B0h], 20h
+ mov dword ptr [eax+0D4h], 1
+ mov dword ptr [eax+0CCh], 4
+ mov [eax+0D0h], ecx
+ mov [eax+0D8h], ecx
+ mov [eax+32EF4h], cl
+ retn
+NCompress_NLZMA_CEncoder_CEncoder endp
+
+; =============== S U B R O U T I N E =======================================
+
+; int __thiscall sub_4D0250(void *Memory, char)
+sub_4D0250 proc near ; DATA XREF: .rdata:00517B0Co
+
+arg_0 = byte ptr 4
+
+ push esi
+ mov esi, ecx
+ call sub_4CF810
+ test [esp+4+arg_0], 1
+ jz short loc_4D0268
+ push esi ; Memory
+ call j__free
+ add esp, 4
+
+loc_4D0268: ; CODE XREF: sub_4D0250+Dj
+ mov eax, esi
+ pop esi
+ retn 4
+sub_4D0250 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+sub_4D0270 proc near ; CODE XREF: CEncoder_SetStreams+14p
+ push esi
+ mov esi, ecx
+ mov eax, [esi+40h]
+ test eax, eax
+ push edi
+ mov edi, 100000h
+ jz short loc_4D0297
+ cmp [esi+50h], edi
+ jz short loc_4D02C5
+ test eax, eax
+ jz short loc_4D0297
+ push 8000h ; dwFreeType
+ push 0 ; dwSize
+ push eax ; lpAddress
+ call ds:VirtualFree
+
+loc_4D0297: ; CODE XREF: sub_4D0270+Ej
+ ; sub_4D0270+17j
+ push 4 ; flProtect
+ push 1000h ; flAllocationType
+ push edi ; dwSize
+ push 0 ; lpAddress
+ mov dword ptr [esi+40h], 0
+ mov [esi+50h], edi
+ call ds:VirtualAlloc
+ test eax, eax
+ mov [esi+40h], eax
+ setnz al
+ test al, al
+ jnz short loc_4D02C5
+ pop edi
+ mov eax, 8007000Eh
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4D02C5: ; CODE XREF: sub_4D0270+13j
+ ; sub_4D0270+4Bj
+ mov eax, [esi+33B68h]
+ mov ecx, [esi+33B64h]
+ cmp dword ptr [esi+0D4h], 0
+ push ebx
+ push eax
+ push ecx
+ lea ecx, [esi+32650h]
+ setnz bl
+ call sub_4CD940
+ test al, al
+ jz short loc_4D034F
+ mov ecx, [esi+33B6Ch]
+ mov edx, 1000000h
+ cmp edx, ecx
+ sbb eax, eax
+ neg eax
+ push ebp
+ mov ebp, [esi+32EF8h]
+ mov [esi+0D8h], eax
+ mov eax, ebp
+ shr eax, 1
+ add eax, 10h
+ test bl, bl
+ jnz short loc_4D0318
+ shr eax, 1
+
+loc_4D0318: ; CODE XREF: sub_4D0270+A4j
+ mov edx, [esi+33B90h]
+ test edx, edx
+ jz short loc_4D0324
+ mov eax, edx
+
+loc_4D0324: ; CODE XREF: sub_4D0270+B0j
+ push offset off_546E20
+ push 111h
+ push ebp
+ push 1000h
+ push ecx
+ lea edi, [esi+84h]
+ push edi
+ mov [esi+0B0h], eax
+ call sub_4CBA60
+ add esp, 18h
+ test eax, eax
+ pop ebp
+ jnz short loc_4D0358
+
+loc_4D034F: ; CODE XREF: sub_4D0270+7Bj
+ pop ebx
+ pop edi
+ mov eax, 8007000Eh
+ pop esi
+ retn
+; ---------------------------------------------------------------------------
+
+loc_4D0358: ; CODE XREF: sub_4D0270+DDj
+ mov [esi+80h], edi
+ add esi, 68h
+ push esi
+ push edi
+ call sub_4CCAA0
+ add esp, 8
+ pop ebx
+ pop edi
+ xor eax, eax
+ pop esi
+ retn
+sub_4D0270 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_SetStreams proc near ; CODE XREF: CEncoder_CodeReal+4Ap
+
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+
+ mov eax, [esp+arg_0]
+ push esi
+ mov esi, ecx
+ mov [esi+33B84h], eax
+ mov byte ptr [esi+33B80h], 0
+ call sub_4D0270
+ test eax, eax
+ jnz loc_4D0441
+ mov edx, [esp+4+arg_4]
+ mov ecx, [esi+4]
+ lea eax, [esi+4]
+ push edx
+ push eax
+ mov eax, [ecx+0Ch]
+ call eax
+ test eax, eax
+ jnz loc_4D0441
+ mov ecx, esi
+ call sub_4CDEA0
+ test eax, eax
+ jnz short loc_4D0441
+ cmp [esi+32EF4h], al
+ jnz short loc_4D03DB
+ mov ecx, esi
+ call CEncoder_FillDistancesPrices
+ mov ecx, esi
+ call CEncoder_FillAlignPrices
+
+loc_4D03DB: ; CODE XREF: CEncoder_SetStreams+4Bj
+ mov ecx, [esi+32EF8h]
+ sub ecx, 1
+ mov [esi+2D9C0h], ecx
+ mov ecx, [esi+33B5Ch]
+ mov edx, 1
+ shl edx, cl
+ lea ecx, [esi+28DB8h]
+ push edx
+ call sub_4CF780
+ mov ecx, [esi+33B5Ch]
+ mov eax, [esi+32EF8h]
+ mov edx, 1
+ shl edx, cl
+ sub eax, 1
+ lea ecx, [esi+2DA04h]
+ mov [esi+3260Ch], eax
+ push edx
+ call sub_4CF780
+ mov dword ptr [esi+33B78h], 0
+ mov dword ptr [esi+33B7Ch], 0
+ xor eax, eax
+
+loc_4D0441: ; CODE XREF: CEncoder_SetStreams+1Bj
+ ; CEncoder_SetStreams+34j ...
+ pop esi
+ retn 10h
+CEncoder_SetStreams endp
+
+;Compress_lzma_internal proc near ; CODE XREF: Compress_lzma+34p
+_starcraft_compress_lzma proc near ; CODE XREF: Compress_lzma+34p
+; sub_4D0450
+
+var_58 = dword ptr -58h
+var_54 = dword ptr -54h
+var_50 = dword ptr -50h
+var_4C = dword ptr -4Ch
+var_48 = dword ptr -48h
+var_44 = dword ptr -44h
+var_40 = dword ptr -40h
+var_3C = word ptr -3Ch
+var_34 = dword ptr -34h
+var_2C = word ptr -2Ch
+var_24 = dword ptr -24h
+var_1C = dword ptr -1Ch
+var_14 = dword ptr -14h
+var_C = dword ptr -0Ch
+var_4 = dword ptr -4
+pbInBuffer = dword ptr 4
+cbInBuffer = dword ptr 8
+pcbInBuffer = dword ptr 0Ch
+pbOutBuffer = dword ptr 10h
+cbOutBuffer = dword ptr 14h
+dummy = dword ptr 18h
+pcbOutBuffer = dword ptr 1Ch
+pfnAllocateMemory= dword ptr 20h
+pfnFreeMemory = dword ptr 24h
+pfnGiveData = dword ptr 28h
+
+ push 0FFFFFFFFh
+ push offset loc_4DA0FB
+ mov eax, dword ptr fs:[0]
+ push eax
+ sub esp, 4Ch
+ push ebx
+ push ebp
+ push esi
+ push edi
+ mov eax, dword_544960
+ xor eax, esp
+ push eax
+ lea eax, [esp+6Ch+var_C]
+ mov dword ptr fs:[0], eax
+ mov eax, dword_553598
+ xor ebx, ebx
+ cmp eax, ebx
+ jnz short loc_4D04A1
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ cmp eax, ebx
+ jz short loc_4D049A
+ mov [eax], ebx
+ mov [eax+4], ebx
+ mov [eax+8], ebx
+ jmp short loc_4D049C
+; ---------------------------------------------------------------------------
+
+loc_4D049A: ; CODE XREF: Compress_lzma_internal+3Ej
+ xor eax, eax
+
+loc_4D049C: ; CODE XREF: Compress_lzma_internal+48j
+ mov dword ptr dword_553598, eax
+
+loc_4D04A1: ; CODE XREF: Compress_lzma_internal+30j
+ cmp [eax], ebx
+ jnz short loc_4D04B3
+ mov ecx, [esp+6Ch+pfnAllocateMemory]
+ mov [eax], ecx
+ mov eax, dword_553598
+
+loc_4D04B3: ; CODE XREF: Compress_lzma_internal+53j
+ cmp eax, ebx
+ jnz short loc_4D04D6
+ push 0Ch ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ cmp eax, ebx
+ jz short loc_4D04CF
+ mov [eax], ebx
+ mov [eax+4], ebx
+ mov [eax+8], ebx
+ jmp short loc_4D04D1
+; ---------------------------------------------------------------------------
+
+loc_4D04CF: ; CODE XREF: Compress_lzma_internal+73j
+ xor eax, eax
+
+loc_4D04D1: ; CODE XREF: Compress_lzma_internal+7Dj
+ mov dword_553598, eax
+
+loc_4D04D6: ; CODE XREF: Compress_lzma_internal+65j
+ cmp [eax+4], ebx
+ jnz short loc_4D04EA
+ mov edx, [esp+6Ch+pfnFreeMemory]
+ mov [eax+4], edx
+ mov eax, dword_553598
+
+loc_4D04EA: ; CODE XREF: Compress_lzma_internal+89j
+ cmp [eax+8], ebx
+ jnz short loc_4D04F9
+ mov ecx, [esp+6Ch+pfnGiveData]
+ mov [eax+8], ecx
+
+loc_4D04F9: ; CODE XREF: Compress_lzma_internal+9Dj
+ mov edx, [esp+6Ch+pcbOutBuffer]
+ mov ebp, [esp+6Ch+pcbInBuffer]
+ cmp ebp, ebx
+ mov esi, [esp+6Ch+cbInBuffer]
+ mov [edx], ebx
+ mov edx, 1
+ mov eax, esi
+ mov ecx, ebp
+ ja short loc_4D0520
+ cmp esi, ebx
+ jbe short loc_4D053A
+ jmp short loc_4D0520
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4D0520: ; CODE XREF: Compress_lzma_internal+C5j
+ ; Compress_lzma_internal+CBj ...
+ shrd eax, ecx, 1
+ add edx, edx
+ shr ecx, 1
+ cmp edx, 2000000h
+ ja short loc_4D053A
+ cmp ecx, ebx
+ ja short loc_4D0520
+ jb short loc_4D053A
+ cmp eax, ebx
+ ja short loc_4D0520
+
+loc_4D053A: ; CODE XREF: Compress_lzma_internal+C9j
+ ; Compress_lzma_internal+DEj ...
+ mov eax, 13h
+ push 33B98h ; Size
+ mov [esp+70h+var_48], 470h
+ mov [esp+70h+var_44], 400h
+ mov [esp+70h+var_40], 450h
+ mov [esp+70h+var_3C], ax
+ mov [esp+70h+var_2C], ax
+ mov word ptr [esp+70h+var_1C], ax
+ mov [esp+70h+var_34], 2
+ mov [esp+70h+var_24], edx
+ mov [esp+70h+var_14], 40h
+ mov [esp+70h+var_58], ebx
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ mov [esp+6Ch+var_4C], eax
+ cmp eax, ebx
+ mov [esp+6Ch+var_4], ebx
+ jz short loc_4D05A4
+ mov ecx, eax
+ call NCompress_NLZMA_CEncoder_CEncoder
+ mov [esp+6Ch+var_54], eax
+ jmp short loc_4D05AA
+; ---------------------------------------------------------------------------
+
+loc_4D05A4: ; CODE XREF: Compress_lzma_internal+145j
+ mov [esp+6Ch+var_54], ebx
+ mov eax, ebx
+
+loc_4D05AA: ; CODE XREF: Compress_lzma_internal+152j
+ or edi, 0FFFFFFFFh
+ cmp eax, ebx
+ mov [esp+6Ch+var_4], edi
+ jz short loc_4D05D1
+ mov ecx, [eax+8]
+ push 3
+ lea edx, [esp+70h+var_3C]
+ push edx
+ add eax, 8
+ lea edx, [esp+74h+var_48]
+ push edx
+ push eax
+ mov eax, [ecx+0Ch]
+ call eax ; ICompressSetCodeProperties::SetCoderProperties
+ test eax, eax
+ jz short loc_4D05D5
+
+loc_4D05D1: ; CODE XREF: Compress_lzma_internal+163j
+ mov [esp+6Ch+var_58], edi
+
+loc_4D05D5: ; CODE XREF: Compress_lzma_internal+17Fj
+ push 28h ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ cmp eax, ebx
+ jz short loc_4D060E
+ mov ecx, [esp+6Ch+pbInBuffer]
+ mov [eax+4], ebx
+ add dword ptr [eax+4], 1
+ mov dword ptr [eax], offset off_517A90
+ mov [eax+8], ecx
+ mov [eax+10h], esi
+ mov [eax+14h], ebp
+ mov [eax+18h], ebx
+ mov [eax+1Ch], ebx
+ mov [eax+20h], bl
+ mov edi, eax ; EDI = pInStreamMemory
+ mov [esp+6Ch+var_50], eax
+ jmp short loc_4D0614
+; ---------------------------------------------------------------------------
+
+loc_4D060E: ; CODE XREF: Compress_lzma_internal+191j
+ xor edi, edi
+ mov [esp+6Ch+var_50], edi
+
+loc_4D0614: ; CODE XREF: Compress_lzma_internal+1BCj
+ push 28h ; Size
+ call _operator_new ; operator new(uint)
+ add esp, 4
+ cmp eax, ebx
+ jz short loc_4D0657
+ mov edx, [esp+6Ch+pbOutBuffer]
+ mov ecx, [esp+6Ch+cbOutBuffer]
+ mov [eax+4], ebx
+ add dword ptr [eax+4], 1
+ mov [eax+8], edx
+ mov edx, [esp+6Ch+dummy]
+ mov dword ptr [eax], offset off_517AA4
+ mov [eax+10h], ecx
+ mov [eax+14h], edx
+ mov [eax+18h], ebx
+ mov [eax+1Ch], ebx
+ mov [eax+20h], bl
+ mov esi, eax ; ESI = pOutStreamMemory
+ jmp short loc_4D0659
+; ---------------------------------------------------------------------------
+
+loc_4D0657: ; CODE XREF: Compress_lzma_internal+1D0j
+ xor esi, esi
+
+loc_4D0659: ; CODE XREF: Compress_lzma_internal+205j
+ cmp edi, ebx
+ jz short loc_4D0661
+ cmp esi, ebx
+ jnz short loc_4D0669
+
+loc_4D0661: ; CODE XREF: Compress_lzma_internal+20Bj
+ mov [esp+6Ch+var_58], 0FFFFFFFFh
+
+loc_4D0669: ; CODE XREF: Compress_lzma_internal+20Fj
+ mov eax, [esi] ; EAX = pOutStreamMemory->vftable
+ mov ecx, [eax+10h] ; ECX =
+ push ebx
+ mov edi, 1
+ push edi
+ push ebx
+ push esi
+ call ecx
+ test eax, eax
+ jz short loc_4D0681
+ mov [esp+6Ch+var_58], edi
+
+loc_4D0681: ; CODE XREF: Compress_lzma_internal+22Bj
+ mov eax, [esp+6Ch+var_54]
+ mov edx, [eax+0Ch]
+ add eax, 0Ch
+ push esi
+ push eax
+ mov eax, [edx+0Ch]
+ call eax
+ test eax, eax
+ jz short loc_4D069A
+ mov [esp+6Ch+var_58], edi
+
+loc_4D069A: ; CODE XREF: Compress_lzma_internal+244j
+ xor edi, edi
+ jmp short loc_4D06A4
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4D06A0: ; CODE XREF: Compress_lzma_internal+27Fj
+ mov ebp, [esp+6Ch+pcbInBuffer]
+
+loc_4D06A4: ; CODE XREF: Compress_lzma_internal+24Cj
+ mov eax, [esp+6Ch+cbInBuffer]
+ push ebx
+ push 1
+ mov edx, ebp
+ mov ecx, edi
+ call __allshr ; Microsoft VisualC 2-8/net runtime
+ push eax
+ mov eax, [esi]
+ mov ecx, [eax+10h]
+ push esi
+ call ecx
+ test eax, eax
+ jz short loc_4D06C9
+ mov [esp+6Ch+var_58], 1
+
+loc_4D06C9: ; CODE XREF: Compress_lzma_internal+26Fj
+ add edi, 8
+ cmp edi, 40h
+ jl short loc_4D06A0
+ mov ebp, [esp+6Ch+var_54]
+ xor edi, edi
+ cmp [esp+6Ch+var_58], ebx
+ jnz short loc_4D0723
+ mov eax, [esp+6Ch+var_50]
+ mov edx, [ebp+0]
+ mov ecx, [edx+0Ch]
+ push ebx
+ push ebx
+ push ebx
+ push esi
+ push eax
+ push ebp
+ call ecx
+ mov ecx, [esi+18h]
+ mov edi, eax
+ mov eax, [esi+1Ch]
+ cmp eax, ebx
+ ja short loc_4D0700
+ cmp ecx, 0FFFFFFFFh
+ jbe short loc_4D0709
+
+loc_4D0700: ; CODE XREF: Compress_lzma_internal+2A9j
+ or ecx, 0FFFFFFFFh
+ mov [esp+6Ch+pcbInBuffer], ebx
+ jmp short loc_4D070D
+; ---------------------------------------------------------------------------
+
+loc_4D0709: ; CODE XREF: Compress_lzma_internal+2AEj
+ mov [esp+6Ch+pcbInBuffer], eax
+
+loc_4D070D: ; CODE XREF: Compress_lzma_internal+2B7j
+ mov edx, [esp+6Ch+pcbOutBuffer]
+ mov [edx], ecx
+ cmp [esi+20h], bl
+ jz short loc_4D0723
+ mov [esp+6Ch+var_58], 1
+
+loc_4D0723: ; CODE XREF: Compress_lzma_internal+28Bj
+ ; Compress_lzma_internal+2C9j
+ mov eax, [esp+6Ch+var_50]
+ cmp eax, ebx
+ jz short loc_4D0733
+ mov ecx, [eax]
+ mov edx, [ecx+8]
+ push eax
+ call edx
+
+loc_4D0733: ; CODE XREF: Compress_lzma_internal+2D9j
+ mov eax, [esi]
+ mov ecx, [eax+8]
+ push esi
+ call ecx
+ mov edx, [ebp+0]
+ mov eax, [edx+10h]
+ push 1
+ mov ecx, ebp
+ call eax
+ mov eax, [esp+6Ch+var_58]
+ cmp eax, ebx
+ jnz short loc_4D0755
+ neg edi
+ sbb edi, edi
+ mov eax, edi
+
+loc_4D0755: ; CODE XREF: Compress_lzma_internal+2FDj
+ mov ecx, [esp+6Ch+var_C]
+ mov dword ptr fs:[0], ecx
+ pop ecx
+ pop edi
+ pop esi
+ pop ebp
+ pop ebx
+ add esp, 58h
+ retn
+_starcraft_compress_lzma endp
+;Compress_lzma_internal endp
+
+; =============== S U B R O U T I N E =======================================
+
+Compress_lzma proc near ; DATA XREF: .rdata:00509684o
+
+pbOutBuffer = dword ptr 4
+pcbOutBuffer = dword ptr 8
+pbInBuffer = dword ptr 0Ch
+cbInBuffer = dword ptr 10h
+
+ push esi
+ push edi
+; call sub_47F198
+ mov esi, [esp+8+pcbOutBuffer] ; ESI = pcbOutBuffer
+ mov edi, [esp+8+cbInBuffer] ; EDI = cbInBuffer
+; push offset GiveDataToCompress
+; push offset FreeMemory_47F3AB
+; push offset AllocateMemory_47F396
+ push esi ; pcbOutBuffer
+ push 0
+ mov [eax+493E0h], eax
+ push dword ptr [esi] ; cbOutBuffer
+ push [esp+20h+pbOutBuffer] ; pbOutBuffer
+ push 0
+ push edi ; cbInBuffer
+ push [esp+2Ch+pbInBuffer] ; pbInBuffer
+; call Compress_lzma_internal
+ add esp, 28h
+ sub eax, 0
+ jz short loc_47F401
+ mov [esi], edi
+ dec eax
+
+loc_47F401: ; CODE XREF: Compress_lzma+3Fj
+ pop edi
+ pop esi
+ retn
+Compress_lzma endp
+
+; =============== S U B R O U T I N E =======================================
+
+sub_4D0770 proc near ; CODE XREF: CEncoder_Flush+1Ap
+
+arg_0 = dword ptr 4
+
+ push edi
+ mov edi, ecx
+ cmp byte ptr [edi+33B94h], 0
+ jz loc_4D0881
+ movzx eax, byte ptr [edi+10h]
+ mov ecx, [edi+38h]
+ shl eax, 4
+ push ebx
+ mov ebx, [esp+8+arg_0]
+ add eax, ebx
+ lea edx, [edi+eax*4+280F0h]
+ push ebp
+ push esi
+ lea esi, [edi+28h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [edx]
+ add [esi+8], eax
+ adc dword ptr [esi+0Ch], 0
+ sub ecx, eax
+ mov [esi+10h], ecx
+ mov eax, [edx]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edx], eax
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D07D3
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D07D3: ; CODE XREF: sub_4D0770+54j
+ movzx edx, byte ptr [edi+10h]
+ mov ecx, [esi+10h]
+ lea eax, [edi+edx*4+283F0h]
+ shr ecx, 0Bh
+ imul ecx, [eax]
+ mov [esi+10h], ecx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [esi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0811
+ shl eax, 8
+ mov ecx, esi
+ mov [esi+10h], eax
+ call loc_4CF640
+
+loc_4D0811: ; CODE XREF: sub_4D0770+92j
+ movzx eax, byte ptr [edi+10h]
+ mov cl, ds:kMatchNextStates[eax]
+ push ebx
+ mov [edi+10h], cl
+ cmp byte ptr [edi+32EF4h], 0
+ push 0
+ lea ebp, [edi+28DB8h]
+ push esi
+ mov ecx, ebp
+ setz byte ptr [esp+1Ch+arg_0]
+ call sub_4D0020
+ cmp byte ptr [esp+10h+arg_0], 0
+ jz short loc_4D0854
+ add dword ptr [ebp+ebx*4+4C0Ch], 0FFFFFFFFh
+ jnz short loc_4D0854
+ push ebx
+ mov ecx, ebp
+ call sub_4CF740
+
+loc_4D0854: ; CODE XREF: sub_4D0770+D0j
+ ; sub_4D0770+DAj
+ push 3Fh
+ push esi
+ lea ecx, [edi+287B0h]
+ call sub_4CFC60
+ push 1Ah
+ push 3FFFFFFh
+ mov ecx, esi
+ call sub_4CF6E0
+ push 0Fh
+ push esi
+ lea ecx, [edi+28D78h]
+ call sub_4CFD00
+ pop esi
+ pop ebp
+ pop ebx
+
+loc_4D0881: ; CODE XREF: sub_4D0770+Aj
+ pop edi
+ retn 4
+sub_4D0770 endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_Flush proc near ; CODE XREF: CEncoder_CodeOneBlock+BAp
+ ; CEncoder_CodeOneBlock+1D0p ...
+
+arg_0 = dword ptr 4
+
+ push esi
+ mov esi, ecx
+ mov eax, [esi+0ECh]
+ test eax, eax
+ jnz short loc_4D08E5
+ mov eax, [esi+33B60h]
+ and eax, [esp+4+arg_0]
+ push ebx
+ push edi
+ push eax
+ call sub_4D0770
+ lea ebx, [esi+28h]
+ mov edi, 5
+
+loc_4D08B7: ; CODE XREF: CEncoder_Flush+31j
+ mov ecx, ebx
+ call loc_4CF640
+ sub edi, 1
+ jnz short loc_4D08B7
+ mov ecx, [esi+4Ch]
+ add esi, 40h
+ cmp ecx, [esi+4]
+ pop edi
+ pop ebx
+ jz short loc_4D08E3
+
+loc_4D08D0: ; CODE XREF: CEncoder_Flush+51j
+ mov ecx, esi
+ call sub_4CF450
+ test eax, eax
+ jnz short loc_4D08E5
+ mov edx, [esi+0Ch]
+ cmp edx, [esi+4]
+ jnz short loc_4D08D0
+
+loc_4D08E3: ; CODE XREF: CEncoder_Flush+3Ej
+ xor eax, eax
+
+loc_4D08E5: ; CODE XREF: CEncoder_Flush+Bj
+ ; CEncoder_Flush+49j
+ pop esi
+ retn 4
+CEncoder_Flush endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+; =============== S U B R O U T I N E =======================================
+
+CEncoder_CodeOneBlock proc near ; CODE XREF: CEncoder_CodeReal+B1p
+ ; CEncoder_CodeReal+F5p
+
+var_20 = byte ptr -20h
+var_1C = dword ptr -1Ch
+var_18 = dword ptr -18h
+var_14 = dword ptr -14h
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_8 = dword ptr -8
+var_4 = dword ptr -4
+arg_0 = dword ptr 4
+arg_4 = dword ptr 8
+arg_8 = dword ptr 0Ch
+
+ sub esp, 20h
+ push ebp
+ push esi
+ mov esi, ecx
+ push edi
+ mov edi, [esi+33B84h]
+ xor ebp, ebp
+ cmp edi, ebp
+ jz short loc_4D0952
+ mov eax, [edi]
+ mov ecx, [eax+4]
+ push edi
+ call ecx
+ mov eax, [esi+33B8Ch]
+ cmp eax, ebp
+ jz short loc_4D091E
+ mov edx, [eax]
+ push eax
+ mov eax, [edx+8]
+ call eax
+
+loc_4D091E: ; CODE XREF: CEncoder_CodeOneBlock+24j
+ mov [esi+33B8Ch], edi
+ mov ecx, [esi+80h]
+ mov edx, [esi+68h]
+ lea eax, [esi+33B88h]
+ push ecx
+ mov dword ptr [eax], offset loc_4CF210
+ mov [esi+0B8h], eax
+ call edx
+ add esp, 4
+ mov byte ptr [esi+33B95h], 1
+ mov [esi+33B84h], ebp
+
+loc_4D0952: ; CODE XREF: CEncoder_CodeOneBlock+12j
+ mov eax, [esp+2Ch+arg_8]
+ mov dword ptr [eax], 1
+ cmp byte ptr [esi+33B80h], 0
+ jz short loc_4D0974
+ mov eax, [esi+0ECh]
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4D0974: ; CODE XREF: CEncoder_CodeOneBlock+73j
+ mov ecx, [esi+33B78h]
+ or ecx, [esi+33B7Ch]
+ push ebx
+ mov byte ptr [esi+33B80h], 1
+ jnz loc_4D0A9C
+ mov edx, [esi+80h]
+ mov eax, [esi+70h]
+ push edx
+ call eax
+ add esp, 4
+ test eax, eax
+ jnz short loc_4D09B9
+ mov ecx, [esi+33B78h]
+ push ecx
+ mov ecx, esi
+ call CEncoder_Flush
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4D09B9: ; CODE XREF: CEncoder_CodeOneBlock+AFj
+ lea edx, [esp+30h+var_4]
+ push edx
+ mov ecx, esi
+ call sub_4CB3B0
+ movzx ecx, byte ptr [esi+10h]
+ mov eax, [esi+33B60h]
+ and eax, [esi+33B78h]
+ mov edx, [esi+38h]
+ lea edi, [esi+28h]
+ shl ecx, 4
+ add eax, ecx
+ shr edx, 0Bh
+ imul edx, [esi+eax*4+280F0h]
+ lea eax, [esi+eax*4+280F0h]
+ mov [edi+10h], edx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0A1C
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0A1C: ; CODE XREF: CEncoder_CodeOneBlock+11Dj
+ movzx eax, byte ptr [esi+10h]
+ mov cl, ds:kLiteralNextStates[eax]
+ mov [esi+10h], cl
+ mov edx, [esi+32F04h]
+ mov eax, [esi+80h]
+ mov ecx, [esi+6Ch]
+ neg edx
+ push edx
+ push eax
+ call ecx
+ mov bl, al
+ mov eax, [esi+32654h]
+ add esp, 8
+ mov byte ptr [esp+30h+var_10], bl
+ mov edx, [esp+30h+var_10]
+ push edx
+ movzx edx, byte ptr [esi+11h]
+ push edi
+ mov edi, [esi+3265Ch]
+ and edi, [esi+33B78h]
+ mov ecx, 8
+ sub cl, al
+ shr edx, cl
+ mov ecx, eax
+ shl edi, cl
+ add edx, edi
+ imul edx, 0C00h
+ add edx, [esi+32650h]
+ mov ecx, edx
+ call sub_4CFE30
+ add dword ptr [esi+32F04h], 0FFFFFFFFh
+ add dword ptr [esi+33B78h], 1
+ mov [esi+11h], bl
+ adc [esi+33B7Ch], ebp
+
+loc_4D0A9C: ; CODE XREF: CEncoder_CodeOneBlock+98j
+ mov edi, [esi+33B78h]
+ mov eax, [esi+80h]
+ mov ecx, [esi+70h]
+ push eax
+ mov [esp+34h+var_14], edi
+ mov [esp+34h+var_4], edi
+ call ecx
+ add esp, 4
+ test eax, eax
+ jnz short loc_4D0AD4
+ push edi
+ mov ecx, esi
+ call CEncoder_Flush
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 0Ch
+; ---------------------------------------------------------------------------
+ align 10h
+
+loc_4D0AD0: ; CODE XREF: CEncoder_CodeOneBlock+735j
+ ; CEncoder_CodeOneBlock+78Bj
+ mov edi, [esp+30h+var_14]
+
+loc_4D0AD4: ; CODE XREF: CEncoder_CodeOneBlock+1CBj
+ cmp byte ptr [esi+32EF4h], 0
+ mov ecx, esi
+ jz short loc_4D0AEB
+ lea edx, [esp+30h+var_1C]
+ push edx
+ call CEncoder_GetOptimumFast
+ jmp short loc_4D0AF6
+; ---------------------------------------------------------------------------
+
+loc_4D0AEB: ; CODE XREF: CEncoder_CodeOneBlock+1EDj
+ lea eax, [esp+30h+var_1C]
+ push eax
+ push edi
+ call CEncoder_GetOptimum
+
+loc_4D0AF6: ; CODE XREF: CEncoder_CodeOneBlock+1F9j
+ mov ebx, [esi+33B60h]
+ and ebx, edi
+ cmp eax, 1
+ mov [esp+30h+var_18], eax
+ jnz loc_4D0C0E
+ cmp [esp+30h+var_1C], 0FFFFFFFFh
+ jnz loc_4D0C0E
+ movzx ecx, byte ptr [esi+10h]
+ mov edx, [esi+38h]
+ lea ebp, [esi+28h]
+ shl ecx, 4
+ shr edx, 0Bh
+ add ecx, ebx
+ imul edx, [esi+ecx*4+280F0h]
+ lea eax, [esi+ecx*4+280F0h]
+ mov [ebp+10h], edx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [ebp+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0B61
+ shl eax, 8
+ mov ecx, ebp
+ mov [ebp+10h], eax
+ call loc_4CF640
+
+loc_4D0B61: ; CODE XREF: CEncoder_CodeOneBlock+262j
+ mov eax, [esi+32F04h]
+ mov ecx, [esi+80h]
+ mov edx, [esi+6Ch]
+ neg eax
+ push eax
+ push ecx
+ call edx
+ movzx edi, byte ptr [esi+11h]
+ mov edx, [esi+3265Ch]
+ and edx, [esp+38h+var_14]
+ mov bl, al
+ mov eax, [esi+32654h]
+ mov ecx, 8
+ sub cl, al
+ shr edi, cl
+ mov ecx, eax
+ shl edx, cl
+ add esp, 8
+ mov byte ptr [esp+30h+var_10], bl
+ add edi, edx
+ imul edi, 0C00h
+ add edi, [esi+32650h]
+ cmp byte ptr [esi+10h], 7
+ jnb short loc_4D0BC3
+ mov eax, [esp+30h+var_10]
+ push eax
+ push ebp
+ mov ecx, edi
+ call sub_4CFE30
+ jmp short loc_4D0BF5
+; ---------------------------------------------------------------------------
+
+loc_4D0BC3: ; CODE XREF: CEncoder_CodeOneBlock+2C2j
+ mov edx, [esi+80h]
+ mov eax, [esi+6Ch]
+ or ecx, 0FFFFFFFFh
+ sub ecx, [esi+14h]
+ sub ecx, [esi+32F04h]
+ push ecx
+ push edx
+ call eax
+ mov ecx, [esp+38h+var_10]
+ add esp, 8
+ mov byte ptr [esp+30h+var_C], al
+ mov edx, [esp+30h+var_C]
+ push ecx
+ push edx
+ push ebp
+ mov ecx, edi
+ call sub_4CFED0
+
+loc_4D0BF5: ; CODE XREF: CEncoder_CodeOneBlock+2D1j
+ movzx eax, byte ptr [esi+10h]
+ mov cl, ds:kLiteralNextStates[eax]
+ mov ebp, [esp+30h+var_18]
+ mov [esi+10h], cl
+ mov [esi+11h], bl
+ jmp loc_4D1013
+; ---------------------------------------------------------------------------
+
+loc_4D0C0E: ; CODE XREF: CEncoder_CodeOneBlock+215j
+ ; CEncoder_CodeOneBlock+220j
+ movzx edx, byte ptr [esi+10h]
+ mov ecx, [esi+38h]
+ lea edi, [esi+28h]
+ shl edx, 4
+ mov eax, ecx
+ shr eax, 0Bh
+ add edx, ebx
+ imul eax, [esi+edx*4+280F0h]
+ add [edi+8], eax
+ lea edx, [esi+edx*4+280F0h]
+ mov ebp, 0
+ adc [edi+0Ch], ebp
+ sub ecx, eax
+ mov [edi+10h], ecx
+ mov eax, [edx]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edx], eax
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0C63
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0C63: ; CODE XREF: CEncoder_CodeOneBlock+364j
+ cmp [esp+30h+var_1C], 4
+ movzx edx, byte ptr [esi+10h]
+ mov ecx, [edi+10h]
+ jnb loc_4D0E91
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [esi+edx*4+283F0h]
+ add [edi+8], eax
+ lea edx, [esi+edx*4+283F0h]
+ adc [edi+0Ch], ebp
+ sub ecx, eax
+ mov [edi+10h], ecx
+ mov eax, [edx]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edx], eax
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0CB6
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0CB6: ; CODE XREF: CEncoder_CodeOneBlock+3B7j
+ mov eax, [esp+30h+var_1C]
+ cmp eax, ebp
+ mov ecx, [edi+10h]
+ jnz short loc_4D0D24
+ movzx edx, byte ptr [esi+10h]
+ lea eax, [esi+edx*4+28420h]
+ shr ecx, 0Bh
+ imul ecx, [eax]
+ mov [edi+10h], ecx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0CFC
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0CFC: ; CODE XREF: CEncoder_CodeOneBlock+3FDj
+ mov ebp, [esp+30h+var_18]
+ movzx ecx, byte ptr [esi+10h]
+ xor eax, eax
+ cmp ebp, 1
+ setnz al
+ shl ecx, 4
+ add ecx, ebx
+ lea ecx, [esi+ecx*4+284B0h]
+ push eax
+ push edi
+ call sub_4CFAC0
+ jmp loc_4D0E2E
+; ---------------------------------------------------------------------------
+
+loc_4D0D24: ; CODE XREF: CEncoder_CodeOneBlock+3CFj
+ mov edx, [esi+eax*4+14h]
+ movzx eax, byte ptr [esi+10h]
+ mov [esp+30h+var_8], edx
+ lea edx, [esi+eax*4+28420h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [edx]
+ add [edi+8], eax
+ adc [edi+0Ch], ebp
+ sub ecx, eax
+ mov [edi+10h], ecx
+ mov eax, [edx]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edx], eax
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0D6C
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0D6C: ; CODE XREF: CEncoder_CodeOneBlock+46Dj
+ cmp [esp+30h+var_1C], 1
+ mov ecx, [edi+10h]
+ jnz short loc_4D0DB3
+ movzx edx, byte ptr [esi+10h]
+ lea eax, [esi+edx*4+28450h]
+ shr ecx, 0Bh
+ imul ecx, [eax]
+ mov [edi+10h], ecx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0E1D
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+ jmp short loc_4D0E1D
+; ---------------------------------------------------------------------------
+
+loc_4D0DB3: ; CODE XREF: CEncoder_CodeOneBlock+484j
+ movzx eax, byte ptr [esi+10h]
+ lea edx, [esi+eax*4+28450h]
+ mov eax, ecx
+ shr eax, 0Bh
+ imul eax, [edx]
+ add [edi+8], eax
+ adc [edi+0Ch], ebp
+ sub ecx, eax
+ mov [edi+10h], ecx
+ mov eax, [edx]
+ mov ecx, eax
+ shr ecx, 5
+ sub eax, ecx
+ mov [edx], eax
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0DF3
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0DF3: ; CODE XREF: CEncoder_CodeOneBlock+4F4j
+ mov ebp, [esp+30h+var_1C]
+ movzx eax, byte ptr [esi+10h]
+ lea edx, [ebp-2]
+ push edx
+ push edi
+ lea ecx, [esi+eax*4+28480h]
+ call sub_4CFAC0
+ cmp ebp, 3
+ jnz short loc_4D0E17
+ mov ecx, [esi+1Ch]
+ mov [esi+20h], ecx
+
+loc_4D0E17: ; CODE XREF: CEncoder_CodeOneBlock+51Fj
+ mov edx, [esi+18h]
+ mov [esi+1Ch], edx
+
+loc_4D0E1D: ; CODE XREF: CEncoder_CodeOneBlock+4B2j
+ ; CEncoder_CodeOneBlock+4C1j
+ mov eax, [esi+14h]
+ mov ecx, [esp+30h+var_8]
+ mov ebp, [esp+30h+var_18]
+ mov [esi+18h], eax
+ mov [esi+14h], ecx
+
+loc_4D0E2E: ; CODE XREF: CEncoder_CodeOneBlock+42Fj
+ cmp ebp, 1
+ jnz short loc_4D0E45
+ movzx edx, byte ptr [esi+10h]
+ mov al, ds:kShortRepNextStates[edx]
+ mov [esi+10h], al
+ jmp loc_4D0FF5
+; ---------------------------------------------------------------------------
+
+loc_4D0E45: ; CODE XREF: CEncoder_CodeOneBlock+541j
+ cmp byte ptr [esi+32EF4h], 0
+ push ebx
+ lea edx, [ebp-2]
+ push edx
+ lea ecx, [esi+2DA04h]
+ push edi
+ setz [esp+3Ch+var_20]
+ call sub_4D0020
+ cmp [esp+30h+var_20], 0
+ jz short loc_4D0E7F
+ add dword ptr [esi+ebx*4+32610h], 0FFFFFFFFh
+ lea ecx, [esi+2DA04h]
+ jnz short loc_4D0E7F
+ push ebx
+ call sub_4CF740
+
+loc_4D0E7F: ; CODE XREF: CEncoder_CodeOneBlock+577j
+ ; CEncoder_CodeOneBlock+587j
+ movzx eax, byte ptr [esi+10h]
+ mov cl, ds:kRepNextStates[eax]
+ mov [esi+10h], cl
+ jmp loc_4D0FF5
+; ---------------------------------------------------------------------------
+
+loc_4D0E91: ; CODE XREF: CEncoder_CodeOneBlock+37Fj
+ lea eax, [esi+edx*4+283F0h]
+ shr ecx, 0Bh
+ imul ecx, [eax]
+ mov [edi+10h], ecx
+ mov ecx, [eax]
+ mov edx, 800h
+ sub edx, ecx
+ shr edx, 5
+ add edx, ecx
+ mov [eax], edx
+ mov eax, [edi+10h]
+ cmp eax, 1000000h
+ jnb short loc_4D0EC8
+ shl eax, 8
+ mov ecx, edi
+ mov [edi+10h], eax
+ call loc_4CF640
+
+loc_4D0EC8: ; CODE XREF: CEncoder_CodeOneBlock+5C9j
+ movzx eax, byte ptr [esi+10h]
+ mov cl, ds:kMatchNextStates[eax]
+ mov eax, [esp+30h+var_18]
+ mov [esi+10h], cl
+ cmp byte ptr [esi+32EF4h], 0
+ push ebx
+ setz [esp+34h+var_20]
+ add eax, 0FFFFFFFEh
+ push eax
+ lea ebp, [esi+28DB8h]
+ push edi
+ mov ecx, ebp
+ call sub_4D0020
+ cmp [esp+30h+var_20], 0
+ jz short loc_4D0F11
+ add dword ptr [ebp+ebx*4+4C0Ch], 0FFFFFFFFh
+ jnz short loc_4D0F11
+ push ebx
+ mov ecx, ebp
+ call sub_4CF740
+
+loc_4D0F11: ; CODE XREF: CEncoder_CodeOneBlock+60Dj
+ ; CEncoder_CodeOneBlock+617j
+ mov eax, [esp+30h+var_1C]
+ sub eax, 4
+ cmp eax, 2000h
+ mov [esp+30h+var_1C], eax
+ jnb short loc_4D0F2C
+ movzx ebp, byte ptr dword_551198[eax]
+ jmp short loc_4D0F4F
+; ---------------------------------------------------------------------------
+
+loc_4D0F2C: ; CODE XREF: CEncoder_CodeOneBlock+631j
+ cmp eax, 2000000h
+ jnb short loc_4D0F42
+ shr eax, 0Ch
+ movzx ebp, byte ptr dword_551198[eax]
+ add ebp, 18h
+ jmp short loc_4D0F4F
+; ---------------------------------------------------------------------------
+
+loc_4D0F42: ; CODE XREF: CEncoder_CodeOneBlock+641j
+ shr eax, 18h
+ movzx ebp, byte ptr dword_551198[eax]
+ add ebp, 30h
+
+loc_4D0F4F: ; CODE XREF: CEncoder_CodeOneBlock+63Aj
+ ; CEncoder_CodeOneBlock+650j
+ mov eax, [esp+30h+var_18]
+ add eax, 0FFFFFFFEh
+ cmp eax, 4
+ jb short loc_4D0F60
+ mov eax, 3
+
+loc_4D0F60: ; CODE XREF: CEncoder_CodeOneBlock+669j
+ push ebp
+ shl eax, 8
+ push edi
+ lea ecx, [eax+esi+287B0h]
+ call sub_4CFC60
+ cmp ebp, 4
+ jb short loc_4D0FD1
+ mov ebx, [esp+30h+var_1C]
+ mov ecx, ebp
+ mov eax, ebp
+ and eax, 1
+ shr ecx, 1
+ sub ecx, 1
+ or eax, 2
+ shl eax, cl
+ sub ebx, eax
+ cmp ebp, 0Eh
+ jnb short loc_4D0FA9
+ push ebx
+ push ecx
+ sub eax, ebp
+ lea edx, [esi+eax*4+28BACh]
+ push edi
+ push edx
+ call sub_4CFD90
+ add esp, 10h
+ jmp short loc_4D0FD1
+; ---------------------------------------------------------------------------
+
+loc_4D0FA9: ; CODE XREF: CEncoder_CodeOneBlock+6A0j
+ add ecx, 0FFFFFFFCh
+ push ecx
+ mov eax, ebx
+ shr eax, 4
+ push eax
+ mov ecx, edi
+ call sub_4CF6E0
+ and ebx, 0Fh
+ push ebx
+ push edi
+ lea ecx, [esi+28D78h]
+ call sub_4CFD00
+ add dword ptr [esi+33B54h], 1
+
+loc_4D0FD1: ; CODE XREF: CEncoder_CodeOneBlock+684j
+ ; CEncoder_CodeOneBlock+6B7j
+ mov ecx, [esi+1Ch]
+ mov edx, [esi+18h]
+ mov eax, [esi+14h]
+ add dword ptr [esi+33B70h], 1
+ mov ebp, [esp+30h+var_18]
+ mov [esi+20h], ecx
+ mov ecx, [esp+30h+var_1C]
+ mov [esi+1Ch], edx
+ mov [esi+18h], eax
+ mov [esi+14h], ecx
+
+loc_4D0FF5: ; CODE XREF: CEncoder_CodeOneBlock+550j
+ ; CEncoder_CodeOneBlock+59Cj
+ mov eax, [esi+80h]
+ mov ecx, [esi+6Ch]
+ mov edx, ebp
+ sub edx, [esi+32F04h]
+ sub edx, 1
+ push edx
+ push eax
+ call ecx
+ add esp, 8
+ mov [esi+11h], al
+
+loc_4D1013: ; CODE XREF: CEncoder_CodeOneBlock+319j
+ sub [esi+32F04h], ebp
+ mov eax, [esi+32F04h]
+ add [esp+30h+var_14], ebp
+ test eax, eax
+ jnz loc_4D0AD0
+ cmp [esi+32EF4h], al
+ jnz short loc_4D1056
+ cmp dword ptr [esi+33B70h], 80h
+ jb short loc_4D1046
+ mov ecx, esi
+ call CEncoder_FillDistancesPrices
+
+loc_4D1046: ; CODE XREF: CEncoder_CodeOneBlock+74Dj
+ cmp dword ptr [esi+33B54h], 10h
+ jb short loc_4D1056
+ mov ecx, esi
+ call CEncoder_FillAlignPrices
+
+loc_4D1056: ; CODE XREF: CEncoder_CodeOneBlock+741j
+ ; CEncoder_CodeOneBlock+75Dj
+ mov edx, [esi+80h]
+ mov eax, [esi+70h]
+ push edx
+ call eax
+ add esp, 4
+ test eax, eax
+ mov eax, [esp+30h+var_14]
+ jz short loc_4D10D7
+ mov ecx, [esp+30h+var_4]
+ mov edx, eax
+ sub edx, ecx
+ cmp edx, 4000h
+ jb loc_4D0AD0
+ sub eax, ecx
+ add [esi+33B78h], eax
+ mov ecx, [esi+33B78h]
+ mov eax, [esp+30h+arg_0]
+ adc dword ptr [esi+33B7Ch], 0
+ mov [eax], ecx
+ mov edx, [esi+33B7Ch]
+ lea ecx, [esi+28h]
+ mov [eax+4], edx
+ call sub_4CD8B0
+ mov ecx, [esp+30h+arg_4]
+ mov [ecx], eax
+ mov eax, [esp+30h+arg_8]
+ mov [ecx+4], edx
+ pop ebx
+ mov byte ptr [esi+33B80h], 0
+ pop edi
+ mov dword ptr [eax], 0
+ mov eax, [esi+0ECh]
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 0Ch
+; ---------------------------------------------------------------------------
+
+loc_4D10D7: ; CODE XREF: CEncoder_CodeOneBlock+77Bj
+ push eax
+ mov ecx, esi
+ call CEncoder_Flush
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 0Ch
+CEncoder_CodeOneBlock endp
+
+; ---------------------------------------------------------------------------
+ align 10h
+CEncoder_CodeReal proc near ; CODE XREF: CEncoder_Code+49p
+
+var_20 = dword ptr -20h
+processedOutSize= byte ptr -1Ch
+processedInSize = byte ptr -14h
+var_C = dword ptr -0Ch
+var_4 = dword ptr -4
+inStream = dword ptr 4
+outStream = dword ptr 8
+inSize = dword ptr 0Ch
+outSize = dword ptr 10h
+progress = dword ptr 14h
+
+ push 0FFFFFFFFh
+ push offset loc_4DA128
+ mov eax, dword ptr fs:[0]
+ push eax
+ sub esp, 14h
+ push ebp
+ push esi
+ push edi
+ mov eax, dword_544960
+ xor eax, esp
+ push eax
+ lea eax, [esp+30h+var_C]
+ mov dword ptr fs:[0], eax
+ mov esi, ecx
+ mov [esp+30h+var_20], esi
+ mov eax, [esp+30h+outSize]
+ mov ecx, [esp+30h+inSize]
+ mov edx, [esp+30h+outStream]
+ push eax
+ mov eax, [esp+34h+inStream]
+ push ecx
+ push edx
+ push eax
+ mov ecx, esi
+ mov [esp+40h+var_4], 0
+ call CEncoder_SetStreams
+ mov edi, eax
+ test edi, edi
+ jz short loc_4D1190
+ cmp dword ptr [esi+80h], 0
+ mov [esp+30h+var_4], 0FFFFFFFFh
+ jz short loc_4D1166
+ cmp byte ptr [esi+33B95h], 0
+ jz short loc_4D1166
+ mov byte ptr [esi+33B95h], 0
+
+loc_4D1166: ; CODE XREF: CEncoder_CodeReal+64j
+ ; CEncoder_CodeReal+6Dj
+ mov eax, [esi+33B8Ch]
+ test eax, eax
+ jz short loc_4D1182
+ mov ecx, [eax]
+ mov edx, [ecx+8]
+ push eax
+ call edx
+ mov dword ptr [esi+33B8Ch], 0
+
+loc_4D1182: ; CODE XREF: CEncoder_CodeReal+7Ej
+ mov ecx, [esi+4]
+ mov edx, [ecx+10h]
+ lea eax, [esi+4]
+ push eax
+ call edx
+ jmp short loc_4D1201
+; ---------------------------------------------------------------------------
+
+loc_4D1190: ; CODE XREF: CEncoder_CodeReal+53j
+ lea eax, [esp+30h+outSize]
+ push eax
+ lea ecx, [esp+34h+processedOutSize]
+ push ecx
+ lea edx, [esp+38h+processedInSize]
+ push edx
+ mov ecx, esi
+ call CEncoder_CodeOneBlock
+ mov edi, eax
+ test edi, edi
+ jnz short loc_4D11F0
+ mov ebp, [esp+30h+progress]
+
+loc_4D11B0: ; CODE XREF: CEncoder_CodeReal+FEj
+ cmp [esp+30h+outSize], 0
+ jnz short loc_4D1218
+ test ebp, ebp
+ jz short loc_4D11D4
+ mov eax, [ebp+0]
+ mov eax, [eax+0Ch]
+ lea ecx, [esp+30h+processedOutSize]
+ push ecx
+ lea edx, [esp+34h+processedInSize]
+ push edx
+ push ebp
+ call eax ; SetRatioInfo
+ mov edi, eax
+ test edi, edi
+ jnz short loc_4D11F0
+
+loc_4D11D4: ; CODE XREF: CEncoder_CodeReal+C9j
+ lea ecx, [esp+30h+outSize]
+ push ecx
+ lea edx, [esp+34h+processedOutSize]
+ push edx
+ lea eax, [esp+38h+processedInSize]
+ push eax
+ mov ecx, esi
+ call CEncoder_CodeOneBlock
+ mov edi, eax
+ test edi, edi
+ jz short loc_4D11B0
+
+loc_4D11F0: ; CODE XREF: CEncoder_CodeReal+BAj
+ ; CEncoder_CodeReal+E2j
+ lea ecx, [esp+30h+var_20]
+ mov [esp+30h+var_4], 0FFFFFFFFh
+ call sub_4CDA70
+
+loc_4D1201: ; CODE XREF: CEncoder_CodeReal+9Ej
+ mov eax, edi
+ mov ecx, [esp+30h+var_C]
+ mov dword ptr fs:[0], ecx
+ pop ecx
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 14h
+; ---------------------------------------------------------------------------
+
+loc_4D1218: ; CODE XREF: CEncoder_CodeReal+C5j
+ lea ecx, [esp+30h+var_20]
+ mov [esp+30h+var_4], 0FFFFFFFFh
+ call sub_4CDA70
+ xor eax, eax
+ mov ecx, [esp+30h+var_C]
+ mov dword ptr fs:[0], ecx
+ pop ecx
+ pop edi
+ pop esi
+ pop ebp
+ add esp, 20h
+ retn 14h
+CEncoder_CodeReal endp
+
+; =============== S U B R O U T I N E =======================================
+; Attributes: bp-based frame
+
+CEncoder_Code proc near ; DATA XREF: .rdata:00517B08o
+; sub_4D1240
+
+var_10 = dword ptr -10h
+var_C = dword ptr -0Ch
+var_4 = dword ptr -4
+pThis = dword ptr 8
+pInStream = dword ptr 0Ch
+pOutStream = dword ptr 10h
+pInSize = dword ptr 14h
+pOutSize = dword ptr 18h
+progress = dword ptr 1Ch
+
+ push ebp
+ mov ebp, esp
+ push 0FFFFFFFFh
+ push offset loc_4DA150
+ mov eax, dword ptr fs:[0]
+ push eax
+ sub esp, 8
+ push ebx
+ push esi
+ push edi
+ mov eax, dword_544960
+ xor eax, ebp
+ push eax
+ lea eax, [ebp+var_C]
+ mov dword ptr fs:[0], eax
+ mov [ebp+var_10], esp
+ mov eax, [ebp+progress]
+ mov ecx, [ebp+pOutSize]
+ mov edx, [ebp+pInSize]
+ push eax
+ mov eax, [ebp+pOutStream]
+ push ecx
+ mov ecx, [ebp+pInStream]
+ push edx
+ push eax
+ push ecx
+ mov ecx, [ebp+pThis]
+ mov [ebp+var_4], 0
+ call CEncoder_CodeReal
+ mov ecx, [ebp+var_C]
+ mov dword ptr fs:[0], ecx
+ pop ecx
+ pop edi
+ pop esi
+ pop ebx
+ mov esp, ebp
+ pop ebp
+ retn 18h
+CEncoder_Code endp
+
+; ---------------------------------------------------------------------------
+
+loc_4DA0FB: ; DATA XREF: Compress_lzma_internal+2o
+ mov edx, [esp+8]
+ lea eax, [edx-5Ch]
+ mov ecx, [edx-60h]
+ xor ecx, eax
+ call sub_4A0686
+ mov eax, 0 ; offset dword_526E44
+ int 3;
+; jmp ___CxxFrameHandler3
+
+loc_4DA0C9: ; DATA XREF: sub_4CF810+2o
+ mov edx, [esp+8]
+ lea eax, [edx-0Ch]
+ mov ecx, [edx-10h]
+ xor ecx, eax
+ call sub_4A0686
+ mov eax, 0 ; offset dword_526E18
+ int 3;
+; jmp ___CxxFrameHandler3
+
+loc_4DA128: ; DATA XREF: CEncoder_CodeReal+2o
+ mov edx, [esp+8]
+ lea eax, [edx-20h]
+ mov ecx, [edx-24h]
+ xor ecx, eax
+ call sub_4A0686
+ mov eax, 0 ; offset unk_526E70
+ int 3;
+; jmp ___CxxFrameHandler3
+
+loc_4DA150: ; DATA XREF: CEncoder_Code+5o
+ mov edx, [esp+8]
+ lea eax, [edx+0Ch]
+ mov ecx, [edx-18h]
+ xor ecx, eax
+ call sub_4A0686
+ mov eax, 0 ; offset unk_526ED8
+ int 3;
+; jmp ___CxxFrameHandler3
+
+END
diff --git a/dep/libmpq/AUTHORS b/dep/libmpq/AUTHORS
deleted file mode 100644
index 3d7da7bec9a..00000000000
--- a/dep/libmpq/AUTHORS
+++ /dev/null
@@ -1,10 +0,0 @@
-Project Initiator:
-
- * Maik Broemme <mbroemme@plusserver.de>
-
-Developers:
-
- * Maik Broemme <mbroemme@plusserver.de>
- * Tilman Sauerbeck <tilman@code-monkey.de>
- * Forrest Voight <voights@gmail.com>
- * Georg Lukas <georg@op-co.de>
diff --git a/dep/libmpq/CMakeLists.txt b/dep/libmpq/CMakeLists.txt
deleted file mode 100644
index cd14098c698..00000000000
--- a/dep/libmpq/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
-#
-# This file is free software; as a special exception the author gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-file(GLOB sources_mpq libmpq/*.c libmpq/*.h)
-
-set(mpq_STAT_SRCS
- ${sources_mpq}
-)
-
-if( UNIX )
- include_directories(
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/dep/zlib
- ${CMAKE_SOURCE_DIR}/dep/bzip2
- )
-elseif( WIN32 )
- include_directories(
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/win
- ${CMAKE_SOURCE_DIR}/dep/zlib
- ${CMAKE_SOURCE_DIR}/dep/bzip2
- )
-endif()
-
-add_library(mpq STATIC ${mpq_STAT_SRCS})
-
-set_target_properties(mpq PROPERTIES LINKER_LANGUAGE CXX)
diff --git a/dep/libmpq/COPYING b/dep/libmpq/COPYING
deleted file mode 100644
index 4189933be9f..00000000000
--- a/dep/libmpq/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19yy name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/dep/libmpq/FAQ b/dep/libmpq/FAQ
deleted file mode 100644
index 52ca9f3c705..00000000000
--- a/dep/libmpq/FAQ
+++ /dev/null
@@ -1,68 +0,0 @@
-FAQ - Frequently Asked Questions
-================================
-
-Q: What is libmpq?
-A: libmpq is a library for manipulating MoPaQ mpq archives mostly used
- used by Blizzard in their games.
-
-Q: What can i do with libmpq?
-A: With libmpq you can write applications which can extract, create
- and manipulate mpq archives.
-
-Q: Is it legal?
-A: Yes, i think so. I have no idea why it should not, all informations
- about the fileformat are available.
-
-Q: Is there a description of the functions?
-A: Since version 0.4.0 libmpq comes with a API documentation for
- developers. The documentation is written as manual pages.
-
-Q: Can i help?
-A: Yes, help is needed, not only with developing, also with testing.
- A good point to start is using a recent SVN version of libmpq and
- trying to use it with every mpq archive you could get :)
-
-Q: Can you give a small example to demonstrate the usage?
-A: Of course :) The example below takes first parameter as mpq archive
- and extracts the first file to a buffer.
-
- /*
- * Compile with:
- *
- * x86_32:
- *
- * gcc \
- * -D_FILE_OFFSET_BITS=64 \
- * -D_LARGE_FILES=1 \
- * -D_LARGEFILE_SOURCE=1 \
- * mpq-example.c -o mpq-example -lmpq -lz -lbz2 -I/usr/local/include/libmpq
- *
- * x86_64:
- *
- * gcc \
- * -D_LARGE_FILES=1 \
- * mpq-example.c -o mpq-example -lmpq -lz -lbz2 -I/usr/local/include/libmpq
- */
-
- #include <mpq.h>
- #include <stdlib.h>
- #include <limits.h>
-
- int main(int argc, char **argv) {
- mpq_archive_s *mpq_archive;
- off_t out_size;
- char *out_buf;
-
- /* open the mpq archive given as first parameter. */
- libmpq__archive_open(&mpq_archive, argv[1], -1);
-
- /* get size of first file (0) and malloc output buffer. */
- libmpq__file_unpacked_size(mpq_archive, 0, &out_size);
- out_buf = malloc(out_size);
-
- /* read, decrypt and unpack file to output buffer. */
- libmpq__file_read(mpq_archive, 0, out_buf, out_size, NULL);
-
- /* close the mpq archive. */
- libmpq__archive_close(mpq_archive);
- }
diff --git a/dep/libmpq/INSTALL b/dep/libmpq/INSTALL
deleted file mode 100644
index b42a17ac464..00000000000
--- a/dep/libmpq/INSTALL
+++ /dev/null
@@ -1,182 +0,0 @@
-Basic Installation
-==================
-
- These are generic installation instructions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, a file
-`config.cache' that saves the results of its tests to speed up
-reconfiguring, and a file `config.log' containing compiler output
-(useful mainly for debugging `configure').
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If at some point `config.cache'
-contains results you don't want to keep, you may remove or edit it.
-
- The file `configure.in' is used to create `configure' by a program
-called `autoconf'. You only need `configure.in' if you want to change
-it or regenerate `configure' using a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. If you're
- using `csh' on an old version of System V, you might need to type
- `sh ./configure' instead to prevent `csh' from trying to execute
- `configure' itself.
-
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. You can give `configure'
-initial values for variables by setting them in the environment. Using
-a Bourne-compatible shell, you can do that on the command line like
-this:
- CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-
-Or on systems that have the `env' program, you can do it like this:
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- If you have to use a `make' that does not supports the `VPATH'
-variable, you have to compile the package for one architecture at a time
-in the source code directory. After you have installed the package for
-one architecture, use `make distclean' before reconfiguring for another
-architecture.
-
-Installation Names
-==================
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' can not figure out
-automatically, but needs to determine by the type of host the package
-will run on. Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
-`--host=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name with three fields:
- CPU-COMPANY-SYSTEM
-
-See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the host type.
-
- If you are building compiler tools for cross-compiling, you can also
-use the `--target=TYPE' option to select the type of system they will
-produce code for and the `--build=TYPE' option to select the type of
-system on which you are compiling the package.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Operation Controls
-==================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--cache-file=FILE'
- Use and save the results of the tests in FILE instead of
- `./config.cache'. Set FILE to `/dev/null' to disable caching, for
- debugging `configure'.
-
-`--help'
- Print a summary of the options to `configure', and exit.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`--version'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`configure' also accepts some other, not widely useful, options.
diff --git a/dep/libmpq/Makefile.am b/dep/libmpq/Makefile.am
deleted file mode 100644
index 0a9b54c2526..00000000000
--- a/dep/libmpq/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# any directories which should be built and installed.
-SUBDIRS = libmpq bindings doc
-
-# the directories which are part of the distribution.
-DIST_SUBDIRS = $(SUBDIRS)
-
-# libmpq runtime configuration script.
-bin_SCRIPTS = libmpq-config
-
-# pkg-config installation directory.
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libmpq.pc
-
-# extra stuff.
-EXTRA_DIST = \
- AUTHORS \
- COPYING \
- FAQ \
- INSTALL \
- NEWS \
- README \
- THANKS \
- TODO
diff --git a/dep/libmpq/NEWS b/dep/libmpq/NEWS
deleted file mode 100644
index 74850a8a5bb..00000000000
--- a/dep/libmpq/NEWS
+++ /dev/null
@@ -1,76 +0,0 @@
-Changes version 0.4.2 (2008-05-16)
-==================================
-
- * added full extraction support for protected maps used in
- warcraft 3.
-
- * added full extraction support for all blizzard titles until
- world of warcraft - the burning crusade.
-
- * added support for archives version 2 with extended header and
- extended block table.
-
- * added support for the bzip2 compression algorithm.
-
- * added support for archives and files inside archive > 2gb.
-
- * added generic read functions, which will do decryption,
- decompression or exploding.
-
- * the info functions are no longer exported by the library and
- were replaced by separate api functions.
-
- * the file number and block number are count from 0 instead
- of 1.
-
- * added python bindings.
-
- * linking against libmpq requires from now on the usual largefile
- macros -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES=1 -D_LARGEFILE_SOURCE=1
-
-Changes version 0.4.1 (2008-04-02)
-==================================
-
- * memory, speed and stability improvements.
-
- * split sourcecode into library and utility package.
-
-Changes version 0.4.0 (2008-03-31)
-==================================
-
- * added robust error handling to make the library and extracting
- utility more stable.
-
- * added c++ bindings to public include and moved internal defines
- and functions to private include.
-
- * added support for 64-bit architectures and removed any stupid
- pointer to int arithmetics.
-
- * added much better member names to the structures to make
- developers able to understand the code on reading.
-
- * added full api documentation using manual pages.
-
- * added full extraction support for all blizzard titles until
- warcraft 3 - the frozen throne.
-
- * added support for single sector and stored files (neither
- compressed nor imploded).
-
- * added support for files which have compressed size greater than
- uncompressed size.
-
- * removed the external listfile database support from 0.3.0 it
- was a weird implementation.
-
-Changes version 0.3.0 (2004-02-12)
-==================================
-
- * added listfile database support from external files.
-
-Initial version 0.2.1 (2004-01-17)
-==================================
-
- * first version which was able to extract some of the older mopaq
- archives.
diff --git a/dep/libmpq/README b/dep/libmpq/README
deleted file mode 100644
index 3f1bd3a1e9f..00000000000
--- a/dep/libmpq/README
+++ /dev/null
@@ -1,34 +0,0 @@
-Introduction
-============
-
-'libmpq' is a library which can be easily used in own applications
-to extract, create or manipulate MoPaQ mpq archives.
-
-MPQ, or MoPaQ, is a proprietary archive format created by
-Mike O'Brien, the man hailed as Blizzard's multiplayer engine
-genius, back in 1996 as a general purpose archive for use with
-Diablo, and named narcissistically for its creator
-"Mike O'brien PaCK". The copyrights to it, however, are held by
-Havas Interactive, Blizzard's parent company. The archive format
-is used by many Blizzard titles like Diablo, Diablo 2, Starcraft,
-Warcraft 2: BNE, a newer version in Warcraft 3 and World of
-Warcraft (WoW).
-
-Manual
-======
-
-Since version 0.4.0 the 'libmpq' package comes with a manpage for
-every library function. If you use 'libmpq' first time it is a good
-idea to read the `FAQ' file.
-
-Reporting Bugs
-==============
-
-Bug reports for 'libmpq' can be send to me directly.
-
- * Maik Broemme <mbroemme@plusserver.de>
-
-Enjoy!
-
-Maik Broemme <mbroemme@plusserver.de>
-http://www.babelize.org/
diff --git a/dep/libmpq/THANKS b/dep/libmpq/THANKS
deleted file mode 100644
index 42da1235476..00000000000
--- a/dep/libmpq/THANKS
+++ /dev/null
@@ -1,21 +0,0 @@
-'libmpq' was originaly created by Maik Broemme <mbroemme@plusserver.de>
-and i want to thank some people which helped by supplying knowledge, code or
-something else.
-
- * Romy Trompke <rtnet@web.de>
- - my lovely girlfriend for her patience
-
- * Ladislav Zezula <ladik@zezula.net>
- - stormlib creator
-
- * Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
- - initial port of stormlib to linux
-
- * Tom Amigo <tomamigo@apexmail.com>
- - first people who decrypts the MoPaQ archive format
-
- * ShadowFlare <BlakFlare@hiotmail.com>
- - creator of the ShadowFlare MPQ API
-
- * Justin Olbrantz (Quantam) <omega@dragonfire.net>
- - creator of the client using ShadowFlare MPQ API
diff --git a/dep/libmpq/TODO b/dep/libmpq/TODO
deleted file mode 100644
index 0c1951f0b46..00000000000
--- a/dep/libmpq/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-Features and functionality which should be added in the future.
-
- * Porting for big endian systems.
- * Porting for Windows? :)
- * Creating mpq archives.
- * Brute all unknown filenames, Blizzard uses in their
- archives.
-
-Look at the AUTHORS file if you want help me with 'libmpq', or
-if you have other interesting features which should be added.
diff --git a/dep/libmpq/autogen.sh b/dep/libmpq/autogen.sh
deleted file mode 100644
index 16871edd70d..00000000000
--- a/dep/libmpq/autogen.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-#
-echo "Generating build information using aclocal, autoheader, automake and autoconf"
-echo "This may take a while ..."
-
-# Touch the timestamps on all the files since CVS messes them up
-directory=`dirname $0`
-touch $directory/configure.ac
-
-# Regenerate configuration files
-libtoolize --copy
-aclocal
-autoheader
-automake --foreign --add-missing --copy
-autoconf
-
-# Run configure for this platform
-#./configure $*
-echo "Now you are ready to run ./configure"
diff --git a/dep/libmpq/bindings/Makefile.am b/dep/libmpq/bindings/Makefile.am
deleted file mode 100644
index b9fefe306ef..00000000000
--- a/dep/libmpq/bindings/Makefile.am
+++ /dev/null
@@ -1,6 +0,0 @@
-# any directories which should be built and installed.
-SUBDIRS = d
-
-if HAVE_PYTHON
-SUBDIRS += python
-endif
diff --git a/dep/libmpq/bindings/d/Makefile.am b/dep/libmpq/bindings/d/Makefile.am
deleted file mode 100644
index 4de7285ae51..00000000000
--- a/dep/libmpq/bindings/d/Makefile.am
+++ /dev/null
@@ -1,6 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# install D binding to /usr/include/d by default
-libmpq_includedir = $(includedir)/d
-libmpq_include_HEADERS = mpq.d
diff --git a/dep/libmpq/bindings/d/dsss.conf b/dep/libmpq/bindings/d/dsss.conf
deleted file mode 100644
index 252482c4933..00000000000
--- a/dep/libmpq/bindings/d/dsss.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[mpq.d]
-type=sourcelibrary
diff --git a/dep/libmpq/bindings/d/mpq.d b/dep/libmpq/bindings/d/mpq.d
deleted file mode 100644
index d72c2d2a986..00000000000
--- a/dep/libmpq/bindings/d/mpq.d
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * mpq.d -- D programming language module for libmpq
- *
- * Copyright (c) 2008 Georg Lukas <georg@op-co.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * This module is written to support Phobos. Patches to allow binding to
- * Tango are welcome.
- */
-
-module mpq;
-
-/* the following pragma does not work on DMD/Linux, generates a warning on
- * GDC/Linux and has not been tested on Windows. Commented out for now. */
-// pragma(lib, "libmpq");
-
-import std.string; // for format() and toStringz()
-import std.traits; // for ParameterTypeTuple!()
-
-/* XXX: this assumes that libmpq is compiled with Large File Support on */
-alias long off_t;
-
-/* libmpq error return values */
-const LIBMPQ_ERROR_OPEN = -1; /* open error on file. */
-const LIBMPQ_ERROR_CLOSE = -2; /* close error on file. */
-const LIBMPQ_ERROR_SEEK = -3; /* lseek error on file. */
-const LIBMPQ_ERROR_READ = -4; /* read error on file. */
-const LIBMPQ_ERROR_WRITE = -5; /* write error on file. */
-const LIBMPQ_ERROR_MALLOC = -6; /* memory allocation error. */
-const LIBMPQ_ERROR_FORMAT = -7; /* format errror. */
-const LIBMPQ_ERROR_NOT_INITIALIZED = -8; /* init() wasn't called. */
-const LIBMPQ_ERROR_SIZE = -9; /* buffer size is to small. */
-const LIBMPQ_ERROR_EXIST = -10; /* file or block does not exist in archive. */
-const LIBMPQ_ERROR_DECRYPT = -11; /* we don't know the decryption seed. */
-const LIBMPQ_ERROR_UNPACK = -12; /* error on unpacking file. */
-
-/** libmpq internal meta-data for an archive */
-extern struct mpq_archive_s;
-
-extern(C) {
-
-/* libmpq__generic information about library. */
-char *libmpq__version();
-
-/* libmpq__generic mpq archive information. */
-int libmpq__archive_open(mpq_archive_s **mpq_archive, char *mpq_filename, off_t archive_offset);
-int libmpq__archive_close(mpq_archive_s *mpq_archive);
-int libmpq__archive_packed_size(mpq_archive_s *mpq_archive, off_t *packed_size);
-int libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, off_t *unpacked_size);
-int libmpq__archive_offset(mpq_archive_s *mpq_archive, off_t *offset);
-int libmpq__archive_version(mpq_archive_s *mpq_archive, uint *version_);
-int libmpq__archive_files(mpq_archive_s *mpq_archive, uint *files);
-
-/* libmpq__generic file processing functions. */
-int libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint file_number, off_t *packed_size);
-int libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, off_t *unpacked_size);
-int libmpq__file_offset(mpq_archive_s *mpq_archive, uint file_number, off_t *offset);
-int libmpq__file_blocks(mpq_archive_s *mpq_archive, uint file_number, uint *blocks);
-int libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint file_number, uint *encrypted);
-int libmpq__file_compressed(mpq_archive_s *mpq_archive, uint file_number, uint *compressed);
-int libmpq__file_imploded(mpq_archive_s *mpq_archive, uint file_number, uint *imploded);
-int libmpq__file_number(mpq_archive_s *mpq_archive, char *filename, uint *number);
-int libmpq__file_read(mpq_archive_s *mpq_archive, uint file_number, ubyte *out_buf, off_t out_size, off_t *transferred);
-
-/* libmpq__generic block processing functions. */
-int libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint file_number);
-int libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint file_number);
-int libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, uint block_number, off_t *unpacked_size);
-int libmpq__block_read(mpq_archive_s *mpq_archive, uint file_number, uint block_number, ubyte *out_buf, off_t out_size, off_t *transferred);
-
-}
-
-
-/** exception class for failed libmpq calls */
-class MPQException : Exception {
- const string[] Errors = [
- "unknown error",
- "open error on file",
- "close error on file",
- "lseek error on file",
- "read error on file",
- "write error on file",
- "memory allocation error",
- "format errror",
- "init() wasn't called",
- "buffer size is to small",
- "file or block does not exist in archive",
- "we don't know the decryption seed",
- "error on unpacking file"];
-
- public int errno;
- this(char[] fnname = "unknown_function", int errno = 0) {
-
- this.errno = errno;
- if (-errno >= Errors.length)
- errno = 0;
- super(std.string.format("Error in %s(): %s (%d)",
- fnname, Errors[-errno], errno));
- }
-}
-
-
-/** template to wrap function calls and throw exceptions in case of error
- *
- * thanks for the idea to while(nan) blog,
- * http://while-nan.blogspot.com/2007/06/wrapping-functions-for-fun-and-profit.html
- *
- * use: MPQ_CHECKERR(libmpq__archive_open)(&m, "foo.mpq", -1);
- * returns the retval of archive_open on success;
- * throws an MPQException on failure.
- *
- * @param Fn libmpq__function reference
- * @param args libmpq__function parameters
- * @return return value of libmpq__function on success
- * @throw MPQException on error
- */
-int MPQ_CHECKERR(alias Fn)(ParameterTypeTuple!(Fn) args)
-{
- int result = Fn(args);
- if (result < 0) {
- /* XXX: relying on non-specified stringof() behaviour */
- throw new MPQException((&Fn).stringof[2..$], result);
- }
- return result;
-}
-
-
-/** mixin alias to wrap library functions into MPQ_CHECKERR.
- *
- * alias mpq.func_name(...) to MPQ_CHECKERR(libmpq__func_name)(...)
- * @param func_name name of the function to be wrapped
- */
-template MPQ_FUNC(char[] func_name) {
- const char[] MPQ_FUNC = "alias MPQ_CHECKERR!(libmpq__" ~ func_name ~ ") " ~ func_name ~ ";";
-}
-
-alias libmpq__version libversion; /* must be direct alias because it returns char*, not error int */
-mixin(MPQ_FUNC!("archive_open"));
-mixin(MPQ_FUNC!("archive_close"));
-mixin(MPQ_FUNC!("archive_packed_size"));
-mixin(MPQ_FUNC!("archive_unpacked_size"));
-mixin(MPQ_FUNC!("archive_offset"));
-mixin(MPQ_FUNC!("archive_version"));
-mixin(MPQ_FUNC!("archive_files"));
-mixin(MPQ_FUNC!("file_packed_size"));
-mixin(MPQ_FUNC!("file_unpacked_size"));
-mixin(MPQ_FUNC!("file_offset"));
-mixin(MPQ_FUNC!("file_blocks"));
-mixin(MPQ_FUNC!("file_encrypted"));
-mixin(MPQ_FUNC!("file_compressed"));
-mixin(MPQ_FUNC!("file_imploded"));
-mixin(MPQ_FUNC!("file_number"));
-mixin(MPQ_FUNC!("file_read"));
-mixin(MPQ_FUNC!("block_open_offset"));
-mixin(MPQ_FUNC!("block_close_offset"));
-mixin(MPQ_FUNC!("block_unpacked_size"));
-mixin(MPQ_FUNC!("block_read"));
-
-/** getter function named name for returning archive_* single values:
- *
- * <type> Archive.<name>() { return libmpq__archive_<name>() }
- *
- * @param type return type for the original function reference
- * @param name name of the original function
- * @param name2 name for the prototype (defaults to name, used for "version")
- * @return getter function mixin
- */
-template MPQ_A_GET(char[] type, char[] name, char[] name2 = name) {
- const char[] MPQ_A_GET = type ~ " " ~ name2 ~ "() { " ~
- type ~ " ret; " ~
- "archive_" ~ name ~ "(m, &ret); return ret;" ~
- "}";
-}
-
-/** wrapper class for an MPQ Archive
- *
- * syntax: auto a = new mpq.Archive("somefile.mpq");
- */
-class Archive {
- mpq_archive_s *m;
- File listfile;
- char[][] listfiledata;
-
- this(char[] archivename, off_t offset = -1) {
- archive_open(&m, toStringz(archivename), offset);
- }
-
- mixin(MPQ_A_GET!("off_t", "packed_size"));
- mixin(MPQ_A_GET!("off_t", "unpacked_size"));
- mixin(MPQ_A_GET!("off_t", "offset"));
- mixin(MPQ_A_GET!("uint", "version", "version_"));
- mixin(MPQ_A_GET!("uint", "files"));
-
- ~this() {
- archive_close(m);
- }
-
- mpq_archive_s* archive() {
- return m;
- }
-
- File opIndex(char[] fname) {
- return new File(this, fname);
- }
- File opIndex(int fno) {
- return new File(this, fno);
- }
-
- char[][] filelist() {
- try {
- if (!listfile) {
- listfile = this["(listfile)"];
- listfiledata = (cast(char[])listfile.read()).splitlines();
- }
- return listfiledata;
- } catch (MPQException e) {
- return [];
- }
- }
-
- /+uint filenumber(char[] filename) {
- try {
- if (!listfile) {
- listfile = this["(listfile)"];
- listfiledata = (cast(char[])listfile.read()).splitlines();
- }
- return listfiledata;
- } catch (MPQException e) {
- return [];
- }
- }+/
-
-}
-
-
-/** getter function named name for returning file_* single values:
- *
- * <type> File.<name>() { return libmpq__file_<name>() }
- *
- * @param type return type for the original function reference
- * @param name name of the original function
- * @param name2 name for the prototype (defaults to name, used for "version")
- * @return getter function mixin
- */
-template MPQ_F_GET(char[] type, char[] name, char[] name2 = name) {
- const char[] MPQ_F_GET = type ~ " " ~ name2 ~ "() { " ~
- type ~ " ret; " ~
- "file_" ~ name ~ "(am, fileno, &ret); " ~
- "return ret;" ~
- "}";
-}
-
-/** wrapper class for a single file in an MPQ Archive
- *
- * syntax:
- * auto a = new mpq.Archive("somefile.mpq");
- * auto f = a["(listfile)"];
- * auto f2 = a[0];
- * auto f3 = new File(a, "(listfile)");
- */
-class File {
- Archive a;
- mpq_archive_s* am;
- char[] filename;
- uint fileno;
-
- this(Archive a, int fileno) {
- this.a = a;
- this.am = a.archive();
- if (fileno >= a.files) {
- throw new MPQException(format("File(%d)", fileno),
- LIBMPQ_ERROR_EXIST);
- }
- this.filename = format("file%04d.xxx", fileno);
- this.fileno = fileno;
- }
-
- this(Archive a, char[] filename) {
- this.a = a;
- this.am = a.archive();
- this.filename = filename;
- /* this line will throw an exception when the file is not there */
- mpq.file_number(am, toStringz(filename), &this.fileno);
- }
-
- mixin(MPQ_F_GET!("off_t", "packed_size"));
- mixin(MPQ_F_GET!("off_t", "unpacked_size"));
- mixin(MPQ_F_GET!("off_t", "offset"));
- mixin(MPQ_F_GET!("uint", "blocks"));
- mixin(MPQ_F_GET!("uint", "encrypted"));
- mixin(MPQ_F_GET!("uint", "compressed"));
- mixin(MPQ_F_GET!("uint", "imploded"));
-
- uint no() { return fileno; }
- char[] name() { return filename; }
-
- ubyte[] read() {
- ubyte[] content;
- content.length = this.unpacked_size();
- off_t trans;
- mpq.file_read(am, fileno, content.ptr, content.length, &trans);
- content.length = trans;
- return content;
- }
-}
diff --git a/dep/libmpq/bindings/python/Makefile.am b/dep/libmpq/bindings/python/Makefile.am
deleted file mode 100644
index 6971a9b2f6d..00000000000
--- a/dep/libmpq/bindings/python/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# library information and headers which should not be installed.
-python_PYTHON = mpq.py
diff --git a/dep/libmpq/bindings/python/mpq-info b/dep/libmpq/bindings/python/mpq-info
deleted file mode 100644
index 2c67aa1d0cc..00000000000
--- a/dep/libmpq/bindings/python/mpq-info
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import division
-
-import sys
-
-import mpq
-
-archive = mpq.Archive(sys.argv[1])
-
-print "Name: %s" % sys.argv[1]
-print "Version: %s" % archive.filename
-print "Offset: %s" % archive.offset
-print "Packed size: %s" % archive.packed_size
-print "Unpacked size: %s" % archive.unpacked_size
-print "Compression ratio: %s" % (archive.packed_size/archive.unpacked_size)
diff --git a/dep/libmpq/bindings/python/mpq.py b/dep/libmpq/bindings/python/mpq.py
deleted file mode 100644
index cf6ecaae800..00000000000
--- a/dep/libmpq/bindings/python/mpq.py
+++ /dev/null
@@ -1,322 +0,0 @@
-"""wrapper for libmpq"""
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-import ctypes
-import ctypes.util
-import os
-
-libmpq = ctypes.CDLL(ctypes.util.find_library("mpq"))
-
-class Error(Exception):
- pass
-
-errors = {
- -1: (IOError, "open"),
- -2: (IOError, "close"),
- -3: (IOError, "seek"),
- -4: (IOError, "read"),
- -5: (IOError, "write"),
- -6: (MemoryError,),
- -7: (Error, "file is not an mpq or is corrupted"),
- -8: (AssertionError, "not initialized"),
- -9: (AssertionError, "buffer size too small"),
- -10: (IndexError, "file not in archive"),
- -11: (AssertionError, "decrypt"),
- -12: (AssertionError, "unpack"),
-}
-
-def check_error(result, func, arguments, errors=errors):
- try:
- error = errors[result]
- except KeyError:
- return result
- else:
- raise error[0](*error[1:])
-
-libmpq.libmpq__version.restype = ctypes.c_char_p
-
-libmpq.libmpq__archive_open.errcheck = check_error
-libmpq.libmpq__archive_close.errcheck = check_error
-libmpq.libmpq__archive_packed_size.errcheck = check_error
-libmpq.libmpq__archive_unpacked_size.errcheck = check_error
-libmpq.libmpq__archive_offset.errcheck = check_error
-libmpq.libmpq__archive_version.errcheck = check_error
-libmpq.libmpq__archive_files.errcheck = check_error
-
-libmpq.libmpq__file_packed_size.errcheck = check_error
-libmpq.libmpq__file_unpacked_size.errcheck = check_error
-libmpq.libmpq__file_offset.errcheck = check_error
-libmpq.libmpq__file_blocks.errcheck = check_error
-libmpq.libmpq__file_encrypted.errcheck = check_error
-libmpq.libmpq__file_compressed.errcheck = check_error
-libmpq.libmpq__file_imploded.errcheck = check_error
-libmpq.libmpq__file_number.errcheck = check_error
-libmpq.libmpq__file_read.errcheck = check_error
-
-libmpq.libmpq__block_open_offset.errcheck = check_error
-libmpq.libmpq__block_close_offset.errcheck = check_error
-libmpq.libmpq__block_unpacked_size.errcheck = check_error
-libmpq.libmpq__block_read.errcheck = check_error
-
-__version__ = libmpq.libmpq__version()
-
-
-class Reader(object):
- def __init__(self, file, libmpq=libmpq):
- self._file = file
- self._pos = 0
- self._buf = []
- self._cur_block = 0
- libmpq.libmpq__block_open_offset(self._file._archive._mpq,
- self._file.number)
-
- def __iter__(self):
- return self
-
- def __repr__(self):
- return "iter(%r)" % self._file
-
- def seek(self, offset, whence=os.SEEK_SET, os=os):
- if whence == os.SEEK_SET:
- pass
- elif whence == os.SEEK_CUR:
- offset += self._pos
- elif whence == os.SEEK_END:
- offset += self._file.unpacked_size
- else:
- raise ValueError, "invalid whence"
-
- if offset >= self._pos:
- self.read(offset - self._pos)
- else:
- self._pos = 0
- self._buf = []
- self._cur_block = 0
- self.read(offset)
-
- def tell(self):
- return self._pos
-
- def _read_block(self, ctypes=ctypes, libmpq=libmpq):
- block_size = ctypes.c_uint64()
- libmpq.libmpq__block_unpacked_size(self._file._archive._mpq,
- self._file.number, self._cur_block, ctypes.byref(block_size))
- block_data = ctypes.create_string_buffer(block_size.value)
- libmpq.libmpq__block_read(self._file._archive._mpq,
- self._file.number, self._cur_block,
- block_data, ctypes.c_uint64(len(block_data)), None)
- self._buf.append(block_data.raw)
- self._cur_block += 1
-
- def read(self, size=-1):
- while size < 0 or sum(map(len, self._buf)) < size:
- if self._cur_block == self._file.blocks:
- break
- self._read_block()
- buf = "".join(self._buf)
- if size < 0:
- ret = buf
- self._buf = []
- else:
- ret = buf[:size]
- self._buf = [buf[size:]]
- self._pos += len(ret)
- return ret
-
- def readline(self, os=os):
- line = []
- while True:
- char = self.read(1)
- if char == "":
- break
- if char not in '\r\n' and line and line[-1] in '\r\n':
- self.seek(-1, os.SEEK_CUR)
- break
- line.append(char)
- return ''.join(line)
-
- def next(self):
- line = self.readline()
- if not line:
- raise StopIteration
- return line
-
- def readlines(self, sizehint=-1):
- res = []
- while sizehint < 0 or sum(map(len, res)) < sizehint:
- line = self.readline()
- if not line:
- break
- res.append(line)
- return res
-
- xreadlines = __iter__
-
- def __del__(self, libmpq=libmpq):
- libmpq.libmpq__block_close_offset(self._file._archive._mpq,
- self._file.number)
-
-
-class File(object):
- def __init__(self, archive, number, ctypes=ctypes, libmpq=libmpq):
- self._archive = archive
- self.number = number
-
- for name, atype in [
- ("packed_size", ctypes.c_uint64),
- ("unpacked_size", ctypes.c_uint64),
- ("offset", ctypes.c_uint64),
- ("blocks", ctypes.c_uint32),
- ("encrypted", ctypes.c_uint32),
- ("compressed", ctypes.c_uint32),
- ("imploded", ctypes.c_uint32),
- ]:
- data = atype()
- func = getattr(libmpq, "libmpq__file_"+name)
- func(self._archive._mpq, self.number, ctypes.byref(data))
- setattr(self, name, data.value)
-
- def __str__(self, ctypes=ctypes, libmpq=libmpq):
- data = ctypes.create_string_buffer(self.unpacked_size)
- libmpq.libmpq__file_read(self._archive._mpq, self.number,
- data, ctypes.c_uint64(len(data)), None)
- return data.raw
-
- def __repr__(self):
- return "%r[%i]" % (self._archive, self.number)
-
- def __iter__(self, Reader=Reader):
- return Reader(self)
-
-
-class Archive(object):
- def __init__(self, source, ctypes=ctypes, File=File, libmpq=libmpq):
- self._source = source
- if isinstance(source, File):
- assert not source.encrypted
- assert not source.compressed
- assert not source.imploded
- self.filename = source._archive.filename
- offset = source._archive.offset + source.offset
- else:
- self.filename = source
- offset = -1
-
- self._mpq = ctypes.c_void_p()
- libmpq.libmpq__archive_open(ctypes.byref(self._mpq), self.filename,
- ctypes.c_uint64(offset))
- self._opened = True
-
- for field_name, field_type in [
- ("packed_size", ctypes.c_uint64),
- ("unpacked_size", ctypes.c_uint64),
- ("offset", ctypes.c_uint64),
- ("version", ctypes.c_uint32),
- ("files", ctypes.c_uint32),
- ]:
- func = getattr(libmpq, "libmpq__archive_" + field_name)
- data = field_type()
- func(self._mpq, ctypes.byref(data))
- setattr(self, field_name, data.value)
-
- def __del__(self, libmpq=libmpq):
- if getattr(self, "_opened", False):
- libmpq.libmpq__archive_close(self._mpq)
-
- def __len__(self):
- return self.files
-
- def __contains__(self, item, ctypes=ctypes, libmpq=libmpq):
- if isinstance(item, str):
- data = ctypes.c_uint32()
- try:
- libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
- ctypes.byref(data))
- except IndexError:
- return False
- return True
- return 0 <= item < self.files
-
- def __getitem__(self, item, ctypes=ctypes, File=File, libmpq=libmpq):
- if isinstance(item, str):
- data = ctypes.c_int()
- libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
- ctypes.byref(data))
- item = data.value
- else:
- if not 0 <= item < self.files:
- raise IndexError, "file not in archive"
- return File(self, item)
-
- def __repr__(self):
- return "mpq.Archive(%r)" % self._source
-
-# Remove clutter - everything except Error and Archive.
-del os, check_error, ctypes, errors, File, libmpq, Reader
-
-if __name__ == "__main__":
- import sys, random
- archive = Archive(sys.argv[1])
- print repr(archive)
- for k, v in archive.__dict__.iteritems():
- #if k[0] == '_': continue
- print " " * (4 - 1), k, v
- assert '(listfile)' in archive
- assert 0 in archive
- assert len(archive) == archive.files
- files = [x.strip() for x in archive['(listfile)']]
- files.extend(xrange(archive.files))
- for key in files: #sys.argv[2:] if sys.argv[2:] else xrange(archive.files):
- file = archive[key]
- print
- print " " * (4 - 1), repr(file)
- for k, v in file.__dict__.iteritems():
- #if k[0] == '_': continue
- print " " * (8 - 1), k, v
-
- a = str(file)
-
- b = iter(file).read()
-
- reader = iter(file)
- c = []
- while True:
- l = random.randrange(1, 10)
- d = reader.read(l)
- if not d: break
- assert len(d) <= l
- c.append(d)
- c = "".join(c)
-
- d = []
- reader.seek(0)
- for line in reader:
- d.append(line)
- d = "".join(d)
-
- assert a == b == c == d, map(hash, [a,b,c,d])
- assert len(a) == file.unpacked_size
-
- repr(iter(file))
-
-
- reader.seek(0)
- a = reader.readlines()
-
- reader.seek(0)
- b = list(reader)
-
- assert a == b
diff --git a/dep/libmpq/config.h b/dep/libmpq/config.h
deleted file mode 100644
index c69fb13211b..00000000000
--- a/dep/libmpq/config.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-#define HAVE_LIBBZ2 1
-
-/* Define to 1 if you have the `z' library (-lz). */
-#define HAVE_LIBZ 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Name of package */
-#define PACKAGE "libmpq"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "mbroemme@plusserver.de"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libmpq"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libmpq 0.4.2"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libmpq"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.4.2"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.4.2"
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#define _FILE_OFFSET_BITS 64
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
diff --git a/dep/libmpq/configure.ac b/dep/libmpq/configure.ac
deleted file mode 100644
index d274eab07c6..00000000000
--- a/dep/libmpq/configure.ac
+++ /dev/null
@@ -1,84 +0,0 @@
-# the autoconf initilization.
-AC_INIT(libmpq, 0.4.2, [mbroemme@plusserver.de], [libmpq])
-
-# detect the canonical host and target build environment.
-AC_CANONICAL_SYSTEM
-
-# initialize autoconf and automake system.
-AM_INIT_AUTOMAKE([no-dependencies])
-AC_CONFIG_HEADERS([config.h:config.h.in])
-
-# notices.
-AC_PREREQ(2.53)
-AC_REVISION($Revision: 1.6 $)
-
-# checking for programs.
-AC_PROG_LIBTOOL
-AC_PROG_MAKE_SET
-AC_PROG_CC
-AC_SYS_LARGEFILE
-AC_FUNC_FSEEKO
-
-# check if we need to export some largefile flags.
-if test "$enable_largefile" != no; then
- if test "$ac_cv_sys_file_offset_bits" != 'no'; then
- if test -z "$LFS_CFLAGS" ; then
- LFS_CFLAGS="-D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
- else
- LFS_CFLAGS="$LFS_CFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
- fi
- fi
- if test "$ac_cv_sys_large_files" != 'no'; then
- if test -z "$LFS_CFLAGS" ; then
- LFS_CFLAGS="-D_LARGE_FILES=1"
- else
- LFS_CFLAGS="$LFS_CFLAGS -D_LARGE_FILES=1"
- fi
- fi
- if test "$ac_cv_sys_largefile_source" != 'no'; then
- if test -z "$LFS_CFLAGS" ; then
- LFS_CFLAGS="-D_LARGEFILE_SOURCE=1"
- else
- LFS_CFLAGS="$LFS_CFLAGS -D_LARGEFILE_SOURCE=1"
- fi
- fi
-fi
-
-# export largefile flags.
-AC_SUBST(LFS_CFLAGS)
-
-# check for zlib library.
-AC_CHECK_HEADER([zlib.h], [], [AC_MSG_ERROR([*** zlib.h is required, install zlib header files])])
-AC_CHECK_LIB([z], [inflateEnd], [], [AC_MSG_ERROR([*** inflateEnd is required, install zlib library files])])
-
-# check for bzlib2 library.
-AC_CHECK_HEADER([bzlib.h], [], [AC_MSG_ERROR([*** bzlib.h is required, install bzip2 header files])])
-AC_CHECK_LIB([bz2], [BZ2_bzDecompressInit], [], [AC_MSG_ERROR([*** BZ2_bzDecompressInit is required, install bzip2 library files])])
-
-# When we're running gcc 4 or greater, compile with -fvisibility=hidden.
-AC_TRY_COMPILE([
-#if !defined(__GNUC__) || (__GNUC__ < 4)
-#error not gcc4
-#endif
-], [], [CFLAGS="$CFLAGS -fvisibility=hidden"])
-
-# find python for binding
-AM_PATH_PYTHON([2.4],,[:])
-AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
-
-# configuration files.
-AC_CONFIG_FILES([libmpq.pc])
-AC_CONFIG_FILES([libmpq-config],[chmod +x libmpq-config])
-
-# creating files.
-AC_OUTPUT([
-Makefile
-libmpq/Makefile
-bindings/Makefile
-bindings/d/Makefile
-bindings/python/Makefile
-doc/Makefile
-doc/man1/Makefile
-doc/man3/Makefile
-tools/Makefile
-])
diff --git a/dep/libmpq/debian/changelog b/dep/libmpq/debian/changelog
deleted file mode 100644
index 55d2d918755..00000000000
--- a/dep/libmpq/debian/changelog
+++ /dev/null
@@ -1,35 +0,0 @@
-libmpq (0.4.2-svn288-1) unstable; urgency=low
-
- [ babyface ]
- * Due to the nature of MPQ archives which can have valid block entries
- * removed function libmpq__init() and libmpq__shutdown(), because they
- are no longer required and libmpq__file_name(), because it is up to
- the application to provide listfile support
- * updated documentation to latest API changes
- * removed API documentation for removed function prototypes
- * removed no longer required files from target
-
- [ forrestv ]
- * mpq.py fix
- * spelling - huffmann to huffman
- * changed pkware/pkzip to pkzip and used constants instead of numbers
- in extract.c
- * sanified huffman decoder a bit
- * cleanup + update of mpq.py
- * Added support for library finding on platforms besides Linux.
- * python bindings - sequence methods on Archive, example code
-
- [ georg ]
- * libmpq: file number search now continued over hashtable end
- * debian debug package
-
- -- Georg Lukas <georg@op-co.de> Fri, 22 May 2009 22:38:26 +0200
-
-libmpq (0.4.2-svn270-1) unstable; urgency=low
-
- * First debian package
- * compatible to new libmpq API (post 0.4.2)
- * contains preliminary python-mpq package
-
- -- Georg Lukas <georg@op-co.de> Tue, 07 Oct 2008 14:38:58 +0200
-
diff --git a/dep/libmpq/debian/compat b/dep/libmpq/debian/compat
deleted file mode 100644
index 7f8f011eb73..00000000000
--- a/dep/libmpq/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/dep/libmpq/debian/control b/dep/libmpq/debian/control
deleted file mode 100644
index f35bb060015..00000000000
--- a/dep/libmpq/debian/control
+++ /dev/null
@@ -1,50 +0,0 @@
-Source: libmpq
-Priority: extra
-Maintainer: Georg Lukas <georg@op-co.de>
-Build-Depends: debhelper (>= 7), autotools-dev, libbz2-dev
-Standards-Version: 3.7.3
-Section: libs
-Homepage: https://libmpq.org/
-
-Package: libmpq-dev
-Section: libdevel
-Architecture: any
-Depends: libmpq0 (= ${binary:Version})
-Description: Headers for libmpq, a library for MoPaQ mpq archives
- libmpq is a library for extracting and manipulating MoPaQ mpq archives.
- This package provides header files and bindings for applications using
- the libmpq library for the following languages:
- * C
- * Python
- * D
-
-Package: libmpq0
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: A library for extracting and manipulating MoPaQ mpq archives
- MPQ, or MoPaQ, is a proprietary archive format created by
- Mike O'Brien, the man hailed as Blizzard's multiplayer engine
- genius, back in 1996 as a general purpose archive for use with
- Diablo, and named narcissistically for its creator
- "Mike O'brien PaCK". The copyrights to it, however, are held by
- Havas Interactive, Blizzard's parent company. The archive format
- is used by many Blizzard titles like Diablo, Diablo 2, Starcraft,
- Warcraft 2: BNE, a newer version in Warcraft 3 and World of
- Warcraft (WoW).
-
-Package: libmpq0-dbg
-Section: libdevel
-Architecture: any
-Depends: libmpq0 (= ${binary:Version})
-Description: Debug symbols for libmpq0 library package
-
-Package: python-mpq
-Architecture: all
-Depends: ${python:Depends}
-XB-Python-Version: ${python:Versions}
-XS-Python-Version: current
-Description: Python bindings for libmpq, a library for MoPaQ mpq archives
- libmpq is a library for extracting and manipulating MoPaQ mpq archives.
- This package provides the python bindings for libmpq.
-
diff --git a/dep/libmpq/debian/copyright b/dep/libmpq/debian/copyright
deleted file mode 100644
index f014cf14de7..00000000000
--- a/dep/libmpq/debian/copyright
+++ /dev/null
@@ -1,23 +0,0 @@
-This package was debianized by Georg Lukas <georg@op-co.de> on
-Fri, 04 Jul 2008 18:17:08 +0200.
-
-It was downloaded from <https://libmpq.org/>
-
-Upstream Author:
-
- Maik Broemme <mbroemme@plusserver.de>
-
-Copyright:
-
- Copyright (C) 2008 Maik Broemme
-
-License:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
-
-The Debian packaging is (C) 2008, Georg Lukas <georg@op-co.de> and
-is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
diff --git a/dep/libmpq/debian/libmpq-dev.dirs b/dep/libmpq/debian/libmpq-dev.dirs
deleted file mode 100644
index 7b6c7ee6ec1..00000000000
--- a/dep/libmpq/debian/libmpq-dev.dirs
+++ /dev/null
@@ -1,6 +0,0 @@
-usr/bin
-usr/lib
-usr/lib/pkgconfig
-usr/include
-usr/share/man/man1
-usr/share/man/man3
diff --git a/dep/libmpq/debian/libmpq-dev.install b/dep/libmpq/debian/libmpq-dev.install
deleted file mode 100644
index 4e6ab3278e3..00000000000
--- a/dep/libmpq/debian/libmpq-dev.install
+++ /dev/null
@@ -1,6 +0,0 @@
-usr/bin/*
-usr/include/*
-usr/lib/lib*.a
-usr/lib/pkgconfig/*
-usr/lib/*.la
-usr/share/man/man?/*
diff --git a/dep/libmpq/debian/libmpq0.dirs b/dep/libmpq/debian/libmpq0.dirs
deleted file mode 100644
index 68457717bd8..00000000000
--- a/dep/libmpq/debian/libmpq0.dirs
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib
diff --git a/dep/libmpq/debian/libmpq0.docs b/dep/libmpq/debian/libmpq0.docs
deleted file mode 100644
index 5ac7060850c..00000000000
--- a/dep/libmpq/debian/libmpq0.docs
+++ /dev/null
@@ -1,6 +0,0 @@
-FAQ
-NEWS
-README
-TODO
-THANKS
-AUTHORS
diff --git a/dep/libmpq/debian/libmpq0.install b/dep/libmpq/debian/libmpq0.install
deleted file mode 100644
index 8aa4466a68e..00000000000
--- a/dep/libmpq/debian/libmpq0.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/lib*.so*
diff --git a/dep/libmpq/debian/python-mpq.install b/dep/libmpq/debian/python-mpq.install
deleted file mode 100644
index a7aba2013b0..00000000000
--- a/dep/libmpq/debian/python-mpq.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/python?.?
diff --git a/dep/libmpq/debian/rules b/dep/libmpq/debian/rules
deleted file mode 100644
index 1e101be5faf..00000000000
--- a/dep/libmpq/debian/rules
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
-CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
-else
-CROSS= --build $(DEB_BUILD_GNU_TYPE)
-endif
-
-
-
-
-# shared library versions, option 1
-version=2.0.5
-major=2
-# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
-#version=`ls src/.libs/lib*.so.* | \
-# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
-#major=`ls src/.libs/lib*.so.* | \
-# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
-
-config.status: configure
- dh_testdir
- # Add here commands to configure the package.
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
- cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
- cp -f /usr/share/misc/config.guess config.guess
-endif
- ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS) -ggdb" LDFLAGS="-Wl,-z,defs"
-
-
-build: build-stamp
-build-stamp: config.status
- dh_testdir
-
- # Add here commands to compile the package.
- $(MAKE)
-
- touch $@
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp
-
- # Add here commands to clean up after the build process.
- [ ! -f Makefile ] || $(MAKE) distclean
- rm -f config.sub config.guess
-
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_clean -k
- dh_installdirs
-
- # Add here commands to install the package into debian/tmp
- $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
-
-
-# Build architecture-independent files here.
-binary-indep: build install
- dh_pysupport usr/lib/python?.?/site-packages
-
-# Build architecture-dependent files here.
-binary-arch: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs
- dh_installdocs
- dh_installexamples
- dh_install
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_installinit
-# dh_installcron
-# dh_installinfo
- dh_installman
- dh_link
- dh_strip --dbg-package=libmpq0-dbg
- dh_compress
- dh_fixperms
-# dh_perl
- dh_makeshlibs
- dh_installdeb
- dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/dep/libmpq/doc/Makefile.am b/dep/libmpq/doc/Makefile.am
deleted file mode 100644
index e7ccd5f4518..00000000000
--- a/dep/libmpq/doc/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# any directories which should be built and installed.
-SUBDIRS = man1 man3
diff --git a/dep/libmpq/doc/man1/Makefile.am b/dep/libmpq/doc/man1/Makefile.am
deleted file mode 100644
index 055f1aab533..00000000000
--- a/dep/libmpq/doc/man1/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# manual page directory.
-EXTRA_DIST = $(man_MANS)
-
-# manual pages for the installed binaries.
-man_MANS = \
- libmpq-config.1
diff --git a/dep/libmpq/doc/man1/libmpq-config.1 b/dep/libmpq/doc/man1/libmpq-config.1
deleted file mode 100644
index c025f5ce4f4..00000000000
--- a/dep/libmpq/doc/man1/libmpq-config.1
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 1 2008-02-10 "The MoPaQ archive library"
-.SH NAME
-libmpq-config \- script to get information about the installed version of libmpq.
-.SH SYNOPSIS
-.B libmpq-config
-[\-\-prefix\fI[=DIR]\fP] [\-\-exec\-prefix\fI[=DIR]\fP] [\-\-version]
-.br
-[\-\-cflags] [\-\-libs] [\-\-static\-libs]
-.SH DESCRIPTION
-.PP
-\fIlibmpq-config\fP is a tool that is used to determine the compiler and linker flags that should be used to compile and link programs that use \fIlibmpq\fP. Finally, it's also used internally by the .m4 macros for GNU autoconf that are included with \fIlibmpq\fP.
-.SH OPTIONS
-\fIlibmpq-config\fP accepts the following options:
-.TP 8
-.B \-\-version
-.ti 15
-Print the currently installed version of \fIlibmpq\fP on the standard output.
-.TP 8
-.B \-\-libs
-.ti 15
-Print the linker flags that are necessary to link \fIlibmpq\fP to a program.
-.TP 8
-.B \-\-static\-libs
-.ti 15
-Print the linker flags that are necessary to statically link \fIlibmpq\fP to a program.
-.TP 8
-.B \-\-cflags
-.ti 15
-Print the compiler flags that are necessary to compile a program that use \fIlibmpq\fP.
-.TP 8
-.B \-\-prefix=PREFIX
-.ti 15
-If specified, use PREFIX instead of the installation prefix that \fIlibmpq\fP was built with when computing the output for the \-\-cflags and \-\-libs options. This option is also used for the exec prefix if \-\-exec\-prefix was not specified. This option must be specified before any \-\-libs or \-\-cflags options.
-.TP 8
-.B \-\-exec\-prefix=PREFIX
-.ti 15
-If specified, use PREFIX instead of the installation exec prefix that \fIlibmpq\fP was built with when computing the output for the \-\-cflags and \-\-libs options. This option must be specified before any \-\-libs or \-\-cflags options.
-.SH NOTE
-Instead of using this configuration script you should better use the pkg-config version because this would be more platform independent and makes the usage within GNU autoconf much easier.
-.SH SEE ALSO
-\fBlibmpq\fR(3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/Makefile.am b/dep/libmpq/doc/man3/Makefile.am
deleted file mode 100644
index cad3d865dc1..00000000000
--- a/dep/libmpq/doc/man3/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# manual page directory.
-EXTRA_DIST = $(man_MANS)
-
-# manual pages for the installed binaries.
-man_MANS = \
- libmpq.3 \
- libmpq__archive_close.3 \
- libmpq__archive_files.3 \
- libmpq__archive_offset.3 \
- libmpq__archive_open.3 \
- libmpq__archive_packed_size.3 \
- libmpq__archive_unpacked_size.3 \
- libmpq__archive_version.3 \
- libmpq__block_close_offset.3 \
- libmpq__block_open_offset.3 \
- libmpq__block_read.3 \
- libmpq__block_unpacked_size.3 \
- libmpq__file_blocks.3 \
- libmpq__file_compressed.3 \
- libmpq__file_encrypted.3 \
- libmpq__file_imploded.3 \
- libmpq__file_number.3 \
- libmpq__file_offset.3 \
- libmpq__file_packed_size.3 \
- libmpq__file_read.3 \
- libmpq__file_unpacked_size.3 \
- libmpq__strerror.3 \
- libmpq__version.3
diff --git a/dep/libmpq/doc/man3/libmpq.3 b/dep/libmpq/doc/man3/libmpq.3
deleted file mode 100644
index 768dab0a712..00000000000
--- a/dep/libmpq/doc/man3/libmpq.3
+++ /dev/null
@@ -1,207 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "const char *libmpq__version();"
-.sp
-.BI "const char *libmpq__strerror(int32_t returncode);"
-.sp
-.BI "int32_t libmpq__archive_open("
-.BI " mpq_archive_s **" "mpq_archive",
-.BI " const char *" "mpq_filename",
-.BI " off_t " "archive_offset"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_close("
-.BI " mpq_archive_s *" "mpq_archive"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_packed_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "packed_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "offset"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_version("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t *" "version"
-.BI ");"
-.sp
-.BI "int32_t libmpq__archive_files("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t *" "files"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_packed_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "packed_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "offset"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_blocks("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "blocks"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_encrypted("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "encrypted"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_compressed("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "compressed"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_imploded("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "imploded"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_number("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " const char *" "filename",
-.BI " uint32_t *" "number"
-.BI ");"
-.sp
-.BI "int32_t libmpq__file_read("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint8_t *" "out_buf",
-.BI " off_t " "out_size",
-.BI " off_t *" "transferred"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_open_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_close_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_packed_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " off_t *" "packed_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " off_t *" "offset"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_seed("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " uint32_t *" "seed"
-.BI ");"
-.sp
-.BI "int32_t libmpq__block_read("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " uint8_t *" "out_buf",
-.BI " off_t " "out_size",
-.BI " off_t *" "transferred"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-The \fIlibmpq\fP library supports decrypting, decompressing, exploding and various manipulations of the MoPaQ archive files. It uses \fIzlib(3)\fP and \fIbzip2(1)\fP compression library. At this moment \fIlibmpq\fP is not able to create MoPaQ archives, this limitation will be removed in a future version.
-.SH SEE ALSO
-.BR libmpq__version (3),
-.BR libmpq__strerror (3),
-.BR libmpq__archive_open (3),
-.BR libmpq__archive_close (3),
-.BR libmpq__archive_packed_size (3),
-.BR libmpq__archive_unpacked_size (3),
-.BR libmpq__archive_offset (3),
-.BR libmpq__archive_version (3),
-.BR libmpq__archive_files (3),
-.BR libmpq__file_packed_size (3),
-.BR libmpq__file_unpacked_size (3),
-.BR libmpq__file_offset (3),
-.BR libmpq__file_blocks (3),
-.BR libmpq__file_encrypted (3),
-.BR libmpq__file_compressed (3),
-.BR libmpq__file_imploded (3),
-.BR libmpq__file_number (3),
-.BR libmpq__file_read (3),
-.BR libmpq__block_open_offset (3),
-.BR libmpq__block_close_offset (3),
-.BR libmpq__block_packed_size (3),
-.BR libmpq__block_unpacked_size (3),
-.BR libmpq__block_offset (3),
-.BR libmpq__block_seed (3),
-.BR libmpq__block_read (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_close.3 b/dep/libmpq/doc/man3/libmpq__archive_close.3
deleted file mode 100644
index dfc652a6721..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_close.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_close("
-.BI " mpq_archive_s *" "mpq_archive"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_close\fP() to close a mpq archive which was opened by \fBlibmpq__archive_open\fP(). The function frees the archive structure itself and the contents of it.
-.LP
-The \fBlibmpq__archive_close\fP() function one takes one argument of the archive structure \fImpq_archive\fP which has to be set by \fBlibmpq__archive_open\fP.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_CLOSE
-The given file could not be closed.
-.SH SEE ALSO
-.BR libmpq__archive_open (3),
-.BR libmpq__archive_packed_size (3),
-.BR libmpq__archive_unpacked_size (3),
-.BR libmpq__archive_offset (3),
-.BR libmpq__archive_version (3),
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_files.3 b/dep/libmpq/doc/man3/libmpq__archive_files.3
deleted file mode 100644
index 6663b99161a..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_files.3
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_files("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t *" "files"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_files\fP() to get the number of files inside the archive. It will count only valid files and skip files which have deleted or freed hash entries.
-.LP
-The \fBlibmpq__archive_files\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the number of \fIfiles\fP in the archive.
-.SH RETURN VALUE
-On success, a zero is returned.
-.SH SEE ALSO
-.BR libmpq__file_blocks (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_offset.3 b/dep/libmpq/doc/man3/libmpq__archive_offset.3
deleted file mode 100644
index 696ac5e809f..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_offset.3
+++ /dev/null
@@ -1,51 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "offset"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_offset\fP() to get the offset of the archive, which is the absolute position in the file. It also supports archives within archives.
-.LP
-The \fBlibmpq__archive_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the archive starting position \fIoffset\fP in file.
-.SH RETURN VALUE
-On success, a zero is returned.
-.SH SEE ALSO
-.BR libmpq__file_offset (3),
-.BR libmpq__block_offset (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_open.3 b/dep/libmpq/doc/man3/libmpq__archive_open.3
deleted file mode 100644
index 02c021f8948..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_open.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_open("
-.BI " mpq_archive_s **" "mpq_archive",
-.BI " const char *" "mpq_filename",
-.BI " off_t " "archive_offset"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_open\fP() to open a given mpq archive for later use to extract or manipulate files inside the archive. It will create all required file structures and you have to call \fBlibmpq__archive_close\fP() on success to clean the opened structures. On failure there is no need to call \fBlibmpq__archive_close\fP() because everything will be cleaned up.
-.LP
-The \fBlibmpq__archive_open\fP() function takes as first argument a reference to the archive structure \fImpq_archive\fP and will open the file \fImpq_filename\fP to the structure pointed to by \fImpq_archive\fP. The last argument, \fIarchive_offset\fP is normally -1, but can be specified when the archive offset is known, or not 512-byte aligned.
-.SH RETURN VALUE
-On success, *\fImpq_archive\fP is set to a new \fBmpq_archive_s\fP* and zero is returned, and on error one of the following constants is returned.
-.TP
-.B LIBMPQ_ERROR_OPEN
-The given file could not be opened.
-.TP
-.B LIBMPQ_ERROR_MALLOC
-Not enough memory for creating required structures.
-.TP
-.B LIBMPQ_ERROR_SEEK
-Seeking in file failed.
-.TP
-.B LIBMPQ_ERROR_FORMAT
-The given file is no valid mpq archive.
-.TP
-.B LIBMPQ_ERROR_READ
-Reading in archive failed.
-.SH SEE ALSO
-.BR libmpq__archive_close (3),
-.BR libmpq__archive_packed_size (3),
-.BR libmpq__archive_unpacked_size (3),
-.BR libmpq__archive_offset (3),
-.BR libmpq__archive_version (3),
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_packed_size.3 b/dep/libmpq/doc/man3/libmpq__archive_packed_size.3
deleted file mode 100644
index 6c3061f2031..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_packed_size.3
+++ /dev/null
@@ -1,51 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_packed_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "packed_size"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_packed_size\fP() to get the packed size of all files in the archive. It will count compressed and imploded files as well as stored only.
-.LP
-The \fBlibmpq__archive_packed_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the compressed, imploded or stored size \fIpacked_size\fP of file.
-.SH RETURN VALUE
-On success, a zero is returned.
-.SH SEE ALSO
-.BR libmpq__file_packed_size (3),
-.BR libmpq__block_packed_size (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_unpacked_size.3 b/dep/libmpq/doc/man3/libmpq__archive_unpacked_size.3
deleted file mode 100644
index d2ba923c8f0..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_unpacked_size.3
+++ /dev/null
@@ -1,51 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_unpacked_size\fP() to get the unpacked size of all files in the archive. It will count uncompressed and exploded files as well as stored only.
-.LP
-The \fBlibmpq__archive_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of file.
-.SH RETURN VALUE
-On success, a zero is returned.
-.SH SEE ALSO
-.BR libmpq__file_unpacked_size (3),
-.BR libmpq__block_unpacked_size (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__archive_version.3 b/dep/libmpq/doc/man3/libmpq__archive_version.3
deleted file mode 100644
index 1764046895a..00000000000
--- a/dep/libmpq/doc/man3/libmpq__archive_version.3
+++ /dev/null
@@ -1,48 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__archive_version("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t *" "version"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__archive_version\fP() to get the archive version. Currently there exist two known versions, version 1 which supports archives until 2GB total size and version 2 which supports archives above 2GB total size and both are supported.
-.LP
-The \fBlibmpq__archive_version\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the \fIversion\fP of archive.
-.SH RETURN VALUE
-On success, a zero is returned.
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__block_close_offset.3 b/dep/libmpq/doc/man3/libmpq__block_close_offset.3
deleted file mode 100644
index 1ec0c06f70d..00000000000
--- a/dep/libmpq/doc/man3/libmpq__block_close_offset.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__block_close_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__block_close_offset\fP() to close the block offset table for the given file. It will close the block offset table regardless of compression (compressed, imploded or stored) type of file.
-.LP
-The \fBlibmpq__block_close_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file to close.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File or block does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__block_open_offset (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__block_open_offset.3 b/dep/libmpq/doc/man3/libmpq__block_open_offset.3
deleted file mode 100644
index a60b133f406..00000000000
--- a/dep/libmpq/doc/man3/libmpq__block_open_offset.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__block_open_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__block_open_offset\fP() to open the block offset table for the given file. It will open the block offset table regardless of compression (compressed, imploded or stored) type of file.
-.LP
-The \fBlibmpq__block_open_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file to open.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File or block does not exist in archive.
-.TP
-.B LIBMPQ_ERROR_SEEK
-Seeking in file failed.
-.TP
-.B LIBMPQ_ERROR_MALLOC
-Not enough memory for creating required structures.
-.TP
-.B LIBMPQ_ERROR_READ
-Reading in archive failed.
-.TP
-.B LIBMPQ_ERROR_DECRYPT
-Decrypting block failed.
-.SH SEE ALSO
-.BR libmpq__block_close_offset (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__block_read.3 b/dep/libmpq/doc/man3/libmpq__block_read.3
deleted file mode 100644
index 3272c64c7ed..00000000000
--- a/dep/libmpq/doc/man3/libmpq__block_read.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__block_read("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number,
-.BI " uint8_t *" "out_buf",
-.BI " off_t " "out_size",
-.BI " off_t " "transferred"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__block_read\fP() to read a given block into memory. If the block is encrypted it will be first decrypted and then if it is packed (compressed or imploded) it will be unpacked.
-.LP
-The \fBlibmpq__block_read\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file, the third argument \fIblock_number\fP is the number of block. The fourth argument \fIout_buf\fP is the output data buffer which contains the extracted data and the fifth argument \fIout_size\fP is the size of \fIout_buf\fP. The sixth argument is a reference to the \fItransferred\fP bytes of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-Block does not exist in archive.
-.TP
-.B LIBMPQ_ERROR_OPEN
-Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
-.TP
-.B LIBMPQ_ERROR_SIZE
-The output buffer is to small.
-.TP
-.B LIBMPQ_ERROR_SEEK
-Seeking in file failed.
-.TP
-.B LIBMPQ_ERROR_MALLOC
-Not enough memory for creating required structures.
-.TP
-.B LIBMPQ_ERROR_READ
-Reading in archive failed.
-.TP
-.B LIBMPQ_ERROR_DECRYPT
-Decrypting block failed.
-.TP
-.B LIBMPQ_ERROR_UNPACK
-Unpacking block failed.
-.SH SEE ALSO
-.BR libmpq__file_read (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__block_unpacked_size.3 b/dep/libmpq/doc/man3/libmpq__block_unpacked_size.3
deleted file mode 100644
index a21ca48159a..00000000000
--- a/dep/libmpq/doc/man3/libmpq__block_unpacked_size.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__block_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t " "block_number",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__block_unpacked_size\fP() to get the unpacked size of a given block in the file. It will return a valid size for compressed and imploded blocks as well as stored only.
-.LP
-The \fBlibmpq__block_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file, the third argument \fIblock_number\fP is the number of block and the fourth argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of block.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File or block does not exist in archive.
-.TP
-.B LIBMPQ_ERROR_OPEN
-Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
-.SH SEE ALSO
-.BR libmpq__archive_unpacked_size (3),
-.BR libmpq__file_unpacked_size (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_blocks.3 b/dep/libmpq/doc/man3/libmpq__file_blocks.3
deleted file mode 100644
index 85baeffc603..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_blocks.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_blocks("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t *" "blocks"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_blocks\fP() to get the number of blocks for a given file. It will count all blocks for files stored in multiple sectors or count one for files stored in single sector.
-.LP
-The \fBlibmpq__file_blocks\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the number of \fIblocks\fP of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_compressed.3 b/dep/libmpq/doc/man3/libmpq__file_compressed.3
deleted file mode 100644
index 24b44f0b666..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_compressed.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_compressed("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t *" "compressed"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_compressed\fP() to get the compression status of the given file. It will return true for compressed files and false otherwise.
-.LP
-The \fBlibmpq__file_compressed\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the compression status \fIcompressed\fP of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_encrypted.3 b/dep/libmpq/doc/man3/libmpq__file_encrypted.3
deleted file mode 100644
index 798f4019c7a..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_encrypted.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_encrypted("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t *" "encrypted"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_encrypted\fP() to get the encryption status of the given file. It will return true for encrypted files and false otherwise.
-.LP
-The \fBlibmpq__file_encrypted\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the encryption status \fIencrypted\fP of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_imploded.3 b/dep/libmpq/doc/man3/libmpq__file_imploded.3
deleted file mode 100644
index 9adce38cb5f..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_imploded.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_imploded("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint32_t *" "imploded"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_imploded\fP() to get the implosion status of the given file. It will return true for imploded files and false otherwise.
-.LP
-The \fBlibmpq__file_imploded\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the implosion status \fIimploded\fP of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_files (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_number.3 b/dep/libmpq/doc/man3/libmpq__file_number.3
deleted file mode 100644
index 8d7a47769ee..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_number.3
+++ /dev/null
@@ -1,52 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_number("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " const char *" "filename",
-.BI " uint32_t *" "number"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_number\fP() to get the number of a given file in the archive. This function will return a file number regardless of a known or opened listfile.
-.LP
-The \fBlibmpq__file_number\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfilename\fP is the name of the file and the third argument is a reference to the \fInumber\fP of the file.
-.SH RETURN VALUE
-On success, the number of the file is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_offset.3 b/dep/libmpq/doc/man3/libmpq__file_offset.3
deleted file mode 100644
index 392a66d0b04..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_offset.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_offset("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "offset"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_offset\fP() to get the offset of the file, which is the absolute position in the archive. It also supports archives within archives.
-.LP
-The \fBlibmpq__file_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the file starting position \fIoffset\fP in archive.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_offset (3),
-.BR libmpq__block_offset (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_packed_size.3 b/dep/libmpq/doc/man3/libmpq__file_packed_size.3
deleted file mode 100644
index b584ddf77dd..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_packed_size.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_packed_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "packed_size"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_packed_size\fP() to get the packed size of a given file in the archive. It will return a valid size for compressed and imploded files as well as stored only.
-.LP
-The \fBlibmpq__file_packed_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the compressed, imploded or stored size \fIpacked_size\fP of file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_packed_size (3),
-.BR libmpq__block_packed_size (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_read.3 b/dep/libmpq/doc/man3/libmpq__file_read.3
deleted file mode 100644
index cbfafbd0f4f..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_read.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_read("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " uint8_t *" "out_buf",
-.BI " off_t " "out_size",
-.BI " off_t *" "transferred"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_read\fP() to read a given file into memory. If the file is encrypted it will be first decrypted and then if it is packed (compressed or imploded) it will be unpacked.
-.LP
-The \fBlibmpq__file_read\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the file to extract, the third argument \fIout_buf\fP is the output data buffer which contains the extracted data. The fourth argument \fIout_size\fP is the size of \fIout_buf\fP and the fifth argument is a reference to the \fItransferred\fP bytes of the file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.TP
-.B LIBMPQ_ERROR_OPEN
-Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
-.TP
-.B LIBMPQ_ERROR_SIZE
-The output buffer is to small.
-.TP
-.B LIBMPQ_ERROR_SEEK
-Seeking in file failed.
-.TP
-.B LIBMPQ_ERROR_MALLOC
-Not enough memory for creating required structures.
-.TP
-.B LIBMPQ_ERROR_READ
-Reading in archive failed.
-.TP
-.B LIBMPQ_ERROR_DECRYPT
-Decrypting file failed.
-.TP
-.B LIBMPQ_ERROR_UNPACK
-Unpacking file failed.
-.SH SEE ALSO
-.BR libmpq__block_read (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__file_unpacked_size.3 b/dep/libmpq/doc/man3/libmpq__file_unpacked_size.3
deleted file mode 100644
index a81cf7a4e76..00000000000
--- a/dep/libmpq/doc/man3/libmpq__file_unpacked_size.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "int32_t libmpq__file_unpacked_size("
-.BI " mpq_archive_s *" "mpq_archive",
-.BI " uint32_t " "file_number",
-.BI " off_t *" "unpacked_size"
-.BI ");"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__file_unpacked_size\fP() to get the unpacked size of a given file in the archive. It will return a valid size for compressed and imploded files as well as stored only.
-.LP
-The \fBlibmpq__file_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of file.
-.SH RETURN VALUE
-On success, a zero is returned and on error one of the following constants.
-.TP
-.B LIBMPQ_ERROR_EXIST
-File does not exist in archive.
-.SH SEE ALSO
-.BR libmpq__archive_unpacked_size (3),
-.BR libmpq__block_unpacked_size (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__strerror.3 b/dep/libmpq/doc/man3/libmpq__strerror.3
deleted file mode 100644
index 246f422eed0..00000000000
--- a/dep/libmpq/doc/man3/libmpq__strerror.3
+++ /dev/null
@@ -1,45 +0,0 @@
-.\" Copyright (c) 2010 Georg Lukas <georg@op-co.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2010-07-18 "The MoPaQ archive library"
-.SH NAME
-libmpq__strerror \- return string describing libmpq error number
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "const char *libmpq__strerror(int32_t returncode);"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__strerror\fP() to get a string message for the return code of one of the other libmpq functions.
-.SH RETURN VALUE
-The function returns a string pointer to non-writable memory or NULL if \fBreturncode\fP is not a return code of a libmpq function.
-.SH SEE ALSO
-.BR libmpq (3), strerror (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/doc/man3/libmpq__version.3 b/dep/libmpq/doc/man3/libmpq__version.3
deleted file mode 100644
index 5500d7314f5..00000000000
--- a/dep/libmpq/doc/man3/libmpq__version.3
+++ /dev/null
@@ -1,45 +0,0 @@
-.\" Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
-.\"
-.\" This is free documentation; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License as
-.\" published by the Free Software Foundation; either version 2 of
-.\" the License, or (at your option) any later version.
-.\"
-.\" The GNU General Public License's references to "object code"
-.\" and "executables" are to be interpreted as the output of any
-.\" document formatting or typesetting system, including
-.\" intermediate and printed output.
-.\"
-.\" This manual is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public
-.\" License along with this manual; if not, write to the Free
-.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
-.\" USA.
-.TH libmpq 3 2008-03-31 "The MoPaQ archive library"
-.SH NAME
-libmpq \- cross-platform C library for manipulating mpq archives.
-.SH SYNOPSIS
-.nf
-.B
-#include <mpq.h>
-.sp
-.BI "const char *libmpq__version();"
-.fi
-.SH DESCRIPTION
-.PP
-Call \fBlibmpq__version\fP() to get information about the version of the library, it is useful to create minimum required version verifications.
-.SH RETURN VALUE
-The function returns the library version.
-.SH SEE ALSO
-.BR libmpq (3)
-.SH AUTHOR
-Check documentation.
-.TP
-libmpq is (c) 2003-2008
-.B Maik Broemme <mbroemme@plusserver.de>
-.PP
-The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
diff --git a/dep/libmpq/libmpq-config.in b/dep/libmpq/libmpq-config.in
deleted file mode 100644
index d345efdbe09..00000000000
--- a/dep/libmpq/libmpq-config.in
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-
-prefix="@prefix@"
-exec_prefix="@exec_prefix@"
-exec_prefix_set=no
-
-usage="\
-Usage: libmpq-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
-
-if test "$#" -eq "0"; then
- echo "${usage}" 1>&2
- exit 1
-fi
-
-while test "$#" -gt "0"; do
- case "$1" in
- -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- case "$1" in
- --prefix=*)
- prefix="$optarg"
- if test "$exec_prefix_set" = "no" ; then
- exec_prefix="$optarg"
- fi
- ;;
- --prefix)
- echo "$prefix"
- ;;
- --exec-prefix=*)
- exec_prefix="$optarg"
- exec_prefix_set=yes
- ;;
- --exec-prefix)
- echo "$exec_prefix"
- ;;
- --version)
- echo "@VERSION@"
- ;;
- --cflags)
- largefile="@LFS_CFLAGS@"
- includes=-I@includedir@/libmpq
- echo "$includes $largefile"
- ;;
- --libs)
- libdirs="-L@libdir@"
- echo "$libdirs -lmpq"
- ;;
- *)
- echo "${usage}" 1>&2
- exit 1
- ;;
- esac
- shift
-done
-
diff --git a/dep/libmpq/libmpq.pc.in b/dep/libmpq/libmpq.pc.in
deleted file mode 100644
index 8c53bea35a0..00000000000
--- a/dep/libmpq/libmpq.pc.in
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: libmpq
-Description: GPL version of the libmpq library
-Version: @VERSION@
-Libs: -L${libdir} -lmpq
-Cflags: -I${includedir}/libmpq @LFS_CFLAGS@
diff --git a/dep/libmpq/libmpq/Makefile.am b/dep/libmpq/libmpq/Makefile.am
deleted file mode 100644
index 409e3dfe02f..00000000000
--- a/dep/libmpq/libmpq/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# library information and headers which should not be installed.
-lib_LTLIBRARIES = libmpq.la
-noinst_HEADERS = common.h explode.h extract.h huffman.h mpq-internal.h wave.h
-
-# directory where the include files will be installed.
-libmpq_includedir = $(includedir)/libmpq
-
-# header files to install.
-libmpq_include_HEADERS = mpq.h
-
-libmpq_la_SOURCES = $(GENERAL_SRCS)
-libmpq_la_LDFLAGS = -release $(PACKAGE_VERSION)
-
-GENERAL_SRCS = \
- common.c \
- huffman.c \
- extract.c \
- explode.c \
- mpq.c \
- wave.c
diff --git a/dep/libmpq/libmpq/common.c b/dep/libmpq/libmpq/common.c
deleted file mode 100644
index 879bd902b58..00000000000
--- a/dep/libmpq/libmpq/common.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * common.c -- shared functions used by mpq-tools.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* generic includes. */
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-/* libmpq main includes. */
-#include "mpq.h"
-#include "mpq-internal.h"
-
-/* libmpq generic includes. */
-#include "extract.h"
-
-#include "common.h"
-
-/* the global shared decryption buffer. it's a static array compiled into the
- * library, and can be re-created by compiling and running crypt_buf_gen.c
- */
-#include "crypt_buf.h"
-
-/* function to return the hash to a given string. */
-uint32_t libmpq__hash_string(const char *key, uint32_t offset) {
-
- /* some common variables. */
- uint32_t seed1 = 0x7FED7FED;
- uint32_t seed2 = 0xEEEEEEEE;
-
- /* one key character. */
- uint32_t ch;
-
- /* prepare seeds. */
- while (*key != 0) {
- ch = toupper(*key++);
- seed1 = crypt_buf[offset + ch] ^ (seed1 + seed2);
- seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
- }
-
- return seed1;
-}
-
-/* function to encrypt a block. */
-int32_t libmpq__encrypt_block(uint32_t *in_buf, uint32_t in_size, uint32_t seed) {
-
- /* some common variables. */
- uint32_t seed2 = 0xEEEEEEEE;
- uint32_t ch;
-
- /* we're processing the data 4 bytes at a time. */
- for (; in_size >= 4; in_size -= 4) {
- seed2 += crypt_buf[0x400 + (seed & 0xFF)];
- ch = *in_buf ^ (seed + seed2);
- seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B);
- seed2 = *in_buf + seed2 + (seed2 << 5) + 3;
- *in_buf++ = ch;
- }
-
- /* if no error was found, return decrypted bytes. */
- return LIBMPQ_SUCCESS;
-}
-
-
-/* function to decrypt a block. */
-int32_t libmpq__decrypt_block(uint32_t *in_buf, uint32_t in_size, uint32_t seed) {
-
- /* some common variables. */
- uint32_t seed2 = 0xEEEEEEEE;
- uint32_t ch;
-
- /* we're processing the data 4 bytes at a time. */
- for (; in_size >= 4; in_size -= 4) {
- seed2 += crypt_buf[0x400 + (seed & 0xFF)];
- ch = *in_buf ^ (seed + seed2);
- seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- *in_buf++ = ch;
- }
-
- /* if no error was found, return decrypted bytes. */
- return LIBMPQ_SUCCESS;
-}
-
-/* function to detect decryption key. */
-int32_t libmpq__decrypt_key(uint8_t *in_buf, uint32_t in_size, uint32_t block_size, uint32_t *key) {
-
- /* some common variables. */
- uint32_t saveseed1;
-
- /* temp = seed1 + seed2 */
- uint32_t temp;
- uint32_t i = 0;
-
- /* temp = seed1 + buffer[0x400 + (seed1 & 0xFF)] */
- temp = (*(uint32_t *)in_buf ^ in_size) - 0xEEEEEEEE;
-
- /* try all 255 possibilities. */
- for (i = 0; i < 0x100; i++) {
-
- /* some common variables. */
- uint32_t seed1;
- uint32_t seed2 = 0xEEEEEEEE;
- uint32_t ch;
- uint32_t ch2;
-
- /* try the first uint32_t's (we exactly know the value). */
- seed1 = temp - crypt_buf[0x400 + i];
- seed2 += crypt_buf[0x400 + (seed1 & 0xFF)];
- ch = ((uint32_t *)in_buf)[0] ^ (seed1 + seed2);
-
- if (ch != in_size) {
- continue;
- }
-
- /* add one because we are decrypting block positions. */
- saveseed1 = seed1 + 1;
- ch2 = ch;
-
- /*
- * if ok, continue and test the second value. we don't know exactly the value,
- * but we know that the second one has lower 16 bits set to zero (no compressed
- * block is larger than 0xFFFF bytes)
- */
- seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- seed2 += crypt_buf[0x400 + (seed1 & 0xFF)];
- ch = ((uint32_t *)in_buf)[1] ^ (seed1 + seed2);
-
- /* check if we found the file seed. */
- if ((ch - ch2) <= block_size) {
-
- /* file seed found, so return it. */
- *key = saveseed1;
- return LIBMPQ_SUCCESS;
- }
- }
-
- /* if no file seed was found return with error. */
- return LIBMPQ_ERROR_DECRYPT;
-}
-
-/* function to decompress or explode a block from mpq archive. */
-int32_t libmpq__decompress_block(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size, uint32_t compression_type) {
-
- /* some common variables. */
- int32_t tb = 0;
-
- /* check if buffer is not compressed. */
- if (compression_type == LIBMPQ_FLAG_COMPRESS_NONE) {
-
- /* no compressed data, so copy input buffer to output buffer. */
- memcpy(out_buf, in_buf, out_size);
-
- /* store number of bytes copied. */
- tb = out_size;
- }
-
- /* check if one compression mode is used. */
- else if (compression_type == LIBMPQ_FLAG_COMPRESS_PKZIP ||
- compression_type == LIBMPQ_FLAG_COMPRESS_MULTI) {
-
- /* check if block is really compressed, some blocks have set the compression flag, but are not compressed. */
- if (in_size < out_size) {
-
- /* check if we are using pkzip compression algorithm. */
- if (compression_type == LIBMPQ_FLAG_COMPRESS_PKZIP) {
-
- /* decompress using pkzip. */
- if ((tb = libmpq__decompress_pkzip(in_buf, in_size, out_buf, out_size)) < 0) {
-
- /* something on decompression failed. */
- return tb;
- }
- }
-
- /* check if we are using multiple compression algorithm. */
- else if (compression_type == LIBMPQ_FLAG_COMPRESS_MULTI) {
-
- /*
- * check if it is a file compressed by blizzard's multiple compression, note that storm.dll
- * version 1.0.9 distributed with warcraft 3 passes the full path name of the opened archive
- * as the new last parameter.
- */
- if ((tb = libmpq__decompress_multi(in_buf, in_size, out_buf, out_size)) < 0) {
-
- /* something on decompression failed. */
- return tb;
- }
- }
- } else {
-
- /* block has set compression flag, but is not compressed, so copy data to output buffer. */
- memcpy(out_buf, in_buf, out_size);
-
- /* save the number of transferred bytes. */
- tb = in_size;
- }
- }
-
- /* if no error was found, return transferred bytes. */
- return tb;
-}
diff --git a/dep/libmpq/libmpq/common.h b/dep/libmpq/libmpq/common.h
deleted file mode 100644
index b9e03126434..00000000000
--- a/dep/libmpq/libmpq/common.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * common.h -- header functions used by mpq-tools.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _COMMON_H
-#define _COMMON_H
-
-/* function to return the hash to a given string. */
-uint32_t libmpq__hash_string(
- const char *key,
- uint32_t offset
-);
-
-/* function to encrypt a block. */
-int32_t libmpq__encrypt_block(
- uint32_t *in_buf,
- uint32_t in_size,
- uint32_t seed
-);
-
-/* function to decrypt a block. */
-int32_t libmpq__decrypt_block(
- uint32_t *in_buf,
- uint32_t in_size,
- uint32_t seed
-);
-
-/* function to detect decryption key. */
-int32_t libmpq__decrypt_key(
- uint8_t *in_buf,
- uint32_t in_size,
- uint32_t block_size,
- uint32_t *key
-);
-
-/* function to decompress or explode block from archive. */
-int32_t libmpq__decompress_block(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size,
- uint32_t compression_type
-);
-
-#endif /* _COMMON_H */
diff --git a/dep/libmpq/libmpq/crypt_buf.h b/dep/libmpq/libmpq/crypt_buf.h
deleted file mode 100644
index 34184b017fe..00000000000
--- a/dep/libmpq/libmpq/crypt_buf.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/* DO NOT CHANGE! this file is auto-generated by crypt_buf_gen.c */
-static const uint32_t crypt_buf[0x500] = {
- 0x55c636e2, 0x02be0170, 0x584b71d4, 0x2984f00e, 0xb682c809, 0x91cf876b,
- 0x775a9c24, 0x597d5ca5, 0x5a1afeb2, 0xd3e9ce0d, 0x32cdcdf8, 0xb18201cd,
- 0x3cce05ce, 0xa55d13be, 0xbb0afe71, 0x9376ab33, 0x848f645e, 0x87e45a45,
- 0x45b86017, 0x5e656ca8, 0x1b851a95, 0x2542dbd7, 0xab4df9e4, 0x5976ae9b,
- 0x6c317e7d, 0xcddd2f94, 0x3c3c13e5, 0x335b1371, 0x31a592ca, 0x51e4fc4c,
- 0xf7db5b2f, 0x8abdbe41, 0x8beaa674, 0x20d6b319, 0xde6c9a9d, 0xc5ac84e5,
- 0x445a5feb, 0x94958cb0, 0x1e7d3847, 0xf35d29b0, 0xca5cceda, 0xb732c8b5,
- 0xfdcc41dd, 0x0edcec16, 0x9d01feae, 0x1165d38e, 0x9ee193c8, 0xbf33b13c,
- 0x61bc0dfc, 0xef3e7be9, 0xf8d4d4c5, 0xc79b7694, 0x5a255943, 0x0b3dd20a,
- 0x9d1ab5a3, 0xcfa8ba57, 0x5e6d7069, 0xcb89b731, 0x3dc0d15b, 0x0d4d7e7e,
- 0x97e37f2b, 0xfefc2bb1, 0xf95b16b5, 0x27a55b93, 0x45f22729, 0x4c986630,
- 0x7c666862, 0x5fa40847, 0xa3f16205, 0x791b7764, 0x386b36d6, 0x6e6c3fef,
- 0xc75855db, 0x4abc7dc7, 0x4a328f9b, 0xcef20c0f, 0x60b88f07, 0xf7bb4b8f,
- 0x830b5192, 0x94f711ec, 0x20250752, 0x399d21a3, 0xe5c0840d, 0xe76cffa5,
- 0x624fab29, 0x5df133e6, 0x83e0b9b8, 0xc5796bfb, 0x4a7ab2d0, 0xba59a821,
- 0x03a81e4c, 0xcd3adfdb, 0x32b26b8c, 0x8e35c533, 0x9e6300e9, 0x8cf92ac5,
- 0x880d18eb, 0x131a53b3, 0x2ed2dc64, 0xb23257c1, 0xa06450c1, 0x1b92cb8e,
- 0x72ed730e, 0x19a685f0, 0x82836483, 0x42d94e8a, 0xee9bd6f6, 0x556d0b6a,
- 0xba65589a, 0xde24cce4, 0x53329f6c, 0xc754fe8b, 0x503d2dc7, 0x10027ba4,
- 0xd3b60a8b, 0x68e68d83, 0x0a9128a9, 0x595fa35f, 0x0b03b5be, 0x150a45c4,
- 0xb1629cce, 0xe5f7497b, 0x8a7098a4, 0xb8233e69, 0x8ea0f978, 0x5b579970,
- 0xeab14318, 0x4b28b263, 0xb6766cef, 0x06782877, 0x155c6dd0, 0xc711333c,
- 0xf819cedf, 0x00eb1d68, 0xd6fffa6e, 0x439e5962, 0xd765d6db, 0xcb0bcee9,
- 0x6d3c5647, 0x965466f3, 0x0ca983c9, 0x74ecc1ce, 0xfc0563b6, 0x42b08fee,
- 0xc5b38853, 0xfe502ceb, 0x7b432faf, 0xc309e610, 0x2c3997d8, 0x43774654,
- 0x15bd9d2c, 0xed6a420d, 0xc7ff520c, 0xb8a97fd1, 0x5e4d60cc, 0xb9738d11,
- 0xda2181ff, 0x73ac2597, 0x3a8eec8d, 0xac85e779, 0xf3f975d6, 0xb9fe7b91,
- 0x0f155d1e, 0x2860b6dd, 0x835977cb, 0xb0607436, 0x9cab7f6b, 0x8ab91186,
- 0xc12b51e9, 0x20084e8b, 0x44ba8ead, 0xa542b130, 0x82bcd5c4, 0xcc747f4e,
- 0x0f1909d8, 0xda242e1c, 0x6f7d1aa0, 0xd2626486, 0x88d0781e, 0xab695ccd,
- 0xfa569145, 0xb4feb55c, 0xbe47e896, 0xe70a7a88, 0xd56185a2, 0xacf4c871,
- 0x09282332, 0x1ddeeaa8, 0x590c7adb, 0xf4a97667, 0xbfd85705, 0x0ea77ccc,
- 0xa9f85364, 0x83195869, 0x8bfb041a, 0xdb842f5c, 0xd6f0f315, 0xa7756ea7,
- 0x0a51b439, 0xa9edf8a3, 0xd9084e2f, 0x827407f8, 0xd4ac8284, 0x09739d0d,
- 0xb3bb6cfc, 0xd539c77d, 0x6bbc9ac0, 0x35c641aa, 0x934c96b0, 0xd17af317,
- 0x29c6baef, 0xb275cdac, 0xd72662de, 0x9f5c2544, 0xc1a98f75, 0xd98e8f9a,
- 0x47bd5c86, 0x70c610a6, 0xb5482ed4, 0x23b9c68c, 0x3c1bae66, 0x69556e7f,
- 0xd902f5e0, 0x653d195b, 0xde6541fb, 0x07bcc6ac, 0xc6ee7788, 0x801534d4,
- 0x2c1f35c0, 0xd9de614d, 0xbdccac85, 0xb4d4a0da, 0x242d549b, 0x9d964796,
- 0xb9ceb982, 0x59fa99a9, 0xd8986cc1, 0x9e90c1a1, 0x01bbd82f, 0xd7f1c5fd,
- 0xdd847eba, 0x883d305d, 0x25f13152, 0x4a92694d, 0x77f1e601, 0x8024e6e7,
- 0x02a5f53d, 0x9c3ef4d9, 0xaf403ccc, 0xe2ad03c0, 0x46edf6ec, 0x6f9bd3e6,
- 0xcc24ad7a, 0x47afab12, 0x82298df7, 0x708c9eec, 0x76f8c1b1, 0xb39459d2,
- 0x3f1e26d9, 0xe1811be7, 0x56ed1c4d, 0xc9d18af8, 0xe828060e, 0x91cada2e,
- 0x5ccbf9b7, 0xf1a552d4, 0x3c9d4343, 0xe1008785, 0x2adfeebf, 0xf90240a0,
- 0x3d08cce7, 0x426e6fb0, 0x573c984f, 0x13a843ae, 0x406b7439, 0x636085d9,
- 0x5000ba9a, 0xad4a47ab, 0xaf001d8d, 0x419907ae, 0x185c8f96, 0xe5e9ed4d,
- 0x61764133, 0xd3703d97, 0xac98f0c6, 0xdbc3a37c, 0x85f010c4, 0x90491e32,
- 0xf12e18bf, 0xc88c96e1, 0xd3fbd6d9, 0xe3c28b08, 0xd5bf08cc, 0xb1e78859,
- 0x2546ddcf, 0xb030b200, 0xaafd2811, 0x55b22d21, 0xd38bf567, 0x469c7a2b,
- 0x5ad05792, 0xa1a5981e, 0x7dfb8384, 0x34d1ca0a, 0x7eb0dbe0, 0xd61ce0f6,
- 0x398068b7, 0xe6406d1f, 0x95ae6b47, 0xe4281230, 0xb0843061, 0xa70a3a68,
- 0xe340f625, 0x72dcbffd, 0x8eb8afcd, 0x18b6661f, 0x17ef5a5c, 0x000c5b22,
- 0x6ba13836, 0x6165e383, 0x74481c5b, 0xe56f0711, 0xa26f5024, 0x5ff22e60,
- 0x31a5e829, 0xa1094bf0, 0xc680ec6c, 0x8cf327d7, 0xebf1348a, 0x6a227d2f,
- 0x74065184, 0x8df65112, 0x2bbd05ee, 0xe4d00ed6, 0x2980ee1a, 0x6ae1da73,
- 0xe84614da, 0x6c9906ab, 0xcf8e02db, 0xd3723e97, 0x92f66caf, 0xac8491c7,
- 0xaec65696, 0xb98997cf, 0xfa16c762, 0x6d73c65f, 0x205d22a6, 0x4dd3aaa5,
- 0x2deb6bc0, 0x9f37686c, 0x71a5282b, 0x376bb9e0, 0x7fff2a1b, 0xde67982f,
- 0x9cbf33ce, 0x2e6dab37, 0x6e3424b9, 0x0ee143bc, 0x832a60d9, 0xbb6329e1,
- 0x13f6befd, 0x5965fb84, 0xf60b233c, 0x3d695183, 0x433224a1, 0xb5d9cae5,
- 0x82459bab, 0x9f21b311, 0xaf6c5247, 0xb447b13a, 0x7b2676c3, 0xc38979cd,
- 0x8526ae25, 0xc550ad5b, 0x685099a7, 0x65e9c2bd, 0xe5c6dc36, 0xe10b37a9,
- 0x88016878, 0xce81d4e4, 0x24d6fc80, 0x4106152d, 0x6d4f5f90, 0xc4dc74be,
- 0xdb48676c, 0x6cb569b7, 0xf3bf598f, 0x042b08d9, 0x02ccb2de, 0xb1056f65,
- 0x47994af4, 0xfa141ba4, 0x9376ab2e, 0x07a76737, 0x75e7e6fc, 0x449d80a1,
- 0x03b7259d, 0xf6df358a, 0x5a75d5b9, 0x47286923, 0x3b1a30ef, 0xeebe3d6a,
- 0x9db1aa00, 0x007a90d9, 0x24667071, 0x019c73cf, 0x69039bcd, 0x95900744,
- 0x6518b1eb, 0x6905f202, 0xee3951b2, 0xe141fca9, 0x797fa832, 0x5a95e55b,
- 0xd6263b15, 0x5b61f394, 0x897acb1c, 0x005f83a9, 0x22420f71, 0xf495176e,
- 0x7e138f3d, 0x1392e384, 0x373bf7aa, 0x8e512816, 0xa960b3ca, 0x0474d74c,
- 0xffacd6d7, 0x2ef5ed9e, 0x60992aaa, 0x7e690e99, 0x23c0749d, 0xd8e29105,
- 0x555d5909, 0x15631bfe, 0xa69c5a1c, 0x501017ca, 0x99438048, 0x38733ac7,
- 0xe682e2c8, 0xd4655fd6, 0x956e4c04, 0x347df643, 0x2f4b177b, 0x93ed3aa4,
- 0xa77e1dd5, 0x7ae55702, 0xd2a52fd9, 0xef8ba18c, 0xb7d3c1ee, 0x8078ba8d,
- 0xab5aaadb, 0x752be08f, 0x068b31c1, 0x078aae3c, 0xaa5a8343, 0x123d9268,
- 0x2ceaee43, 0x8ebdb239, 0x650251f3, 0x04883648, 0x8c62e12e, 0x12b32167,
- 0xe5112e9a, 0x10002548, 0x3e7a818d, 0x077e5327, 0xf140cc21, 0x6ce7d75d,
- 0x9b99f9a5, 0x3215741c, 0xb6aadbae, 0x738768dc, 0x82a3742f, 0x76517020,
- 0xdd872ad8, 0x9d0902b2, 0x7d1a6b04, 0x49381592, 0x63a652a5, 0x0c15e626,
- 0xe22f70d6, 0x01e84385, 0xb29de134, 0x20c5000e, 0xe961f443, 0x2d31662e,
- 0x3ce6bc28, 0x34f9dd94, 0xfa45de53, 0x497588bd, 0x9468215b, 0x0777fa5c,
- 0x6f7114c0, 0xe0e82694, 0xe4371986, 0x57112de2, 0xe0cac289, 0xf2a3cee0,
- 0x6a41e1b9, 0xbfcea77d, 0xf927fd52, 0x69747d98, 0xbea76cdb, 0x8dd39557,
- 0x04db5ece, 0x2a0885c8, 0x3be4e8ee, 0x21d785dc, 0x09de7c0e, 0x3258ea33,
- 0x51922982, 0xee8dd024, 0x3df6965d, 0x30c1237b, 0xf7f6686a, 0x9faca186,
- 0x7c400076, 0x85acef8a, 0xf4b6d220, 0xddc3481c, 0x439eaec4, 0x717bbe63,
- 0x8259faa7, 0xd682bd68, 0x932a8610, 0x38bf0a7f, 0x6212e2c7, 0x88ee3168,
- 0xb3c27047, 0x6133cb1e, 0x15295506, 0x5ae66246, 0x1d208ddd, 0xa91d3dba,
- 0xc315968d, 0x6aa2664b, 0x716d0cca, 0x891f4956, 0x80866bff, 0xbd56c847,
- 0x9093425a, 0x28dd9e87, 0x84ef3e08, 0x690a49d6, 0x6a7eff82, 0xabcfe400,
- 0x3d3be5ca, 0x381b650c, 0x4b7c8622, 0x3e0246f3, 0xa3561654, 0x9488865c,
- 0x3aef1bf2, 0x5e5d68a2, 0xd32f1ddc, 0x51972bf0, 0x177a213b, 0x469375c2,
- 0x37640bd0, 0xfc3324c8, 0x07091a09, 0x2d63d3fb, 0x2153f023, 0x48223875,
- 0x61a55826, 0x8c136538, 0x49f71d98, 0x84c7d51e, 0x85551a73, 0x13d604c5,
- 0xd701a626, 0x87b844ca, 0x741eb29d, 0x2a2c977c, 0xc797ca03, 0x6c4085d7,
- 0x2dacf79b, 0x734fa2eb, 0xcc290557, 0xfa1e75e4, 0x06b29a27, 0xbece2a7a,
- 0x70a4554b, 0xc935942e, 0xa764bbc1, 0x1fe391d6, 0x7807f0c2, 0x40606ed9,
- 0xe5153086, 0xe91d7dd2, 0xed5d3ba9, 0xaa14b64a, 0x83b24dd9, 0xec1ff5cd,
- 0xba33ead3, 0xe4ef735c, 0xbc062438, 0xd8bfd523, 0x473d1e04, 0x2007f8a7,
- 0xb02903ed, 0x86ea8ada, 0x95ab69cf, 0xfd1f9809, 0x9cb3d8bb, 0x51f45958,
- 0x9cdd4276, 0xc245865e, 0x8f0c836b, 0x4ee7dc07, 0xf6368d9d, 0xef2c1dc1,
- 0xee56b54b, 0xbd62ce2f, 0xf4916aad, 0xc81cb594, 0x41729f49, 0x24bef0a4,
- 0xdef487a9, 0x222e05b8, 0x8d3bf5c6, 0x11b55009, 0xad09d2b3, 0x19db9fd1,
- 0xd7427085, 0x33dbfc8b, 0x526b9378, 0x790e1bc8, 0xb2998a00, 0xa5641703,
- 0x0676d249, 0x6b9185cc, 0x30e4348f, 0x82c52f65, 0x57c7dc24, 0x489c1ecd,
- 0x9fcab02a, 0x56d61117, 0xfe869cac, 0x55fc5140, 0x7fbbb382, 0x9e5afc79,
- 0x10047c99, 0xfc9f5984, 0x56587e2d, 0xb98193f0, 0x98fe5e8e, 0x29b15b6b,
- 0x9561f055, 0xbb0caa25, 0x1e4ecc15, 0x23f5393b, 0x0845b458, 0xceff67ca,
- 0xb099900c, 0x00b1564f, 0x39eef3d1, 0xfcc1bf84, 0xac8893b5, 0x6484bf0e,
- 0x91c02ab3, 0x8c0c0c70, 0x686fa8c6, 0xe171bed6, 0xdfae37df, 0xd5a1a4e7,
- 0xe3eb49a1, 0x5e6014e0, 0x205b21ac, 0xfd58b3da, 0x2e7c07cd, 0xef2cc85a,
- 0xd7587b46, 0xf417847d, 0x8a30cec1, 0x70984f6c, 0xf0b63388, 0xc220c98d,
- 0xede62936, 0x92c0a7b3, 0x1ef371e8, 0x2005f7af, 0x91a47265, 0xb0cf5504,
- 0xd500aba8, 0xcb5c4bd3, 0x9b3bcbc3, 0xcf6644b5, 0xce9488ef, 0x003fc96e,
- 0xaa42222f, 0x4844f3d0, 0x4db89d77, 0x08681aae, 0x662f3a28, 0x761552db,
- 0x1df7a17a, 0x93feed9a, 0xcc496a4f, 0xa217cfcd, 0x3ba3c930, 0x268f7e77,
- 0x0797b4a1, 0x8bebfc51, 0x068930c4, 0x16c874e2, 0xc242da24, 0xfb229f76,
- 0xa0795b02, 0x689fc036, 0x17a73732, 0xd21aec00, 0xac00a692, 0x5b217f18,
- 0xae421624, 0x2bc05cc0, 0x48c1db7a, 0x4f4e63b4, 0x1667f04e, 0x34020f94,
- 0x972b2555, 0x9a07355b, 0x01665970, 0x7db60c6f, 0x3ad7103b, 0x5c3d09c0,
- 0xeea3dada, 0x88c21c10, 0x102436d7, 0x6a3b3400, 0xeb523c4c, 0xfb97d896,
- 0x964cb86b, 0xdd878038, 0x0529da4d, 0x0b1468a5, 0x18739ac8, 0xf7f26668,
- 0xf64f4471, 0x5c14f5c3, 0x44a081fb, 0x39ac7e37, 0x8a17c26b, 0x868f5e67,
- 0x3931978d, 0x6edf7817, 0x4951cc67, 0x943407f3, 0xcc5e748f, 0x2b7ee729,
- 0xcbb320f0, 0x11fec8e7, 0xfccfc658, 0x03454354, 0x373aa1ec, 0x1d58fe9a,
- 0x064710ae, 0xa88aa0ba, 0xd183a23e, 0x40d150a3, 0xf531b8d1, 0xa7d99f85,
- 0x11838cd5, 0xb19e64b3, 0x3d67a5e9, 0xb02c5ac6, 0x99b9b9e8, 0x4c202b7a,
- 0x15f261d3, 0xa84c2d0d, 0x50f185a6, 0x33ba41d5, 0x39791013, 0x4baff44e,
- 0xeeeeaa1c, 0xe0488314, 0x559ccd2b, 0xa104f445, 0x636f37c4, 0x264d5e3b,
- 0x75c17f35, 0x75424131, 0xbb115739, 0x74fe755a, 0x7d3a7aa6, 0x2d8be784,
- 0x83ed154a, 0xfc2673d8, 0x44dd4a7f, 0x79056cc8, 0x82cc8831, 0x9d3c1b7c,
- 0xe9453bfa, 0x24315694, 0x661f3253, 0x75549f5c, 0xbb2b63ed, 0x67e00d96,
- 0xf48966c7, 0x0d7bea56, 0xc25f92ef, 0xa947a79d, 0xde4adf6f, 0xac0f0342,
- 0xd3eb246b, 0xa4aa118e, 0x3c3e6a46, 0x457f4441, 0xa50a406f, 0x6c508d9f,
- 0xe9ac18e7, 0x1ecdb4ba, 0x39ac7e3a, 0x7fb304fa, 0x6f38f8e8, 0x4aecea6d,
- 0x61035e73, 0x81708907, 0xebc07205, 0x90fd7614, 0xb52d217f, 0x6c4de195,
- 0x1dd49084, 0x64ee482c, 0x94c7a521, 0x540c09d8, 0x75df8dd5, 0x414131f7,
- 0x3698fd76, 0xf784db4f, 0xf8c97a03, 0x048f39b9, 0x3bf4f0bd, 0x8cb50992,
- 0x9b58d9ee, 0xe5ab79cc, 0x9a5f6052, 0xbd9591b0, 0xfad2232b, 0x5a632254,
- 0x0286e618, 0x8ad3c8f7, 0xe4060176, 0x754c4617, 0x5c10490b, 0x6f7d6fff,
- 0x2187b42a, 0x5775095b, 0x02f4c663, 0x5a5dca06, 0xfe4ad4c7, 0x53e19f7d,
- 0x59ff46b5, 0xbcc42ba5, 0xfd2f4a97, 0xbed6d905, 0x95629b6b, 0x21a1c0db,
- 0xaa10b45d, 0xe6ef6d58, 0x2892cf4d, 0x9fed6c10, 0x1e386bf7, 0x9be0c6e8,
- 0x2b2f15ef, 0x19f5ac7b, 0x7aff0e72, 0x31da576f, 0x30252cb4, 0x577960ac,
- 0x166e9e5a, 0xa9374a61, 0x71369c96, 0x7ff826ae, 0xe8175326, 0xcabbfd33,
- 0x0191190e, 0x699d3c3e, 0x36b40b22, 0xb3950513, 0x9b889bfa, 0xa52a5007,
- 0xac290fed, 0x3b4e4a4f, 0xb753d8d6, 0x3c531f22, 0x582f6427, 0xa9cd93a9,
- 0x546e39ae, 0x242faad2, 0xd2e0f747, 0x09f6325d, 0x59d48719, 0xad7eb66e,
- 0xd5512878, 0x56debf9d, 0x5107e5a5, 0xf1c00aa4, 0x814ccca8, 0x600d90f0,
- 0x9be97619, 0x915fa5f2, 0x2b5628dd, 0xa33d5f5a, 0x595df7c1, 0x6966215d,
- 0x50ec8337, 0xf1d21372, 0x0ee2eefb, 0xad9e70b7, 0xab0d2fe4, 0xcf277b5d,
- 0x62585a2c, 0x835a7844, 0x74b1fa6b, 0x49baffd5, 0x2ea9c864, 0x129311a8,
- 0xbdfa1867, 0x83ca5997, 0x9d1db719, 0x84bb79e6, 0x9e3f99f2, 0x313f6101,
- 0x1b99245b, 0xd15d8fb2, 0xcef90f81, 0x2945268d, 0xdbbcf573, 0xb1021886,
- 0x9ee7ec1d, 0x1cf824f7, 0x7eaa2e32, 0x69c0a2b5, 0x7494419c, 0xe253d7d3,
- 0x48da3d12, 0x45b8b571, 0xdb4d147a, 0xd82d8dde, 0x265d10a2, 0xb0a6eb9a,
- 0x7e1c93a6, 0x36fe2f46, 0xdcad6b00, 0x05439191, 0xb0ce5484, 0x61d1c309,
- 0x8da62a03, 0x06d0fe2f, 0xbac6dd3c, 0xca2006f3, 0x8321b1af, 0x0411a6f3,
- 0xe8918eac, 0x21a2c152, 0x91c0d54f, 0x6aaa14fa, 0xdd22a440, 0x88cb2075,
- 0x7a4eb813, 0x67afa071, 0xd8d98c9c, 0x31f10d47, 0x6ff1a8a8, 0x2faaf0a1,
- 0x48a221bb, 0x3be6948b, 0xaa79e79b, 0x0ea7278c, 0x7a3857ef, 0x49b7fe55,
- 0xd51cb931, 0x041c018d, 0x00b90501, 0x45ea7881, 0x8fc1dbcf, 0xb80b32a9,
- 0xabacd2e9, 0x677bdc40, 0xecace542, 0x6d6514eb, 0x31c09ff7, 0x5e6c1abd,
- 0x1c391d0f, 0x0e9d77f1, 0x7119392d, 0x6be9b0ba, 0x6194fa77, 0x45e62148,
- 0x42234af2, 0xc3239d66, 0x939cbdbc, 0x56200d9c, 0x6b275208, 0x001a61f3,
- 0xccc2a546, 0x4b722be0, 0xee25f2b7, 0x6d86cf9e, 0xaa6be0cd, 0x4dcda7b6,
- 0x78d4aa13, 0x36ea7ad9, 0x3f29d700, 0xdeea2d84, 0x6a6af5bd, 0x18afb81c,
- 0xd8e4e73c, 0x8aa708ba, 0x658b94d9, 0xa676478c, 0xcfa10c22, 0x25593c74,
- 0x8d962235, 0x5f980270, 0x3df6ebc0, 0x8e7d92fa, 0xc3ee55e1, 0xd5f72447,
- 0x02b0fa95, 0x52b0b520, 0x70d2c11f, 0x3a6fdd6c, 0x193aa698, 0x5496f7d5,
- 0x4208931b, 0x7a4106ec, 0x83e86840, 0xf49b6f8c, 0xba3d9a51, 0x55f54ddd,
- 0x2de51372, 0x9afb571b, 0x3ab35406, 0xad64ff1f, 0xc77764fe, 0x7f864466,
- 0x416d9cd4, 0xa2489278, 0xe30b86e4, 0x0b5231b6, 0xba67aed6, 0xe5ab2467,
- 0x60028b90, 0x1d9e20c6, 0x2a7c692a, 0x6b691cdb, 0x9e51f817, 0x9b763dec,
- 0x3d29323f, 0xcfe12b68, 0x754b459b, 0xa2238047, 0xd9c55514, 0x6bdcffc1,
- 0x693e6340, 0x82383fe7, 0x1916ea5f, 0xec7bcd59, 0x72de165a, 0xe79a1617,
- 0x8ec86234, 0xa8f0d284, 0x20c90226, 0x7bf98884, 0x28a58331, 0x3ec3fa6e,
- 0x4ce0895b, 0xc353b4d0, 0x33ef064f, 0x21e5e210, 0xc8bb589d, 0xe85dcab2,
- 0xac65829f, 0xa7bf92d0, 0x05a6174d, 0x25a50c2e, 0xe5c78777, 0x3d75021f,
- 0x4baa9c98, 0x23bdc884, 0x9653bbd7, 0xbadce7f5, 0xc283a484, 0xc040df2e,
- 0x9370a841, 0x2f316022, 0x36eed231, 0xac2cbc0c, 0x13c0a49b, 0xcdd12997,
- 0x07fe91b2, 0xcd7eabcd, 0x2c01271d, 0x18432df8, 0x599c6bc7, 0x75e93d5a,
- 0xb67a6ee2, 0x8e738e16, 0xff9073fd, 0xaf77026a, 0xf86ea2fc, 0x91509ea3,
- 0x33a78dc6, 0x4f79234a, 0x3a7535bc, 0x3539fcb1, 0x3103ee52, 0x4f6f1e69,
- 0x6bb3ebbc, 0x4cb77555, 0x8dd1e999, 0x2ade439d, 0x11521fae, 0xb94d2545,
- 0x8dde9abd, 0x1909393f, 0xb792a23d, 0x749c455b, 0xb5b60f2c, 0x380459ce,
- 0x0dad5820, 0xb130845b, 0x291cbd52, 0xde9a5bb7, 0x51def961, 0x515b6408,
- 0xca6e823e, 0x382e6e74, 0xeebe3d71, 0x4c8f0c6a, 0xe676dcea, 0x14e1dc7c,
- 0x6f7fc634, 0xcf85a943, 0xd39ea96e, 0x136e7c93, 0x7164b304, 0xf32f1333,
- 0x35c34034, 0xde39d721, 0x91a87439, 0xc410111f, 0x29f17aac, 0x1316a6ff,
- 0x12f194ee, 0x420b9499, 0xf72db0dc, 0x690b9f93, 0x17d14bb2, 0x8f931ab8,
- 0x217500bc, 0x875413f8, 0x98b2e43d, 0xc51f9571, 0x54cebdca, 0x0719cc79,
- 0xf3c7080d, 0xe4286771, 0xa3eab3cd, 0x4a6b00e0, 0x11cf0759, 0x7e897379,
- 0x5b32876c, 0x5e8cd4f6, 0x0cedfa64, 0x919ac2c7, 0xb214f3b3, 0x0e89c38c,
- 0xf0c43a39, 0xeae10522, 0x835bce06, 0x9eec43c2, 0xea26a9d6, 0x69531821,
- 0x6725b24a, 0xda81b0e2, 0xd5b4ae33, 0x080f99fb, 0x15a83daf, 0x29dfc720,
- 0x91e1900f, 0x28163d58, 0x83d107a2, 0x4eac149a, 0x9f71da18, 0x61d5c4fa,
- 0xe3ab2a5f, 0xc7b0d63f, 0xb3cc752a, 0x61ebcfb6, 0x26ffb52a, 0xed789e3f,
- 0xaa3bc958, 0x455a8788, 0xc9c082a9, 0x0a1bef0e, 0xc29a5a7e, 0x150d4735,
- 0x943809e0, 0x69215510, 0xef0b0da9, 0x3b4e9fb3, 0xd8b5d04c, 0xc7a023a8,
- 0xb0d50288, 0x64821375, 0xc260e8cf, 0x8496bd2c, 0xff4f5435, 0x0fb5560c,
- 0x7cd74a52, 0x93589c80, 0x88975c47, 0x83bda89d, 0x8bcc4296, 0x01b82c21,
- 0xfd821dbf, 0x26520b47, 0x04983e19, 0xd3e1ca27, 0x782c580f, 0x326ff573,
- 0xc157bcc7, 0x4f5e6b84, 0x44ebfbfb, 0xda26d9d8, 0x6cd9d08e, 0x1719f1d8,
- 0x715c0487, 0x2c2d3c92, 0x53faaba9, 0xbc836146, 0x510c92d6, 0xe089f82a,
- 0x4680171f, 0x369f00de, 0x70ec2331, 0x0e253d55, 0xdafb9717, 0xe5dd922d,
- 0x95915d21, 0xa0202f96, 0xa161cc47, 0xeacfa6f1, 0xed5e9189, 0xdab87684,
- 0xa4b76d4a, 0xfa704897, 0x631f10ba, 0xd39da8f9, 0x5db4c0e4, 0x16fde42a,
- 0x2dff7580, 0xb56fec7e, 0xc3ffb370, 0x8e6f36bc, 0x6097d459, 0x514d5d36,
- 0xa5a737e2, 0x3977b9b3, 0xfd31a0ca, 0x903368db, 0xe8370d61, 0x98109520,
- 0xade23cac, 0x99f82e04, 0x41de7ea3, 0x84a1c295, 0x09191be0, 0x30930d02,
- 0x1c9fa44a, 0xc406b6d7, 0xeedca152, 0x6149809c, 0xb0099ef4, 0xc5f653a5,
- 0x4c10790d, 0x7303286c
-};
diff --git a/dep/libmpq/libmpq/explode.c b/dep/libmpq/libmpq/explode.c
deleted file mode 100644
index 2d778d25c39..00000000000
--- a/dep/libmpq/libmpq/explode.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * explode.c -- explode function of pkware data compression library.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This source was adepted from the C++ version of pkware.cpp included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* generic includes. */
-#include <string.h>
-
-/* libmpq main includes. */
-#include "mpq.h"
-
-/* libmpq generic includes. */
-#include "explode.h"
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_dist_bits[] = {
- 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_dist_code[] = {
- 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
- 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
- 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
- 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
-};
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_clen_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
-};
-
-/* tables used for data extraction. */
-static const uint16_t pkzip_len_base[] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
-};
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_slen_bits[] = {
- 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
-};
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_len_code[] = {
- 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
-};
-
-/* tables used for data extraction. */
-static const uint8_t pkzip_bits_asc[] = {
- 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
- 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
- 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
- 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
- 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
- 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
- 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
-};
-
-/* tables used for data extraction. */
-static const uint16_t pkzip_code_asc[] = {
- 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
- 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
- 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
- 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
- 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
- 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
- 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
- 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
- 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
- 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
- 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
- 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
- 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
- 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
- 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
- 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
- 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
- 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
- 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
- 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
- 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
- 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
- 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
- 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
- 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
- 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
- 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
- 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
- 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
- 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
- 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
- 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
-};
-
-/* local unused variables. */
-char pkware_copyright[] = "PKWARE Data Compression Library for Win32\r\n"
- "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
- "Patent No. 5,051,745\r\n"
- "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
- "Version 1.11\r\n";
-
-/* skips given number of bits. */
-static int32_t skip_bit(pkzip_cmp_s *mpq_pkzip, uint32_t bits) {
-
- /* check if number of bits required is less than number of bits in the buffer. */
- if (bits <= mpq_pkzip->extra_bits) {
- mpq_pkzip->extra_bits -= bits;
- mpq_pkzip->bit_buf >>= bits;
- return 0;
- }
-
- /* load input buffer if necessary. */
- mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits;
- if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) {
- mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
- if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) {
- return 1;
- }
- mpq_pkzip->in_pos = 0;
- }
-
- /* update bit buffer. */
- mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8);
- mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits);
- mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8;
-
- /* if no error was found, return zero. */
- return 0;
-}
-
-/* this function generate the decode tables used for decryption. */
-static void generate_tables_decode(int32_t count, uint8_t *bits, const uint8_t *code, uint8_t *buf2) {
-
- /* some common variables. */
- int32_t i;
-
- /* EBX - count */
- for (i = count-1; i >= 0; i--) {
-
- /* some common variables. */
- uint32_t idx1 = code[i];
- uint32_t idx2 = 1 << bits[i];
-
- /* loop until table is ready. */
- do {
- buf2[idx1] = (uint8_t)i;
- idx1 += idx2;
- } while (idx1 < 0x100);
- }
-}
-
-/* this function generate the tables for ascii decompression. */
-static void generate_tables_ascii(pkzip_cmp_s *mpq_pkzip) {
-
- /* some common variables. */
- const uint16_t *code_asc = &pkzip_code_asc[0xFF];
- uint32_t acc;
- uint32_t add;
- uint16_t count;
-
- /* loop through ascii table. */
- for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) {
- uint8_t *bits_asc = mpq_pkzip->bits_asc + count;
- uint8_t bits_tmp = *bits_asc;
-
- /* check if byte is finished. */
- if (bits_tmp <= 8) {
- add = (1 << bits_tmp);
- acc = *code_asc;
- do {
- mpq_pkzip->offs_2c34[acc] = (uint8_t)count;
- acc += add;
- } while (acc < 0x100);
- } else {
- if ((acc = (*code_asc & 0xFF)) != 0) {
- mpq_pkzip->offs_2c34[acc] = 0xFF;
- if (*code_asc & 0x3F) {
-
- /* decrease bit by four. */
- bits_tmp -= 4;
- *bits_asc = bits_tmp;
- add = (1 << bits_tmp);
- acc = *code_asc >> 4;
- do {
- mpq_pkzip->offs_2d34[acc] = (uint8_t)count;
- acc += add;
- } while (acc < 0x100);
- } else {
-
- /* decrease bit by six. */
- bits_tmp -= 6;
- *bits_asc = bits_tmp;
- add = (1 << bits_tmp);
- acc = *code_asc >> 6;
- do {
- mpq_pkzip->offs_2e34[acc] = (uint8_t)count;
- acc += add;
- } while (acc < 0x80);
- }
- } else {
-
- /* decrease bit by eight. (one byte) */
- bits_tmp -= 8;
- *bits_asc = bits_tmp;
- add = (1 << bits_tmp);
- acc = *code_asc >> 8;
- do {
- mpq_pkzip->offs_2eb4[acc] = (uint8_t)count;
- acc += add;
- } while (acc < 0x100);
- }
- }
- }
-}
-
-/*
- * decompress the imploded data using coded literals.
- *
- * returns: 0x000 - 0x0FF : one byte from compressed file.
- * 0x100 - 0x305 : copy previous block. (0x100 = 1 byte)
- * 0x306 : out of buffer?
- */
-static uint32_t decode_literal(pkzip_cmp_s *mpq_pkzip) {
-
- /* number of bits to skip. */
- uint32_t bits;
-
- /* position in buffers. */
- uint32_t value;
-
- /* check if bit the current buffer is set, if not return the next byte. */
- if (mpq_pkzip->bit_buf & 1) {
-
- /* skip current bit in the buffer. */
- if (skip_bit(mpq_pkzip, 1)) {
- return 0x306;
- }
-
- /* the next bits are position in buffers. */
- value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)];
-
- /* get number of bits to skip. */
- if (skip_bit(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
- return 0x306;
- }
-
- /* check bits. */
- if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
-
- /* some common variables. */
- uint32_t val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
-
- /* check if we should skip one bit. */
- if (skip_bit(mpq_pkzip, bits)) {
-
- /* check position if we should skip the bit. */
- if ((value + val2) != 0x10E) {
- return 0x306;
- }
- }
-
- /* fill values. */
- value = mpq_pkzip->len_base[value] + val2;
- }
-
- /* return number of bytes to repeat. */
- return value + 0x100;
- }
-
- /* skip one bit. */
- if (skip_bit(mpq_pkzip, 1)) {
- return 0x306;
- }
-
- /* check the binary compression type, read 8 bits and return them as one byte. */
- if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
-
- /* fill values. */
- value = mpq_pkzip->bit_buf & 0xFF;
-
- /* check if we should skip one bit. */
- if (skip_bit(mpq_pkzip, 8)) {
- return 0x306;
- }
-
- /* return value from bit buffer. */
- return value;
- }
-
- /* check if ascii compression is used. */
- if (mpq_pkzip->bit_buf & 0xFF) {
-
- /* fill values. */
- value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
-
- /* check value. */
- if (value == 0xFF) {
- if (mpq_pkzip->bit_buf & 0x3F) {
-
- /* check if four bits are in bit buffer for skipping. */
- if (skip_bit(mpq_pkzip, 4)) {
- return 0x306;
- }
-
- /* fill values. */
- value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
- } else {
-
- /* check if six bits are in bit buffer for skipping. */
- if (skip_bit(mpq_pkzip, 6)) {
- return 0x306;
- }
-
- /* fill values. */
- value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
- }
- }
- } else {
-
- /* check if eight bits are in bit buffer for skipping. */
- if (skip_bit(mpq_pkzip, 8)) {
- return 0x306;
- }
-
- /* fill values. */
- value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
- }
-
- /* return out of buffer error (0x306) or position in buffer. */
- return skip_bit(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
-}
-
-/* this function retrieves the number of bytes to move back. */
-static uint32_t decode_distance(pkzip_cmp_s *mpq_pkzip, uint32_t length) {
-
- /* some common variables. */
- uint32_t pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
-
- /* number of bits to skip. */
- uint32_t skip = mpq_pkzip->dist_bits[pos];
-
- /* skip the appropriate number of bits. */
- if (skip_bit(mpq_pkzip, skip) == 1) {
- return 0;
- }
-
- /* check if length is two. */
- if (length == 2) {
- pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
-
- /* skip the bits. */
- if (skip_bit(mpq_pkzip, 2) == 1) {
- return 0;
- }
- } else {
- pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask);
-
- /* skip the bits */
- if (skip_bit(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
- return 0;
- }
- }
-
- /* return the bytes to move back. */
- return pos + 1;
-}
-
-/*
- * function loads data from the input buffer used by mpq_pkzip
- * "implode" and "explode" function as user defined callback and
- * returns number of bytes loaded.
- *
- * char *buf - pointer to a buffer where to store loaded data.
- * uint32_t *size - maximum number of bytes to read.
- * void *param - custom pointer, parameter of implode/explode.
- */
-static uint32_t data_read_input(char *buf, uint32_t *size, void *param) {
-
- /* some common variables. */
- pkzip_data_s *info = (pkzip_data_s *)param;
- uint32_t max_avail = (info->in_bytes - info->in_pos);
- uint32_t to_read = *size;
-
- /* check the case when not enough data available. */
- if (to_read > max_avail) {
- to_read = max_avail;
- }
-
- /* load data and increment offsets. */
- memcpy(buf, info->in_buf + info->in_pos, to_read);
- info->in_pos += to_read;
-
- /* return bytes read. */
- return to_read;
-}
-
-/*
- * function for store output data used by mpq_pkzip "implode" and
- * "explode" as userdefined callback.
- *
- * char *buf - pointer to data to be written.
- * uint32_t *size - number of bytes to write.
- * void *param - custom pointer, parameter of implode/explode.
- */
-static void data_write_output(char *buf, uint32_t *size, void *param) {
-
- /* some common variables. */
- pkzip_data_s *info = (pkzip_data_s *)param;
- uint32_t max_write = (info->max_out - info->out_pos);
- uint32_t to_write = *size;
-
- /* check the case when not enough space in the output buffer. */
- if (to_write > max_write) {
- to_write = max_write;
- }
-
- /* write output data and increments offsets. */
- memcpy(info->out_buf + info->out_pos, buf, to_write);
- info->out_pos += to_write;
-}
-
-/* this function extract the data from input stream. */
-static uint32_t expand(pkzip_cmp_s *mpq_pkzip) {
-
- /* number of bytes to copy. */
- uint32_t copy_bytes;
-
- /* one byte from compressed file. */
- uint32_t one_byte;
-
- /* some common variables. */
- uint32_t result;
-
- /* initialize output buffer position. */
- mpq_pkzip->out_pos = 0x1000;
-
- /* check if end of data or error, so terminate decompress. */
- while ((result = one_byte = decode_literal(mpq_pkzip)) < 0x305) {
-
- /* check if one byte is greater than 0x100, which means 'repeat n - 0xFE bytes'. */
- if (one_byte >= 0x100) {
-
- /* ECX */
- uint8_t *source;
-
- /* EDX */
- uint8_t *target;
-
- /* some common variables. */
- uint32_t copy_length = one_byte - 0xFE;
- uint32_t move_back;
-
- /* get length of data to copy. */
- if ((move_back = decode_distance(mpq_pkzip, copy_length)) == 0) {
- result = 0x306;
- break;
- }
-
- /* target and source pointer. */
- target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos];
- source = target - move_back;
- mpq_pkzip->out_pos += copy_length;
-
- /* copy until nothing left. */
- while (copy_length-- > 0) {
- *target++ = *source++;
- }
- } else {
-
- /* byte is 0x100 great, so add one byte. */
- mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (uint8_t)one_byte;
- }
-
- /* check if number of extracted bytes has reached 1/2 of output buffer, so flush output buffer. */
- if (mpq_pkzip->out_pos >= 0x2000) {
-
- /* copy decompressed data into user buffer. */
- copy_bytes = 0x1000;
- mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
-
- /* check if there are some data left, keep them alive. */
- memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000);
- mpq_pkzip->out_pos -= 0x1000;
- }
- }
-
- /* copy the rest. */
- copy_bytes = mpq_pkzip->out_pos - 0x1000;
- mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
-
- /* return copied bytes. */
- return result;
-}
-
-/* this function explode the data stream. */
-uint32_t libmpq__do_decompress_pkzip(uint8_t *work_buf, void *param) {
-
- /* some common variables. */
- pkzip_cmp_s *mpq_pkzip = (pkzip_cmp_s *)work_buf;
-
- /* set the whole work buffer to zeros. */
- memset(mpq_pkzip, 0, sizeof(pkzip_cmp_s));
-
- /* initialize work struct and load compressed data. */
- mpq_pkzip->read_buf = data_read_input;
- mpq_pkzip->write_buf = data_write_output;
- mpq_pkzip->param = param;
- mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
- mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param);
-
- /* check if we have pkzip data. */
- if (mpq_pkzip->in_bytes <= 4) {
- return LIBMPQ_PKZIP_CMP_BAD_DATA;
- }
-
- /* get the compression type. */
- mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0];
-
- /* get the dictionary size. */
- mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1];
-
- /* initialize 16-bit bit buffer. */
- mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2];
-
- /* extra (over 8) bits. */
- mpq_pkzip->extra_bits = 0;
-
- /* position in input buffer. */
- mpq_pkzip->in_pos = 3;
-
- /* check if valid dictionary size. */
- if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
- return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
- }
-
- /* shifted by 'sar' instruction. */
- mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits);
-
- /* check if we are using binary compression. */
- if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
-
- /* check if we are using ascii compression. */
- if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
- return LIBMPQ_PKZIP_CMP_INV_MODE;
- }
-
- /* create ascii buffer. */
- memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
- generate_tables_ascii(mpq_pkzip);
- }
-
- /* create the tables for decode. */
- memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
- generate_tables_decode(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
-
- /* create the tables for decode. */
- memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits));
- memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base));
- memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits));
- generate_tables_decode(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
-
- /* check if data extraction works. */
- if (expand(mpq_pkzip) != 0x306) {
- return LIBMPQ_PKZIP_CMP_NO_ERROR;
- }
-
- /* something failed, so return error. */
- return LIBMPQ_PKZIP_CMP_ABORT;
-}
diff --git a/dep/libmpq/libmpq/explode.h b/dep/libmpq/libmpq/explode.h
deleted file mode 100644
index 1d14dfc0e0a..00000000000
--- a/dep/libmpq/libmpq/explode.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * explode.h -- header file for pkware data decompression library
- * used by mpq-tools.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This source was adepted from the C++ version of pklib.h included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _EXPLODE_H
-#define _EXPLODE_H
-
-/* define compression constants and return values. */
-#define LIBMPQ_PKZIP_CMP_BINARY 0 /* binary compression. */
-#define LIBMPQ_PKZIP_CMP_ASCII 1 /* ascii compression. */
-#define LIBMPQ_PKZIP_CMP_NO_ERROR 0
-#define LIBMPQ_PKZIP_CMP_INV_DICTSIZE 1
-#define LIBMPQ_PKZIP_CMP_INV_MODE 2
-#define LIBMPQ_PKZIP_CMP_BAD_DATA 3
-#define LIBMPQ_PKZIP_CMP_ABORT 4
-
-#include "pack_begin.h"
-/* compression structure. */
-typedef struct {
- uint32_t offs0000; /* 0000 - start. */
- uint32_t cmp_type; /* 0004 - compression type (binary or ascii). */
- uint32_t out_pos; /* 0008 - position in output buffer. */
- uint32_t dsize_bits; /* 000C - dict size (4, 5, 6 for 0x400, 0x800, 0x1000). */
- uint32_t dsize_mask; /* 0010 - dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000). */
- uint32_t bit_buf; /* 0014 - 16-bit buffer for processing input data. */
- uint32_t extra_bits; /* 0018 - number of extra (above 8) bits in bit buffer. */
- uint32_t in_pos; /* 001C - position in in_buf. */
- uint32_t in_bytes; /* 0020 - number of bytes in input buffer. */
- void *param; /* 0024 - custom parameter. */
- uint32_t (*read_buf)(char *buf, uint32_t *size, void *param); /* 0028 offset.*/
- void (*write_buf)(char *buf, uint32_t *size, void *param); /* 002C offset. */
- uint8_t out_buf[0x2000]; /* 0030 - output circle buffer, starting position is 0x1000. */
- uint8_t offs_2030[0x204]; /* 2030 - whats that? */
- uint8_t in_buf[0x800]; /* 2234 - buffer for data to be decompressed. */
- uint8_t pos1[0x100]; /* 2A34 - positions in buffers. */
- uint8_t pos2[0x100]; /* 2B34 - positions in buffers. */
- uint8_t offs_2c34[0x100]; /* 2C34 - buffer. */
- uint8_t offs_2d34[0x100]; /* 2D34 - buffer. */
- uint8_t offs_2e34[0x80]; /* 2EB4 - buffer. */
- uint8_t offs_2eb4[0x100]; /* 2EB4 - buffer. */
- uint8_t bits_asc[0x100]; /* 2FB4 - buffer. */
- uint8_t dist_bits[0x40]; /* 30B4 - numbers of bytes to skip copied block length. */
- uint8_t slen_bits[0x10]; /* 30F4 - numbers of bits for skip copied block length. */
- uint8_t clen_bits[0x10]; /* 3104 - number of valid bits for copied block. */
- uint16_t len_base[0x10]; /* 3114 - buffer. */
-} PACK_STRUCT pkzip_cmp_s;
-#include "pack_end.h"
-
-/* data structure. */
-typedef struct {
- uint8_t *in_buf; /* pointer to input data buffer. */
- uint32_t in_pos; /* current offset in input data buffer. */
- int32_t in_bytes; /* number of bytes in the input buffer. */
- uint8_t *out_buf; /* pointer to output data buffer. */
- uint32_t out_pos; /* position in the output buffer. */
- int32_t max_out; /* maximum number of bytes in the output buffer. */
-} pkzip_data_s;
-
-/* decompress the stream using pkzip compression. */
-uint32_t libmpq__do_decompress_pkzip(
- uint8_t *work_buf,
- void *param
-);
-
-#endif /* _EXPLODE_H */
diff --git a/dep/libmpq/libmpq/extract.c b/dep/libmpq/libmpq/extract.c
deleted file mode 100644
index 11de1071683..00000000000
--- a/dep/libmpq/libmpq/extract.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * extract.c -- global extracting function for all known file compressions
- * in a mpq archive.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* generic includes. */
-#include <stdlib.h>
-#include <string.h>
-
-/* zlib includes. */
-#include <zlib.h>
-#include <bzlib.h>
-
-/* libmpq main includes. */
-#include "mpq.h"
-
-/* libmpq generic includes. */
-#include "explode.h"
-#include "extract.h"
-#include "huffman.h"
-#include "wave.h"
-
-/* table with decompression bits and functions. */
-static decompress_table_s dcmp_table[] = {
- {LIBMPQ_COMPRESSION_HUFFMAN, libmpq__decompress_huffman}, /* decompression using huffman trees. */
- {LIBMPQ_COMPRESSION_ZLIB, libmpq__decompress_zlib}, /* decompression with the zlib library. */
- {LIBMPQ_COMPRESSION_PKZIP, libmpq__decompress_pkzip}, /* decompression with pkware data compression library. */
- {LIBMPQ_COMPRESSION_BZIP2, libmpq__decompress_bzip2}, /* decompression with bzip2 library. */
- {LIBMPQ_COMPRESSION_WAVE_MONO, libmpq__decompress_wave_mono}, /* decompression for mono waves. */
- {LIBMPQ_COMPRESSION_WAVE_STEREO, libmpq__decompress_wave_stereo} /* decompression for stereo waves. */
-};
-
-/* this function decompress a stream using huffman algorithm. */
-int32_t libmpq__decompress_huffman(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* TODO: make typdefs of this structs? */
- /* some common variables. */
- int32_t tb = 0;
- struct huffman_tree_s *ht;
- struct huffman_input_stream_s *is;
-
- /* allocate memory for the huffman tree. */
- if ((ht = malloc(sizeof(struct huffman_tree_s))) == NULL ||
- (is = malloc(sizeof(struct huffman_input_stream_s))) == NULL) {
-
- /* memory allocation problem. */
- return LIBMPQ_ERROR_MALLOC;
- }
-
- /* cleanup structures. */
- memset(ht, 0, sizeof(struct huffman_tree_s));
- memset(is, 0, sizeof(struct huffman_input_stream_s));
-
- /* initialize input stream. */
- is->bit_buf = *(uint32_t *)in_buf;
- in_buf += sizeof(int32_t);
- is->in_buf = (uint8_t *)in_buf;
- is->bits = 32;
-
-// TODO: add all the mallocs to init function and add function libmpq__huffman_tree_free() */
-// if ((result = libmpq__huffman_tree_init(ht, LIBMPQ_HUFF_DECOMPRESS)) < 0) {
-//
-// /* something on zlib initialization failed. */
-// return LIBMPQ_ERROR_UNPACK;
-// }
-
- /* initialize the huffman tree for decompression. */
- libmpq__huffman_tree_init(ht, LIBMPQ_HUFF_DECOMPRESS);
-
- /* save the number of copied bytes. */
- tb = libmpq__do_decompress_huffman(ht, is, out_buf, out_size);
-
- /* free structures. */
- free(is);
- free(ht);
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using zlib algorithm. */
-int32_t libmpq__decompress_zlib(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t result = 0;
- int32_t tb = 0;
- z_stream z;
-
- /* fill the stream structure for zlib. */
- z.next_in = (Bytef *)in_buf;
- z.avail_in = (uInt)in_size;
- z.total_in = in_size;
- z.next_out = (Bytef *)out_buf;
- z.avail_out = (uInt)out_size;
- z.total_out = 0;
- z.zalloc = NULL;
- z.zfree = NULL;
-
- /* initialize the decompression structure, storm.dll uses zlib version 1.1.3. */
- if ((result = inflateInit(&z)) != Z_OK) {
-
- /* something on zlib initialization failed. */
- return result;
- }
-
- /* call zlib to decompress the data. */
- if ((result = inflate(&z, Z_FINISH)) != Z_STREAM_END) {
-
- /* something on zlib decompression failed. */
- return result;
- }
-
- /* save transferred bytes. */
- tb = z.total_out;
-
- /* cleanup zlib. */
- if ((result = inflateEnd(&z)) != Z_OK) {
-
- /* something on zlib finalization failed. */
- return result;
- }
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using pkzip algorithm. */
-int32_t libmpq__decompress_pkzip(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t tb = 0;
- uint8_t *work_buf;
- pkzip_data_s info;
-
- /* allocate memory for pkzip data structure. */
- if ((work_buf = malloc(sizeof(pkzip_cmp_s))) == NULL) {
-
- /* memory allocation problem. */
- return LIBMPQ_ERROR_MALLOC;
- }
-
- /* cleanup. */
- memset(work_buf, 0, sizeof(pkzip_cmp_s));
-
- /* fill data information structure. */
- info.in_buf = in_buf;
- info.in_pos = 0;
- info.in_bytes = in_size;
- info.out_buf = out_buf;
- info.out_pos = 0;
- info.max_out = out_size;
-
- /* do the decompression. */
- if ((tb = libmpq__do_decompress_pkzip(work_buf, &info)) < 0) {
-
- /* free working buffer. */
- free(work_buf);
-
- /* something failed on pkzip decompression. */
- return tb;
- }
-
- /* save transferred bytes. */
- tb = info.out_pos;
-
- /* free working buffer. */
- free(work_buf);
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using bzip2 library. */
-int32_t libmpq__decompress_bzip2(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t result = 0;
- int32_t tb = 0;
- bz_stream strm;
-
- /* initialize the bzlib decompression. */
- strm.bzalloc = NULL;
- strm.bzfree = NULL;
-
- /* initialize the structure. */
- if ((result = BZ2_bzDecompressInit(&strm, 0, 0)) != BZ_OK) {
-
- /* something on bzlib initialization failed. */
- return result;
- }
-
- /* fill the stream structure for bzlib. */
- strm.next_in = (char *)in_buf;
- strm.avail_in = in_size;
- strm.next_out = (char *)out_buf;
- strm.avail_out = out_size;
-
- /* do the decompression. */
- while (BZ2_bzDecompress(&strm) != BZ_STREAM_END);
-
- /* save transferred bytes. */
- tb = strm.total_out_lo32;
-
- /* cleanup of bzip stream. */
- BZ2_bzDecompressEnd(&strm);
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using wave algorithm. (1 channel) */
-int32_t libmpq__decompress_wave_mono(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t tb = 0;
-
- /* save the number of copied bytes. */
- if ((tb = libmpq__do_decompress_wave(out_buf, out_size, in_buf, in_size, 1)) < 0) {
-
- /* something on wave decompression failed. */
- return tb;
- }
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using wave algorithm. (2 channels) */
-int32_t libmpq__decompress_wave_stereo(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t tb = 0;
-
- /* save the number of copied bytes. */
- if ((tb = libmpq__do_decompress_wave(out_buf, out_size, in_buf, in_size, 2)) < 0) {
-
- /* something on wave decompression failed. */
- return tb;
- }
-
- /* return transferred bytes. */
- return tb;
-}
-
-/* this function decompress a stream using a combination of the other compression algorithm. */
-int32_t libmpq__decompress_multi(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
-
- /* some common variables. */
- int32_t tb = 0;
- uint32_t count = 0;
- uint32_t entries = (sizeof(dcmp_table) / sizeof(decompress_table_s));
- uint8_t *temp_buf = NULL;
- uint8_t *work_buf = 0;
- uint8_t decompress_flag, decompress_unsupp;
- uint32_t i;
-
- /* get applied compression types. */
- decompress_flag = decompress_unsupp = *in_buf++;
-
- /* decrement data size. */
- in_size--;
-
- /* search decompression table type and get all types of compression. */
- for (i = 0; i < entries; i++) {
-
- /* check if have to apply this decompression. */
- if (decompress_flag & dcmp_table[i].mask) {
-
- /* increase counter for used compression algorithms. */
- count++;
- /* this algorithm is supported, remove from unsupp mask */
- decompress_unsupp &= ~dcmp_table[i].mask;
- }
- }
-
- /* check if there is some method unhandled. (e.g. compressed by future versions) */
- if (decompress_unsupp) {
-
- /* compression type is unknown and we need to implement it. :) */
- return LIBMPQ_ERROR_UNPACK;
- }
-
- /* if multiple decompressions should be made, we need temporary buffer for the data. */
- if (count > 1) {
-
- /* allocate memory for temporary buffer. */
- if ((temp_buf = malloc(out_size)) == NULL) {
-
- /* memory allocation problem. */
- return LIBMPQ_ERROR_MALLOC;
- }
-
- /* cleanup. */
- memset(temp_buf, 0, out_size);
- }
-
- /* apply all decompressions. */
- for (i = 0, count = 0; i < entries; i++) {
-
- /* check if not used this kind of compression. */
- if (decompress_flag & dcmp_table[i].mask) {
-
- /* if multiple decompressions should be made, we need temporary buffer for the data. */
- if (count == 0) {
-
- /* use output buffer as working buffer. */
- work_buf = out_buf;
- } else {
-
- /* use temporary buffer as working buffer. */
- work_buf = temp_buf;
- }
-
- /* decompress buffer using corresponding function. */
- if ((tb = dcmp_table[i].decompress(in_buf, in_size, work_buf, out_size)) < 0) {
-
- /* free temporary buffer. */
- free(temp_buf);
-
- /* something on decompression failed. */
- return tb;
- }
-
- /* move output size to source size for next compression. */
- in_size = out_size;
- in_buf = work_buf;
-
- /* increase counter. */
- count++;
- }
- }
-
- /* if output buffer is not the same like target buffer, we have to copy data (this will happen on multiple decompressions). */
- if (work_buf != out_buf) {
-
- /* copy buffer. */
- memcpy(out_buf, in_buf, out_size);
- }
-
- /* free temporary buffer. */
- free(temp_buf);
-
- /* return transferred bytes. */
- return tb;
-}
diff --git a/dep/libmpq/libmpq/extract.h b/dep/libmpq/libmpq/extract.h
deleted file mode 100644
index d6ea794f162..00000000000
--- a/dep/libmpq/libmpq/extract.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * extract.h -- header for the extraction functions used by mpq-tools.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _EXTRACT_H
-#define _EXTRACT_H
-
-/* define compression types for multilpe compressions. */
-#define LIBMPQ_COMPRESSION_HUFFMAN 0x01 /* huffman compression. (used on wave files only and introduced in starcraft) */
-#define LIBMPQ_COMPRESSION_ZLIB 0x02 /* zlib compression. (introduced in warcraft 3) */
-#define LIBMPQ_COMPRESSION_PKZIP 0x08 /* pkware dcl compression. (first used compression algorithm) */
-#define LIBMPQ_COMPRESSION_BZIP2 0x10 /* bzip compression. (introduced in warcraft 3 - the frozen throne) */
-#define LIBMPQ_COMPRESSION_WAVE_MONO 0x40 /* adpcm 4:1 compression. (introduced in starcraft) */
-#define LIBMPQ_COMPRESSION_WAVE_STEREO 0x80 /* adpcm 4:1 compression. (introduced in starcraft) */
-
-/*
- * table for decompression functions, return value for all functions
- * is the transferred data size or one of the following error constants:
- *
- * LIBMPQ_ERROR_MALLOC
- * LIBMPQ_ERROR_DECOMPRESS
- */
-typedef int32_t (*DECOMPRESS)(uint8_t *, uint32_t, uint8_t *, uint32_t);
-typedef struct {
- uint32_t mask; /* decompression bit. */
- DECOMPRESS decompress; /* decompression function. */
-} decompress_table_s;
-
-/*
- * huffman decompression routine, the in_size parameter is not used,
- * but needs to be specified due to compatibility reasons.
- *
- * 1500F5F0
- */
-extern int32_t libmpq__decompress_huffman(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using zlib. */
-extern int32_t libmpq__decompress_zlib(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using pkzip. */
-extern int32_t libmpq__decompress_pkzip(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using bzip2. */
-extern int32_t libmpq__decompress_bzip2(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using wave. (1 channel) */
-extern int32_t libmpq__decompress_wave_mono(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using wave. (2 channels) */
-extern int32_t libmpq__decompress_wave_stereo(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-/* decompression using multiple of the above algorithm. */
-extern int32_t libmpq__decompress_multi(
- uint8_t *in_buf,
- uint32_t in_size,
- uint8_t *out_buf,
- uint32_t out_size
-);
-
-#endif /* _EXTRACT_H */
diff --git a/dep/libmpq/libmpq/huffman.c b/dep/libmpq/libmpq/huffman.c
deleted file mode 100644
index 8fc87be2f60..00000000000
--- a/dep/libmpq/libmpq/huffman.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- * huffman.c -- functions do decompress files in mpq files which
- * uses a modified huffman version.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * Differences between C++ and C version:
- *
- * - Removed the object oriented stuff.
- * - Replaced the goto things with some better C code.
- *
- * This source was adepted from the C++ version of huffman.cpp included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- * ShadowFlare <BlakFlare@hotmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* generic includes. */
-#include <stdlib.h>
-#include <string.h>
-
-/* libmpq main includes. */
-#include "mpq.h"
-#include "mpq-internal.h"
-
-/* libmpq generic includes. */
-#include "huffman.h"
-
-/* tables for huffman tree. */
-static const uint8_t table_1502A630[] = {
-
- /* data for compression type 0x00. */
- 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00,
-
- /* data for compression type 0x01. */
- 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
- 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
- 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
- 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
- 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
- 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
- 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
- 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
- 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
- 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
- 0x00, 0x00,
-
- /* data for compression type 0x02. */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
- 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
- 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
- 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
- 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
- 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* data for compression type 0x03. */
- 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
- 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
- 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
- 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
- 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
- 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
- 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
- 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
- 0x00, 0x00,
-
- /* data for compression type 0x04. */
- 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* data for compression type 0x05. */
- 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
- 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
- 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
- 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* data for compression type 0x06. */
- 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* data for compression type 0x07. */
- 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* data for compression type 0x08. */
- 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
- 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
- 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-/* this function insert an item to a huffman tree. */
-void libmpq__huffman_insert_item(struct huffman_tree_item_s **p_item, struct huffman_tree_item_s *item, uint32_t where, struct huffman_tree_item_s *item2) {
-
- /* EDI - next to the first item. */
- struct huffman_tree_item_s *next = item->next;
-
- /* ESI - prev to the first item. */
- struct huffman_tree_item_s *prev = item->prev;
-
- /* pointer to previous item. */
- struct huffman_tree_item_s *prev2;
-
- /* pointer to next item. */
- long next2;
-
- /* check the first item already has next one. */
- if (next != 0) {
-
- /* check if previous item exist. */
- if (PTR_INT(prev) < 0) {
-
- /* return previous item. */
- prev = PTR_NOT(prev);
- } else {
-
- /* add item. */
- prev += (item - next->prev);
- }
-
- /* 150083C1 - remove the item from the tree. */
- prev->next = next;
- next->prev = prev;
-
- /* invalidate prev and next pointer. */
- item->next = 0;
- item->prev = 0;
- }
-
- /* EDX - check if the second item is not entered. */
- if (item2 == NULL) {
-
- /* take the first tree item. */
- item2 = PTR_PTR(&p_item[1]);
- }
-
- /* check if items should be switched or new one inserted. */
- switch (where) {
- case SWITCH_ITEMS:
-
- /* item2->next (pointer to pointer to first). */
- item->next = item2->next;
- item->prev = item2->next->prev;
- item2->next->prev = item;
-
- /* set the first item. */
- item2->next = item;
-
- /* return from function. */
- return;
- case INSERT_ITEM:
-
- /* set next item (or pointer to pointer to first item) - insert as last item. */
- item->next = item2;
-
- /* set previous item (or last item in the tree). */
- item->prev = item2->prev;
-
- /* usually NULL. */
- next2 = PTR_INT(p_item[0]);
-
- /* previous item to the second (or last tree item). */
- prev2 = item2->prev;
-
- /* check if previous item is a valid pointer. */
- if (PTR_INT(prev2) < 0) {
-
- /* set values. */
- prev2 = PTR_NOT(prev);
- prev2->next = item;
-
- /* next after last item. */
- item2->prev = item;
-
- /* return from function. */
- return;
- }
-
- /* check if next item is empty. */
- if (next2 < 0) {
-
- /* set next item. */
- next2 = item2 - item2->next->prev;
- }
-
- /* add next item to previous one. */
- prev2 += next2;
- prev2->next = item;
-
- /* set the next and last item. */
- item2->prev = item;
-
- /* return from function. */
- return;
- default:
-
- /* nothing to do, so return from function. */
- return;
- }
-}
-
-/* 1500BC90 - remove item from huffman tree.*/
-void libmpq__huffman_remove_item(struct huffman_tree_item_s *hi) {
-
- /* EDX - some common variables. */
- struct huffman_tree_item_s *temp;
-
- /* check if next item is not empty. */
- if (hi->next != NULL) {
-
- /* fetch previous item. */
- temp = hi->prev;
-
- /* check if previous item is a pointer. */
- if (PTR_INT(temp) <= 0) {
- temp = PTR_NOT(temp);
- } else {
- temp += (hi - hi->next->prev);
- }
-
- /* reorganize tree. */
- temp->next = hi->next;
- hi->next->prev = hi->prev;
- hi->next = hi->prev = NULL;
- }
-}
-
-/* get previous huffman tree item. */
-struct huffman_tree_item_s *libmpq__huffman_previous_item(struct huffman_tree_item_s *hi, long value) {
-
- /* check if previous item exist. */
- if (PTR_INT(hi->prev) < 0) {
-
- /* return previous item. */
- return PTR_NOT(hi->prev);
- }
-
- /* check if something else should returned. */
- if (value < 0) {
-
- /* fetch previous item of next item. */
- value = hi - hi->next->prev;
- }
-
- /* return previous item with value. */
- return hi->prev + value;
-}
-
-/* get one bit from input stream. */
-uint32_t libmpq__huffman_get_1bit(struct huffman_input_stream_s *is) {
-
- /* some common variables. */
- uint32_t bit = (is->bit_buf & 1);
-
- /* shift bit right by one. */
- is->bit_buf >>= 1;
-
- /* check if we should extract bits. */
- if (--is->bits == 0) {
- is->bit_buf = *(uint32_t *)is->in_buf;
- is->in_buf += sizeof(int32_t);
- is->bits = 32;
- }
-
- /* return the bit. */
- return bit;
-}
-
-/* get 7 bits from the input stream. */
-uint32_t libmpq__huffman_get_7bit(struct huffman_input_stream_s *is) {
-
- /* check if we should extract bits. */
- if (is->bits <= 7) {
- is->bit_buf |= *(uint16_t *)is->in_buf << is->bits;
- is->in_buf += sizeof(int16_t);
- is->bits += 16;
- }
-
- /* get 7 bits from input stream. */
- return (is->bit_buf & 0x7F);
-}
-
-/* get the whole byte from the input stream. */
-uint32_t libmpq__huffman_get_8bit(struct huffman_input_stream_s *is) {
-
- /* some common variables. */
- uint32_t one_byte;
-
- /* check if we should extract bits. */
- if (is->bits <= 8) {
- is->bit_buf |= *(uint16_t *)is->in_buf << is->bits;
- is->in_buf += sizeof(int16_t);
- is->bits += 16;
- }
-
- /* fill values. */
- one_byte = (is->bit_buf & 0xFF);
- is->bit_buf >>= 8;
- is->bits -= 8;
-
- /* return the 8 bits. */
- return one_byte;
-}
-
-/* return struct for 1500E740. */
-struct huffman_tree_item_s *libmpq__huffman_call_1500E740(struct huffman_tree_s *ht) {
-
- /* EDX */
- struct huffman_tree_item_s *p_item1 = ht->item3058;
-
- /* EAX */
- struct huffman_tree_item_s *p_item2;
-
- /* some common variables. */
- struct huffman_tree_item_s *p_next;
- struct huffman_tree_item_s *p_prev;
- struct huffman_tree_item_s **pp_item;
-
- /* check if item is empty. */
- if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) {
-
- /* check if item is not empty. */
- if ((p_item2 = &ht->items0008[ht->items++]) != NULL) {
- p_item1 = p_item2;
- } else {
- p_item1 = ht->first;
- }
- } else {
- p_item1 = p_item2;
- }
-
- /* set next item. */
- p_next = p_item1->next;
-
- /* check if next item is not empty. */
- if (p_next != NULL) {
-
- /* set previous item. */
- p_prev = p_item1->prev;
-
- /* check if previous item is a valid pointer. */
- if (PTR_INT(p_prev) <= 0) {
- p_prev = PTR_NOT(p_prev);
- } else {
- p_prev += (p_item1 - p_item1->next->prev);
- }
-
- /* fill values. */
- p_prev->next = p_next;
- p_next->prev = p_prev;
- p_item1->next = NULL;
- p_item1->prev = NULL;
- }
-
- /* ESI */
- pp_item = &ht->first;
- p_item1->next = (struct huffman_tree_item_s *)pp_item;
- p_item1->prev = pp_item[1];
-
- /* EDI = ht->item305C - ECX */
- p_prev = pp_item[1];
-
- /* check if previous pointer is valid. */
- if (p_prev <= 0) {
-
- /* fill values. */
- p_prev = PTR_NOT(p_prev);
- p_prev->next = p_item1;
- p_prev->prev = p_item2;
- p_item2->parent = NULL;
- p_item2->child = NULL;
- } else {
-
- /* check if pointer is valid. */
- if (PTR_INT(ht->item305C) < 0) {
- p_prev += (struct huffman_tree_item_s *)pp_item - (*pp_item)->prev;
- } else {
- p_prev += PTR_INT(ht->item305C);
- }
-
- /* fill values. */
- p_prev->next = p_item1;
- pp_item[1] = p_item2;
- p_item2->parent = NULL;
- p_item2->child = NULL;
- }
-
- /* return item. */
- return p_item2;
-}
-
-/* return struct for 1500E820. */
-void libmpq__huffman_call_1500E820(struct huffman_tree_s *ht, struct huffman_tree_item_s *p_item) {
-
- /* EDI */
- struct huffman_tree_item_s *p_item1;
-
- /* EAX */
- struct huffman_tree_item_s *p_item2 = NULL;
-
- /* EDX */
- struct huffman_tree_item_s *p_item3;
-
- /* EBX */
- struct huffman_tree_item_s *p_prev;
-
- /* loop through parent items. */
- for (; p_item != NULL; p_item = p_item->parent) {
-
- /* increase byte counter. */
- p_item->byte_value++;
-
- /* loop through previous items. */
- for (p_item1 = p_item; ; p_item1 = p_prev) {
-
- /* set previous item. */
- p_prev = p_item1->prev;
-
- /* check if pointer is valid. */
- if (PTR_INT(p_prev) <= 0) {
- p_prev = NULL;
- break;
- }
-
- /* check if byte value of previous item is higher than actual item. */
- if (p_prev->byte_value >= p_item->byte_value) {
- break;
- }
- }
-
- /* check if previous item is same like actual item. */
- if (p_item1 == p_item) {
- continue;
- }
-
- /* check if next item is not empty, */
- if (p_item1->next != NULL) {
-
- /* fill values. */
- p_item2 = libmpq__huffman_previous_item(p_item1, -1);
- p_item2->next = p_item1->next;
- p_item1->next->prev = p_item1->prev;
- p_item1->next = NULL;
- p_item1->prev = NULL;
- }
-
- /* fill values. */
- p_item2 = p_item->next;
- p_item1->next = p_item2;
- p_item1->prev = p_item2->prev;
- p_item2->prev = p_item1;
- p_item->next = p_item1;
-
- /* check if both items are not empty. */
- if ((p_item2 = p_item1) != NULL) {
-
- /* fill values. */
- p_item2 = libmpq__huffman_previous_item(p_item, -1);
- p_item2->next = p_item->next;
- p_item->next->prev = p_item->prev;
- p_item->next = NULL;
- p_item->prev = NULL;
- }
-
- /* check if previous item is empty. */
- if (p_prev == NULL) {
- p_prev = PTR_PTR(&ht->first);
- }
-
- /* fill values. */
- p_item2 = p_prev->next;
- p_item->next = p_item2;
- p_item->prev = p_item2->prev;
- p_item2->prev = p_item;
- p_prev->next = p_item;
- p_item3 = p_item1->parent->child;
- p_item2 = p_item->parent;
-
- /* check if child item and parent item match. */
- if (p_item2->child == p_item) {
- p_item2->child = p_item1;
- }
-
- /* check if items match. */
- if (p_item3 == p_item1) {
- p_item1->parent->child = p_item;
- }
-
- /* fill values. */
- p_item2 = p_item->parent;
- p_item->parent = p_item1->parent;
- p_item1->parent = p_item2;
-
- /* increase counter. */
- ht->offs0004++;
- }
-}
-
-/* this function initialize a huffman tree. */
-void libmpq__huffman_tree_init(struct huffman_tree_s *ht, uint32_t cmp) {
-
- /* some common variables. */
- uint32_t count;
- struct huffman_tree_item_s *hi;
-
- /* clear links for all the items in the tree. */
- for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) {
- hi->next = hi->prev = NULL;
- }
-
- /* fill values. */
- ht->item3050 = NULL;
- ht->item3054 = PTR_PTR(&ht->item3054);
- ht->item3058 = PTR_NOT(ht->item3054);
- ht->item305C = NULL;
- ht->first = PTR_PTR(&ht->first);
- ht->last = PTR_NOT(ht->first);
- ht->offs0004 = 1;
- ht->items = 0;
-
- /* clear all huffman decompress items, do this only if preparing for decompression. */
- if (cmp == LIBMPQ_HUFF_DECOMPRESS) {
- for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress_s); count++) {
- ht->qd3474[count].offs00 = 0;
- }
- }
-}
-
-/* this function build a huffman tree, called with the first 8 bits loaded from input stream. */
-void libmpq__huffman_tree_build(struct huffman_tree_s *ht, uint32_t cmp_type) {
-
- /* [ESP+10] - the greatest character found in table. */
- uint32_t max_byte;
-
- /* [ESP+1C] - pointer to uint8_t in table_1502A630. */
- const uint8_t *byte_array;
-
- /* thats needed to replace the goto stuff from original source. :) */
- uint32_t found;
-
- /* [ESP+14] - Pointer to Huffman tree item pointer array. */
- struct huffman_tree_item_s **p_item;
- struct huffman_tree_item_s *child1;
-
- /* some common variables. */
- uint32_t i;
-
- /* ESI - loop while pointer has a negative value (last entry). */
- while (PTR_INT(ht->last) > 0) {
-
- /* EAX */
- struct huffman_tree_item_s *temp;
-
- /* ESI->next */
- if (ht->last->next != NULL) {
- libmpq__huffman_remove_item(ht->last);
- }
-
- /* [EDI+4] */
- ht->item3058 = PTR_PTR(&ht->item3054);
-
- /* EAX */
- ht->last->prev = ht->item3058;
- temp = libmpq__huffman_previous_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050));
- temp->next = ht->last;
- ht->item3054 = ht->last;
- }
-
- /* clear all pointers in huffman tree item array. */
- memset(ht->items306C, 0, sizeof(ht->items306C));
-
- /* greatest character found init to zero. */
- max_byte = 0;
-
- /* pointer to current entry in huffman tree item pointer array. */
- p_item = (struct huffman_tree_item_s **)&ht->items306C;
-
- /* ensure we have low 8 bits only. */
- cmp_type &= 0xFF;
-
- /* EDI also. */
- byte_array = table_1502A630 + cmp_type * 258;
-
- /* loop to build huffman tree. */
- for (i = 0; i < 0x100; i++, p_item++) {
-
- /* item to be created. */
- struct huffman_tree_item_s *item = ht->item3058;
- struct huffman_tree_item_s *p_item3 = ht->item3058;
- uint8_t one_byte = byte_array[i];
-
- /* skip all the bytes which are zero. */
- if (byte_array[i] == 0) {
- continue;
- }
-
- /* if not valid pointer, take the first available item in the array. */
- if (PTR_INT(item) <= 0) {
- item = &ht->items0008[ht->items++];
- }
-
- /* insert this item as the top of the tree. */
- libmpq__huffman_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
-
- /* invalidate child and parent. */
- item->parent = NULL;
- item->child = NULL;
-
- /* store pointer into pointer array. */
- *p_item = item;
-
- /* store counter. */
- item->dcmp_byte = i;
-
- /* store byte value. */
- item->byte_value = one_byte;
-
- /* check if byte is to big. */
- if (one_byte >= max_byte) {
-
- /* set max byte to highest value. */
- max_byte = one_byte;
-
- /* continue loop. */
- continue;
- }
-
- /* find the first item which has byte value greater than current one byte. */
- found = 0;
-
- /* EDI - Pointer to the last item. */
- if (PTR_INT((p_item3 = ht->last)) > 0) {
-
- /* 15006AF7 */
- if (p_item3 != NULL) {
-
- /* 15006AFB */
- do {
-
- /* check if we found item. */
- if (p_item3->byte_value >= one_byte) {
- found = 1;
- break;
- }
-
- /* switch to previous item. */
- p_item3 = p_item3->prev;
- } while (PTR_INT(p_item3) > 0);
- }
- }
-
- /* check if item was not found. */
- if (found == 0) {
- p_item3 = NULL;
- }
-
- /* 15006B09 */
- if (item->next != NULL) {
- libmpq__huffman_remove_item(item);
- }
-
- /* 15006B15 */
- if (p_item3 == NULL) {
- p_item3 = PTR_PTR(&ht->first);
- }
-
- /* 15006B1F */
- item->next = p_item3->next;
- item->prev = p_item3->next->prev;
- p_item3->next->prev = item;
- p_item3->next = item;
- }
-
- /* 15006B4A */
- for (; i < 0x102; i++) {
-
- /* EDI */
- struct huffman_tree_item_s **p_item2 = &ht->items306C[i];
-
- /* 15006B59 - ESI */
- struct huffman_tree_item_s *item2 = ht->item3058;
-
- /* check if item is a valid pointer. */
- if (PTR_INT(item2) <= 0) {
- item2 = &ht->items0008[ht->items++];
- }
-
- /* insert the item into tree. */
- libmpq__huffman_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL);
-
- /* 15006B89 */
- item2->dcmp_byte = i;
- item2->byte_value = 1;
- item2->parent = NULL;
- item2->child = NULL;
- *p_item2++ = item2;
- }
-
- /* 15006BAA - EDI - last item (first child to item). */
- if (PTR_INT((child1 = ht->last)) > 0) {
-
- /* EBP */
- struct huffman_tree_item_s *child2;
-
- /* ESI */
- struct huffman_tree_item_s *item;
-
- /* 15006BB8 */
- while (PTR_INT((child2 = child1->prev)) > 0) {
- if (PTR_INT((item = ht->item3058)) <= 0) {
- item = &ht->items0008[ht->items++];
- }
-
- /* 15006BE3 */
- libmpq__huffman_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
-
- /* 15006BF3 */
- item->parent = NULL;
- item->child = NULL;
-
- /*
- * EDX = child2->byte_value + child1->byte_value;
- * EAX = child1->byte_value;
- * ECX = max_byte; (the greatest character (0xFF usually))
- * item->byte_value (0x02 usually)
- */
- item->byte_value = child1->byte_value + child2->byte_value;
-
- /* previous item in the tree. */
- item->child = child1;
- child1->parent = item;
- child2->parent = item;
-
- /* EAX = item->byte_value */
- if (item->byte_value >= max_byte) {
- max_byte = item->byte_value;
- } else {
-
- /* EDI */
- struct huffman_tree_item_s *p_item2 = child2->prev;
- found = 0;
-
- /* check if item is a valid pointer. */
- if (PTR_INT(p_item2) > 0) {
-
- /* 15006C2D */
- do {
-
- /* check if we found item. */
- if (p_item2->byte_value >= item->byte_value) {
- found = 1;
- break;
- }
-
- /* switch to previous item. */
- p_item2 = p_item2->prev;
- } while (PTR_INT(p_item2) > 0);
- }
-
- /* check if item was not found. */
- if (found == 0) {
- p_item2 = NULL;
- }
-
- /* check if next item exist. */
- if (item->next != 0) {
-
- /* some common variables. */
- struct huffman_tree_item_s *temp4 = libmpq__huffman_previous_item(item, -1);
-
- /* zhe first item changed. */
- temp4->next = item->next;
-
- /* first->prev changed to negative value. */
- item->next->prev = item->prev;
- item->next = NULL;
- item->prev = NULL;
- }
-
- /* 15006C62 */
- if (p_item2 == NULL) {
- p_item2 = PTR_PTR(&ht->first);
- }
-
- /* set item with 0x100 byte value. */
- item->next = p_item2->next;
-
- /* set item with 0x17 byte value. */
- item->prev = p_item2->next->prev;
-
- /* changed prev of item with. */
- p_item2->next->prev = item;
- p_item2->next = item;
- }
-
- /* 15006C7B */
- if (PTR_INT((child1 = child2->prev)) <= 0) {
- break;
- }
- }
- }
-
- /* 15006C88 */
- ht->offs0004 = 1;
-}
-
-/* this function did the real decompression. */
-int32_t libmpq__do_decompress_huffman(struct huffman_tree_s *ht, struct huffman_input_stream_s *is, uint8_t *out_buf, uint32_t out_length) {
-
- /* some common variables. */
- uint32_t dcmp_byte = 0;
- uint8_t *out_pos = out_buf;
- uint32_t bit_count;
- struct huffman_decompress_s *qd;
- struct huffman_tree_item_s *p_item1;
- struct huffman_tree_item_s *p_item2;
-
- /* 8 bits loaded from input stream. */
- uint32_t n8bits;
-
- /* 7 bits loaded from input stream. */
- uint32_t n7bits;
-
- /* thats needed to replace the goto stuff from original source. :) */
- uint32_t found;
-
- /* can we use quick decompression */
- uint32_t has_qd;
-
- /* test the output length, must not be non zero. */
- if (out_length == 0) {
- return 0;
- }
-
- /* get the compression type from the input stream. */
- n8bits = libmpq__huffman_get_8bit(is);
-
- /* build the Huffman tree. */
- libmpq__huffman_tree_build(ht, n8bits);
-
- /* compression 8 bit or not? */
- ht->cmp0 = (n8bits == 0) ? TRUE : FALSE;
-
- /* loop until break. */
- for(;;) {
-
- /* get 7 bits from input stream. */
- n7bits = libmpq__huffman_get_7bit(is);
-
- /* try to use quick decompression, check huffman decompress struct for corresponding item. */
- qd = &ht->qd3474[n7bits];
-
- /* if there is a quick-pass possible (ebx). */
- has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE;
-
- /* if we can use quick decompress, use it. */
- if (has_qd) {
- found = 0;
- if (qd->bits > 7) {
- is->bit_buf >>= 7;
- is->bits -= 7;
- p_item1 = qd->p_item;
- found = 1;
- }
- if (found == 0) {
- is->bit_buf >>= qd->bits;
- is->bits -= qd->bits;
- dcmp_byte = qd->dcmp_byte;
- }
- } else {
- found = 1;
- p_item1 = ht->first->next->prev;
- if (PTR_INT(p_item1) <= 0) {
- p_item1 = NULL;
- }
- }
-
- /* check if item was found. */
- if (found == 1) {
- bit_count = 0;
- p_item2 = NULL;
-
- /* loop until tree has no deeper level. */
- do {
-
- /* move down by one level. */
- p_item1 = p_item1->child;
-
- /* check if current bit is set, move to previous. */
- if (libmpq__huffman_get_1bit(is)) {
- p_item1 = p_item1->prev;
- }
-
- /* check if we are at 7th bit, save current huffman tree item. */
- if (++bit_count == 7) {
- p_item2 = p_item1;
- }
- } while (p_item1->child != NULL);
-
- /* no quick decompression. :( */
- if (has_qd == FALSE) {
-
- /* check bit counter. */
- if (bit_count > 7) {
- qd->offs00 = ht->offs0004;
- qd->bits = bit_count;
- qd->p_item = p_item2;
- } else {
- uint32_t index = n7bits & (0xFFFFFFFF >> (32 - bit_count));
- uint32_t add = (1 << bit_count);
-
- /* loop through compression. */
- for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) {
- qd->offs00 = ht->offs0004;
- qd->bits = bit_count;
- qd->dcmp_byte = p_item1->dcmp_byte;
- }
- }
- }
-
- /* set compression byte. */
- dcmp_byte = p_item1->dcmp_byte;
- }
-
- /* check if huffman tree needs to be modified. */
- if (dcmp_byte == 0x101) {
-
- /* fill values. */
- n8bits = libmpq__huffman_get_8bit(is);
- p_item1 = (ht->last <= 0) ? NULL : ht->last;
- p_item2 = libmpq__huffman_call_1500E740(ht);
- p_item2->parent = p_item1;
- p_item2->dcmp_byte = p_item1->dcmp_byte;
- p_item2->byte_value = p_item1->byte_value;
- ht->items306C[p_item2->dcmp_byte] = p_item2;
- p_item2 = libmpq__huffman_call_1500E740(ht);
- p_item2->parent = p_item1;
- p_item2->dcmp_byte = n8bits;
- p_item2->byte_value = 0;
- ht->items306C[p_item2->dcmp_byte] = p_item2;
- p_item1->child = p_item2;
-
- /* call 1500E820. */
- libmpq__huffman_call_1500E820(ht, p_item2);
-
- /* check if compression is not set. */
- if (ht->cmp0 == 0) {
- libmpq__huffman_call_1500E820(ht, ht->items306C[n8bits]);
- }
-
- /* set compression byte. */
- dcmp_byte = n8bits;
- }
-
- /* check for compression. */
- if (dcmp_byte == 0x100) {
- break;
- }
-
- /* increase position by compression byte. */
- *out_pos++ = (uint8_t)dcmp_byte;
- if (--out_length == 0) {
- break;
- }
-
- /* check if compression is not set. */
- if (ht->cmp0) {
- libmpq__huffman_call_1500E820(ht, ht->items306C[dcmp_byte]);
- }
- }
-
- /* return copied bytes. */
- return (out_pos - out_buf);
-}
diff --git a/dep/libmpq/libmpq/huffman.h b/dep/libmpq/libmpq/huffman.h
deleted file mode 100644
index 6f691088fa0..00000000000
--- a/dep/libmpq/libmpq/huffman.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * huffman.h -- structures used for huffman compression.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This source was adepted from the C++ version of huffman.h included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- * ShadowFlare <BlakFlare@hotmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _HUFFMAN_H
-#define _HUFFMAN_H
-
-/* define huffman compression and decompression values. */
-#define LIBMPQ_HUFF_DECOMPRESS 0 /* we want to decompress using huffman trees. */
-
-/* define pointer conversions. */
-#define PTR_NOT(ptr) (struct huffman_tree_item_s *)(~(unsigned long)(ptr))
-#define PTR_PTR(ptr) ((struct huffman_tree_item_s *)(ptr))
-#define PTR_INT(ptr) (long)(ptr)
-
-/* define item handling. */
-#define INSERT_ITEM 1 /* insert item into huffman tree. */
-#define SWITCH_ITEMS 2 /* switch items isnide huffman tree. */
-
-/* input stream for huffman decompression. */
-struct huffman_input_stream_s {
- uint8_t *in_buf; /* 00 - input data. */
- uint32_t bit_buf; /* 04 - input bit buffer. */
- uint32_t bits; /* 08 - number of bits remaining in byte. */
-};
-
-/* huffman tree item. */
-struct huffman_tree_item_s {
- struct huffman_tree_item_s *next; /* 00 - pointer to next huffman tree item. */
- struct huffman_tree_item_s *prev; /* 04 - pointer to prev huffman tree item (< 0 if none). */
- uint32_t dcmp_byte; /* 08 - index of this item in item pointer array, decompressed byte value. */
- uint32_t byte_value; /* 0C - some byte value. */
- struct huffman_tree_item_s *parent; /* 10 - pointer to parent huffman tree item (NULL if none). */
- struct huffman_tree_item_s *child; /* 14 - pointer to child huffman tree item. */
-};
-
-/* structure used for quick decompression. */
-struct huffman_decompress_s {
- uint32_t offs00; /* 00 - 1 if resolved. */
- uint32_t bits; /* 04 - bit count. */
- union {
- uint32_t dcmp_byte; /* 08 - byte value for decompress (if bitCount <= 7). */
- struct huffman_tree_item_s *p_item; /* 08 - huffman tree item (if number of bits is greater than 7). */
- };
-};
-
-/* structure for huffman tree. */
-struct huffman_tree_s {
- uint32_t cmp0; /* 0000 - 1 if compression type 0. */
- uint32_t offs0004; /* 0004 - some flag. */
- struct huffman_tree_item_s items0008[0x203]; /* 0008 - huffman tree items. */
- struct huffman_tree_item_s *item3050; /* 3050 - always NULL? */
- struct huffman_tree_item_s *item3054; /* 3054 - pointer to huffman tree item. */
- struct huffman_tree_item_s *item3058; /* 3058 - pointer to huffman tree item (< 0 if invalid). */
- struct huffman_tree_item_s *item305C; /* 305C - usually NULL. */
- struct huffman_tree_item_s *first; /* 3060 - pointer to top (first) huffman tree item. */
- struct huffman_tree_item_s *last; /* 3064 - pointer to bottom (last) huffman tree item (< 0 if invalid). */
- uint32_t items; /* 3068 - number of used huffman tree items. */
- struct huffman_tree_item_s *items306C[0x102]; /* 306C - huffman tree item pointer array. */
- struct huffman_decompress_s qd3474[0x80]; /* 3474 - array for quick decompression. */
- uint8_t table_1502A630[]; /* some table to make struct size flexible. */
-};
-
-/* insert a new item into huffman tree. */
-void libmpq__huffman_insert_item(
- struct huffman_tree_item_s **p_item,
- struct huffman_tree_item_s *item,
- uint32_t where,
- struct huffman_tree_item_s *item2
-);
-
-/* remove item from huffman tree. */
-void libmpq__huffman_remove_item(
- struct huffman_tree_item_s *hi
-);
-
-/* get previous item from huffman tree. */
-struct huffman_tree_item_s *libmpq__huffman_previous_item(
- struct huffman_tree_item_s *hi,
- long value
-);
-
-/* get one bit from stream. */
-uint32_t libmpq__huffman_get_1bit(
- struct huffman_input_stream_s *is
-);
-
-/* get seven bit from stream. */
-uint32_t libmpq__huffman_get_7bit(
- struct huffman_input_stream_s *is
-);
-
-/* get eight bit from stream. */
-uint32_t libmpq__huffman_get_8bit(
- struct huffman_input_stream_s *is
-);
-
-/* call 1500E740. */
-struct huffman_tree_item_s *libmpq__huffman_call_1500E740(
- struct huffman_tree_s *ht
-);
-
-/* call 1500E820- */
-void libmpq__huffman_call_1500E820(
- struct huffman_tree_s *ht,
- struct huffman_tree_item_s *p_item
-);
-
-/* initialize the huffman tree. */
-void libmpq__huffman_tree_init(
- struct huffman_tree_s *ht,
- uint32_t cmp
-);
-
-/* build the huffman tree. */
-void libmpq__huffman_tree_build(
- struct huffman_tree_s *ht,
- uint32_t cmp_type
-);
-
-/* decompress the stream using huffman compression. */
-int32_t libmpq__do_decompress_huffman(
- struct huffman_tree_s *ht,
- struct huffman_input_stream_s *is,
- uint8_t *out_buf,
- uint32_t out_length
-);
-
-#endif /* _HUFFMAN_H */
diff --git a/dep/libmpq/libmpq/mpq-internal.h b/dep/libmpq/libmpq/mpq-internal.h
deleted file mode 100644
index 76eabe4190a..00000000000
--- a/dep/libmpq/libmpq/mpq-internal.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * mpq-internal.h -- some default types and defines, but only required for
- * compilation of the library.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MPQ_INTERNAL_H
-#define _MPQ_INTERNAL_H
-
-/* generic includes. */
-#include <stdint.h>
-#include <stdio.h>
-
-/* define return value if nothing failed. */
-#define LIBMPQ_SUCCESS 0 /* return value for all functions which success. */
-
-/* define generic mpq archive information. */
-#define LIBMPQ_HEADER 0x1A51504D /* mpq archive header ('MPQ\x1A') */
-
-/* define the known archive versions. */
-#define LIBMPQ_ARCHIVE_VERSION_ONE 0 /* version one used until world of warcraft. */
-#define LIBMPQ_ARCHIVE_VERSION_TWO 1 /* version two used from world of warcraft - the burning crusade. */
-
-/* define values used by blizzard as flags. */
-#define LIBMPQ_FLAG_EXISTS 0x80000000 /* set if file exists, reset when the file was deleted. */
-#define LIBMPQ_FLAG_ENCRYPTED 0x00010000 /* indicates whether file is encrypted. */
-#define LIBMPQ_FLAG_COMPRESSED 0x0000FF00 /* file is compressed. */
-#define LIBMPQ_FLAG_COMPRESS_PKZIP 0x00000100 /* compression made by pkware data compression library. */
-#define LIBMPQ_FLAG_COMPRESS_MULTI 0x00000200 /* multiple compressions. */
-#define LIBMPQ_FLAG_COMPRESS_NONE 0x00000300 /* no compression (no blizzard flag used by myself). */
-#define LIBMPQ_FLAG_SINGLE 0x01000000 /* file is stored in one single sector, first seen in world of warcraft. */
-#define LIBMPQ_FLAG_CRC 0x04000000 /* compressed block offset table has CRC checksum. */
-
-/* define generic hash values. */
-#define LIBMPQ_HASH_FREE 0xFFFFFFFF /* hash table entry is empty and has always been empty. */
-
-/* define special files. */
-#define LIBMPQ_LISTFILE_NAME "(listfile)" /* internal listfile. */
-#define LIBMPQ_SIGNATURE_NAME "(signature)" /* internal signature file. */
-#define LIBMPQ_ATTRIBUTES_NAME "(attributes)" /* internal attributes file. */
-
-/* define true and false, because not all systems have them. */
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#include "pack_begin.h"
-/* mpq archive header. */
-typedef struct {
- uint32_t mpq_magic; /* the 0x1A51504D ('MPQ\x1A') signature. */
- uint32_t header_size; /* mpq archive header size. */
- uint32_t archive_size; /* size of mpq archive. */
- uint16_t version; /* 0000 for starcraft and broodwar. */
- uint16_t block_size; /* size of file block is (512 * 2 ^ block size). */
- uint32_t hash_table_offset; /* file position of mpq_hash. */
- uint32_t block_table_offset; /* file position of mpq_block, each entry has 16 bytes. */
- uint32_t hash_table_count; /* number of entries in hash table. */
- uint32_t block_table_count; /* number of entries in the block table. */
-} PACK_STRUCT mpq_header_s;
-
-/* mpq extended archive header, used since world of warcraft - the burning crusade. */
-typedef struct {
- uint64_t extended_offset; /* offset to the beginning of the extended block table, relative to the beginning of the archive. */
- uint16_t hash_table_offset_high; /* upper 16 bits of the hash table offset for large archives. */
- uint16_t block_table_offset_high;/* upper 16 bits of the block table offset for large archives.*/
-} PACK_STRUCT mpq_header_ex_s;
-
-/* hash entry, all files in the archive are searched by their hashes. */
-typedef struct {
- uint32_t hash_a; /* the first two uint32_ts are the encrypted file. */
- uint32_t hash_b; /* the first two uint32_ts are the encrypted file. */
- uint16_t locale; /* locale information. */
- uint16_t platform; /* platform information and zero is default. */
- uint32_t block_table_index; /* index to file description block. */
-} PACK_STRUCT mpq_hash_s;
-
-/* file description block contains informations about the file. */
-typedef struct {
- uint32_t offset; /* block file starting position in the archive. */
- uint32_t packed_size; /* packed file size. */
- uint32_t unpacked_size; /* unpacked file size. */
- uint32_t flags; /* flags. */
-} PACK_STRUCT mpq_block_s;
-
-/* extended file description block contains information about the offset beyond 2^32 (4GB). */
-typedef struct {
- uint16_t offset_high; /* upper 16 bit of the file offset in archive. */
-} PACK_STRUCT mpq_block_ex_s;
-
-/* file structure used since diablo 1.00 (0x38 bytes). */
-typedef struct {
- uint32_t seed; /* seed used for file decrypt. */
- uint32_t *packed_offset; /* position of each file block (only for packed files). */
- uint32_t open_count; /* number of times it has been opened - used for freeing */
-} PACK_STRUCT mpq_file_s;
-
-/* map structure for valid blocks and hashes (first seen in warcraft 3 archives). */
-typedef struct {
- uint32_t block_table_indices; /* real mapping for file number to block entry. */
- uint32_t block_table_diff; /* block table difference between valid blocks and invalid blocks before. */
-} PACK_STRUCT mpq_map_s;
-#include "pack_end.h"
-
-/* archive structure used since diablo 1.00 by blizzard. */
-struct mpq_archive {
-
- /* generic file information. */
- FILE *fp; /* file handle. */
-
- /* generic size information. */
- uint32_t block_size; /* size of the mpq block. */
- off_t archive_offset; /* absolute start position of archive. */
-
- /* archive related buffers and tables. */
- mpq_header_s mpq_header; /* mpq file header. */
- mpq_header_ex_s mpq_header_ex; /* mpq extended file header. */
- mpq_hash_s *mpq_hash; /* hash table. */
- mpq_block_s *mpq_block; /* block table. */
- mpq_block_ex_s *mpq_block_ex; /* extended block table. */
- mpq_file_s **mpq_file; /* pointer to the file pointers which are opened. */
-
- /* non archive structure related members. */
- mpq_map_s *mpq_map; /* map table between valid blocks and hashes. */
- uint32_t files; /* number of files in archive, which could be extracted. */
-};
-
-#endif /* _MPQ_INTERNAL_H */
diff --git a/dep/libmpq/libmpq/mpq.c b/dep/libmpq/libmpq/mpq.c
deleted file mode 100644
index a6ab5db82d9..00000000000
--- a/dep/libmpq/libmpq/mpq.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-/*
- * mpq.c -- functions for developers using libmpq.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* mpq-tools configuration includes. */
-#include "config.h"
-
-/* libmpq main includes. */
-#include "mpq.h"
-#include "mpq-internal.h"
-
-/* libmpq generic includes. */
-#include "common.h"
-
-/* generic includes. */
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-/* support for platform specific things */
-#include "platform.h"
-
-/* this function returns the library version information. */
-const char *libmpq__version(void) {
-
- /* return version information. */
- return VERSION;
-}
-
-static const char *__libmpq_error_strings[] = {
- "success",
- "open error on file",
- "close error on file",
- "lseek error on file",
- "read error on file",
- "write error on file",
- "memory allocation error",
- "format errror",
- "init() wasn't called",
- "buffer size is to small",
- "file or block does not exist in archive",
- "we don't know the decryption seed",
- "error on unpacking file"
- };
-
-/* this function returns a string message for a return code. */
-const char *libmpq__strerror(int32_t returncode) {
- /* check for array bounds */
- if (-returncode < 0 || -returncode > sizeof(__libmpq_error_strings)/sizeof(char*))
- return NULL;
-
- /* return appropriate string */
- return __libmpq_error_strings[-returncode];
-}
-
-/* this function read a file and verify if it is a valid mpq archive, then it read and decrypt the hash table. */
-int32_t libmpq__archive_open(mpq_archive_s **mpq_archive, const char *mpq_filename, libmpq__off_t archive_offset) {
-
- /* some common variables. */
- uint32_t rb = 0;
- uint32_t i = 0;
- uint32_t count = 0;
- int32_t result = 0;
- uint32_t header_search = FALSE;
-
- if (archive_offset == -1) {
- archive_offset = 0;
- header_search = TRUE;
- }
-
- if ((*mpq_archive = calloc(1, sizeof(mpq_archive_s))) == NULL) {
-
- /* archive struct could not be allocated */
- return LIBMPQ_ERROR_MALLOC;
- }
-
- /* check if file exists and is readable */
- if (((*mpq_archive)->fp = fopen(mpq_filename, "rb")) == NULL) {
-
- /* file could not be opened. */
- result = LIBMPQ_ERROR_OPEN;
- goto error;
- }
-
- /* assign some default values. */
- (*mpq_archive)->mpq_header.mpq_magic = 0;
- (*mpq_archive)->files = 0;
-
- /* loop through file and search for mpq signature. */
- while (TRUE) {
-
- /* reset header values. */
- (*mpq_archive)->mpq_header.mpq_magic = 0;
-
- /* seek in file. */
- if (fseeko((*mpq_archive)->fp, archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read header from file. */
- if ((rb = fread(&(*mpq_archive)->mpq_header, 1, sizeof(mpq_header_s), (*mpq_archive)->fp)) != sizeof(mpq_header_s)) {
-
- /* no valid mpq archive. */
- result = LIBMPQ_ERROR_FORMAT;
- goto error;
- }
-
- /* check if we found a valid mpq header. */
- if ((*mpq_archive)->mpq_header.mpq_magic == LIBMPQ_HEADER) {
-
- /* check if we process old mpq archive version. */
- if ((*mpq_archive)->mpq_header.version == LIBMPQ_ARCHIVE_VERSION_ONE) {
-
- /* check if the archive is protected. */
- if ((*mpq_archive)->mpq_header.header_size != sizeof(mpq_header_s)) {
-
- /* correct header size. */
- (*mpq_archive)->mpq_header.header_size = sizeof(mpq_header_s);
- }
- }
-
- /* check if we process new mpq archive version. */
- if ((*mpq_archive)->mpq_header.version == LIBMPQ_ARCHIVE_VERSION_TWO) {
-
- /* check if the archive is protected. */
- if ((*mpq_archive)->mpq_header.header_size != sizeof(mpq_header_s) + sizeof(mpq_header_ex_s)) {
-
- /* correct header size. */
- (*mpq_archive)->mpq_header.header_size = sizeof(mpq_header_s) + sizeof(mpq_header_ex_s);
- }
- }
-
- /* break the loop, because header was found. */
- break;
- }
-
- /* move to the next possible offset. */
- if (!header_search) {
-
- /* no valid mpq archive. */
- result = LIBMPQ_ERROR_FORMAT;
- goto error;
- }
- archive_offset += 512;
- }
-
- /* store block size for later use. */
- (*mpq_archive)->block_size = 512 << (*mpq_archive)->mpq_header.block_size;
-
- /* store archive offset and size for later use. */
- (*mpq_archive)->archive_offset = archive_offset;
-
- /* check if we process new mpq archive version. */
- if ((*mpq_archive)->mpq_header.version == LIBMPQ_ARCHIVE_VERSION_TWO) {
-
- /* seek in file. */
- if (fseeko((*mpq_archive)->fp, sizeof(mpq_header_s) + archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read header from file. */
- if ((rb = fread(&(*mpq_archive)->mpq_header_ex, 1, sizeof(mpq_header_ex_s), (*mpq_archive)->fp)) != sizeof(mpq_header_ex_s)) {
-
- /* no valid mpq archive. */
- result = LIBMPQ_ERROR_FORMAT;
- goto error;
- }
- }
-
- /* allocate memory for the block table, hash table, file and block table to file mapping. */
- if (((*mpq_archive)->mpq_block = calloc((*mpq_archive)->mpq_header.block_table_count, sizeof(mpq_block_s))) == NULL ||
- ((*mpq_archive)->mpq_block_ex = calloc((*mpq_archive)->mpq_header.block_table_count, sizeof(mpq_block_ex_s))) == NULL ||
- ((*mpq_archive)->mpq_hash = calloc((*mpq_archive)->mpq_header.hash_table_count, sizeof(mpq_hash_s))) == NULL ||
- ((*mpq_archive)->mpq_file = calloc((*mpq_archive)->mpq_header.block_table_count, sizeof(mpq_file_s))) == NULL ||
- ((*mpq_archive)->mpq_map = calloc((*mpq_archive)->mpq_header.block_table_count, sizeof(mpq_map_s))) == NULL) {
-
- /* memory allocation problem. */
- result = LIBMPQ_ERROR_MALLOC;
- goto error;
- }
-
- /* seek in file. */
- if (fseeko((*mpq_archive)->fp, (*mpq_archive)->mpq_header.hash_table_offset + (((long long)((*mpq_archive)->mpq_header_ex.hash_table_offset_high)) << 32) + (*mpq_archive)->archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read the hash table into the buffer. */
- if ((rb = fread((*mpq_archive)->mpq_hash, 1, (*mpq_archive)->mpq_header.hash_table_count * sizeof(mpq_hash_s), (*mpq_archive)->fp)) < 0) {
-
- /* something on read failed. */
- result = LIBMPQ_ERROR_READ;
- goto error;
- }
-
- /* decrypt the hashtable. */
- libmpq__decrypt_block((uint32_t *)((*mpq_archive)->mpq_hash), (*mpq_archive)->mpq_header.hash_table_count * sizeof(mpq_hash_s), libmpq__hash_string("(hash table)", 0x300));
-
- /* seek in file. */
- if (fseeko((*mpq_archive)->fp, (*mpq_archive)->mpq_header.block_table_offset + (((long long)((*mpq_archive)->mpq_header_ex.block_table_offset_high)) << 32) + (*mpq_archive)->archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read the block table into the buffer. */
- if ((rb = fread((*mpq_archive)->mpq_block, 1, (*mpq_archive)->mpq_header.block_table_count * sizeof(mpq_block_s), (*mpq_archive)->fp)) < 0) {
-
- /* something on read failed. */
- result = LIBMPQ_ERROR_READ;
- goto error;
- }
-
- /* decrypt block table. */
- libmpq__decrypt_block((uint32_t *)((*mpq_archive)->mpq_block), (*mpq_archive)->mpq_header.block_table_count * sizeof(mpq_block_s), libmpq__hash_string("(block table)", 0x300));
-
- /* check if extended block table is present, regardless of version 2 it is only present in archives > 4GB. */
- if ((*mpq_archive)->mpq_header_ex.extended_offset > 0) {
-
- /* seek in file. */
- if (fseeko((*mpq_archive)->fp, (*mpq_archive)->mpq_header_ex.extended_offset + archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read header from file. */
- if ((rb = fread((*mpq_archive)->mpq_block_ex, 1, (*mpq_archive)->mpq_header.block_table_count * sizeof(mpq_block_ex_s), (*mpq_archive)->fp)) < 0) {
-
- /* no valid mpq archive. */
- result = LIBMPQ_ERROR_FORMAT;
- goto error;
- }
- }
-
- /* loop through all files in mpq archive and check if they are valid. */
- for (i = 0; i < (*mpq_archive)->mpq_header.block_table_count; i++) {
-
- /* save block difference between valid and invalid blocks. */
- (*mpq_archive)->mpq_map[i].block_table_diff = i - count;
-
- /* check if file exists, sizes and offsets are correct. */
- if (((*mpq_archive)->mpq_block[i].flags & LIBMPQ_FLAG_EXISTS) == 0) {
-
- /* file does not exist, so nothing to do with that block. */
- continue;
- }
-
- /* create final indices tables. */
- (*mpq_archive)->mpq_map[count].block_table_indices = i;
-
- /* increase file counter. */
- count++;
- }
-
- /* save the number of files. */
- (*mpq_archive)->files = count;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-
-error:
- if ((*mpq_archive)->fp)
- fclose((*mpq_archive)->fp);
-
- free((*mpq_archive)->mpq_map);
- free((*mpq_archive)->mpq_file);
- free((*mpq_archive)->mpq_hash);
- free((*mpq_archive)->mpq_block);
- free((*mpq_archive)->mpq_block_ex);
- free(*mpq_archive);
-
- *mpq_archive = NULL;
-
- return result;
-}
-
-/* this function close the file descriptor, free the decryption buffer and the file list. */
-int32_t libmpq__archive_close(mpq_archive_s *mpq_archive) {
-
- /* try to close the file */
- if ((fclose(mpq_archive->fp)) < 0) {
-
- /* don't free anything here, so the caller can try calling us
- * again.
- */
- return LIBMPQ_ERROR_CLOSE;
- }
-
- /* free header, tables and list. */
- free(mpq_archive->mpq_map);
- free(mpq_archive->mpq_file);
- free(mpq_archive->mpq_hash);
- free(mpq_archive->mpq_block);
- free(mpq_archive->mpq_block_ex);
- free(mpq_archive);
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the packed size of all files in the archive. */
-int32_t libmpq__archive_packed_size(mpq_archive_s *mpq_archive, libmpq__off_t *packed_size) {
-
- /* some common variables. */
- uint32_t i;
-
- /* loop through all files in archive and count packed size. */
- for (i = 0; i < mpq_archive->files; i++) {
- *packed_size += mpq_archive->mpq_block[mpq_archive->mpq_map[i].block_table_indices].packed_size;
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the unpacked size of all files in the archive. */
-int32_t libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, libmpq__off_t *unpacked_size) {
-
- /* some common variables. */
- uint32_t i;
-
- /* loop through all files in archive and count unpacked size. */
- for (i = 0; i < mpq_archive->files; i++) {
- *unpacked_size += mpq_archive->mpq_block[mpq_archive->mpq_map[i].block_table_indices].unpacked_size;
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the archive offset (beginning of archive in file). */
-int32_t libmpq__archive_offset(mpq_archive_s *mpq_archive, libmpq__off_t *offset) {
-
- /* return archive offset. */
- *offset = mpq_archive->archive_offset;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the archive offset. */
-int32_t libmpq__archive_version(mpq_archive_s *mpq_archive, uint32_t *version) {
-
- /* return archive version. */
- *version = mpq_archive->mpq_header.version + 1;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the number of valid files in archive. */
-int32_t libmpq__archive_files(mpq_archive_s *mpq_archive, uint32_t *files) {
-
- /* return archive version. */
- *files = mpq_archive->files;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-#define CHECK_FILE_NUM(file_number, mpq_archive) \
- if (file_number < 0 || file_number > mpq_archive->files - 1) { \
- return LIBMPQ_ERROR_EXIST; \
- }
-
-#define CHECK_BLOCK_NUM(block_number, mpq_archive) \
- if (block_number < 0 || block_number >= ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) != 0 ? 1 : (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size)) { \
- return LIBMPQ_ERROR_EXIST; \
- }
-
-/* this function return the packed size of the given files in the archive. */
-int32_t libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *packed_size) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* get the packed size of file. */
- *packed_size = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].packed_size;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the unpacked size of the given file in the archive. */
-int32_t libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *unpacked_size) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* get the unpacked size of file. */
- *unpacked_size = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the file offset (beginning of file in archive). */
-int32_t libmpq__file_offset(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *offset) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* return file offset relative to archive start. */
- *offset = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].offset + (((long long)mpq_archive->mpq_block_ex[mpq_archive->mpq_map[file_number].block_table_indices].offset_high) << 32);
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the number of blocks for the given file in the archive. */
-int32_t libmpq__file_blocks(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *blocks) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* return the number of blocks for the given file. */
- *blocks = (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) != 0 ? 1 : (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return if the file is encrypted or not. */
-int32_t libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *encrypted) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* return the encryption status of file. */
- *encrypted = (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_ENCRYPTED) != 0 ? TRUE : FALSE;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return if the file is compressed or not. */
-int32_t libmpq__file_compressed(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *compressed) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* return the compression status of file. */
- *compressed = (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_COMPRESS_MULTI) != 0 ? TRUE : FALSE;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return if the file is imploded or not. */
-int32_t libmpq__file_imploded(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *imploded) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* return the implosion status of file. */
- *imploded = (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_COMPRESS_PKZIP) != 0 ? TRUE : FALSE;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return filenumber by the given name. */
-int32_t libmpq__file_number(mpq_archive_s *mpq_archive, const char *filename, uint32_t *number) {
-
- /* some common variables. */
- uint32_t i, hash1, hash2, hash3, ht_count;
-
- /* if the list of file names doesn't include this one, we'll have
- * to figure out the file number the "hard" way.
- */
- ht_count = mpq_archive->mpq_header.hash_table_count;
-
- hash1 = libmpq__hash_string (filename, 0x0) & (ht_count - 1);
- hash2 = libmpq__hash_string (filename, 0x100);
- hash3 = libmpq__hash_string (filename, 0x200);
-
- /* loop through all files in mpq archive.
- * hash1 gives us a clue about the starting position of this
- * search.
- */
- for (i = hash1; mpq_archive->mpq_hash[i].block_table_index != LIBMPQ_HASH_FREE; i = (i + 1) & (ht_count - 1)) {
-
- /* if the other two hashes match, we found our file number. */
- if (mpq_archive->mpq_hash[i].hash_a == hash2 &&
- mpq_archive->mpq_hash[i].hash_b == hash3) {
-
- /* return the file number. */
- *number = mpq_archive->mpq_hash[i].block_table_index - mpq_archive->mpq_map[mpq_archive->mpq_hash[i].block_table_index].block_table_diff;
-
- /* we found our file, return zero. */
- return LIBMPQ_SUCCESS;
- }
-
- /* check if we have cycled through the whole hash table */
- if (((i + 1) & (ht_count - 1)) == hash1) {
- break;
- }
- }
-
- /* if no matching entry found, so return error. */
- return LIBMPQ_ERROR_EXIST;
-}
-
-/* this function read the given file from archive into a buffer. */
-int32_t libmpq__file_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred) {
-
- /* some common variables. */
- uint32_t i;
- uint32_t blocks = 0;
- int32_t result = 0;
- libmpq__off_t file_offset = 0;
- libmpq__off_t unpacked_size = 0;
- libmpq__off_t transferred_block = 0;
- libmpq__off_t transferred_total = 0;
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* get target size of block. */
- libmpq__file_unpacked_size(mpq_archive, file_number, &unpacked_size);
-
- /* check if target buffer is to small. */
- if (unpacked_size > out_size) {
-
- /* output buffer size is to small or block size is unknown. */
- return LIBMPQ_ERROR_SIZE;
- }
-
- /* fetch file offset. */
- libmpq__file_offset(mpq_archive, file_number, &file_offset);
-
- /* get block count for file. */
- libmpq__file_blocks(mpq_archive, file_number, &blocks);
-
- /* open the packed block offset table. */
- if ((result = libmpq__block_open_offset(mpq_archive, file_number)) < 0) {
-
- /* something on opening packed block offset table failed. */
- return result;
- }
-
- /* loop through all blocks. */
- for (i = 0; i < blocks; i++) {
-
- /* cleanup size variable. */
- unpacked_size = 0;
-
- /* get unpacked block size. */
- libmpq__block_unpacked_size(mpq_archive, file_number, i, &unpacked_size);
-
- /* read block. */
- if ((result = libmpq__block_read(mpq_archive, file_number, i, out_buf + transferred_total, unpacked_size, &transferred_block)) < 0) {
-
- /* close the packed block offset table. */
- libmpq__block_close_offset(mpq_archive, file_number);
-
- /* something on reading block failed. */
- return result;
- }
-
- transferred_total += transferred_block;
-
- }
-
- /* close the packed block offset table. */
- libmpq__block_close_offset(mpq_archive, file_number);
-
- /* check for null pointer. */
- if (transferred != NULL) {
-
- /* store transferred bytes. */
- *transferred = transferred_total;
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function open a file in the given archive and caches the block offset information. */
-int32_t libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint32_t file_number) {
-
- /* some common variables. */
- uint32_t i;
- uint32_t packed_size;
- int32_t rb = 0;
- int32_t result = 0;
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- if (mpq_archive->mpq_file[file_number]) {
-
- /* file already opened, so increment counter */
- mpq_archive->mpq_file[file_number]->open_count++;
- return LIBMPQ_SUCCESS;
- }
-
- /* check if file is not stored in a single sector. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) == 0) {
-
- /* get packed size based on block size and block count. */
- packed_size = sizeof(uint32_t) * (((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size) + 1);
- } else {
-
- /* file is stored in single sector and we need only two entries for the packed block offset table. */
- packed_size = sizeof(uint32_t) * 2;
- }
-
- /* check if data has one extra entry. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_CRC) != 0) {
-
- /* add one uint32_t. */
- packed_size += sizeof(uint32_t);
- }
-
- /* allocate memory for the file. */
- if ((mpq_archive->mpq_file[file_number] = calloc(1, sizeof(mpq_file_s))) == NULL) {
-
- /* memory allocation problem. */
- result = LIBMPQ_ERROR_MALLOC;
- goto error;
- }
-
- /* allocate memory for the packed block offset table. */
- if ((mpq_archive->mpq_file[file_number]->packed_offset = calloc(1, packed_size)) == NULL) {
-
- /* memory allocation problem. */
- result = LIBMPQ_ERROR_MALLOC;
- goto error;
- }
-
- /* initialize counter to one opening */
- mpq_archive->mpq_file[file_number]->open_count = 1;
-
- /* check if we need to load the packed block offset table, we will maintain this table for unpacked files too. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_COMPRESSED) != 0 &&
- (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) == 0) {
-
- /* seek to block position. */
- if (fseeko(mpq_archive->fp, mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].offset + (((long long)mpq_archive->mpq_block_ex[mpq_archive->mpq_map[file_number].block_table_indices].offset_high) << 32) + mpq_archive->archive_offset, SEEK_SET) < 0) {
-
- /* seek in file failed. */
- result = LIBMPQ_ERROR_SEEK;
- goto error;
- }
-
- /* read block positions from begin of file. */
- if ((rb = fread(mpq_archive->mpq_file[file_number]->packed_offset, 1, packed_size, mpq_archive->fp)) < 0) {
-
- /* something on read from archive failed. */
- result = LIBMPQ_ERROR_READ;
- goto error;
- }
-
- /* check if the archive is protected some way, sometimes the file appears not to be encrypted, but it is.
- * a special case are files with an additional sector but LIBMPQ_FLAG_CRC not set. we don't want to handle
- * them as encrypted. */
- if (mpq_archive->mpq_file[file_number]->packed_offset[0] != rb &&
- mpq_archive->mpq_file[file_number]->packed_offset[0] != rb + 4) {
-
- /* file is encrypted. */
- mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags |= LIBMPQ_FLAG_ENCRYPTED;
- }
-
- /* check if packed offset block is encrypted, we have to decrypt it. */
- if (mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_ENCRYPTED) {
-
- /* check if we don't know the file seed, try to find it. */
- if (libmpq__decrypt_key((uint8_t *)mpq_archive->mpq_file[file_number]->packed_offset, packed_size, mpq_archive->block_size, &mpq_archive->mpq_file[file_number]->seed) < 0) {
-
- /* sorry without seed, we cannot extract file. */
- result = LIBMPQ_ERROR_DECRYPT;
- goto error;
- }
-
- /* decrypt block in input buffer. */
- if (libmpq__decrypt_block(mpq_archive->mpq_file[file_number]->packed_offset, packed_size, mpq_archive->mpq_file[file_number]->seed - 1) < 0 ) {
-
- /* something on decrypt failed. */
- result = LIBMPQ_ERROR_DECRYPT;
- goto error;
- }
-
- /* check if the block positions are correctly decrypted. */
- if (mpq_archive->mpq_file[file_number]->packed_offset[0] != packed_size) {
-
- /* sorry without seed, we cannot extract file. */
- result = LIBMPQ_ERROR_DECRYPT;
- goto error;
- }
- }
- } else {
-
- /* check if file is not stored in a single sector. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) == 0) {
-
- /* loop through all blocks and create packed block offset table based on block size. */
- for (i = 0; i < ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size + 1); i++) {
-
- /* check if we process the last block. */
- if (i == ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size)) {
-
- /* store size of last block. */
- mpq_archive->mpq_file[file_number]->packed_offset[i] = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size;
- } else {
-
- /* store default block size. */
- mpq_archive->mpq_file[file_number]->packed_offset[i] = i * mpq_archive->block_size;
- }
- }
- } else {
-
- /* store offsets. */
- mpq_archive->mpq_file[file_number]->packed_offset[0] = 0;
- mpq_archive->mpq_file[file_number]->packed_offset[1] = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].packed_size;
- }
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-
-error:
-
- /* free packed block offset table and file pointer. */
- free(mpq_archive->mpq_file[file_number]->packed_offset);
- free(mpq_archive->mpq_file[file_number]);
-
- /* return error constant. */
- return result;
-}
-
-/* this function free the file pointer to the opened file in archive. */
-int32_t libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint32_t file_number) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- if (mpq_archive->mpq_file[file_number] == NULL) {
-
- /* packed block offset table is not opened. */
- return LIBMPQ_ERROR_OPEN;
- }
-
- mpq_archive->mpq_file[file_number]->open_count--;
-
- if (mpq_archive->mpq_file[file_number]->open_count != 0) {
-
- /* still in use */
- return LIBMPQ_SUCCESS;
- }
-
- /* free packed block offset table and file pointer. */
- free(mpq_archive->mpq_file[file_number]->packed_offset);
- free(mpq_archive->mpq_file[file_number]);
-
- /* mark it as unopened - libmpq__block_open_offset checks for this to decide whether to increment the counter */
- mpq_archive->mpq_file[file_number] = NULL;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the unpacked size of the given file and block in the archive. */
-int32_t libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, libmpq__off_t *unpacked_size) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* check if given block number is not out of range. */
- CHECK_BLOCK_NUM(block_number, mpq_archive)
-
- /* check if packed block offset table is opened. */
- if (mpq_archive->mpq_file[file_number] == NULL ||
- mpq_archive->mpq_file[file_number]->packed_offset == NULL) {
-
- /* packed block offset table is not opened. */
- return LIBMPQ_ERROR_OPEN;
- }
-
- /* check if block is stored as single sector. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) != 0) {
-
- /* return the unpacked size of the block in the mpq archive. */
- *unpacked_size = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size;
- }
-
- /* check if block is not stored as single sector. */
- if ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].flags & LIBMPQ_FLAG_SINGLE) == 0) {
-
- /* check if we not process the last block. */
- if (block_number < ((mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size + mpq_archive->block_size - 1) / mpq_archive->block_size) - 1) {
-
- /* return the block size as unpacked size. */
- *unpacked_size = mpq_archive->block_size;
- } else {
-
- /* return the unpacked size of the last block in the mpq archive. */
- *unpacked_size = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].unpacked_size - mpq_archive->block_size * block_number;
- }
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function return the decryption seed for the given file and block. */
-int32_t libmpq__block_seed(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, uint32_t *seed) {
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* check if given block number is not out of range. */
- CHECK_BLOCK_NUM(block_number, mpq_archive)
-
- /* check if packed block offset table is opened. */
- if (mpq_archive->mpq_file[file_number] == NULL ||
- mpq_archive->mpq_file[file_number]->packed_offset == NULL) {
-
- /* packed block offset table is not opened. */
- return LIBMPQ_ERROR_OPEN;
- }
-
- /* return the decryption key. */
- *seed = mpq_archive->mpq_file[file_number]->seed + block_number;
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
-
-/* this function read the given block from archive into a buffer. */
-int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred) {
-
- /* some common variables. */
- uint8_t *in_buf;
- uint32_t seed = 0;
- uint32_t encrypted = 0;
- uint32_t compressed = 0;
- uint32_t imploded = 0;
- int32_t tb = 0;
- libmpq__off_t block_offset = 0;
- off_t in_size = 0;
- libmpq__off_t unpacked_size = 0;
-
- /* check if given file number is not out of range. */
- CHECK_FILE_NUM(file_number, mpq_archive)
-
- /* check if given block number is not out of range. */
- CHECK_BLOCK_NUM(block_number, mpq_archive)
-
- /* check if packed block offset table is opened. */
- if (mpq_archive->mpq_file[file_number] == NULL ||
- mpq_archive->mpq_file[file_number]->packed_offset == NULL) {
-
- /* packed block offset table is not opened. */
- return LIBMPQ_ERROR_OPEN;
- }
-
- /* get target size of block. */
- libmpq__block_unpacked_size(mpq_archive, file_number, block_number, &unpacked_size);
-
- /* check if target buffer is to small. */
- if (unpacked_size > out_size) {
-
- /* output buffer size is to small or block size is unknown. */
- return LIBMPQ_ERROR_SIZE;
- }
-
- /* fetch some required values like input buffer size and block offset. */
- block_offset = mpq_archive->mpq_block[mpq_archive->mpq_map[file_number].block_table_indices].offset + (((long long)mpq_archive->mpq_block_ex[mpq_archive->mpq_map[file_number].block_table_indices].offset_high) << 32) + mpq_archive->mpq_file[file_number]->packed_offset[block_number];
- in_size = mpq_archive->mpq_file[file_number]->packed_offset[block_number + 1] - mpq_archive->mpq_file[file_number]->packed_offset[block_number];
-
- /* seek in file. */
- if (fseeko(mpq_archive->fp, block_offset + mpq_archive->archive_offset, SEEK_SET) < 0) {
-
- /* something with seek in file failed. */
- return LIBMPQ_ERROR_SEEK;
- }
-
- /* allocate memory for the read buffer. */
- if ((in_buf = calloc(1, in_size)) == NULL) {
-
- /* memory allocation problem. */
- return LIBMPQ_ERROR_MALLOC;
- }
-
- /* read block from file. */
- if (fread(in_buf, 1, in_size, mpq_archive->fp) < 0) {
-
- /* free buffers. */
- free(in_buf);
-
- /* something on reading block failed. */
- return LIBMPQ_ERROR_READ;
- }
-
- /* get encryption status. */
- libmpq__file_encrypted(mpq_archive, file_number, &encrypted);
-
- /* check if file is encrypted. */
- if (encrypted == 1) {
-
- /* get decryption key. */
- libmpq__block_seed(mpq_archive, file_number, block_number, &seed);
-
- /* decrypt block. */
- if (libmpq__decrypt_block((uint32_t *)in_buf, in_size, seed) < 0) {
-
- /* free buffers. */
- free(in_buf);
-
- /* something on decrypting block failed. */
- return LIBMPQ_ERROR_DECRYPT;
- }
- }
-
- /* get compression status. */
- libmpq__file_compressed(mpq_archive, file_number, &compressed);
-
- /* check if file is compressed. */
- if (compressed == 1) {
-
- /* decompress block. */
- if ((tb = libmpq__decompress_block(in_buf, in_size, out_buf, out_size, LIBMPQ_FLAG_COMPRESS_MULTI)) < 0) {
-
- /* free temporary buffer. */
- free(in_buf);
-
- /* something on decompressing block failed. */
- return LIBMPQ_ERROR_UNPACK;
- }
- }
-
- /* get implosion status. */
- libmpq__file_imploded(mpq_archive, file_number, &imploded);
-
- /* check if file is imploded. */
- if (imploded == 1) {
-
- /* explode block. */
- if ((tb = libmpq__decompress_block(in_buf, in_size, out_buf, out_size, LIBMPQ_FLAG_COMPRESS_PKZIP)) < 0) {
-
- /* free temporary buffer. */
- free(in_buf);
-
- /* something on decompressing block failed. */
- return LIBMPQ_ERROR_UNPACK;
- }
- }
-
- /* check if file is neither compressed nor imploded. */
- if (compressed == 0 && imploded == 0) {
-
- /* copy block. */
- if ((tb = libmpq__decompress_block(in_buf, in_size, out_buf, out_size, LIBMPQ_FLAG_COMPRESS_NONE)) < 0) {
-
- /* free temporary buffer. */
- free(in_buf);
-
- /* something on decompressing block failed. */
- return LIBMPQ_ERROR_UNPACK;
- }
- }
-
- /* free read buffer. */
- free(in_buf);
-
- /* check for null pointer. */
- if (transferred != NULL) {
-
- /* store transferred bytes. */
- *transferred = tb;
- }
-
- /* if no error was found, return zero. */
- return LIBMPQ_SUCCESS;
-}
diff --git a/dep/libmpq/libmpq/mpq.h b/dep/libmpq/libmpq/mpq.h
deleted file mode 100644
index abd4862c334..00000000000
--- a/dep/libmpq/libmpq/mpq.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * mpq.h -- some default types and defines.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- *
- * Some parts (the encryption and decryption stuff) were adapted from
- * the C++ version of StormLib.h and StormPort.h included in stormlib.
- * The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- * Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MPQ_H
-#define _MPQ_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* generic includes. */
-#include <stdint.h>
-#include <sys/types.h>
-
-#if defined(__GNUC__) && (__GNUC__ >= 4)
-# define LIBMPQ_API __attribute__((visibility("default")))
-#else
-# define LIBMPQ_API
-#endif
-
-/* define errors. */
-#define LIBMPQ_ERROR_OPEN -1 /* open error on file. */
-#define LIBMPQ_ERROR_CLOSE -2 /* close error on file. */
-#define LIBMPQ_ERROR_SEEK -3 /* lseek error on file. */
-#define LIBMPQ_ERROR_READ -4 /* read error on file. */
-#define LIBMPQ_ERROR_WRITE -5 /* write error on file. */
-#define LIBMPQ_ERROR_MALLOC -6 /* memory allocation error. */
-#define LIBMPQ_ERROR_FORMAT -7 /* format errror. */
-#define LIBMPQ_ERROR_NOT_INITIALIZED -8 /* libmpq__init() wasn't called. */
-#define LIBMPQ_ERROR_SIZE -9 /* buffer size is to small. */
-#define LIBMPQ_ERROR_EXIST -10 /* file or block does not exist in archive. */
-#define LIBMPQ_ERROR_DECRYPT -11 /* we don't know the decryption seed. */
-#define LIBMPQ_ERROR_UNPACK -12 /* error on unpacking file. */
-
-/* internal data structure. */
-typedef struct mpq_archive mpq_archive_s;
-
-/* file offset data type for API*/
-typedef int64_t libmpq__off_t;
-
-/* generic information about library. */
-extern LIBMPQ_API const char *libmpq__version(void);
-
-/* string error message for a libmpq return code. */
-extern LIBMPQ_API const char *libmpq__strerror(int32_t returncode);
-
-/* generic mpq archive information. */
-extern LIBMPQ_API int32_t libmpq__archive_open(mpq_archive_s **mpq_archive, const char *mpq_filename, libmpq__off_t archive_offset);
-extern LIBMPQ_API int32_t libmpq__archive_close(mpq_archive_s *mpq_archive);
-extern LIBMPQ_API int32_t libmpq__archive_packed_size(mpq_archive_s *mpq_archive, libmpq__off_t *packed_size);
-extern LIBMPQ_API int32_t libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, libmpq__off_t *unpacked_size);
-extern LIBMPQ_API int32_t libmpq__archive_offset(mpq_archive_s *mpq_archive, libmpq__off_t *offset);
-extern LIBMPQ_API int32_t libmpq__archive_version(mpq_archive_s *mpq_archive, uint32_t *version);
-extern LIBMPQ_API int32_t libmpq__archive_files(mpq_archive_s *mpq_archive, uint32_t *files);
-
-/* generic file processing functions. */
-extern LIBMPQ_API int32_t libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *packed_size);
-extern LIBMPQ_API int32_t libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *unpacked_size);
-extern LIBMPQ_API int32_t libmpq__file_offset(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *offset);
-extern LIBMPQ_API int32_t libmpq__file_blocks(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *blocks);
-extern LIBMPQ_API int32_t libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *encrypted);
-extern LIBMPQ_API int32_t libmpq__file_compressed(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *compressed);
-extern LIBMPQ_API int32_t libmpq__file_imploded(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *imploded);
-extern LIBMPQ_API int32_t libmpq__file_number(mpq_archive_s *mpq_archive, const char *filename, uint32_t *number);
-extern LIBMPQ_API int32_t libmpq__file_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred);
-
-/* generic block processing functions. */
-extern LIBMPQ_API int32_t libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint32_t file_number);
-extern LIBMPQ_API int32_t libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint32_t file_number);
-extern LIBMPQ_API int32_t libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, libmpq__off_t *unpacked_size);
-extern LIBMPQ_API int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MPQ_H */
diff --git a/dep/libmpq/libmpq/pack_begin.h b/dep/libmpq/libmpq/pack_begin.h
deleted file mode 100644
index eb4a6ddebbb..00000000000
--- a/dep/libmpq/libmpq/pack_begin.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * pack_begin.h -- header file for struct packing used by libmpq.
- *
- * Copyright (c) 2010 Georg Lukas <georg@op-co.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _PACK_BEGIN
-#define _PACK_BEGIN
-#else
-#error "pack_begin.h may not be included twice!"
-#endif
-
-#ifdef _MSC_VER
- #pragma pack(push,1)
- #define PACK_STRUCT
-#else
- /* we assume GNU here */
- #define PACK_STRUCT __attribute__((packed))
-#endif
-
diff --git a/dep/libmpq/libmpq/pack_end.h b/dep/libmpq/libmpq/pack_end.h
deleted file mode 100644
index a8a35113bfb..00000000000
--- a/dep/libmpq/libmpq/pack_end.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * pack_end.h -- header file for struct packing used by libmpq.
- *
- * Copyright (c) 2010 Georg Lukas <georg@op-co.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef _PACK_BEGIN
-#undef _PACK_BEGIN
-#else
-#error "pack_begin.h must be includede before pack_end.h"
-#endif
-
-#ifdef _MSC_VER
- #pragma pack(pop)
-#endif
-
-#undef PACK_STRUCT
diff --git a/dep/libmpq/libmpq/platform.h b/dep/libmpq/libmpq/platform.h
deleted file mode 100644
index 68fdfdc5ded..00000000000
--- a/dep/libmpq/libmpq/platform.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * platform.h -- header file for platform specific parts.
- *
- * Copyright (c) 2010 Georg Lukas <georg@op-co.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _PLATFORM_H
-#define _PLATFORM_H
-
-#ifdef _MSC_VER
- #define fseeko _fseeki64
-#endif
-
-#endif /* _PLATFORM_H */
diff --git a/dep/libmpq/libmpq/wave.c b/dep/libmpq/libmpq/wave.c
deleted file mode 100644
index 628593fce83..00000000000
--- a/dep/libmpq/libmpq/wave.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * wave.c -- this file contains decompression methods used by mpq-tools
- * to decompress wave files.
- *
- * Copyright (c) 2003-2007 Maik Broemme <mbroemme@plusserver.de>
- *
- * This source was adepted from the C++ version of wave.cpp included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik@zezula.net>
- * Tom Amigo <tomamigo@apexmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* generic includes. */
-#include <stdint.h>
-
-/* libmpq generic includes. */
-#include "wave.h"
-
-/* table necessary dor decompression. */
-static const uint32_t wave_table_1503f120[] = {
- 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
- 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
- 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
- 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
-};
-
-/* table necessary dor decompression. */
-static const uint32_t wave_table_1503f1a0[] = {
- 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
- 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
- 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
- 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
- 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
- 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
- 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
- 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
- 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
- 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
- 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
- 0x00007FFF
-};
-
-/* this function decompress a wave file, mono or stereo, 1500F230 offset. */
-int32_t libmpq__do_decompress_wave(uint8_t *out_buf, int32_t out_length, uint8_t *in_buf, int32_t in_length, int32_t channels) {
-
- /* some common variables. */
- byte_and_int16_t out;
- byte_and_int16_t in;
- uint32_t index;
- int32_t nr_array1[2];
- int32_t nr_array2[2];
- int32_t count = 0;
-
- /* end on input buffer. */
- uint8_t *in_end = in_buf + in_length;
-
- /* assign default values. */
- out.pb = out_buf;
- in.pb = in_buf;
- nr_array1[0] = 0x2C;
- nr_array1[1] = 0x2C;
-
- /* increase. */
- in.pw++;
-
- /* 15007AD7 */
- for (count = 0; count < channels; count++) {
-
- /* some common variables. */
- int32_t temp;
-
- /* save pointer. */
- temp = *(int16_t *)in.pw++;
- nr_array2[count] = temp;
-
- /* check if should break. */
- if (out_length < 2) {
- return out.pb - out_buf;
- }
-
- /* return values. */
- *out.pw++ = (uint16_t)temp;
- out_length -= 2;
- }
-
- /* decrease channels. */
- index = channels - 1;
-
- /* loop through input buffer until end reached. */
- while (in.pb < in_end) {
-
- /* save the byte. */
- uint8_t one_byte = *in.pb++;
-
- /* check how many channels and set index. */
- if (channels == 2) {
- index = (index == 0) ? 1 : 0;
- }
-
- /* 15007B25 - get one byte from input buffer. */
- if (one_byte & 0x80) {
-
- /* 15007B32 */
- switch (one_byte & 0x7F) {
- case 0:
-
- /* 15007B8E */
- if (nr_array1[index] != 0) {
- nr_array1[index]--;
- }
-
- /* check if should break. */
- if (out_length < 2) {
- break;
- }
-
- /* return values. */
- *out.pw++ = (uint16_t)nr_array2[index];
- out_length -= 2;
-
- /* continue loop. */
- continue;
- case 1:
- /* 15007B72 and EBX. */
- nr_array1[index] += 8;
-
- /* check index. */
- if (nr_array1[index] > 0x58) {
- nr_array1[index] = 0x58;
- }
-
- /* check how many channels and set index. */
- if (channels == 2) {
- index = (index == 0) ? 1 : 0;
- }
-
- /* continue loop. */
- continue;
- case 2:
-
- /* nothing todo, so continue. */
- continue;
- default:
-
- /* decrease index. */
- nr_array1[index] -= 8;
-
- /* check index. */
- if (nr_array1[index] < 0) {
- nr_array1[index] = 0;
- }
-
- /* check if two channels left. */
- if (channels != 2) {
- continue;
- }
- index = (index == 0) ? 1 : 0;
-
- /* continue loop. */
- continue;
- }
- } else {
-
- /* EDI */
- uint32_t temp1 = wave_table_1503f1a0[nr_array1[index]];
-
- /* ESI */
- uint32_t temp2 = temp1 >> in_buf[1];
-
- /* ECX */
- int32_t temp3 = nr_array2[index];
-
- /* EBX = one byte. */
- if (one_byte & 0x01) {
- temp2 += (temp1 >> 0);
- }
- if (one_byte & 0x02) {
- temp2 += (temp1 >> 1);
- }
- if (one_byte & 0x04) {
- temp2 += (temp1 >> 2);
- }
- if (one_byte & 0x08) {
- temp2 += (temp1 >> 3);
- }
- if (one_byte & 0x10) {
- temp2 += (temp1 >> 4);
- }
- if (one_byte & 0x20) {
- temp2 += (temp1 >> 5);
- }
- if (one_byte & 0x40) {
- temp3 -= temp2;
- if (temp3 <= (int32_t)0xFFFF8000) {
- temp3 = (int32_t)0xFFFF8000;
- }
- } else {
- temp3 += temp2;
- if (temp3 >= 0x7FFF) {
- temp3 = 0x7FFF;
- }
- }
-
- /* restore index. */
- nr_array2[index] = temp3;
-
- /* check if should break. */
- if (out_length < 2) {
- break;
- }
-
- /* assign values. */
- temp2 = nr_array1[index];
- one_byte &= 0x1F;
- *out.pw++ = (uint16_t)temp3;
- out_length -= 2;
- temp2 += wave_table_1503f120[one_byte];
- nr_array1[index] = temp2;
-
- /* check index. */
- if (nr_array1[index] < 0) {
- nr_array1[index] = 0;
- } else {
-
- /* check index. */
- if (nr_array1[index] > 0x58) {
- nr_array1[index] = 0x58;
- }
- }
- }
- }
-
- /* return copied bytes. */
- return (out.pb - out_buf);
-}
diff --git a/dep/libmpq/libmpq/wave.h b/dep/libmpq/libmpq/wave.h
deleted file mode 100644
index 1b9491bd70a..00000000000
--- a/dep/libmpq/libmpq/wave.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * wave.h -- header file for wav unplode functions used by mpq-tools.
- *
- * Copyright (c) 2003-2007 Maik Broemme <mbroemme@plusserver.de>
- *
- * This source was adepted from the C++ version of wave.h included
- * in stormlib. The C++ version belongs to the following authors:
- *
- * Ladislav Zezula <ladik.zezula.net>
- * Tom Amigo <tomamigo@apexmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _WAVE_H
-#define _WAVE_H
-
-/* buffer. */
-typedef union {
- uint16_t *pw;
- uint8_t *pb;
-} byte_and_int16_t;
-
-/* decompress a wave file, mono or stereo, 1500F230 offset. */
-int32_t libmpq__do_decompress_wave(
- uint8_t *out_buf,
- int32_t out_length,
- uint8_t *in_buf,
- int32_t in_length,
- int32_t channels
-);
-
-#endif /* _WAVE_H */
diff --git a/dep/libmpq/tools/Makefile.am b/dep/libmpq/tools/Makefile.am
deleted file mode 100644
index 607205379a4..00000000000
--- a/dep/libmpq/tools/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-# minimum required automake 1.6
-AUTOMAKE_OPTIONS = 1.6
-
-# the main programs.
-bin_PROGRAMS = crypt_buf_gen
-
-# sources for crypt_buf_gen program.
-crypt_buf_gen_SOURCES = crypt_buf_gen.c
diff --git a/dep/libmpq/tools/crypt_buf_gen.c b/dep/libmpq/tools/crypt_buf_gen.c
deleted file mode 100644
index 3d150fc661f..00000000000
--- a/dep/libmpq/tools/crypt_buf_gen.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * crypt_buf_gen.c -- tool to re-create the static decryption buffer.
- *
- * Copyright (c) 2003-2008 Maik Broemme <mbroemme@plusserver.de>
- * Copyright (c) 2008 Georg Lukas <georg@op-co.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Usage:
- * $ make crypt_buf_gen
- * $ ./crypt_buf_gen > crypt_buf.h
- *
- */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static uint32_t *buffer;
-
-int32_t libmpq__buffer_init() {
- buffer = malloc(sizeof(uint32_t) * 0x500);
-
- if (!buffer)
- return -1;
-
- /* some common variables. */
- uint32_t seed = 0x00100001;
- uint32_t index1 = 0;
- uint32_t index2 = 0;
- uint32_t i;
-
- /* initialize the decryption buffer. */
- for (index1 = 0; index1 < 0x100; index1++) {
- for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
-
- /* some common variables. */
- uint32_t temp1, temp2;
-
- /* temporary copy. */
- seed = (seed * 125 + 3) % 0x2AAAAB;
- temp1 = (seed & 0xFFFF) << 0x10;
-
- /* temporary copy. */
- seed = (seed * 125 + 3) % 0x2AAAAB;
- temp2 = (seed & 0xFFFF);
-
- /* assign buffer. */
- buffer[index2] = (temp1 | temp2);
- }
- }
-
- /* if no error was found, return zero. */
- return 0;
-}
-
-int main() {
- if (libmpq__buffer_init() != 0)
- perror("libmpq__buffer_init()");
- int x;
- printf("/* DO NOT CHANGE! this file is auto-generated by crypt_buf_gen.c */\n");
- printf("static const uint32_t crypt_buf[0x500] = {\n\t");
- for (x = 0; x < 0x500; x++) {
- printf("0x%08x", buffer[x]);
- if (x < 0x500 - 1) {
- if (x % 6 == 5)
- printf(",\n\t");
- else
- printf(", ");
- }
- }
- printf("\n};\n");
-}
diff --git a/dep/libmpq/win/config.h b/dep/libmpq/win/config.h
deleted file mode 100644
index 6833494624d..00000000000
--- a/dep/libmpq/win/config.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `bz2' library (-lbz2). */
-#define HAVE_LIBBZ2 1
-
-/* Define to 1 if you have the `z' library (-lz). */
-#define HAVE_LIBZ 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 0
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Name of package */
-#define PACKAGE "libmpq"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "mbroemme@plusserver.de"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libmpq"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libmpq 0.4.2"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libmpq"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.4.2"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.4.2"
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
diff --git a/dep/libmpq/win/dirent.h b/dep/libmpq/win/dirent.h
deleted file mode 100644
index 6425174092d..00000000000
--- a/dep/libmpq/win/dirent.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*****************************************************************************
- * dirent.h - dirent API for Microsoft Visual Studio
- *
- * Copyright (C) 2006 Toni Ronkko
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * ``Software''), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Dec 15, 2009, John Cunningham
- * Added rewinddir member function
- *
- * Jan 18, 2008, Toni Ronkko
- * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
- * between multi-byte and unicode representations. This makes the
- * code simpler and also allows the code to be compiled under MingW. Thanks
- * to Azriel Fasten for the suggestion.
- *
- * Mar 4, 2007, Toni Ronkko
- * Bug fix: due to the strncpy_s() function this file only compiled in
- * Visual Studio 2005. Using the new string functions only when the
- * compiler version allows.
- *
- * Nov 2, 2006, Toni Ronkko
- * Major update: removed support for Watcom C, MS-DOS and Turbo C to
- * simplify the file, updated the code to compile cleanly on Visual
- * Studio 2005 with both unicode and multi-byte character strings,
- * removed rewinddir() as it had a bug.
- *
- * Aug 20, 2006, Toni Ronkko
- * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
- * comments by removing SGML tags.
- *
- * May 14 2002, Toni Ronkko
- * Embedded the function definitions directly to the header so that no
- * source modules need to be included in the Visual Studio project. Removed
- * all the dependencies to other projects so that this very header can be
- * used independently.
- *
- * May 28 1998, Toni Ronkko
- * First version.
- *****************************************************************************/
-#ifndef DIRENT_H
-#define DIRENT_H
-
-#include <windows.h>
-#include <string.h>
-#include <assert.h>
-
-
-typedef struct dirent
-{
- char d_name[MAX_PATH + 1]; /* current dir entry (multi-byte char string) */
- WIN32_FIND_DATAA data; /* file attributes */
-} dirent;
-
-
-typedef struct DIR
-{
- dirent current; /* Current directory entry */
- int cached; /* Indicates un-processed entry in memory */
- HANDLE search_handle; /* File search handle */
- char patt[MAX_PATH + 3]; /* search pattern (3 = pattern + "\\*\0") */
-} DIR;
-
-
-/* Forward declarations */
-static DIR *opendir (const char *dirname);
-static struct dirent *readdir (DIR *dirp);
-static int closedir (DIR *dirp);
-static void rewinddir(DIR* dirp);
-
-
-/* Use the new safe string functions introduced in Visual Studio 2005 */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-# define STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
-#else
-# define STRNCPY(dest,src,size) strncpy((dest),(src),(size))
-#endif
-
-
-/*****************************************************************************
- * Open directory stream DIRNAME for read and return a pointer to the
- * internal working area that is used to retrieve individual directory
- * entries.
- */
-static DIR *opendir(const char *dirname)
-{
- DIR *dirp;
- assert (dirname != NULL);
- assert (strlen (dirname) < MAX_PATH);
-
- /* construct new DIR structure */
- dirp = (DIR*) malloc (sizeof (struct DIR));
- if (dirp != NULL) {
- char *p;
-
- /* take directory name... */
- STRNCPY (dirp->patt, dirname, sizeof(dirp->patt));
- dirp->patt[MAX_PATH] = '\0';
-
- /* ... and append search pattern to it */
- p = strchr (dirp->patt, '\0');
- if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') {
- *p++ = '\\';
- }
- *p++ = '*';
- *p = '\0';
-
- /* open stream and retrieve first file */
- dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- /* invalid search pattern? */
- free (dirp);
- return NULL;
- }
-
- /* there is an un-processed directory entry in memory now */
- dirp->cached = 1;
- }
-
- return dirp;
-}
-
-
-/*****************************************************************************
- * Read a directory entry, and return a pointer to a dirent structure
- * containing the name of the entry in d_name field. Individual directory
- * entries returned by this very function include regular files,
- * sub-directories, pseudo-directories "." and "..", but also volume labels,
- * hidden files and system files may be returned.
- */
-static struct dirent *readdir(DIR *dirp)
-{
- assert (dirp != NULL);
-
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- /* directory stream was opened/rewound incorrectly or ended normally */
- return NULL;
- }
-
- /* get next directory entry */
- if (dirp->cached != 0) {
- /* a valid directory entry already in memory */
- dirp->cached = 0;
- } else {
- /* read next directory entry from disk */
- if (FindNextFileA (dirp->search_handle, &dirp->current.data) == FALSE) {
- /* the very last file has been processed or an error occured */
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- return NULL;
- }
- }
-
- /* copy as a multibyte character string */
- STRNCPY ( dirp->current.d_name,
- dirp->current.data.cFileName,
- sizeof(dirp->current.d_name) );
- dirp->current.d_name[MAX_PATH] = '\0';
-
- return &dirp->current;
-}
-
-
-/*****************************************************************************
- * Close directory stream opened by opendir() function. Close of the
- * directory stream invalidates the DIR structure as well as any previously
- * read directory entry.
- */
-static int closedir(DIR *dirp)
-{
- assert (dirp != NULL);
-
- /* release search handle */
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- }
-
- /* release directory handle */
- free (dirp);
- return 0;
-}
-
-
-/*****************************************************************************
- * Resets the position of the directory stream to which dirp refers to the
- * beginning of the directory. It also causes the directory stream to refer
- * to the current state of the corresponding directory, as a call to opendir()
- * would have done. If dirp does not refer to a directory stream, the effect
- * is undefined.
- */
-static void rewinddir(DIR* dirp)
-{
- /* release search handle */
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- }
-
- /* open new search handle and retrieve first file */
- dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- /* invalid search pattern? */
- free (dirp);
- return;
- }
-
- /* there is an un-processed directory entry in memory now */
- dirp->cached = 1;
-}
-
-
-#endif /*DIRENT_H*/
diff --git a/dep/libmpq/win/stdint.h b/dep/libmpq/win/stdint.h
deleted file mode 100644
index d02608a5972..00000000000
--- a/dep/libmpq/win/stdint.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2008 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
-extern "C" {
-#endif
-# include <wchar.h>
-#ifdef __cplusplus
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-# define _W64 __w64
-# else
-# define _W64
-# endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-#else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
-#endif
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef signed __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef _W64 signed int intptr_t;
- typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-#define INTMAX_C INT64_C
-#define UINTMAX_C UINT64_C
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-
-#endif // _MSC_STDINT_H_ ]
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 1f247a6b8ef..eb47e39e274 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -1,6 +1,6 @@
-- MySQL dump 10.13 Distrib 5.6.9-rc, for Win64 (x86_64)
--
--- Host: localhost Database: auth
+-- Host: localhost Database: auth_4x
-- ------------------------------------------------------
-- Server version 5.6.9-rc
@@ -37,7 +37,7 @@ CREATE TABLE `account` (
`lock_country` varchar(2) NOT NULL DEFAULT '00',
`last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
- `expansion` tinyint(3) unsigned NOT NULL DEFAULT '2',
+ `expansion` tinyint(3) unsigned NOT NULL DEFAULT '3',
`mutetime` bigint(20) NOT NULL DEFAULT '0',
`mutereason` varchar(255) NOT NULL DEFAULT '',
`muteby` varchar(50) NOT NULL DEFAULT '',
@@ -479,7 +479,7 @@ CREATE TABLE `realmlist` (
`timezone` tinyint(3) unsigned NOT NULL DEFAULT '0',
`allowedSecurityLevel` tinyint(3) unsigned NOT NULL DEFAULT '0',
`population` float unsigned NOT NULL DEFAULT '0',
- `gamebuild` int(10) unsigned NOT NULL DEFAULT '12340',
+ `gamebuild` int(10) unsigned NOT NULL DEFAULT '15595',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='Realm System';
@@ -491,7 +491,7 @@ CREATE TABLE `realmlist` (
LOCK TABLES `realmlist` WRITE;
/*!40000 ALTER TABLE `realmlist` DISABLE KEYS */;
-INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,12340);
+INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,15595);
/*!40000 ALTER TABLE `realmlist` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 46b6a1a2bdb..4f698c10288 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1,6 +1,6 @@
-- MySQL dump 10.13 Distrib 5.6.9-rc, for Win64 (x86_64)
--
--- Host: localhost Database: characters
+-- Host: localhost Database: characters_4x
-- ------------------------------------------------------
-- Server version 5.6.9-rc
@@ -593,6 +593,67 @@ LOCK TABLES `character_battleground_random` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `character_cuf_profiles`
+--
+
+DROP TABLE IF EXISTS `character_cuf_profiles`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_cuf_profiles` (
+ `guid` int(10) unsigned NOT NULL COMMENT 'Character Guid',
+ `id` tinyint(3) unsigned NOT NULL COMMENT 'Profile Id (0-4)',
+ `name` varchar(12) NOT NULL COMMENT 'Profile Name',
+ `frameHeight` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Height',
+ `frameWidth` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Width',
+ `sortBy` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Sort By',
+ `healthText` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Health Text',
+ `boolOptions` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Many Configurable Bool Options',
+ `unk146` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk147` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk148` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk150` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk152` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk154` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ PRIMARY KEY (`guid`,`id`),
+ KEY `index` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_cuf_profiles`
+--
+
+LOCK TABLES `character_cuf_profiles` WRITE;
+/*!40000 ALTER TABLE `character_cuf_profiles` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_cuf_profiles` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `character_currency`
+--
+
+DROP TABLE IF EXISTS `character_currency`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_currency` (
+ `guid` int(10) unsigned NOT NULL,
+ `currency` smallint(5) unsigned NOT NULL,
+ `total_count` int(10) unsigned NOT NULL,
+ `week_count` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`guid`,`currency`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_currency`
+--
+
+LOCK TABLES `character_currency` WRITE;
+/*!40000 ALTER TABLE `character_currency` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_currency` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `character_declinedname`
--
@@ -709,6 +770,9 @@ CREATE TABLE `character_glyphs` (
`glyph4` smallint(5) unsigned DEFAULT '0',
`glyph5` smallint(5) unsigned DEFAULT '0',
`glyph6` smallint(5) unsigned DEFAULT '0',
+ `glyph7` smallint(5) unsigned DEFAULT '0',
+ `glyph8` smallint(5) unsigned DEFAULT '0',
+ `glyph9` smallint(5) unsigned DEFAULT '0',
PRIMARY KEY (`guid`,`spec`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -823,7 +887,6 @@ CREATE TABLE `character_pet` (
`slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
`curhealth` int(10) unsigned NOT NULL DEFAULT '1',
`curmana` int(10) unsigned NOT NULL DEFAULT '0',
- `curhappiness` int(10) unsigned NOT NULL DEFAULT '0',
`savetime` int(10) unsigned NOT NULL DEFAULT '0',
`abdata` text,
PRIMARY KEY (`id`),
@@ -1168,8 +1231,6 @@ CREATE TABLE `character_stats` (
`maxpower3` int(10) unsigned NOT NULL DEFAULT '0',
`maxpower4` int(10) unsigned NOT NULL DEFAULT '0',
`maxpower5` int(10) unsigned NOT NULL DEFAULT '0',
- `maxpower6` int(10) unsigned NOT NULL DEFAULT '0',
- `maxpower7` int(10) unsigned NOT NULL DEFAULT '0',
`strength` int(10) unsigned NOT NULL DEFAULT '0',
`agility` int(10) unsigned NOT NULL DEFAULT '0',
`stamina` int(10) unsigned NOT NULL DEFAULT '0',
@@ -1230,6 +1291,36 @@ LOCK TABLES `character_talent` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `character_void_storage`
+--
+
+DROP TABLE IF EXISTS `character_void_storage`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_void_storage` (
+ `itemId` bigint(20) unsigned NOT NULL,
+ `playerGuid` int(10) unsigned NOT NULL,
+ `itemEntry` mediumint(8) unsigned NOT NULL,
+ `slot` tinyint(3) unsigned NOT NULL,
+ `creatorGuid` int(10) unsigned NOT NULL DEFAULT '0',
+ `randomProperty` int(10) unsigned NOT NULL DEFAULT '0',
+ `suffixFactor` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`itemId`),
+ UNIQUE KEY `idx_player_slot` (`playerGuid`,`slot`),
+ KEY `idx_player` (`playerGuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_void_storage`
+--
+
+LOCK TABLES `character_void_storage` WRITE;
+/*!40000 ALTER TABLE `character_void_storage` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_void_storage` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `characters`
--
@@ -1240,12 +1331,13 @@ CREATE TABLE `characters` (
`guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
`account` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Account Identifier',
`name` varchar(12) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
`race` tinyint(3) unsigned NOT NULL DEFAULT '0',
`class` tinyint(3) unsigned NOT NULL DEFAULT '0',
`gender` tinyint(3) unsigned NOT NULL DEFAULT '0',
`level` tinyint(3) unsigned NOT NULL DEFAULT '0',
`xp` int(10) unsigned NOT NULL DEFAULT '0',
- `money` int(10) unsigned NOT NULL DEFAULT '0',
+ `money` bigint(20) unsigned NOT NULL DEFAULT '0',
`playerBytes` int(10) unsigned NOT NULL DEFAULT '0',
`playerBytes2` int(10) unsigned NOT NULL DEFAULT '0',
`playerFlags` int(10) unsigned NOT NULL DEFAULT '0',
@@ -1266,6 +1358,7 @@ CREATE TABLE `characters` (
`rest_bonus` float NOT NULL DEFAULT '0',
`resettalents_cost` int(10) unsigned NOT NULL DEFAULT '0',
`resettalents_time` int(10) unsigned NOT NULL DEFAULT '0',
+ `talentTree` varchar(10) NOT NULL DEFAULT '0 0',
`trans_x` float NOT NULL DEFAULT '0',
`trans_y` float NOT NULL DEFAULT '0',
`trans_z` float NOT NULL DEFAULT '0',
@@ -1277,15 +1370,10 @@ CREATE TABLE `characters` (
`zone` smallint(5) unsigned NOT NULL DEFAULT '0',
`death_expire_time` int(10) unsigned NOT NULL DEFAULT '0',
`taxi_path` text,
- `arenaPoints` int(10) unsigned NOT NULL DEFAULT '0',
- `totalHonorPoints` int(10) unsigned NOT NULL DEFAULT '0',
- `todayHonorPoints` int(10) unsigned NOT NULL DEFAULT '0',
- `yesterdayHonorPoints` int(10) unsigned NOT NULL DEFAULT '0',
`totalKills` int(10) unsigned NOT NULL DEFAULT '0',
`todayKills` smallint(5) unsigned NOT NULL DEFAULT '0',
`yesterdayKills` smallint(5) unsigned NOT NULL DEFAULT '0',
`chosenTitle` int(10) unsigned NOT NULL DEFAULT '0',
- `knownCurrencies` bigint(20) unsigned NOT NULL DEFAULT '0',
`watchedFaction` int(10) unsigned NOT NULL DEFAULT '0',
`drunk` tinyint(3) unsigned NOT NULL DEFAULT '0',
`health` int(10) unsigned NOT NULL DEFAULT '0',
@@ -1294,14 +1382,11 @@ CREATE TABLE `characters` (
`power3` int(10) unsigned NOT NULL DEFAULT '0',
`power4` int(10) unsigned NOT NULL DEFAULT '0',
`power5` int(10) unsigned NOT NULL DEFAULT '0',
- `power6` int(10) unsigned NOT NULL DEFAULT '0',
- `power7` int(10) unsigned NOT NULL DEFAULT '0',
`latency` mediumint(8) unsigned NOT NULL DEFAULT '0',
`speccount` tinyint(3) unsigned NOT NULL DEFAULT '1',
`activespec` tinyint(3) unsigned NOT NULL DEFAULT '0',
`exploredZones` longtext,
`equipmentCache` longtext,
- `ammoId` int(10) unsigned NOT NULL DEFAULT '0',
`knownTitles` longtext,
`actionBars` tinyint(3) unsigned NOT NULL DEFAULT '0',
`grantableLevels` tinyint(3) unsigned NOT NULL DEFAULT '0',
@@ -1344,7 +1429,6 @@ CREATE TABLE `corpse` (
`itemCache` text NOT NULL,
`bytes1` int(10) unsigned NOT NULL DEFAULT '0',
`bytes2` int(10) unsigned NOT NULL DEFAULT '0',
- `guildId` int(10) unsigned NOT NULL DEFAULT '0',
`flags` tinyint(3) unsigned NOT NULL DEFAULT '0',
`dynFlags` tinyint(3) unsigned NOT NULL DEFAULT '0',
`time` int(10) unsigned NOT NULL DEFAULT '0',
@@ -1666,6 +1750,9 @@ CREATE TABLE `guild` (
`motd` varchar(128) NOT NULL DEFAULT '',
`createdate` int(10) unsigned NOT NULL DEFAULT '0',
`BankMoney` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `level` int(10) unsigned DEFAULT '1',
+ `experience` bigint(20) unsigned DEFAULT '0',
+ `todayExperience` bigint(20) unsigned DEFAULT '0',
PRIMARY KEY (`guildid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Guild System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -1680,6 +1767,57 @@ LOCK TABLES `guild` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `guild_achievement`
+--
+
+DROP TABLE IF EXISTS `guild_achievement`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_achievement` (
+ `guildId` int(10) unsigned NOT NULL,
+ `achievement` smallint(5) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ `guids` text NOT NULL,
+ PRIMARY KEY (`guildId`,`achievement`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_achievement`
+--
+
+LOCK TABLES `guild_achievement` WRITE;
+/*!40000 ALTER TABLE `guild_achievement` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_achievement` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `guild_achievement_progress`
+--
+
+DROP TABLE IF EXISTS `guild_achievement_progress`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_achievement_progress` (
+ `guildId` int(10) unsigned NOT NULL,
+ `criteria` smallint(5) unsigned NOT NULL,
+ `counter` int(10) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ `completedGuid` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`guildId`,`criteria`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_achievement_progress`
+--
+
+LOCK TABLES `guild_achievement_progress` WRITE;
+/*!40000 ALTER TABLE `guild_achievement_progress` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_achievement_progress` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `guild_bank_eventlog`
--
@@ -1825,6 +1963,62 @@ LOCK TABLES `guild_eventlog` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `guild_finder_applicant`
+--
+
+DROP TABLE IF EXISTS `guild_finder_applicant`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_finder_applicant` (
+ `guildId` int(10) unsigned DEFAULT NULL,
+ `playerGuid` int(10) unsigned DEFAULT NULL,
+ `availability` tinyint(3) unsigned DEFAULT '0',
+ `classRole` tinyint(3) unsigned DEFAULT '0',
+ `interests` tinyint(3) unsigned DEFAULT '0',
+ `comment` varchar(255) DEFAULT NULL,
+ `submitTime` int(10) unsigned DEFAULT NULL,
+ UNIQUE KEY `guildId` (`guildId`,`playerGuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_finder_applicant`
+--
+
+LOCK TABLES `guild_finder_applicant` WRITE;
+/*!40000 ALTER TABLE `guild_finder_applicant` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_finder_applicant` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `guild_finder_guild_settings`
+--
+
+DROP TABLE IF EXISTS `guild_finder_guild_settings`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_finder_guild_settings` (
+ `guildId` int(10) unsigned NOT NULL,
+ `availability` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `classRoles` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `interests` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `level` tinyint(3) unsigned NOT NULL DEFAULT '1',
+ `listed` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `comment` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`guildId`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_finder_guild_settings`
+--
+
+LOCK TABLES `guild_finder_guild_settings` WRITE;
+/*!40000 ALTER TABLE `guild_finder_guild_settings` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_finder_guild_settings` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `guild_member`
--
@@ -1867,6 +2061,8 @@ CREATE TABLE `guild_member_withdraw` (
`tab3` int(10) unsigned NOT NULL DEFAULT '0',
`tab4` int(10) unsigned NOT NULL DEFAULT '0',
`tab5` int(10) unsigned NOT NULL DEFAULT '0',
+ `tab6` int(10) unsigned NOT NULL DEFAULT '0',
+ `tab7` int(10) unsigned NOT NULL DEFAULT '0',
`money` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Guild Member Daily Withdraws';
@@ -1882,6 +2078,37 @@ LOCK TABLES `guild_member_withdraw` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `guild_news_log`
+--
+
+DROP TABLE IF EXISTS `guild_newslog`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_newslog` (
+ `guildid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Guild Identificator',
+ `LogGuid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Log record identificator - auxiliary column',
+ `EventType` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Event type',
+ `PlayerGuid` int(10) unsigned NOT NULL DEFAULT '0',
+ `Flags` int(10) unsigned NOT NULL DEFAULT '0',
+ `Value` int(10) unsigned NOT NULL DEFAULT '0',
+ `TimeStamp` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Event UNIX time',
+ PRIMARY KEY (`guildid`,`LogGuid`),
+ KEY `guildid_key` (`guildid`),
+ KEY `Idx_PlayerGuid` (`PlayerGuid`),
+ KEY `Idx_LogGuid` (`LogGuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_newslog`
+--
+
+LOCK TABLES `guild_newslog` WRITE;
+/*!40000 ALTER TABLE `guild_newslog` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_newslog` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `guild_rank`
--
@@ -2173,8 +2400,8 @@ CREATE TABLE `mail` (
`has_items` tinyint(3) unsigned NOT NULL DEFAULT '0',
`expire_time` int(10) unsigned NOT NULL DEFAULT '0',
`deliver_time` int(10) unsigned NOT NULL DEFAULT '0',
- `money` int(10) unsigned NOT NULL DEFAULT '0',
- `cod` int(10) unsigned NOT NULL DEFAULT '0',
+ `money` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `cod` bigint(20) unsigned NOT NULL DEFAULT '0',
`checked` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_receiver` (`receiver`)
diff --git a/sql/old/3.3.5a/2011_12_13_02_creature_template_addon.sql b/sql/old/3.3.5a/2011_12_13_02_creature_template_addon.sql
new file mode 100644
index 00000000000..2e7280927bf
--- /dev/null
+++ b/sql/old/3.3.5a/2011_12_13_02_creature_template_addon.sql
@@ -0,0 +1,2 @@
+-- Fix speed of oculus drakes
+UPDATE `creature_template_addon` SET `auras`='50325' WHERE `entry` IN (27755,27692,27756); \ No newline at end of file
diff --git a/sql/old/3.3.5a/2011_12_14_01_gameobject_template.sql b/sql/old/3.3.5a/2011_12_14_01_gameobject_template.sql
new file mode 100644
index 00000000000..12729afd6b8
--- /dev/null
+++ b/sql/old/3.3.5a/2011_12_14_01_gameobject_template.sql
@@ -0,0 +1 @@
+UPDATE `gameobject_template` SET `scriptName` = 'go_ethereal_teleport_pad' WHERE `entry` = 184073; -- Update Ethereal Teleport Pad scriptname \ No newline at end of file
diff --git a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_13_00_world_misc.sql b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_13_00_world_misc.sql
index 13958e75761..48848c368f1 100644
--- a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_13_00_world_misc.sql
+++ b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_13_00_world_misc.sql
@@ -3,4 +3,4 @@ INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`pr
(28012,0,0,'The trickster Mage-Lord Urom protects the third ring. He will appear alone and defenseless, but do not be fooled by appearences! Urom is a powerful conjurer who commands a menagerie of Phantasmal creatures. Seek him out above.',12,0,0,0,0,0,''),
(28012,1,1,'Your greatest challenge lies ahead. Ley-Guardian Eregos is a Blue dragon of immense power. You will find him flying above the uppermost ring.',12,0,0,0,0,0,'');
-UPDATE `creature_template` SET `ScriptName`='npc_image_belgaristrasz' WHERE `entry`=28012;
+UPDATE `creature_template` SET `ScriptName`='npc_image_belgaristrasz' WHERE `entry`=28012; \ No newline at end of file
diff --git a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_creature_template.sql b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_creature_template.sql
index 3ff9d630c54..156fd431359 100644
--- a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_creature_template.sql
+++ b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_creature_template.sql
@@ -1,4 +1,4 @@
-- Greater Fire Elemental script
UPDATE `creature_template` SET `ScriptName`='npc_fire_elemental' WHERE `entry`=15438;
-- Greater Earth Elemental script
-UPDATE `creature_template` SET `ScriptName`='npc_earth_elemental' WHERE `entry`=15352;
+UPDATE `creature_template` SET `ScriptName`='npc_earth_elemental' WHERE `entry`=15352; \ No newline at end of file
diff --git a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_spell_bonus_data.sql b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_spell_bonus_data.sql
index 5864b9ac042..3250bda4fdb 100644
--- a/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_spell_bonus_data.sql
+++ b/sql/old/3.3.5a/TDB44_to_TDB45_updates/world/2011_12_16_00_world_spell_bonus_data.sql
@@ -2,4 +2,4 @@
DELETE FROM `spell_bonus_data` WHERE `entry` IN (13376,57984);
INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`,`ap_bonus`, `ap_dot_bonus`, `comments`) VALUES
(13376,0.032,-1,-1,-1,'Greater Fire Elemental - Fire Shield'),
-(57984,0.4289,-1,-1,-1,'Greater Fire Elemental - Fire Blast');
+(57984,0.4289,-1,-1,-1,'Greater Fire Elemental - Fire Blast'); \ No newline at end of file
diff --git a/sql/old/3.3.5a/TDB48_to_TDB49_updates/world/2012_09_09_02_world_spell_script_names.sql b/sql/old/3.3.5a/TDB48_to_TDB49_updates/world/2012_09_09_02_world_spell_script_names.sql
index 36e5b08c36d..a4304663d9c 100644
--- a/sql/old/3.3.5a/TDB48_to_TDB49_updates/world/2012_09_09_02_world_spell_script_names.sql
+++ b/sql/old/3.3.5a/TDB48_to_TDB49_updates/world/2012_09_09_02_world_spell_script_names.sql
@@ -1,10 +1,4 @@
--- Gift of the Naaru
-DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_gift_of_naaru';
-INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
-(28880,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_WARRIOR
-(59542,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_PALADIN
-(59543,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_HUNTER
-(59544,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_PRIEST
-(59545,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_DEATHKNIGHT
-(59547,'spell_gen_gift_of_naaru'), -- SPELLFAMILY_SHAMAN
-(59548,'spell_gen_gift_of_naaru'); -- SPELLFAMILY_MAGE
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warl_banish','spell_warl_create_healthstone','spell_warl_ritual_of_doom_effect');
+INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES
+(710,'spell_warl_banish'),
+(6201,'spell_warl_create_healthstone');
diff --git a/sql/old/3.3.5a/TDB49_to_TDB50_updates/world/2012_12_18_00_characters_worldstates.sql b/sql/old/3.3.5a/TDB49_to_TDB50_updates/world/2012_12_18_00_characters_worldstates.sql
index 98fabde6776..c6fc15e60b7 100644
--- a/sql/old/3.3.5a/TDB49_to_TDB50_updates/world/2012_12_18_00_characters_worldstates.sql
+++ b/sql/old/3.3.5a/TDB49_to_TDB50_updates/world/2012_12_18_00_characters_worldstates.sql
@@ -1,4 +1,5 @@
-DELETE FROM `worldstates` WHERE `entry` IN (20004,20007);
+DELETE FROM `worldstates` WHERE `entry` IN (20004,20007,20050);
INSERT INTO `worldstates` (`entry`, `value`, `comment`) VALUES
(20004,0,'CleaningFlags'),
-(20007,0,'NextMonthlyQuestResetTime');
+(20007,0,'NextMonthlyQuestResetTime'),
+(20050,0,'NextWeeklyGuildResetTime');
diff --git a/sql/old/4.2.2/2011_11_24_01_world_command_4x.sql b/sql/old/4.2.2/2011_11_24_01_world_command_4x.sql
new file mode 100644
index 00000000000..849a7538621
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_24_01_world_command_4x.sql
@@ -0,0 +1,2 @@
+UPDATE `command` SET `help`='Syntax: .account set addon [$account] #addon\n\nSet user (possible targeted) expansion addon level allowed. Addon values: 0 - normal, 1 - tbc, 2 - wotlk, 3 - cata.' WHERE `name`='account set addon';
+UPDATE `command` SET `help`='Syntax: .account addon #addon\nSet expansion addon level allowed. Addon values: 0 - normal, 1 - tbc, 2 - wotlk, 3 - cata.' WHERE `name`='account addon';
diff --git a/sql/old/4.2.2/2011_11_24_02_world_player_xp_for_level_4x.sql b/sql/old/4.2.2/2011_11_24_02_world_player_xp_for_level_4x.sql
new file mode 100644
index 00000000000..d108b01824d
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_24_02_world_player_xp_for_level_4x.sql
@@ -0,0 +1,7 @@
+DELETE FROM `player_xp_for_level` WHERE `lvl` BETWEEN 80 AND 84;
+INSERT INTO `player_xp_for_level` (`lvl`, `xp_for_next_level`) VALUES
+(80, 1686300),
+(81, 2121500),
+(82, 4004000),
+(83, 5203400),
+(84, 9165100);
diff --git a/sql/old/4.2.2/2011_11_25_00_characters_character_stats_4x.sql b/sql/old/4.2.2/2011_11_25_00_characters_character_stats_4x.sql
new file mode 100644
index 00000000000..60506a491e3
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_00_characters_character_stats_4x.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `character_stats`
+ADD COLUMN `maxpower8` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `maxpower7`,
+ADD COLUMN `maxpower9` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `maxpower8`,
+ADD COLUMN `maxpower10` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `maxpower9`,
+ADD COLUMN `maxpower11` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `maxpower10`;
diff --git a/sql/old/4.2.2/2011_11_25_01_characters_characters_4x.sql b/sql/old/4.2.2/2011_11_25_01_characters_characters_4x.sql
new file mode 100644
index 00000000000..6e56aaf9aea
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_01_characters_characters_4x.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `characters`
+ADD COLUMN `power8` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `power7`,
+ADD COLUMN `power9` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `power8`,
+ADD COLUMN `power10` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `power9`,
+ADD COLUMN `power11` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `power10`;
diff --git a/sql/old/4.2.2/2011_11_25_02_characters_character_pet_4x.sql b/sql/old/4.2.2/2011_11_25_02_characters_character_pet_4x.sql
new file mode 100644
index 00000000000..61a1490b219
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_02_characters_character_pet_4x.sql
@@ -0,0 +1 @@
+ALTER TABLE `character_pet` DROP COLUMN `curhappiness`;
diff --git a/sql/old/4.2.2/2011_11_25_02_world_item_script_names_4x.sql b/sql/old/4.2.2/2011_11_25_02_world_item_script_names_4x.sql
new file mode 100644
index 00000000000..aaf843b91ae
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_02_world_item_script_names_4x.sql
@@ -0,0 +1,17 @@
+DROP TABLE IF EXISTS `item_script_names`;
+CREATE TABLE `item_script_names` (
+`Id` int(10) unsigned not null,
+`ScriptName` varchar(64) not null,
+PRIMARY KEY(`Id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
+
+INSERT INTO `item_script_names`
+SELECT
+`item_template`.`entry` AS `Id`,
+`item_template`.`ScriptName` AS `ScriptName`
+FROM
+`item_template`
+WHERE
+length(`item_template`.`ScriptName`)>0;
+
+ALTER TABLE `item_template` DROP `ScriptName`;
diff --git a/sql/old/4.2.2/2011_11_25_02_world_item_template_4x.sql b/sql/old/4.2.2/2011_11_25_02_world_item_template_4x.sql
new file mode 100644
index 00000000000..9580838fdb7
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_02_world_item_template_4x.sql
@@ -0,0 +1,43 @@
+ALTER TABLE `item_template`
+ ADD `stat_unk1_1` int(11) not null default 0 AFTER `stat_value1`,
+ ADD `stat_unk2_1` int(11) not null default 0 AFTER `stat_unk1_1`,
+ ADD `stat_unk1_2` int(11) not null default 0 AFTER `stat_value2`,
+ ADD `stat_unk2_2` int(11) not null default 0 AFTER `stat_unk1_2`,
+ ADD `stat_unk1_3` int(11) not null default 0 AFTER `stat_value3`,
+ ADD `stat_unk2_3` int(11) not null default 0 AFTER `stat_unk1_3`,
+ ADD `stat_unk1_4` int(11) not null default 0 AFTER `stat_value4`,
+ ADD `stat_unk2_4` int(11) not null default 0 AFTER `stat_unk1_4`,
+ ADD `stat_unk1_5` int(11) not null default 0 AFTER `stat_value5`,
+ ADD `stat_unk2_5` int(11) not null default 0 AFTER `stat_unk1_5`,
+ ADD `stat_unk1_6` int(11) not null default 0 AFTER `stat_value6`,
+ ADD `stat_unk2_6` int(11) not null default 0 AFTER `stat_unk1_6`,
+ ADD `stat_unk1_7` int(11) not null default 0 AFTER `stat_value7`,
+ ADD `stat_unk2_7` int(11) not null default 0 AFTER `stat_unk1_7`,
+ ADD `stat_unk1_8` int(11) not null default 0 AFTER `stat_value8`,
+ ADD `stat_unk2_8` int(11) not null default 0 AFTER `stat_unk1_8`,
+ ADD `stat_unk1_9` int(11) not null default 0 AFTER `stat_value9`,
+ ADD `stat_unk2_9` int(11) not null default 0 AFTER `stat_unk1_9`,
+ ADD `stat_unk1_10` int(11) not null default 0 AFTER `stat_value10`,
+ ADD `stat_unk2_10` int(11) not null default 0 AFTER `stat_unk1_10`,
+ DROP `StatsCount`,
+ DROP `ScalingStatValue`,
+ CHANGE `dmg_type1` `DamageType` tinyint(3) unsigned not null default 0 AFTER `ScalingStatDistribution`,
+ DROP `dmg_min1`,
+ DROP `dmg_max1`,
+ DROP `dmg_min2`,
+ DROP `dmg_max2`,
+ DROP `dmg_type2`,
+ DROP `armor`,
+ DROP `holy_res`,
+ DROP `fire_res`,
+ DROP `nature_res`,
+ DROP `frost_res`,
+ DROP `shadow_res`,
+ DROP `arcane_res`,
+ DROP `ammo_type`,
+ DROP `block`,
+ DROP `RequiredDisenchantSkill`,
+ DROP `DisenchantId`,
+ ADD `StatScalingFactor` float not null default 0 AFTER `HolidayId`,
+ ADD `Field130` int(11) not null default 0 AFTER `StatScalingFactor`,
+ ADD `Field131` int(11) not null default 0 AFTER `Field130`;
diff --git a/sql/old/4.2.2/2011_11_25_02_world_item_template_addon_4x.sql b/sql/old/4.2.2/2011_11_25_02_world_item_template_addon_4x.sql
new file mode 100644
index 00000000000..62692f00e6b
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_02_world_item_template_addon_4x.sql
@@ -0,0 +1,43 @@
+DROP TABLE IF EXISTS `item_template_addon`;
+CREATE TABLE `item_template_addon` (
+`Id` int(10) unsigned not null,
+`BuyCount` tinyint(3) unsigned not null default 1,
+`FoodType` tinyint(3) unsigned not null default 0,
+`MinMoneyLoot` int(10) unsigned not null default 0,
+`MaxMoneyLoot` int(10) unsigned not null default 0,
+`SpellPPMChance` float unsigned not null default 0,
+PRIMARY KEY(`Id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
+
+INSERT INTO `item_template_addon`
+SELECT
+`item_template`.`entry` AS `Id`,
+`item_template`.`BuyCount` AS `BuyCount`,
+`item_template`.`FoodType` AS `FoodType`,
+`item_template`.`minMoneyLoot` AS `MinMoneyLoot`,
+`item_template`.`maxMoneyLoot` AS `MaxMoneyLoot`,
+ABS(IF(`item_template`.`spelltrigger_1`=2, `item_template`.`spellppmRate_1`,
+ IF (`item_template`.`spelltrigger_2`=2, `item_template`.`spellppmRate_2`,
+ IF (`item_template`.`spelltrigger_3`=2, `item_template`.`spellppmRate_3`,
+ IF (`item_template`.`spelltrigger_4`=2, `item_template`.`spellppmRate_4`,
+ IF (`item_template`.`spelltrigger_5`=2, `item_template`.`spellppmRate_5`, 0))))))
+ AS `SpellPPMChance`
+FROM
+`item_template`
+HAVING -- need to use having due to `SpellPPMChance` usage which is not an actual field in table
+`item_template`.`BuyCount`!=1 OR
+`item_template`.`FoodType`!=0 OR
+(`item_template`.`minMoneyLoot`!=0 AND
+`item_template`.`maxMoneyLoot`!=0) OR
+`SpellPPMChance`!=0;
+
+ALTER TABLE `item_template`
+ DROP `BuyCount`,
+ DROP `FoodType`,
+ DROP `minMoneyLoot`,
+ DROP `maxMoneyLoot`,
+ DROP `spellppmRate_1`,
+ DROP `spellppmRate_2`,
+ DROP `spellppmRate_3`,
+ DROP `spellppmRate_4`,
+ DROP `spellppmRate_5`;
diff --git a/sql/old/4.2.2/2011_11_25_03_characters_character_stats_4x.sql b/sql/old/4.2.2/2011_11_25_03_characters_character_stats_4x.sql
new file mode 100644
index 00000000000..5f41b6e40db
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_03_characters_character_stats_4x.sql
@@ -0,0 +1,7 @@
+ALTER TABLE `character_stats`
+DROP COLUMN `maxpower6`,
+DROP COLUMN `maxpower7`,
+DROP COLUMN `maxpower8`,
+DROP COLUMN `maxpower9`,
+DROP COLUMN `maxpower10`,
+DROP COLUMN `maxpower11`;
diff --git a/sql/old/4.2.2/2011_11_25_03_characters_characters_4x.sql b/sql/old/4.2.2/2011_11_25_03_characters_characters_4x.sql
new file mode 100644
index 00000000000..cede344b6bf
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_03_characters_characters_4x.sql
@@ -0,0 +1,9 @@
+ALTER TABLE `characters`
+DROP COLUMN `power6`,
+DROP COLUMN `power7`,
+DROP COLUMN `power8`,
+DROP COLUMN `power9`,
+DROP COLUMN `power10`,
+DROP COLUMN `power11`,
+DROP COLUMN `ammoId`,
+ADD COLUMN `guildId` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `grantableLevels`;
diff --git a/sql/old/4.2.2/2011_11_25_03_characters_corpse_4x.sql b/sql/old/4.2.2/2011_11_25_03_characters_corpse_4x.sql
new file mode 100644
index 00000000000..e1823602b65
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_25_03_characters_corpse_4x.sql
@@ -0,0 +1 @@
+ALTER TABLE `corpse` DROP COLUMN `guildId`;
diff --git a/sql/old/4.2.2/2011_11_26_00_characters_characters_4x.sql b/sql/old/4.2.2/2011_11_26_00_characters_characters_4x.sql
new file mode 100644
index 00000000000..9fe2b4c804e
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_26_00_characters_characters_4x.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `characters`
+DROP COLUMN `todayHonorPoints`,
+DROP COLUMN `yesterdayHonorPoints`,
+DROP COLUMN `knownCurrencies`,
+CHANGE COLUMN `arenaPoints` `conquestPoints` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `taxi_path`;
diff --git a/sql/old/4.2.2/2011_11_26_02_world_quest_template_4x.sql b/sql/old/4.2.2/2011_11_26_02_world_quest_template_4x.sql
new file mode 100644
index 00000000000..b43abd6f85d
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_26_02_world_quest_template_4x.sql
@@ -0,0 +1,31 @@
+ALTER TABLE `quest_template` ADD COLUMN `MinimapTargetMark` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `SpecialFlags`,
+ ADD COLUMN `RewardSkillId` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardArenaPoints`,
+ ADD COLUMN `RewardSkillPoints` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardSkillId`,
+ ADD COLUMN `RewardReputationMask` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardSkillPoints`,
+ ADD COLUMN `QuestGiverPortrait` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardReputationMask`,
+ ADD COLUMN `QuestTurnInPortrait` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestGiverPortrait`,
+ ADD COLUMN `RequiredSpell` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredItemCount6`,
+ ADD COLUMN `RewardCurrencyId1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `ObjectiveText4`,
+ ADD COLUMN `RewardCurrencyId2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyId1`,
+ ADD COLUMN `RewardCurrencyId3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyId2`,
+ ADD COLUMN `RewardCurrencyId4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyId3`,
+ ADD COLUMN `RewardCurrencyCount1` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyId4`,
+ ADD COLUMN `RewardCurrencyCount2` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyCount1`,
+ ADD COLUMN `RewardCurrencyCount3` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyCount2`,
+ ADD COLUMN `RewardCurrencyCount4` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyCount3`,
+ ADD COLUMN `RequiredCurrencyId1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardCurrencyCount4`,
+ ADD COLUMN `RequiredCurrencyId2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyId1`,
+ ADD COLUMN `RequiredCurrencyId3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyId2`,
+ ADD COLUMN `RequiredCurrencyId4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyId3`,
+ ADD COLUMN `RequiredCurrencyCount1` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyId4`,
+ ADD COLUMN `RequiredCurrencyCount2` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyCount1`,
+ ADD COLUMN `RequiredCurrencyCount3` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyCount2`,
+ ADD COLUMN `RequiredCurrencyCount4` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredCurrencyCount3`,
+ ADD COLUMN `QuestGiverTextWindow` TEXT NULL DEFAULT NULL AFTER `RequiredCurrencyCount4`,
+ ADD COLUMN `QuestGiverTargetName` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow`,
+ ADD COLUMN `QuestTurnTextWindow` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName`,
+ ADD COLUMN `QuestTurnTargetName` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow`,
+ ADD COLUMN `SoundAccept` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '890' AFTER `QuestTurnTargetName`,
+ ADD COLUMN `SoundTurnIn` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '878' AFTER `SoundAccept`;
+
+ALTER TABLE `quest_template` DROP COLUMN `Unknown0`; -- Not found on 422
diff --git a/sql/old/4.2.2/2011_11_26_03_world_disenchant_loot_template_4x.sql b/sql/old/4.2.2/2011_11_26_03_world_disenchant_loot_template_4x.sql
new file mode 100644
index 00000000000..48f5d712533
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_26_03_world_disenchant_loot_template_4x.sql
@@ -0,0 +1,225 @@
+SET @LESSER_MAGIC = 10938;
+SET @GREATER_MAGIC = 10939;
+SET @STRANGE_DUST = 10940;
+SET @SMALL_GLIMMERING = 10978;
+SET @LESSER_ASTRAL = 10998;
+SET @GREATER_ASTRAL = 11082;
+SET @SOUL_DUST = 11083;
+SET @LARGE_GLIMMERING = 11084;
+SET @LESSER_MYSTIC = 11134;
+SET @GREATER_MYSTIC = 11135;
+SET @VISION_DUST = 11137;
+SET @SMALL_GLOWING = 11138;
+SET @LARGE_GLOWING = 11139;
+SET @LESSER_NETHER = 11174;
+SET @GREATER_NETHER = 11175;
+SET @DREAM_DUST = 11176;
+SET @SMALL_RADIANT = 11177;
+SET @LARGE_RADIANT = 11178;
+SET @SMALL_BRILLIANT = 14343;
+SET @LARGE_BRILLIANT = 14344;
+SET @LESSER_ETERNAL = 16202;
+SET @GREATER_ETERNAL = 16203;
+SET @ILLUSION_DUST = 16204;
+SET @NEXUS_CRYSTAL = 20725;
+SET @ARCANE_DUST = 22445;
+SET @GREATER_PLANAR = 22446;
+SET @LESSER_PLANAR = 22447;
+SET @SMALL_PRISMATIC = 22448;
+SET @LARGE_PRISMATIC = 22449;
+SET @VOID_CRYSTAL = 22450;
+SET @DREAM_SHARD = 34052;
+SET @SMALL_DREAM = 34053;
+SET @INFINITE_DUST = 34054;
+SET @GREATER_COSMIC = 34055;
+SET @LESSER_COSMIC = 34056;
+SET @ABYSS_CRYSTAL = 34057;
+SET @HEAVENLY_SHARD = 52721;
+SET @SMALL_HEAVENLY = 52720;
+SET @HYPN_DUST = 52555;
+SET @GREATER_CEL = 52719;
+SET @LESSER_CEL = 52718;
+SET @MAELSTROM_CRYSTAL = 52722;
+
+TRUNCATE `disenchant_loot_template`;
+INSERT INTO `disenchant_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
+(3,@STRANGE_DUST,20,1,1,1,2),
+(4,@STRANGE_DUST,80,1,1,1,2),
+(5,@STRANGE_DUST,75,1,1,2,3),
+(6,@STRANGE_DUST,20,1,1,2,3),
+(7,@STRANGE_DUST,15,1,1,4,6),
+(8,@STRANGE_DUST,75,1,1,4,6),
+(13,@SOUL_DUST,75,1,1,1,2),
+(14,@SOUL_DUST,20,1,1,1,2),
+(17,@SOUL_DUST,75,1,1,2,5),
+(18,@SOUL_DUST,20,1,1,2,5),
+(21,@VISION_DUST,75,1,1,1,2),
+(22,@VISION_DUST,20,1,1,1,2),
+(25,@VISION_DUST,75,1,1,2,5),
+(26,@VISION_DUST,20,1,1,2,5),
+(29,@DREAM_DUST,75,1,1,1,2),
+(30,@DREAM_DUST,20,1,1,1,2),
+(31,@DREAM_DUST,22,1,1,2,5),
+(32,@DREAM_DUST,75,1,1,2,5),
+(46,@ILLUSION_DUST,75,1,1,1,2),
+(47,@ILLUSION_DUST,22,1,1,1,2),
+(52,@ILLUSION_DUST,75,1,1,2,5),
+(53,@ILLUSION_DUST,22,1,1,2,5),
+(56,@ARCANE_DUST,75,1,1,1,3),
+(57,@ARCANE_DUST,22,1,1,1,2),
+(62,@ARCANE_DUST,22,1,1,2,5),
+(63,@ARCANE_DUST,75,1,1,2,5),
+(70,@ARCANE_DUST,75,1,1,2,3),
+(71,@ARCANE_DUST,22,1,1,2,3),
+(82,@INFINITE_DUST,75,1,1,1,3),
+(83,@INFINITE_DUST,22,1,1,1,3),
+(88,@INFINITE_DUST,75,1,1,4,7),
+(89,@INFINITE_DUST,22,1,1,4,7),
+(94,@HYPN_DUST,75,1,1,1,2),
+(95,@HYPN_DUST,75,1,1,1,3),
+(96,@HYPN_DUST,60,1,1,1,4),
+(97,@HYPN_DUST,80,1,1,2,4),
+(98,@HYPN_DUST,50,1,1,2,5),
+(99,@HYPN_DUST,25,1,1,1,2),
+(100,@HYPN_DUST,25,1,1,1,3),
+(101,@HYPN_DUST,35,1,1,1,4),
+(102,@HYPN_DUST,30,1,1,2,4),
+(103,@HYPN_DUST,30,1,1,2,5),
+(3,@LESSER_MAGIC,80,1,1,1,2),
+(4,@LESSER_MAGIC,20,1,1,1,2),
+(5,@GREATER_MAGIC,20,1,1,1,2),
+(6,@GREATER_MAGIC,75,1,1,1,2),
+(7,@LESSER_ASTRAL,75,1,1,1,2),
+(8,@LESSER_ASTRAL,15,1,1,1,2),
+(13,@GREATER_ASTRAL,20,1,1,1,2),
+(14,@GREATER_ASTRAL,75,1,1,1,2),
+(17,@LESSER_MYSTIC,20,1,1,1,2),
+(18,@LESSER_MYSTIC,75,1,1,1,2),
+(21,@GREATER_MYSTIC,20,1,1,1,2),
+(22,@GREATER_MYSTIC,75,1,1,1,2),
+(25,@LESSER_NETHER,20,1,1,1,2),
+(26,@LESSER_NETHER,75,1,1,1,2),
+(29,@GREATER_NETHER,20,1,1,1,2),
+(30,@GREATER_NETHER,75,1,1,1,2),
+(31,@LESSER_ETERNAL,75,1,1,1,2),
+(32,@LESSER_ETERNAL,20,1,1,1,2),
+(46,@GREATER_ETERNAL,20,1,1,1,2),
+(47,@GREATER_ETERNAL,75,1,1,1,2),
+(52,@GREATER_ETERNAL,20,1,1,2,3),
+(53,@GREATER_ETERNAL,75,1,1,2,3),
+(56,@LESSER_PLANAR,22,1,1,1,3),
+(57,@LESSER_PLANAR,75,1,1,1,2),
+(62,@GREATER_PLANAR,75,1,1,1,2),
+(63,@GREATER_PLANAR,22,1,1,1,2),
+(70,@LESSER_PLANAR,22,1,1,2,3),
+(71,@LESSER_PLANAR,75,1,1,2,3),
+(82,@LESSER_COSMIC,22,1,1,1,2),
+(83,@LESSER_COSMIC,75,1,1,1,2),
+(88,@GREATER_COSMIC,22,1,1,1,2),
+(89,@GREATER_COSMIC,75,1,1,1,2),
+(94,@LESSER_CEL,25,1,1,1,2),
+(95,@LESSER_CEL,25,1,1,1,3),
+(96,@LESSER_CEL,40,1,1,2,4),
+(97,@GREATER_CEL,20,1,1,1,2),
+(98,@GREATER_CEL,50,1,1,2,3),
+(99,@LESSER_CEL,75,1,1,1,2),
+(100,@LESSER_CEL,75,1,1,1,3),
+(101,@LESSER_CEL,65,1,1,2,4),
+(102,@GREATER_CEL,70,1,1,1,2),
+(103,@GREATER_CEL,70,1,1,2,3),
+(5,@SMALL_GLIMMERING,5,1,1,1,1),
+(6,@SMALL_GLIMMERING,5,1,1,1,1),
+(7,@SMALL_GLIMMERING,10,1,1,1,1),
+(8,@SMALL_GLIMMERING,10,1,1,1,1),
+(9,@SMALL_GLIMMERING,100,1,1,1,1),
+(10,@SMALL_GLIMMERING,100,1,1,1,1),
+(11,@LARGE_GLIMMERING,100,1,1,1,1),
+(12,@LARGE_GLIMMERING,100,1,1,1,1),
+(13,@LARGE_GLIMMERING,5,1,1,1,1),
+(14,@LARGE_GLIMMERING,5,1,1,1,1),
+(15,@SMALL_GLOWING,100,1,1,1,1),
+(16,@SMALL_GLOWING,100,1,1,1,1),
+(17,@SMALL_GLOWING,5,1,1,1,1),
+(18,@SMALL_GLOWING,5,1,1,1,1),
+(19,@LARGE_GLOWING,100,1,1,1,1),
+(20,@LARGE_GLOWING,100,1,1,1,1),
+(21,@LARGE_GLOWING,5,1,1,1,1),
+(22,@LARGE_GLOWING,5,1,1,1,1),
+(23,@SMALL_RADIANT,100,1,1,1,1),
+(24,@SMALL_RADIANT,100,1,1,1,1),
+(25,@SMALL_RADIANT,5,1,1,1,1),
+(26,@SMALL_RADIANT,5,1,1,1,1),
+(27,@LARGE_RADIANT,100,1,1,1,1),
+(28,@LARGE_RADIANT,100,1,1,1,1),
+(29,@LARGE_RADIANT,5,1,1,1,1),
+(30,@LARGE_RADIANT,5,1,1,1,1),
+(31,@SMALL_BRILLIANT,3,1,1,1,1),
+(32,@SMALL_BRILLIANT,5,1,1,1,1),
+(34,@SMALL_BRILLIANT,100,1,1,1,1),
+(35,@SMALL_BRILLIANT,100,1,1,1,1),
+(38,@SMALL_RADIANT,100,1,1,2,4),
+(39,@SMALL_RADIANT,100,1,1,2,4),
+(40,@LARGE_RADIANT,100,1,1,2,4),
+(41,@LARGE_RADIANT,100,1,1,2,4),
+(42,@SMALL_BRILLIANT,100,1,1,2,4),
+(43,@SMALL_BRILLIANT,100,1,1,2,4),
+(44,@LARGE_BRILLIANT,99.5,1,1,1,1),
+(45,@LARGE_BRILLIANT,99.5,1,1,1,1),
+(46,@LARGE_BRILLIANT,5,1,1,1,1),
+(47,@LARGE_BRILLIANT,3,1,1,1,1),
+(50,@SMALL_PRISMATIC,99.5,1,1,1,1),
+(51,@SMALL_PRISMATIC,99.5,1,1,1,1),
+(52,@LARGE_BRILLIANT,5,1,1,1,1),
+(53,@LARGE_BRILLIANT,3,1,1,1,1),
+(56,@SMALL_PRISMATIC,3,1,1,1,1),
+(57,@SMALL_PRISMATIC,3,1,1,1,1),
+(58,@SMALL_PRISMATIC,100,1,1,1,1),
+(59,@SMALL_PRISMATIC,100,1,1,1,1),
+(62,@LARGE_PRISMATIC,3,1,1,1,1),
+(63,@LARGE_PRISMATIC,3,1,1,1,1),
+(64,@LARGE_PRISMATIC,99.5,1,1,1,1),
+(65,@LARGE_PRISMATIC,99.5,1,1,1,1),
+(68,@SMALL_PRISMATIC,100,1,1,1,2),
+(69,@SMALL_PRISMATIC,100,1,1,1,2),
+(70,@SMALL_PRISMATIC,3,1,1,1,1),
+(71,@SMALL_PRISMATIC,3,1,1,1,1),
+(72,@SMALL_GLIMMERING,100,1,1,2,4),
+(73,@SMALL_GLIMMERING,100,1,1,2,4),
+(74,@LARGE_GLIMMERING,100,1,1,2,4),
+(75,@LARGE_GLIMMERING,100,1,1,2,4),
+(76,@SMALL_GLOWING,100,1,1,2,4),
+(77,@SMALL_GLOWING,100,1,1,2,4),
+(78,@LARGE_GLOWING,100,1,1,2,4),
+(79,@LARGE_GLOWING,100,1,1,2,4),
+(82,@SMALL_DREAM,3,1,1,1,1),
+(83,@SMALL_DREAM,3,1,1,1,1),
+(84,@SMALL_DREAM,100,1,1,1,1),
+(85,@SMALL_DREAM,100,1,1,1,1),
+(86,@DREAM_SHARD,99.5,1,1,1,1),
+(87,@DREAM_SHARD,99.5,1,1,1,1),
+(88,@DREAM_SHARD,3,1,1,1,1),
+(89,@DREAM_SHARD,3,1,1,1,1),
+(104,@SMALL_HEAVENLY,100,1,1,1,1),
+(105,@SMALL_HEAVENLY,100,1,1,1,2),
+(106,@HEAVENLY_SHARD,100,1,1,1,1),
+(107,@HEAVENLY_SHARD,100,1,1,1,1),
+(44,@NEXUS_CRYSTAL,0.5,1,1,1,1),
+(45,@NEXUS_CRYSTAL,0.5,1,1,1,1),
+(48,@NEXUS_CRYSTAL,100,1,1,1,1),
+(49,@NEXUS_CRYSTAL,100,1,1,1,1),
+(50,@NEXUS_CRYSTAL,0.5,1,1,1,1),
+(51,@NEXUS_CRYSTAL,0.5,1,1,1,1),
+(54,@NEXUS_CRYSTAL,100,1,1,1,2),
+(55,@NEXUS_CRYSTAL,100,1,1,1,2),
+(60,@NEXUS_CRYSTAL,100,1,1,1,2),
+(61,@NEXUS_CRYSTAL,100,1,1,1,2),
+(64,@VOID_CRYSTAL,0.5,1,1,1,1),
+(65,@VOID_CRYSTAL,0.5,1,1,1,1),
+(66,@VOID_CRYSTAL,100,1,1,1,2),
+(67,@VOID_CRYSTAL,100,1,1,1,2),
+(80,@ABYSS_CRYSTAL,100,1,1,1,1),
+(81,@ABYSS_CRYSTAL,100,1,1,1,1),
+(86,@ABYSS_CRYSTAL,0.5,1,1,1,1),
+(87,@ABYSS_CRYSTAL,0.5,1,1,1,1),
+(108,@MAELSTROM_CRYSTAL,100,1,1,1,1),
+(109,@MAELSTROM_CRYSTAL,100,1,1,1,1);
diff --git a/sql/old/4.2.2/2011_11_26_07_world_startinfo_4x.sql b/sql/old/4.2.2/2011_11_26_07_world_startinfo_4x.sql
new file mode 100644
index 00000000000..598b6ab72e6
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_26_07_world_startinfo_4x.sql
@@ -0,0 +1,4730 @@
+-- Races:
+SET @HUMAN := 1;
+SET @ORC := 2;
+SET @DWARF := 3;
+SET @NIGHT_ELF := 4;
+SET @UNDEAD := 5;
+SET @TAUREN := 6;
+SET @GNOME := 7;
+SET @TROLL := 8;
+SET @GOBLIN := 9;
+SET @BLOOD_ELF := 10;
+SET @DRAENEI := 11;
+SET @WORGEN := 22;
+-- Classes:
+SET @WARRIOR := 1;
+SET @PALADIN := 2;
+SET @HUNTER := 3;
+SET @ROGUE := 4;
+SET @PRIEST := 5;
+SET @DK := 6;
+SET @SHAMAN := 7;
+SET @MAGE := 8;
+SET @WARLOCK := 9;
+SET @DRUID := 11;
+
+-- Human char create:
+TRUNCATE TABLE `playercreateinfo_spell`;
+INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES
+-- Warrior Human
+(@HUMAN,@WARRIOR,202,'Two-Handed Swords'),
+(@HUMAN,@WARRIOR,196,'One-Handed Axes'),
+(@HUMAN,@WARRIOR,2457,'Battle Stance'),
+(@HUMAN,@WARRIOR,88161,'Strike'),
+(@HUMAN,@WARRIOR,5011,'Crossbows'),
+(@HUMAN,@WARRIOR,3018,'Shoot'),
+(@HUMAN,@WARRIOR,197,'Two-Handed Axes'),
+(@HUMAN,@WARRIOR,1180,'Daggers'),
+(@HUMAN,@WARRIOR,45927,'Summon Friend'),
+(@HUMAN,@WARRIOR,6478,'Opening'),
+(@HUMAN,@WARRIOR,6603,'Auto Attack'),
+(@HUMAN,@WARRIOR,22027,'Remove Insignia'),
+(@HUMAN,@WARRIOR,22810,'Opening - No Text'),
+(@HUMAN,@WARRIOR,21651,'Opening'),
+(@HUMAN,@WARRIOR,21652,'Closing'),
+(@HUMAN,@WARRIOR,2382,'Generic'),
+(@HUMAN,@WARRIOR,3365,'Opening'),
+(@HUMAN,@WARRIOR,3050,'Detect'),
+(@HUMAN,@WARRIOR,9125,'Generic'),
+(@HUMAN,@WARRIOR,8386,'Attacking'),
+(@HUMAN,@WARRIOR,7266,'Duel'),
+(@HUMAN,@WARRIOR,7267,'Grovel'),
+(@HUMAN,@WARRIOR,7355,'Stuck'),
+(@HUMAN,@WARRIOR,6233,'Closing'),
+(@HUMAN,@WARRIOR,6246,'Closing'),
+(@HUMAN,@WARRIOR,6247,'Opening'),
+(@HUMAN,@WARRIOR,6477,'Opening'),
+(@HUMAN,@WARRIOR,61437,'Opening'),
+(@HUMAN,@WARRIOR,68398,'Opening'),
+(@HUMAN,@WARRIOR,96220,'Opening'),
+(@HUMAN,@WARRIOR,203,'Unarmed'),
+(@HUMAN,@WARRIOR,20864,'Mace Specialization'),
+(@HUMAN,@WARRIOR,20599,'Diplomacy'),
+(@HUMAN,@WARRIOR,20597,'Sword Specialization'),
+(@HUMAN,@WARRIOR,20598,'The Human Spirit'),
+(@HUMAN,@WARRIOR,59752,'Every Man for Himself'),
+(@HUMAN,@WARRIOR,79738,'Languages'),
+(@HUMAN,@WARRIOR,49410,'Forceful Deflection'),
+(@HUMAN,@WARRIOR,199,'Two-Handed Maces'),
+(@HUMAN,@WARRIOR,15590,'Fist Weapons'),
+(@HUMAN,@WARRIOR,76268,'Armor Skills'),
+(@HUMAN,@WARRIOR,76290,'Weapon Skills'),
+(@HUMAN,@WARRIOR,88163,'Attack'),
+(@HUMAN,@WARRIOR,200,'Polearms'),
+(@HUMAN,@WARRIOR,668,'Language Common'),
+(@HUMAN,@WARRIOR,227,'Staves'),
+(@HUMAN,@WARRIOR,9116,'Shield'),
+(@HUMAN,@WARRIOR,8737,'Mail'),
+(@HUMAN,@WARRIOR,9077,'Leather'),
+(@HUMAN,@WARRIOR,264,'Bows'),
+(@HUMAN,@WARRIOR,266,'Guns'),
+(@HUMAN,@WARRIOR,107,'Block'),
+(@HUMAN,@WARRIOR,81,'Dodge'),
+(@HUMAN,@WARRIOR,32215,'Victorious State'),
+(@HUMAN,@WARRIOR,5301,'Defensive State (DND)'),
+(@HUMAN,@WARRIOR,204,'Defense'),
+(@HUMAN,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@WARRIOR,2764,'Throw'),
+(@HUMAN,@WARRIOR,2567,'Thrown'),
+(@HUMAN,@WARRIOR,9078,'Cloth'),
+(@HUMAN,@WARRIOR,198,'One-Handed Maces'),
+(@HUMAN,@WARRIOR,201,'One-Handed Swords'),
+-- Palading Human
+(@HUMAN,@PALADIN,202,'Two-Handed Swords'),
+(@HUMAN,@PALADIN,196,'One-Handed Axes'),
+(@HUMAN,@PALADIN,197,'Two-Handed Axes'),
+(@HUMAN,@PALADIN,45927,'Summon Friend'),
+(@HUMAN,@PALADIN,6478,'Opening'),
+(@HUMAN,@PALADIN,6603,'Auto Attack'),
+(@HUMAN,@PALADIN,22027,'Remove Insignia'),
+(@HUMAN,@PALADIN,22810,'Opening - No Text'),
+(@HUMAN,@PALADIN,21651,'Opening'),
+(@HUMAN,@PALADIN,21652,'Closing'),
+(@HUMAN,@PALADIN,2382,'Generic'),
+(@HUMAN,@PALADIN,3365,'Opening'),
+(@HUMAN,@PALADIN,3050,'Detect'),
+(@HUMAN,@PALADIN,9125,'Generic'),
+(@HUMAN,@PALADIN,8386,'Attacking'),
+(@HUMAN,@PALADIN,7266,'Duel'),
+(@HUMAN,@PALADIN,7267,'Grovel'),
+(@HUMAN,@PALADIN,7355,'Stuck'),
+(@HUMAN,@PALADIN,6233,'Closing'),
+(@HUMAN,@PALADIN,6246,'Closing'),
+(@HUMAN,@PALADIN,6247,'Opening'),
+(@HUMAN,@PALADIN,6477,'Opening'),
+(@HUMAN,@PALADIN,27762,'Relic'),
+(@HUMAN,@PALADIN,61437,'Opening'),
+(@HUMAN,@PALADIN,68398,'Opening'),
+(@HUMAN,@PALADIN,96220,'Opening'),
+(@HUMAN,@PALADIN,49410,'Forceful Deflection'),
+(@HUMAN,@PALADIN,203,'Unarmed'),
+(@HUMAN,@PALADIN,20864,'Mace Specialization'),
+(@HUMAN,@PALADIN,20599,'Diplomacy'),
+(@HUMAN,@PALADIN,20597,'Sword Specialization'),
+(@HUMAN,@PALADIN,20598,'The Human Spirit'),
+(@HUMAN,@PALADIN,59752,'Every Man for Himself'),
+(@HUMAN,@PALADIN,79738,'Languages'),
+(@HUMAN,@PALADIN,199,'Two-Handed Maces'),
+(@HUMAN,@PALADIN,76271,'Armor Skills'),
+(@HUMAN,@PALADIN,76294,'Weapon Skills'),
+(@HUMAN,@PALADIN,200,'Polearms'),
+(@HUMAN,@PALADIN,668,'Language Common'),
+(@HUMAN,@PALADIN,35395,'Crusader Strike'),
+(@HUMAN,@PALADIN,60091,'Judgement Anti-Parry/Dodge Passive'),
+(@HUMAN,@PALADIN,9116,'Shield'),
+(@HUMAN,@PALADIN,8737,'Mail'),
+(@HUMAN,@PALADIN,9077,'Leather'),
+(@HUMAN,@PALADIN,107,'Block'),
+(@HUMAN,@PALADIN,81,'Dodge'),
+(@HUMAN,@PALADIN,204,'Defense'),
+(@HUMAN,@PALADIN,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@PALADIN,9078,'Cloth'),
+(@HUMAN,@PALADIN,20208,'Paladin pushback resistance'),
+(@HUMAN,@PALADIN,198,'One-Handed Maces'),
+(@HUMAN,@PALADIN,201,'One-Handed Swords'),
+-- Hunter Human
+(@HUMAN,@HUNTER,202,'Two-Handed Swords'),
+(@HUMAN,@HUNTER,196,'One-Handed Axes'),
+(@HUMAN,@HUNTER,3044,'Arcane Shot'),
+(@HUMAN,@HUNTER,75,'Auto Shot'),
+(@HUMAN,@HUNTER,82928,'Aimed Shot!'),
+(@HUMAN,@HUNTER,5011,'Crossbows'),
+(@HUMAN,@HUNTER,197,'Two-Handed Axes'),
+(@HUMAN,@HUNTER,1180,'Daggers'),
+(@HUMAN,@HUNTER,45927,'Summon Friend'),
+(@HUMAN,@HUNTER,6478,'Opening'),
+(@HUMAN,@HUNTER,6603,'Auto Attack'),
+(@HUMAN,@HUNTER,22027,'Remove Insignia'),
+(@HUMAN,@HUNTER,22810,'Opening - No Text'),
+(@HUMAN,@HUNTER,21651,'Opening'),
+(@HUMAN,@HUNTER,21652,'Closing'),
+(@HUMAN,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@HUMAN,@HUNTER,2382,'Generic'),
+(@HUMAN,@HUNTER,3365,'Opening'),
+(@HUMAN,@HUNTER,3050,'Detect'),
+(@HUMAN,@HUNTER,9125,'Generic'),
+(@HUMAN,@HUNTER,8386,'Attacking'),
+(@HUMAN,@HUNTER,7266,'Duel'),
+(@HUMAN,@HUNTER,7267,'Grovel'),
+(@HUMAN,@HUNTER,7355,'Stuck'),
+(@HUMAN,@HUNTER,6233,'Closing'),
+(@HUMAN,@HUNTER,6246,'Closing'),
+(@HUMAN,@HUNTER,6247,'Opening'),
+(@HUMAN,@HUNTER,6477,'Opening'),
+(@HUMAN,@HUNTER,61437,'Opening'),
+(@HUMAN,@HUNTER,68398,'Opening'),
+(@HUMAN,@HUNTER,96220,'Opening'),
+(@HUMAN,@HUNTER,203,'Unarmed'),
+(@HUMAN,@HUNTER,883,'Call Pet 1'),
+(@HUMAN,@HUNTER,982,'Revive Pet'),
+(@HUMAN,@HUNTER,20864,'Mace Specialization'),
+(@HUMAN,@HUNTER,20599,'Diplomacy'),
+(@HUMAN,@HUNTER,20597,'Sword Specialization'),
+(@HUMAN,@HUNTER,20598,'The Human Spirit'),
+(@HUMAN,@HUNTER,59752,'Every Man for Himself'),
+(@HUMAN,@HUNTER,79738,'Languages'),
+(@HUMAN,@HUNTER,15590,'Fist Weapons'),
+(@HUMAN,@HUNTER,200,'Polearms'),
+(@HUMAN,@HUNTER,668,'Language Common'),
+(@HUMAN,@HUNTER,227,'Staves'),
+(@HUMAN,@HUNTER,9077,'Leather'),
+(@HUMAN,@HUNTER,264,'Bows'),
+(@HUMAN,@HUNTER,266,'Guns'),
+(@HUMAN,@HUNTER,13358,'Defensive State (DND)'),
+(@HUMAN,@HUNTER,81,'Dodge'),
+(@HUMAN,@HUNTER,204,'Defense'),
+(@HUMAN,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@HUMAN,@HUNTER,9078,'Cloth'),
+(@HUMAN,@HUNTER,77442,'Focus'),
+(@HUMAN,@HUNTER,76249,'Weapon Skills'),
+(@HUMAN,@HUNTER,76250,'Armor Skills'),
+(@HUMAN,@HUNTER,87324,'Focused Aim'),
+(@HUMAN,@HUNTER,87816,'General Hunter Passives'),
+(@HUMAN,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Human
+(@HUMAN,@ROGUE,196,'One-Handed Axes'),
+(@HUMAN,@ROGUE,1752,'Sinister Strike'),
+(@HUMAN,@ROGUE,5011,'Crossbows'),
+(@HUMAN,@ROGUE,3018,'Shoot'),
+(@HUMAN,@ROGUE,674,'Dual Wield'),
+(@HUMAN,@ROGUE,1180,'Daggers'),
+(@HUMAN,@ROGUE,45927,'Summon Friend'),
+(@HUMAN,@ROGUE,6478,'Opening'),
+(@HUMAN,@ROGUE,6603,'Auto Attack'),
+(@HUMAN,@ROGUE,22027,'Remove Insignia'),
+(@HUMAN,@ROGUE,22810,'Opening - No Text'),
+(@HUMAN,@ROGUE,21651,'Opening'),
+(@HUMAN,@ROGUE,21652,'Closing'),
+(@HUMAN,@ROGUE,2382,'Generic'),
+(@HUMAN,@ROGUE,3365,'Opening'),
+(@HUMAN,@ROGUE,3050,'Detect'),
+(@HUMAN,@ROGUE,9125,'Generic'),
+(@HUMAN,@ROGUE,8386,'Attacking'),
+(@HUMAN,@ROGUE,7266,'Duel'),
+(@HUMAN,@ROGUE,7267,'Grovel'),
+(@HUMAN,@ROGUE,7355,'Stuck'),
+(@HUMAN,@ROGUE,6233,'Closing'),
+(@HUMAN,@ROGUE,6246,'Closing'),
+(@HUMAN,@ROGUE,6247,'Opening'),
+(@HUMAN,@ROGUE,6477,'Opening'),
+(@HUMAN,@ROGUE,61437,'Opening'),
+(@HUMAN,@ROGUE,68398,'Opening'),
+(@HUMAN,@ROGUE,96220,'Opening'),
+(@HUMAN,@ROGUE,203,'Unarmed'),
+(@HUMAN,@ROGUE,20864,'Mace Specialization'),
+(@HUMAN,@ROGUE,20599,'Diplomacy'),
+(@HUMAN,@ROGUE,20597,'Sword Specialization'),
+(@HUMAN,@ROGUE,20598,'The Human Spirit'),
+(@HUMAN,@ROGUE,59752,'Every Man for Himself'),
+(@HUMAN,@ROGUE,79738,'Languages'),
+(@HUMAN,@ROGUE,15590,'Fist Weapons'),
+(@HUMAN,@ROGUE,76273,'Armor Skills'),
+(@HUMAN,@ROGUE,76297,'Weapon Skills'),
+(@HUMAN,@ROGUE,668,'Language Common'),
+(@HUMAN,@ROGUE,9077,'Leather'),
+(@HUMAN,@ROGUE,264,'Bows'),
+(@HUMAN,@ROGUE,266,'Guns'),
+(@HUMAN,@ROGUE,81,'Dodge'),
+(@HUMAN,@ROGUE,204,'Defense'),
+(@HUMAN,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@ROGUE,16092,'Defensive State (DND)'),
+(@HUMAN,@ROGUE,2764,'Throw'),
+(@HUMAN,@ROGUE,2567,'Thrown'),
+(@HUMAN,@ROGUE,9078,'Cloth'),
+(@HUMAN,@ROGUE,198,'One-Handed Maces'),
+(@HUMAN,@ROGUE,201,'One-Handed Swords'),
+-- Priest Human
+(@HUMAN,@PRIEST,5009,'Wands'),
+(@HUMAN,@PRIEST,5019,'Shoot'),
+(@HUMAN,@PRIEST,1180,'Daggers'),
+(@HUMAN,@PRIEST,45927,'Summon Friend'),
+(@HUMAN,@PRIEST,6478,'Opening'),
+(@HUMAN,@PRIEST,6603,'Auto Attack'),
+(@HUMAN,@PRIEST,22027,'Remove Insignia'),
+(@HUMAN,@PRIEST,22810,'Opening - No Text'),
+(@HUMAN,@PRIEST,21651,'Opening'),
+(@HUMAN,@PRIEST,21652,'Closing'),
+(@HUMAN,@PRIEST,2382,'Generic'),
+(@HUMAN,@PRIEST,3365,'Opening'),
+(@HUMAN,@PRIEST,3050,'Detect'),
+(@HUMAN,@PRIEST,9125,'Generic'),
+(@HUMAN,@PRIEST,8386,'Attacking'),
+(@HUMAN,@PRIEST,7266,'Duel'),
+(@HUMAN,@PRIEST,7267,'Grovel'),
+(@HUMAN,@PRIEST,7355,'Stuck'),
+(@HUMAN,@PRIEST,6233,'Closing'),
+(@HUMAN,@PRIEST,6246,'Closing'),
+(@HUMAN,@PRIEST,6247,'Opening'),
+(@HUMAN,@PRIEST,6477,'Opening'),
+(@HUMAN,@PRIEST,61437,'Opening'),
+(@HUMAN,@PRIEST,68398,'Opening'),
+(@HUMAN,@PRIEST,96220,'Opening'),
+(@HUMAN,@PRIEST,203,'Unarmed'),
+(@HUMAN,@PRIEST,585,'Smite'),
+(@HUMAN,@PRIEST,84733,'Holy Focus'),
+(@HUMAN,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@HUMAN,@PRIEST,88684,'Holy Word: Serenity'),
+(@HUMAN,@PRIEST,101062,'Flash Heal'),
+(@HUMAN,@PRIEST,20864,'Mace Specialization'),
+(@HUMAN,@PRIEST,20599,'Diplomacy'),
+(@HUMAN,@PRIEST,20597,'Sword Specialization'),
+(@HUMAN,@PRIEST,20598,'The Human Spirit'),
+(@HUMAN,@PRIEST,59752,'Every Man for Himself'),
+(@HUMAN,@PRIEST,79738,'Languages'),
+(@HUMAN,@PRIEST,76301,'Weapon Skills'),
+(@HUMAN,@PRIEST,76279,'Armor Skills'),
+(@HUMAN,@PRIEST,84734,'Dark Thoughts'),
+(@HUMAN,@PRIEST,668,'Language Common'),
+(@HUMAN,@PRIEST,227,'Staves'),
+(@HUMAN,@PRIEST,77486,'Shadow Orb Power'),
+(@HUMAN,@PRIEST,81,'Dodge'),
+(@HUMAN,@PRIEST,204,'Defense'),
+(@HUMAN,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@PRIEST,9078,'Cloth'),
+(@HUMAN,@PRIEST,198,'One-Handed Maces'),
+-- Mage Human
+(@HUMAN,@MAGE,71761,'Deep Freeze Immunity State'),
+(@HUMAN,@MAGE,5009,'Wands'),
+(@HUMAN,@MAGE,5019,'Shoot'),
+(@HUMAN,@MAGE,1180,'Daggers'),
+(@HUMAN,@MAGE,45927,'Summon Friend'),
+(@HUMAN,@MAGE,6478,'Opening'),
+(@HUMAN,@MAGE,6603,'Auto Attack'),
+(@HUMAN,@MAGE,22027,'Remove Insignia'),
+(@HUMAN,@MAGE,22810,'Opening - No Text'),
+(@HUMAN,@MAGE,21651,'Opening'),
+(@HUMAN,@MAGE,21652,'Closing'),
+(@HUMAN,@MAGE,2382,'Generic'),
+(@HUMAN,@MAGE,3365,'Opening'),
+(@HUMAN,@MAGE,3050,'Detect'),
+(@HUMAN,@MAGE,9125,'Generic'),
+(@HUMAN,@MAGE,8386,'Attacking'),
+(@HUMAN,@MAGE,7266,'Duel'),
+(@HUMAN,@MAGE,7267,'Grovel'),
+(@HUMAN,@MAGE,7355,'Stuck'),
+(@HUMAN,@MAGE,6233,'Closing'),
+(@HUMAN,@MAGE,6246,'Closing'),
+(@HUMAN,@MAGE,6247,'Opening'),
+(@HUMAN,@MAGE,6477,'Opening'),
+(@HUMAN,@MAGE,61437,'Opening'),
+(@HUMAN,@MAGE,68398,'Opening'),
+(@HUMAN,@MAGE,96220,'Opening'),
+(@HUMAN,@MAGE,79684,'Offensive State (DND)'),
+(@HUMAN,@MAGE,203,'Unarmed'),
+(@HUMAN,@MAGE,20864,'Mace Specialization'),
+(@HUMAN,@MAGE,20599,'Diplomacy'),
+(@HUMAN,@MAGE,20597,'Sword Specialization'),
+(@HUMAN,@MAGE,20598,'The Human Spirit'),
+(@HUMAN,@MAGE,59752,'Every Man for Himself'),
+(@HUMAN,@MAGE,79738,'Languages'),
+(@HUMAN,@MAGE,133,'Fireball'),
+(@HUMAN,@MAGE,92315,'Pyroblast!'),
+(@HUMAN,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@HUMAN,@MAGE,76298,'Weapon Skills'),
+(@HUMAN,@MAGE,76276,'Armor Skills'),
+(@HUMAN,@MAGE,668,'Language Common'),
+(@HUMAN,@MAGE,227,'Staves'),
+(@HUMAN,@MAGE,81,'Dodge'),
+(@HUMAN,@MAGE,204,'Defense'),
+(@HUMAN,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@MAGE,9078,'Cloth'),
+(@HUMAN,@MAGE,201,'One-Handed Swords'),
+-- Warlock Human
+(@HUMAN,@WARLOCK,5009,'Wands'),
+(@HUMAN,@WARLOCK,5019,'Shoot'),
+(@HUMAN,@WARLOCK,1180,'Daggers'),
+(@HUMAN,@WARLOCK,45927,'Summon Friend'),
+(@HUMAN,@WARLOCK,6478,'Opening'),
+(@HUMAN,@WARLOCK,6603,'Auto Attack'),
+(@HUMAN,@WARLOCK,22027,'Remove Insignia'),
+(@HUMAN,@WARLOCK,22810,'Opening - No Text'),
+(@HUMAN,@WARLOCK,21651,'Opening'),
+(@HUMAN,@WARLOCK,21652,'Closing'),
+(@HUMAN,@WARLOCK,2382,'Generic'),
+(@HUMAN,@WARLOCK,3365,'Opening'),
+(@HUMAN,@WARLOCK,3050,'Detect'),
+(@HUMAN,@WARLOCK,9125,'Generic'),
+(@HUMAN,@WARLOCK,8386,'Attacking'),
+(@HUMAN,@WARLOCK,7266,'Duel'),
+(@HUMAN,@WARLOCK,7267,'Grovel'),
+(@HUMAN,@WARLOCK,7355,'Stuck'),
+(@HUMAN,@WARLOCK,6233,'Closing'),
+(@HUMAN,@WARLOCK,6246,'Closing'),
+(@HUMAN,@WARLOCK,6247,'Opening'),
+(@HUMAN,@WARLOCK,6477,'Opening'),
+(@HUMAN,@WARLOCK,61437,'Opening'),
+(@HUMAN,@WARLOCK,68398,'Opening'),
+(@HUMAN,@WARLOCK,96220,'Opening'),
+(@HUMAN,@WARLOCK,203,'Unarmed'),
+(@HUMAN,@WARLOCK,20864,'Mace Specialization'),
+(@HUMAN,@WARLOCK,20599,'Diplomacy'),
+(@HUMAN,@WARLOCK,20597,'Sword Specialization'),
+(@HUMAN,@WARLOCK,20598,'The Human Spirit'),
+(@HUMAN,@WARLOCK,59752,'Every Man for Himself'),
+(@HUMAN,@WARLOCK,79738,'Languages'),
+(@HUMAN,@WARLOCK,688,'Summon Imp'),
+(@HUMAN,@WARLOCK,86213,'Soul Swap Exhale'),
+(@HUMAN,@WARLOCK,89420,'Drain Life'),
+(@HUMAN,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@HUMAN,@WARLOCK,76299,'Weapon Skills'),
+(@HUMAN,@WARLOCK,76277,'Armor Skills'),
+(@HUMAN,@WARLOCK,87330,'Suppression'),
+(@HUMAN,@WARLOCK,668,'Language Common'),
+(@HUMAN,@WARLOCK,227,'Staves'),
+(@HUMAN,@WARLOCK,75445,'Demonic Immolate'),
+(@HUMAN,@WARLOCK,686,'Shadow Bolt'),
+(@HUMAN,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@HUMAN,@WARLOCK,81,'Dodge'),
+(@HUMAN,@WARLOCK,204,'Defense'),
+(@HUMAN,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@HUMAN,@WARLOCK,9078,'Cloth'),
+(@HUMAN,@WARLOCK,201,'One-Handed Swords'),
+-- Orc char create:
+-- Warrior Orc
+(@ORC,@WARRIOR,202,'Two-Handed Swords'),
+(@ORC,@WARRIOR,196,'One-Handed Axes'),
+(@ORC,@WARRIOR,2457,'Battle Stance'),
+(@ORC,@WARRIOR,88161,'Strike'),
+(@ORC,@WARRIOR,5011,'Crossbows'),
+(@ORC,@WARRIOR,3018,'Shoot'),
+(@ORC,@WARRIOR,669,'Language Orcish'),
+(@ORC,@WARRIOR,197,'Two-Handed Axes'),
+(@ORC,@WARRIOR,1180,'Daggers'),
+(@ORC,@WARRIOR,45927,'Summon Friend'),
+(@ORC,@WARRIOR,6478,'Opening'),
+(@ORC,@WARRIOR,6603,'Auto Attack'),
+(@ORC,@WARRIOR,22027,'Remove Insignia'),
+(@ORC,@WARRIOR,22810,'Opening - No Text'),
+(@ORC,@WARRIOR,21651,'Opening'),
+(@ORC,@WARRIOR,21652,'Closing'),
+(@ORC,@WARRIOR,2382,'Generic'),
+(@ORC,@WARRIOR,3365,'Opening'),
+(@ORC,@WARRIOR,3050,'Detect'),
+(@ORC,@WARRIOR,9125,'Generic'),
+(@ORC,@WARRIOR,8386,'Attacking'),
+(@ORC,@WARRIOR,7266,'Duel'),
+(@ORC,@WARRIOR,7267,'Grovel'),
+(@ORC,@WARRIOR,7355,'Stuck'),
+(@ORC,@WARRIOR,6233,'Closing'),
+(@ORC,@WARRIOR,6246,'Closing'),
+(@ORC,@WARRIOR,6247,'Opening'),
+(@ORC,@WARRIOR,6477,'Opening'),
+(@ORC,@WARRIOR,61437,'Opening'),
+(@ORC,@WARRIOR,68398,'Opening'),
+(@ORC,@WARRIOR,96220,'Opening'),
+(@ORC,@WARRIOR,203,'Unarmed'),
+(@ORC,@WARRIOR,49410,'Forceful Deflection'),
+(@ORC,@WARRIOR,21563,'Command'),
+(@ORC,@WARRIOR,20572,'Blood Fury'),
+(@ORC,@WARRIOR,20573,'Hardiness'),
+(@ORC,@WARRIOR,20574,'Axe Specialization'),
+(@ORC,@WARRIOR,79743,'Languages'),
+(@ORC,@WARRIOR,199,'Two-Handed Maces'),
+(@ORC,@WARRIOR,15590,'Fist Weapons'),
+(@ORC,@WARRIOR,76268,'Armor Skills'),
+(@ORC,@WARRIOR,76290,'Weapon Skills'),
+(@ORC,@WARRIOR,88163,'Attack'),
+(@ORC,@WARRIOR,200,'Polearms'),
+(@ORC,@WARRIOR,227,'Staves'),
+(@ORC,@WARRIOR,9116,'Shield'),
+(@ORC,@WARRIOR,8737,'Mail'),
+(@ORC,@WARRIOR,9077,'Leather'),
+(@ORC,@WARRIOR,264,'Bows'),
+(@ORC,@WARRIOR,266,'Guns'),
+(@ORC,@WARRIOR,107,'Block'),
+(@ORC,@WARRIOR,81,'Dodge'),
+(@ORC,@WARRIOR,32215,'Victorious State'),
+(@ORC,@WARRIOR,5301,'Defensive State (DND)'),
+(@ORC,@WARRIOR,204,'Defense'),
+(@ORC,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@ORC,@WARRIOR,2764,'Throw'),
+(@ORC,@WARRIOR,2567,'Thrown'),
+(@ORC,@WARRIOR,9078,'Cloth'),
+(@ORC,@WARRIOR,198,'One-Handed Maces'),
+(@ORC,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Orc
+(@ORC,@HUNTER,202,'Two-Handed Swords'),
+(@ORC,@HUNTER,196,'One-Handed Axes'),
+(@ORC,@HUNTER,3044,'Arcane Shot'),
+(@ORC,@HUNTER,75,'Auto Shot'),
+(@ORC,@HUNTER,82928,'Aimed Shot!'),
+(@ORC,@HUNTER,5011,'Crossbows'),
+(@ORC,@HUNTER,669,'Language Orcish'),
+(@ORC,@HUNTER,197,'Two-Handed Axes'),
+(@ORC,@HUNTER,1180,'Daggers'),
+(@ORC,@HUNTER,45927,'Summon Friend'),
+(@ORC,@HUNTER,6478,'Opening'),
+(@ORC,@HUNTER,6603,'Auto Attack'),
+(@ORC,@HUNTER,22027,'Remove Insignia'),
+(@ORC,@HUNTER,22810,'Opening - No Text'),
+(@ORC,@HUNTER,21651,'Opening'),
+(@ORC,@HUNTER,21652,'Closing'),
+(@ORC,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@ORC,@HUNTER,2382,'Generic'),
+(@ORC,@HUNTER,3365,'Opening'),
+(@ORC,@HUNTER,3050,'Detect'),
+(@ORC,@HUNTER,9125,'Generic'),
+(@ORC,@HUNTER,8386,'Attacking'),
+(@ORC,@HUNTER,7266,'Duel'),
+(@ORC,@HUNTER,7267,'Grovel'),
+(@ORC,@HUNTER,7355,'Stuck'),
+(@ORC,@HUNTER,6233,'Closing'),
+(@ORC,@HUNTER,6246,'Closing'),
+(@ORC,@HUNTER,6247,'Opening'),
+(@ORC,@HUNTER,6477,'Opening'),
+(@ORC,@HUNTER,61437,'Opening'),
+(@ORC,@HUNTER,68398,'Opening'),
+(@ORC,@HUNTER,96220,'Opening'),
+(@ORC,@HUNTER,203,'Unarmed'),
+(@ORC,@HUNTER,883,'Call Pet 1'),
+(@ORC,@HUNTER,982,'Revive Pet'),
+(@ORC,@HUNTER,20572,'Blood Fury'),
+(@ORC,@HUNTER,20573,'Hardiness'),
+(@ORC,@HUNTER,20574,'Axe Specialization'),
+(@ORC,@HUNTER,20576,'Command'),
+(@ORC,@HUNTER,79743,'Languages'),
+(@ORC,@HUNTER,15590,'Fist Weapons'),
+(@ORC,@HUNTER,200,'Polearms'),
+(@ORC,@HUNTER,227,'Staves'),
+(@ORC,@HUNTER,9077,'Leather'),
+(@ORC,@HUNTER,264,'Bows'),
+(@ORC,@HUNTER,266,'Guns'),
+(@ORC,@HUNTER,13358,'Defensive State (DND)'),
+(@ORC,@HUNTER,81,'Dodge'),
+(@ORC,@HUNTER,204,'Defense'),
+(@ORC,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@ORC,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@ORC,@HUNTER,9078,'Cloth'),
+(@ORC,@HUNTER,77442,'Focus'),
+(@ORC,@HUNTER,76249,'Weapon Skills'),
+(@ORC,@HUNTER,76250,'Armor Skills'),
+(@ORC,@HUNTER,87324,'Focused Aim'),
+(@ORC,@HUNTER,87816,'General Hunter Passives'),
+(@ORC,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Orc
+(@ORC,@ROGUE,196,'One-Handed Axes'),
+(@ORC,@ROGUE,1752,'Sinister Strike'),
+(@ORC,@ROGUE,5011,'Crossbows'),
+(@ORC,@ROGUE,3018,'Shoot'),
+(@ORC,@ROGUE,669,'Language Orcish'),
+(@ORC,@ROGUE,674,'Dual Wield'),
+(@ORC,@ROGUE,1180,'Daggers'),
+(@ORC,@ROGUE,45927,'Summon Friend'),
+(@ORC,@ROGUE,6478,'Opening'),
+(@ORC,@ROGUE,6603,'Auto Attack'),
+(@ORC,@ROGUE,22027,'Remove Insignia'),
+(@ORC,@ROGUE,22810,'Opening - No Text'),
+(@ORC,@ROGUE,21651,'Opening'),
+(@ORC,@ROGUE,21652,'Closing'),
+(@ORC,@ROGUE,2382,'Generic'),
+(@ORC,@ROGUE,3365,'Opening'),
+(@ORC,@ROGUE,3050,'Detect'),
+(@ORC,@ROGUE,9125,'Generic'),
+(@ORC,@ROGUE,8386,'Attacking'),
+(@ORC,@ROGUE,7266,'Duel'),
+(@ORC,@ROGUE,7267,'Grovel'),
+(@ORC,@ROGUE,7355,'Stuck'),
+(@ORC,@ROGUE,6233,'Closing'),
+(@ORC,@ROGUE,6246,'Closing'),
+(@ORC,@ROGUE,6247,'Opening'),
+(@ORC,@ROGUE,6477,'Opening'),
+(@ORC,@ROGUE,61437,'Opening'),
+(@ORC,@ROGUE,68398,'Opening'),
+(@ORC,@ROGUE,96220,'Opening'),
+(@ORC,@ROGUE,203,'Unarmed'),
+(@ORC,@ROGUE,21563,'Command'),
+(@ORC,@ROGUE,20572,'Blood Fury'),
+(@ORC,@ROGUE,20573,'Hardiness'),
+(@ORC,@ROGUE,20574,'Axe Specialization'),
+(@ORC,@ROGUE,79743,'Languages'),
+(@ORC,@ROGUE,15590,'Fist Weapons'),
+(@ORC,@ROGUE,76273,'Armor Skills'),
+(@ORC,@ROGUE,76297,'Weapon Skills'),
+(@ORC,@ROGUE,9077,'Leather'),
+(@ORC,@ROGUE,264,'Bows'),
+(@ORC,@ROGUE,266,'Guns'),
+(@ORC,@ROGUE,81,'Dodge'),
+(@ORC,@ROGUE,204,'Defense'),
+(@ORC,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@ORC,@ROGUE,16092,'Defensive State (DND)'),
+(@ORC,@ROGUE,2764,'Throw'),
+(@ORC,@ROGUE,2567,'Thrown'),
+(@ORC,@ROGUE,9078,'Cloth'),
+(@ORC,@ROGUE,198,'One-Handed Maces'),
+(@ORC,@ROGUE,201,'One-Handed Swords'),
+-- Shaman Orc
+(@ORC,@SHAMAN,196,'One-Handed Axes'),
+(@ORC,@SHAMAN,669,'Language Orcish'),
+(@ORC,@SHAMAN,197,'Two-Handed Axes'),
+(@ORC,@SHAMAN,1180,'Daggers'),
+(@ORC,@SHAMAN,45927,'Summon Friend'),
+(@ORC,@SHAMAN,6478,'Opening'),
+(@ORC,@SHAMAN,6603,'Auto Attack'),
+(@ORC,@SHAMAN,22027,'Remove Insignia'),
+(@ORC,@SHAMAN,22810,'Opening - No Text'),
+(@ORC,@SHAMAN,21651,'Opening'),
+(@ORC,@SHAMAN,21652,'Closing'),
+(@ORC,@SHAMAN,2382,'Generic'),
+(@ORC,@SHAMAN,3365,'Opening'),
+(@ORC,@SHAMAN,3050,'Detect'),
+(@ORC,@SHAMAN,9125,'Generic'),
+(@ORC,@SHAMAN,8386,'Attacking'),
+(@ORC,@SHAMAN,7266,'Duel'),
+(@ORC,@SHAMAN,7267,'Grovel'),
+(@ORC,@SHAMAN,7355,'Stuck'),
+(@ORC,@SHAMAN,6233,'Closing'),
+(@ORC,@SHAMAN,6246,'Closing'),
+(@ORC,@SHAMAN,6247,'Opening'),
+(@ORC,@SHAMAN,6477,'Opening'),
+(@ORC,@SHAMAN,27763,'Relic'),
+(@ORC,@SHAMAN,61437,'Opening'),
+(@ORC,@SHAMAN,68398,'Opening'),
+(@ORC,@SHAMAN,96220,'Opening'),
+(@ORC,@SHAMAN,203,'Unarmed'),
+(@ORC,@SHAMAN,20573,'Hardiness'),
+(@ORC,@SHAMAN,20574,'Axe Specialization'),
+(@ORC,@SHAMAN,65222,'Command'),
+(@ORC,@SHAMAN,79743,'Languages'),
+(@ORC,@SHAMAN,33697,'Blood Fury'),
+(@ORC,@SHAMAN,199,'Two-Handed Maces'),
+(@ORC,@SHAMAN,15590,'Fist Weapons'),
+(@ORC,@SHAMAN,76272,'Armor Skills'),
+(@ORC,@SHAMAN,76296,'Weapon Skills'),
+(@ORC,@SHAMAN,89920,'Ancestral Focus'),
+(@ORC,@SHAMAN,227,'Staves'),
+(@ORC,@SHAMAN,9116,'Shield'),
+(@ORC,@SHAMAN,9077,'Leather'),
+(@ORC,@SHAMAN,107,'Block'),
+(@ORC,@SHAMAN,81,'Dodge'),
+(@ORC,@SHAMAN,204,'Defense'),
+(@ORC,@SHAMAN,522,'SPELLDEFENSE (DND)'),
+(@ORC,@SHAMAN,403,'Lightning Bolt'),
+(@ORC,@SHAMAN,9078,'Cloth'),
+(@ORC,@SHAMAN,198,'One-Handed Maces'),
+-- Mage Orc
+(@ORC,@MAGE,71761,'Deep Freeze Immunity State'),
+(@ORC,@MAGE,5009,'Wands'),
+(@ORC,@MAGE,5019,'Shoot'),
+(@ORC,@MAGE,669,'Language Orcish'),
+(@ORC,@MAGE,1180,'Daggers'),
+(@ORC,@MAGE,45927,'Summon Friend'),
+(@ORC,@MAGE,6478,'Opening'),
+(@ORC,@MAGE,6603,'Auto Attack'),
+(@ORC,@MAGE,22027,'Remove Insignia'),
+(@ORC,@MAGE,22810,'Opening - No Text'),
+(@ORC,@MAGE,21651,'Opening'),
+(@ORC,@MAGE,21652,'Closing'),
+(@ORC,@MAGE,2382,'Generic'),
+(@ORC,@MAGE,3365,'Opening'),
+(@ORC,@MAGE,3050,'Detect'),
+(@ORC,@MAGE,9125,'Generic'),
+(@ORC,@MAGE,8386,'Attacking'),
+(@ORC,@MAGE,7266,'Duel'),
+(@ORC,@MAGE,7267,'Grovel'),
+(@ORC,@MAGE,7355,'Stuck'),
+(@ORC,@MAGE,6233,'Closing'),
+(@ORC,@MAGE,6246,'Closing'),
+(@ORC,@MAGE,6247,'Opening'),
+(@ORC,@MAGE,6477,'Opening'),
+(@ORC,@MAGE,61437,'Opening'),
+(@ORC,@MAGE,68398,'Opening'),
+(@ORC,@MAGE,96220,'Opening'),
+(@ORC,@MAGE,79684,'Offensive State (DND)'),
+(@ORC,@MAGE,203,'Unarmed'),
+(@ORC,@MAGE,21563,'Command'),
+(@ORC,@MAGE,33702,'Blood Fury'),
+(@ORC,@MAGE,20573,'Hardiness'),
+(@ORC,@MAGE,20574,'Axe Specialization'),
+(@ORC,@MAGE,79743,'Languages'),
+(@ORC,@MAGE,133,'Fireball'),
+(@ORC,@MAGE,92315,'Pyroblast!'),
+(@ORC,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@ORC,@MAGE,76298,'Weapon Skills'),
+(@ORC,@MAGE,76276,'Armor Skills'),
+(@ORC,@MAGE,227,'Staves'),
+(@ORC,@MAGE,81,'Dodge'),
+(@ORC,@MAGE,204,'Defense'),
+(@ORC,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@ORC,@MAGE,9078,'Cloth'),
+(@ORC,@MAGE,201,'One-Handed Swords'),
+-- Warlock Orc
+(@ORC,@WARLOCK,5009,'Wands'),
+(@ORC,@WARLOCK,5019,'Shoot'),
+(@ORC,@WARLOCK,669,'Language Common'),
+(@ORC,@WARLOCK,1180,'Daggers'),
+(@ORC,@WARLOCK,45927,'Summon Friend'),
+(@ORC,@WARLOCK,6478,'Opening'),
+(@ORC,@WARLOCK,6603,'Auto Attack'),
+(@ORC,@WARLOCK,22027,'Remove Insignia'),
+(@ORC,@WARLOCK,22810,'Opening - No Text'),
+(@ORC,@WARLOCK,21651,'Opening'),
+(@ORC,@WARLOCK,21652,'Closing'),
+(@ORC,@WARLOCK,2382,'Generic'),
+(@ORC,@WARLOCK,3365,'Opening'),
+(@ORC,@WARLOCK,3050,'Detect'),
+(@ORC,@WARLOCK,9125,'Generic'),
+(@ORC,@WARLOCK,8386,'Attacking'),
+(@ORC,@WARLOCK,7266,'Duel'),
+(@ORC,@WARLOCK,7267,'Grovel'),
+(@ORC,@WARLOCK,7355,'Stuck'),
+(@ORC,@WARLOCK,6233,'Closing'),
+(@ORC,@WARLOCK,6246,'Closing'),
+(@ORC,@WARLOCK,6247,'Opening'),
+(@ORC,@WARLOCK,6477,'Opening'),
+(@ORC,@WARLOCK,61437,'Opening'),
+(@ORC,@WARLOCK,68398,'Opening'),
+(@ORC,@WARLOCK,96220,'Opening'),
+(@ORC,@WARLOCK,203,'Unarmed'),
+(@ORC,@WARLOCK,33702,'Blood Fury'),
+(@ORC,@WARLOCK,20573,'Hardiness'),
+(@ORC,@WARLOCK,20574,'Axe Specialization'),
+(@ORC,@WARLOCK,79743,'Languages'),
+(@ORC,@WARLOCK,688,'Summon Imp'),
+(@ORC,@WARLOCK,86213,'Soul Swap Exhale'),
+(@ORC,@WARLOCK,89420,'Drain Life'),
+(@ORC,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@ORC,@WARLOCK,76299,'Weapon Skills'),
+(@ORC,@WARLOCK,76277,'Armor Skills'),
+(@ORC,@WARLOCK,87330,'Suppression'),
+(@ORC,@WARLOCK,227,'Staves'),
+(@ORC,@WARLOCK,75445,'Demonic Immolate'),
+(@ORC,@WARLOCK,686,'Shadow Bolt'),
+(@ORC,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@ORC,@WARLOCK,81,'Dodge'),
+(@ORC,@WARLOCK,204,'Defense'),
+(@ORC,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@ORC,@WARLOCK,9078,'Cloth'),
+(@ORC,@WARLOCK,201,'One-Handed Swords'),
+-- Dwarf char create:
+-- Warrior Dwarf
+(@DWARF,@WARRIOR,202,'Two-Handed Swords'),
+(@DWARF,@WARRIOR,196,'One-Handed Axes'),
+(@DWARF,@WARRIOR,2457,'Battle Stance'),
+(@DWARF,@WARRIOR,88161,'Strike'),
+(@DWARF,@WARRIOR,5011,'Crossbows'),
+(@DWARF,@WARRIOR,3018,'Shoot'),
+(@DWARF,@WARRIOR,197,'Two-Handed Axes'),
+(@DWARF,@WARRIOR,1180,'Daggers'),
+(@DWARF,@WARRIOR,45927,'Summon Friend'),
+(@DWARF,@WARRIOR,6478,'Opening'),
+(@DWARF,@WARRIOR,6603,'Auto Attack'),
+(@DWARF,@WARRIOR,22027,'Remove Insignia'),
+(@DWARF,@WARRIOR,22810,'Opening - No Text'),
+(@DWARF,@WARRIOR,21651,'Opening'),
+(@DWARF,@WARRIOR,21652,'Closing'),
+(@DWARF,@WARRIOR,2382,'Generic'),
+(@DWARF,@WARRIOR,3365,'Opening'),
+(@DWARF,@WARRIOR,3050,'Detect'),
+(@DWARF,@WARRIOR,9125,'Generic'),
+(@DWARF,@WARRIOR,8386,'Attacking'),
+(@DWARF,@WARRIOR,7266,'Duel'),
+(@DWARF,@WARRIOR,7267,'Grovel'),
+(@DWARF,@WARRIOR,7355,'Stuck'),
+(@DWARF,@WARRIOR,6233,'Closing'),
+(@DWARF,@WARRIOR,6246,'Closing'),
+(@DWARF,@WARRIOR,6247,'Opening'),
+(@DWARF,@WARRIOR,6477,'Opening'),
+(@DWARF,@WARRIOR,61437,'Opening'),
+(@DWARF,@WARRIOR,68398,'Opening'),
+(@DWARF,@WARRIOR,96220,'Opening'),
+(@DWARF,@WARRIOR,203,'Unarmed'),
+(@DWARF,@WARRIOR,20596,'Frost Resistance'),
+(@DWARF,@WARRIOR,20595,'Gun Specialization'),
+(@DWARF,@WARRIOR,20594,'Stoneform'),
+(@DWARF,@WARRIOR,59224,'Mace Specialization'),
+(@DWARF,@WARRIOR,92682,'Explorer'),
+(@DWARF,@WARRIOR,79739,'Languages'),
+(@DWARF,@WARRIOR,672,'Language Dwarven'),
+(@DWARF,@WARRIOR,49410,'Forceful Deflection'),
+(@DWARF,@WARRIOR,199,'Two-Handed Maces'),
+(@DWARF,@WARRIOR,15590,'Fist Weapons'),
+(@DWARF,@WARRIOR,76268,'Armor Skills'),
+(@DWARF,@WARRIOR,76290,'Weapon Skills'),
+(@DWARF,@WARRIOR,88163,'Attack'),
+(@DWARF,@WARRIOR,200,'Polearms'),
+(@DWARF,@WARRIOR,668,'Language Common'),
+(@DWARF,@WARRIOR,227,'Staves'),
+(@DWARF,@WARRIOR,9116,'Shield'),
+(@DWARF,@WARRIOR,8737,'Mail'),
+(@DWARF,@WARRIOR,9077,'Leather'),
+(@DWARF,@WARRIOR,264,'Bows'),
+(@DWARF,@WARRIOR,266,'Guns'),
+(@DWARF,@WARRIOR,107,'Block'),
+(@DWARF,@WARRIOR,81,'Dodge'),
+(@DWARF,@WARRIOR,32215,'Victorious State'),
+(@DWARF,@WARRIOR,5301,'Defensive State (DND)'),
+(@DWARF,@WARRIOR,204,'Defense'),
+(@DWARF,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@WARRIOR,2764,'Throw'),
+(@DWARF,@WARRIOR,2567,'Thrown'),
+(@DWARF,@WARRIOR,9078,'Cloth'),
+(@DWARF,@WARRIOR,198,'One-Handed Maces'),
+(@DWARF,@WARRIOR,201,'One-Handed Swords'),
+-- Palading Dwarf
+(@DWARF,@PALADIN,202,'Two-Handed Swords'),
+(@DWARF,@PALADIN,196,'One-Handed Axes'),
+(@DWARF,@PALADIN,197,'Two-Handed Axes'),
+(@DWARF,@PALADIN,45927,'Summon Friend'),
+(@DWARF,@PALADIN,6478,'Opening'),
+(@DWARF,@PALADIN,6603,'Auto Attack'),
+(@DWARF,@PALADIN,22027,'Remove Insignia'),
+(@DWARF,@PALADIN,22810,'Opening - No Text'),
+(@DWARF,@PALADIN,21651,'Opening'),
+(@DWARF,@PALADIN,21652,'Closing'),
+(@DWARF,@PALADIN,2382,'Generic'),
+(@DWARF,@PALADIN,3365,'Opening'),
+(@DWARF,@PALADIN,3050,'Detect'),
+(@DWARF,@PALADIN,9125,'Generic'),
+(@DWARF,@PALADIN,8386,'Attacking'),
+(@DWARF,@PALADIN,7266,'Duel'),
+(@DWARF,@PALADIN,7267,'Grovel'),
+(@DWARF,@PALADIN,7355,'Stuck'),
+(@DWARF,@PALADIN,6233,'Closing'),
+(@DWARF,@PALADIN,6246,'Closing'),
+(@DWARF,@PALADIN,6247,'Opening'),
+(@DWARF,@PALADIN,6477,'Opening'),
+(@DWARF,@PALADIN,27762,'Relic'),
+(@DWARF,@PALADIN,61437,'Opening'),
+(@DWARF,@PALADIN,68398,'Opening'),
+(@DWARF,@PALADIN,96220,'Opening'),
+(@DWARF,@PALADIN,49410,'Forceful Deflection'),
+(@DWARF,@PALADIN,203,'Unarmed'),
+(@DWARF,@PALADIN,20596,'Frost Resistance'),
+(@DWARF,@PALADIN,20595,'Gun Specialization'),
+(@DWARF,@PALADIN,20594,'Stoneform'),
+(@DWARF,@PALADIN,59224,'Mace Specialization'),
+(@DWARF,@PALADIN,92682,'Explorer'),
+(@DWARF,@PALADIN,79739,'Languages'),
+(@DWARF,@PALADIN,672,'Language Dwarven'),
+(@DWARF,@PALADIN,199,'Two-Handed Maces'),
+(@DWARF,@PALADIN,76271,'Armor Skills'),
+(@DWARF,@PALADIN,76294,'Weapon Skills'),
+(@DWARF,@PALADIN,200,'Polearms'),
+(@DWARF,@PALADIN,668,'Language Common'),
+(@DWARF,@PALADIN,35395,'Crusader Strike'),
+(@DWARF,@PALADIN,60091,'Judgement Anti-Parry/Dodge Passive'),
+(@DWARF,@PALADIN,9116,'Shield'),
+(@DWARF,@PALADIN,8737,'Mail'),
+(@DWARF,@PALADIN,9077,'Leather'),
+(@DWARF,@PALADIN,107,'Block'),
+(@DWARF,@PALADIN,81,'Dodge'),
+(@DWARF,@PALADIN,204,'Defense'),
+(@DWARF,@PALADIN,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@PALADIN,9078,'Cloth'),
+(@DWARF,@PALADIN,20208,'Paladin pushback resistance'),
+(@DWARF,@PALADIN,198,'One-Handed Maces'),
+(@DWARF,@PALADIN,201,'One-Handed Swords'),
+-- Hunter Dwarf
+(@DWARF,@HUNTER,202,'Two-Handed Swords'),
+(@DWARF,@HUNTER,196,'One-Handed Axes'),
+(@DWARF,@HUNTER,3044,'Arcane Shot'),
+(@DWARF,@HUNTER,75,'Auto Shot'),
+(@DWARF,@HUNTER,82928,'Aimed Shot!'),
+(@DWARF,@HUNTER,5011,'Crossbows'),
+(@DWARF,@HUNTER,197,'Two-Handed Axes'),
+(@DWARF,@HUNTER,1180,'Daggers'),
+(@DWARF,@HUNTER,45927,'Summon Friend'),
+(@DWARF,@HUNTER,6478,'Opening'),
+(@DWARF,@HUNTER,6603,'Auto Attack'),
+(@DWARF,@HUNTER,22027,'Remove Insignia'),
+(@DWARF,@HUNTER,22810,'Opening - No Text'),
+(@DWARF,@HUNTER,21651,'Opening'),
+(@DWARF,@HUNTER,21652,'Closing'),
+(@DWARF,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@DWARF,@HUNTER,2382,'Generic'),
+(@DWARF,@HUNTER,3365,'Opening'),
+(@DWARF,@HUNTER,3050,'Detect'),
+(@DWARF,@HUNTER,9125,'Generic'),
+(@DWARF,@HUNTER,8386,'Attacking'),
+(@DWARF,@HUNTER,7266,'Duel'),
+(@DWARF,@HUNTER,7267,'Grovel'),
+(@DWARF,@HUNTER,7355,'Stuck'),
+(@DWARF,@HUNTER,6233,'Closing'),
+(@DWARF,@HUNTER,6246,'Closing'),
+(@DWARF,@HUNTER,6247,'Opening'),
+(@DWARF,@HUNTER,6477,'Opening'),
+(@DWARF,@HUNTER,61437,'Opening'),
+(@DWARF,@HUNTER,68398,'Opening'),
+(@DWARF,@HUNTER,96220,'Opening'),
+(@DWARF,@HUNTER,203,'Unarmed'),
+(@DWARF,@HUNTER,883,'Call Pet 1'),
+(@DWARF,@HUNTER,982,'Revive Pet'),
+(@DWARF,@HUNTER,20596,'Frost Resistance'),
+(@DWARF,@HUNTER,20595,'Gun Specialization'),
+(@DWARF,@HUNTER,20594,'Stoneform'),
+(@DWARF,@HUNTER,59224,'Mace Specialization'),
+(@DWARF,@HUNTER,92682,'Explorer'),
+(@DWARF,@HUNTER,79739,'Languages'),
+(@DWARF,@HUNTER,672,'Language Dwarven'),
+(@DWARF,@HUNTER,15590,'Fist Weapons'),
+(@DWARF,@HUNTER,200,'Polearms'),
+(@DWARF,@HUNTER,668,'Language Common'),
+(@DWARF,@HUNTER,227,'Staves'),
+(@DWARF,@HUNTER,9077,'Leather'),
+(@DWARF,@HUNTER,264,'Bows'),
+(@DWARF,@HUNTER,266,'Guns'),
+(@DWARF,@HUNTER,13358,'Defensive State (DND)'),
+(@DWARF,@HUNTER,81,'Dodge'),
+(@DWARF,@HUNTER,204,'Defense'),
+(@DWARF,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@DWARF,@HUNTER,9078,'Cloth'),
+(@DWARF,@HUNTER,77442,'Focus'),
+(@DWARF,@HUNTER,76249,'Weapon Skills'),
+(@DWARF,@HUNTER,76250,'Armor Skills'),
+(@DWARF,@HUNTER,87324,'Focused Aim'),
+(@DWARF,@HUNTER,87816,'General Hunter Passives'),
+(@DWARF,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Dwarf
+(@DWARF,@ROGUE,196,'One-Handed Axes'),
+(@DWARF,@ROGUE,1752,'Sinister Strike'),
+(@DWARF,@ROGUE,5011,'Crossbows'),
+(@DWARF,@ROGUE,3018,'Shoot'),
+(@DWARF,@ROGUE,674,'Dual Wield'),
+(@DWARF,@ROGUE,1180,'Daggers'),
+(@DWARF,@ROGUE,45927,'Summon Friend'),
+(@DWARF,@ROGUE,6478,'Opening'),
+(@DWARF,@ROGUE,6603,'Auto Attack'),
+(@DWARF,@ROGUE,22027,'Remove Insignia'),
+(@DWARF,@ROGUE,22810,'Opening - No Text'),
+(@DWARF,@ROGUE,21651,'Opening'),
+(@DWARF,@ROGUE,21652,'Closing'),
+(@DWARF,@ROGUE,2382,'Generic'),
+(@DWARF,@ROGUE,3365,'Opening'),
+(@DWARF,@ROGUE,3050,'Detect'),
+(@DWARF,@ROGUE,9125,'Generic'),
+(@DWARF,@ROGUE,8386,'Attacking'),
+(@DWARF,@ROGUE,7266,'Duel'),
+(@DWARF,@ROGUE,7267,'Grovel'),
+(@DWARF,@ROGUE,7355,'Stuck'),
+(@DWARF,@ROGUE,6233,'Closing'),
+(@DWARF,@ROGUE,6246,'Closing'),
+(@DWARF,@ROGUE,6247,'Opening'),
+(@DWARF,@ROGUE,6477,'Opening'),
+(@DWARF,@ROGUE,61437,'Opening'),
+(@DWARF,@ROGUE,68398,'Opening'),
+(@DWARF,@ROGUE,96220,'Opening'),
+(@DWARF,@ROGUE,203,'Unarmed'),
+(@DWARF,@ROGUE,20596,'Frost Resistance'),
+(@DWARF,@ROGUE,20595,'Gun Specialization'),
+(@DWARF,@ROGUE,20594,'Stoneform'),
+(@DWARF,@ROGUE,59224,'Mace Specialization'),
+(@DWARF,@ROGUE,92682,'Explorer'),
+(@DWARF,@ROGUE,79739,'Languages'),
+(@DWARF,@ROGUE,672,'Language Dwarven'),
+(@DWARF,@ROGUE,15590,'Fist Weapons'),
+(@DWARF,@ROGUE,76273,'Armor Skills'),
+(@DWARF,@ROGUE,76297,'Weapon Skills'),
+(@DWARF,@ROGUE,668,'Language Common'),
+(@DWARF,@ROGUE,9077,'Leather'),
+(@DWARF,@ROGUE,264,'Bows'),
+(@DWARF,@ROGUE,266,'Guns'),
+(@DWARF,@ROGUE,81,'Dodge'),
+(@DWARF,@ROGUE,204,'Defense'),
+(@DWARF,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@ROGUE,16092,'Defensive State (DND)'),
+(@DWARF,@ROGUE,2764,'Throw'),
+(@DWARF,@ROGUE,2567,'Thrown'),
+(@DWARF,@ROGUE,9078,'Cloth'),
+(@DWARF,@ROGUE,198,'One-Handed Maces'),
+(@DWARF,@ROGUE,201,'One-Handed Swords'),
+-- Priest Dwarf
+(@DWARF,@PRIEST,5009,'Wands'),
+(@DWARF,@PRIEST,5019,'Shoot'),
+(@DWARF,@PRIEST,1180,'Daggers'),
+(@DWARF,@PRIEST,45927,'Summon Friend'),
+(@DWARF,@PRIEST,6478,'Opening'),
+(@DWARF,@PRIEST,6603,'Auto Attack'),
+(@DWARF,@PRIEST,22027,'Remove Insignia'),
+(@DWARF,@PRIEST,22810,'Opening - No Text'),
+(@DWARF,@PRIEST,21651,'Opening'),
+(@DWARF,@PRIEST,21652,'Closing'),
+(@DWARF,@PRIEST,2382,'Generic'),
+(@DWARF,@PRIEST,3365,'Opening'),
+(@DWARF,@PRIEST,3050,'Detect'),
+(@DWARF,@PRIEST,9125,'Generic'),
+(@DWARF,@PRIEST,8386,'Attacking'),
+(@DWARF,@PRIEST,7266,'Duel'),
+(@DWARF,@PRIEST,7267,'Grovel'),
+(@DWARF,@PRIEST,7355,'Stuck'),
+(@DWARF,@PRIEST,6233,'Closing'),
+(@DWARF,@PRIEST,6246,'Closing'),
+(@DWARF,@PRIEST,6247,'Opening'),
+(@DWARF,@PRIEST,6477,'Opening'),
+(@DWARF,@PRIEST,61437,'Opening'),
+(@DWARF,@PRIEST,68398,'Opening'),
+(@DWARF,@PRIEST,96220,'Opening'),
+(@DWARF,@PRIEST,203,'Unarmed'),
+(@DWARF,@PRIEST,585,'Smite'),
+(@DWARF,@PRIEST,84733,'Holy Focus'),
+(@DWARF,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@DWARF,@PRIEST,88684,'Holy Word: Serenity'),
+(@DWARF,@PRIEST,101062,'Flash Heal'),
+(@DWARF,@PRIEST,20596,'Frost Resistance'),
+(@DWARF,@PRIEST,20595,'Gun Specialization'),
+(@DWARF,@PRIEST,20594,'Stoneform'),
+(@DWARF,@PRIEST,59224,'Mace Specialization'),
+(@DWARF,@PRIEST,92682,'Explorer'),
+(@DWARF,@PRIEST,79739,'Languages'),
+(@DWARF,@PRIEST,672,'Language Dwarven'),
+(@DWARF,@PRIEST,76301,'Weapon Skills'),
+(@DWARF,@PRIEST,76279,'Armor Skills'),
+(@DWARF,@PRIEST,84734,'Dark Thoughts'),
+(@DWARF,@PRIEST,668,'Language Common'),
+(@DWARF,@PRIEST,227,'Staves'),
+(@DWARF,@PRIEST,77486,'Shadow Orb Power'),
+(@DWARF,@PRIEST,81,'Dodge'),
+(@DWARF,@PRIEST,204,'Defense'),
+(@DWARF,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@PRIEST,9078,'Cloth'),
+(@DWARF,@PRIEST,198,'One-Handed Maces'),
+-- Shaman Dwarf
+(@DWARF,@SHAMAN,196,'One-Handed Axes'),
+(@DWARF,@SHAMAN,197,'Two-Handed Axes'),
+(@DWARF,@SHAMAN,1180,'Daggers'),
+(@DWARF,@SHAMAN,45927,'Summon Friend'),
+(@DWARF,@SHAMAN,6478,'Opening'),
+(@DWARF,@SHAMAN,6603,'Auto Attack'),
+(@DWARF,@SHAMAN,22027,'Remove Insignia'),
+(@DWARF,@SHAMAN,22810,'Opening - No Text'),
+(@DWARF,@SHAMAN,21651,'Opening'),
+(@DWARF,@SHAMAN,21652,'Closing'),
+(@DWARF,@SHAMAN,2382,'Generic'),
+(@DWARF,@SHAMAN,3365,'Opening'),
+(@DWARF,@SHAMAN,3050,'Detect'),
+(@DWARF,@SHAMAN,9125,'Generic'),
+(@DWARF,@SHAMAN,8386,'Attacking'),
+(@DWARF,@SHAMAN,7266,'Duel'),
+(@DWARF,@SHAMAN,7267,'Grovel'),
+(@DWARF,@SHAMAN,7355,'Stuck'),
+(@DWARF,@SHAMAN,6233,'Closing'),
+(@DWARF,@SHAMAN,6246,'Closing'),
+(@DWARF,@SHAMAN,6247,'Opening'),
+(@DWARF,@SHAMAN,6477,'Opening'),
+(@DWARF,@SHAMAN,27763,'Relic'),
+(@DWARF,@SHAMAN,61437,'Opening'),
+(@DWARF,@SHAMAN,68398,'Opening'),
+(@DWARF,@SHAMAN,96220,'Opening'),
+(@DWARF,@SHAMAN,203,'Unarmed'),
+(@DWARF,@SHAMAN,20596,'Frost Resistance'),
+(@DWARF,@SHAMAN,20595,'Gun Specialization'),
+(@DWARF,@SHAMAN,20594,'Stoneform'),
+(@DWARF,@SHAMAN,59224,'Mace Specialization'),
+(@DWARF,@SHAMAN,92682,'Explorer'),
+(@DWARF,@SHAMAN,79739,'Languages'),
+(@DWARF,@SHAMAN,672,'Language Dwarven'),
+(@DWARF,@SHAMAN,199,'Two-Handed Maces'),
+(@DWARF,@SHAMAN,15590,'Fist Weapons'),
+(@DWARF,@SHAMAN,76272,'Armor Skills'),
+(@DWARF,@SHAMAN,76296,'Weapon Skills'),
+(@DWARF,@SHAMAN,89920,'Ancestral Focus'),
+(@DWARF,@SHAMAN,668,'Language Common'),
+(@DWARF,@SHAMAN,227,'Staves'),
+(@DWARF,@SHAMAN,9116,'Shield'),
+(@DWARF,@SHAMAN,9077,'Leather'),
+(@DWARF,@SHAMAN,107,'Block'),
+(@DWARF,@SHAMAN,81,'Dodge'),
+(@DWARF,@SHAMAN,204,'Defense'),
+(@DWARF,@SHAMAN,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@SHAMAN,403,'Lightning Bolt'),
+(@DWARF,@SHAMAN,9078,'Cloth'),
+(@DWARF,@SHAMAN,198,'One-Handed Maces'),
+-- Mage Dwarf
+(@DWARF,@MAGE,71761,'Deep Freeze Immunity State'),
+(@DWARF,@MAGE,5009,'Wands'),
+(@DWARF,@MAGE,5019,'Shoot'),
+(@DWARF,@MAGE,1180,'Daggers'),
+(@DWARF,@MAGE,45927,'Summon Friend'),
+(@DWARF,@MAGE,6478,'Opening'),
+(@DWARF,@MAGE,6603,'Auto Attack'),
+(@DWARF,@MAGE,22027,'Remove Insignia'),
+(@DWARF,@MAGE,22810,'Opening - No Text'),
+(@DWARF,@MAGE,21651,'Opening'),
+(@DWARF,@MAGE,21652,'Closing'),
+(@DWARF,@MAGE,2382,'Generic'),
+(@DWARF,@MAGE,3365,'Opening'),
+(@DWARF,@MAGE,3050,'Detect'),
+(@DWARF,@MAGE,9125,'Generic'),
+(@DWARF,@MAGE,8386,'Attacking'),
+(@DWARF,@MAGE,7266,'Duel'),
+(@DWARF,@MAGE,7267,'Grovel'),
+(@DWARF,@MAGE,7355,'Stuck'),
+(@DWARF,@MAGE,6233,'Closing'),
+(@DWARF,@MAGE,6246,'Closing'),
+(@DWARF,@MAGE,6247,'Opening'),
+(@DWARF,@MAGE,6477,'Opening'),
+(@DWARF,@MAGE,61437,'Opening'),
+(@DWARF,@MAGE,68398,'Opening'),
+(@DWARF,@MAGE,96220,'Opening'),
+(@DWARF,@MAGE,79684,'Offensive State (DND)'),
+(@DWARF,@MAGE,203,'Unarmed'),
+(@DWARF,@MAGE,20596,'Frost Resistance'),
+(@DWARF,@MAGE,20595,'Gun Specialization'),
+(@DWARF,@MAGE,20594,'Stoneform'),
+(@DWARF,@MAGE,59224,'Mace Specialization'),
+(@DWARF,@MAGE,92682,'Explorer'),
+(@DWARF,@MAGE,79739,'Languages'),
+(@DWARF,@MAGE,672,'Language Dwarven'),
+(@DWARF,@MAGE,133,'Fireball'),
+(@DWARF,@MAGE,92315,'Pyroblast!'),
+(@DWARF,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@DWARF,@MAGE,76298,'Weapon Skills'),
+(@DWARF,@MAGE,76276,'Armor Skills'),
+(@DWARF,@MAGE,668,'Language Common'),
+(@DWARF,@MAGE,227,'Staves'),
+(@DWARF,@MAGE,81,'Dodge'),
+(@DWARF,@MAGE,204,'Defense'),
+(@DWARF,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@MAGE,9078,'Cloth'),
+(@DWARF,@MAGE,201,'One-Handed Swords'),
+-- Warlock Dwarf
+(@DWARF,@WARLOCK,5009,'Wands'),
+(@DWARF,@WARLOCK,5019,'Shoot'),
+(@DWARF,@WARLOCK,1180,'Daggers'),
+(@DWARF,@WARLOCK,45927,'Summon Friend'),
+(@DWARF,@WARLOCK,6478,'Opening'),
+(@DWARF,@WARLOCK,6603,'Auto Attack'),
+(@DWARF,@WARLOCK,22027,'Remove Insignia'),
+(@DWARF,@WARLOCK,22810,'Opening - No Text'),
+(@DWARF,@WARLOCK,21651,'Opening'),
+(@DWARF,@WARLOCK,21652,'Closing'),
+(@DWARF,@WARLOCK,2382,'Generic'),
+(@DWARF,@WARLOCK,3365,'Opening'),
+(@DWARF,@WARLOCK,3050,'Detect'),
+(@DWARF,@WARLOCK,9125,'Generic'),
+(@DWARF,@WARLOCK,8386,'Attacking'),
+(@DWARF,@WARLOCK,7266,'Duel'),
+(@DWARF,@WARLOCK,7267,'Grovel'),
+(@DWARF,@WARLOCK,7355,'Stuck'),
+(@DWARF,@WARLOCK,6233,'Closing'),
+(@DWARF,@WARLOCK,6246,'Closing'),
+(@DWARF,@WARLOCK,6247,'Opening'),
+(@DWARF,@WARLOCK,6477,'Opening'),
+(@DWARF,@WARLOCK,61437,'Opening'),
+(@DWARF,@WARLOCK,68398,'Opening'),
+(@DWARF,@WARLOCK,96220,'Opening'),
+(@DWARF,@WARLOCK,203,'Unarmed'),
+(@DWARF,@WARLOCK,20596,'Frost Resistance'),
+(@DWARF,@WARLOCK,20595,'Gun Specialization'),
+(@DWARF,@WARLOCK,20594,'Stoneform'),
+(@DWARF,@WARLOCK,59224,'Mace Specialization'),
+(@DWARF,@WARLOCK,92682,'Explorer'),
+(@DWARF,@WARLOCK,79739,'Languages'),
+(@DWARF,@WARLOCK,672,'Language Dwarven'),
+(@DWARF,@WARLOCK,688,'Summon Imp'),
+(@DWARF,@WARLOCK,86213,'Soul Swap Exhale'),
+(@DWARF,@WARLOCK,89420,'Drain Life'),
+(@DWARF,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@DWARF,@WARLOCK,76299,'Weapon Skills'),
+(@DWARF,@WARLOCK,76277,'Armor Skills'),
+(@DWARF,@WARLOCK,87330,'Suppression'),
+(@DWARF,@WARLOCK,668,'Language Common'),
+(@DWARF,@WARLOCK,227,'Staves'),
+(@DWARF,@WARLOCK,75445,'Demonic Immolate'),
+(@DWARF,@WARLOCK,686,'Shadow Bolt'),
+(@DWARF,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@DWARF,@WARLOCK,81,'Dodge'),
+(@DWARF,@WARLOCK,204,'Defense'),
+(@DWARF,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@DWARF,@WARLOCK,9078,'Cloth'),
+(@DWARF,@WARLOCK,201,'One-Handed Swords'),
+-- Night Elf char create:
+-- Warrior Night Elf
+(@NIGHT_ELF,@WARRIOR,202,'Two-Handed Swords'),
+(@NIGHT_ELF,@WARRIOR,196,'One-Handed Axes'),
+(@NIGHT_ELF,@WARRIOR,2457,'Battle Stance'),
+(@NIGHT_ELF,@WARRIOR,88161,'Strike'),
+(@NIGHT_ELF,@WARRIOR,5011,'Crossbows'),
+(@NIGHT_ELF,@WARRIOR,3018,'Shoot'),
+(@NIGHT_ELF,@WARRIOR,197,'Two-Handed Axes'),
+(@NIGHT_ELF,@WARRIOR,1180,'Daggers'),
+(@NIGHT_ELF,@WARRIOR,45927,'Summon Friend'),
+(@NIGHT_ELF,@WARRIOR,6478,'Opening'),
+(@NIGHT_ELF,@WARRIOR,6603,'Auto Attack'),
+(@NIGHT_ELF,@WARRIOR,22027,'Remove Insignia'),
+(@NIGHT_ELF,@WARRIOR,22810,'Opening - No Text'),
+(@NIGHT_ELF,@WARRIOR,21651,'Opening'),
+(@NIGHT_ELF,@WARRIOR,21652,'Closing'),
+(@NIGHT_ELF,@WARRIOR,2382,'Generic'),
+(@NIGHT_ELF,@WARRIOR,3365,'Opening'),
+(@NIGHT_ELF,@WARRIOR,3050,'Detect'),
+(@NIGHT_ELF,@WARRIOR,9125,'Generic'),
+(@NIGHT_ELF,@WARRIOR,8386,'Attacking'),
+(@NIGHT_ELF,@WARRIOR,7266,'Duel'),
+(@NIGHT_ELF,@WARRIOR,7267,'Grovel'),
+(@NIGHT_ELF,@WARRIOR,7355,'Stuck'),
+(@NIGHT_ELF,@WARRIOR,6233,'Closing'),
+(@NIGHT_ELF,@WARRIOR,6246,'Closing'),
+(@NIGHT_ELF,@WARRIOR,6247,'Opening'),
+(@NIGHT_ELF,@WARRIOR,6477,'Opening'),
+(@NIGHT_ELF,@WARRIOR,61437,'Opening'),
+(@NIGHT_ELF,@WARRIOR,68398,'Opening'),
+(@NIGHT_ELF,@WARRIOR,96220,'Opening'),
+(@NIGHT_ELF,@WARRIOR,203,'Unarmed'),
+(@NIGHT_ELF,@WARRIOR,76252,'Languages'),
+(@NIGHT_ELF,@WARRIOR,20583,'Nature Resistance'),
+(@NIGHT_ELF,@WARRIOR,20582,'Quickness'),
+(@NIGHT_ELF,@WARRIOR,20585,'Wisp Spirit'),
+(@NIGHT_ELF,@WARRIOR,21009,'Elusiveness'),
+(@NIGHT_ELF,@WARRIOR,58984,'Shadowmeld'),
+(@NIGHT_ELF,@WARRIOR,671,'Language Darnassian'),
+(@NIGHT_ELF,@WARRIOR,49410,'Forceful Deflection'),
+(@NIGHT_ELF,@WARRIOR,199,'Two-Handed Maces'),
+(@NIGHT_ELF,@WARRIOR,15590,'Fist Weapons'),
+(@NIGHT_ELF,@WARRIOR,76268,'Armor Skills'),
+(@NIGHT_ELF,@WARRIOR,76290,'Weapon Skills'),
+(@NIGHT_ELF,@WARRIOR,88163,'Attack'),
+(@NIGHT_ELF,@WARRIOR,200,'Polearms'),
+(@NIGHT_ELF,@WARRIOR,668,'Language Common'),
+(@NIGHT_ELF,@WARRIOR,227,'Staves'),
+(@NIGHT_ELF,@WARRIOR,9116,'Shield'),
+(@NIGHT_ELF,@WARRIOR,8737,'Mail'),
+(@NIGHT_ELF,@WARRIOR,9077,'Leather'),
+(@NIGHT_ELF,@WARRIOR,264,'Bows'),
+(@NIGHT_ELF,@WARRIOR,266,'Guns'),
+(@NIGHT_ELF,@WARRIOR,107,'Block'),
+(@NIGHT_ELF,@WARRIOR,81,'Dodge'),
+(@NIGHT_ELF,@WARRIOR,32215,'Victorious State'),
+(@NIGHT_ELF,@WARRIOR,5301,'Defensive State (DND)'),
+(@NIGHT_ELF,@WARRIOR,204,'Defense'),
+(@NIGHT_ELF,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@WARRIOR,2764,'Throw'),
+(@NIGHT_ELF,@WARRIOR,2567,'Thrown'),
+(@NIGHT_ELF,@WARRIOR,9078,'Cloth'),
+(@NIGHT_ELF,@WARRIOR,198,'One-Handed Maces'),
+(@NIGHT_ELF,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Night Elf
+(@NIGHT_ELF,@HUNTER,202,'Two-Handed Swords'),
+(@NIGHT_ELF,@HUNTER,196,'One-Handed Axes'),
+(@NIGHT_ELF,@HUNTER,3044,'Arcane Shot'),
+(@NIGHT_ELF,@HUNTER,75,'Auto Shot'),
+(@NIGHT_ELF,@HUNTER,82928,'Aimed Shot!'),
+(@NIGHT_ELF,@HUNTER,5011,'Crossbows'),
+(@NIGHT_ELF,@HUNTER,197,'Two-Handed Axes'),
+(@NIGHT_ELF,@HUNTER,1180,'Daggers'),
+(@NIGHT_ELF,@HUNTER,45927,'Summon Friend'),
+(@NIGHT_ELF,@HUNTER,6478,'Opening'),
+(@NIGHT_ELF,@HUNTER,6603,'Auto Attack'),
+(@NIGHT_ELF,@HUNTER,22027,'Remove Insignia'),
+(@NIGHT_ELF,@HUNTER,22810,'Opening - No Text'),
+(@NIGHT_ELF,@HUNTER,21651,'Opening'),
+(@NIGHT_ELF,@HUNTER,21652,'Closing'),
+(@NIGHT_ELF,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@NIGHT_ELF,@HUNTER,2382,'Generic'),
+(@NIGHT_ELF,@HUNTER,3365,'Opening'),
+(@NIGHT_ELF,@HUNTER,3050,'Detect'),
+(@NIGHT_ELF,@HUNTER,9125,'Generic'),
+(@NIGHT_ELF,@HUNTER,8386,'Attacking'),
+(@NIGHT_ELF,@HUNTER,7266,'Duel'),
+(@NIGHT_ELF,@HUNTER,7267,'Grovel'),
+(@NIGHT_ELF,@HUNTER,7355,'Stuck'),
+(@NIGHT_ELF,@HUNTER,6233,'Closing'),
+(@NIGHT_ELF,@HUNTER,6246,'Closing'),
+(@NIGHT_ELF,@HUNTER,6247,'Opening'),
+(@NIGHT_ELF,@HUNTER,6477,'Opening'),
+(@NIGHT_ELF,@HUNTER,61437,'Opening'),
+(@NIGHT_ELF,@HUNTER,68398,'Opening'),
+(@NIGHT_ELF,@HUNTER,96220,'Opening'),
+(@NIGHT_ELF,@HUNTER,203,'Unarmed'),
+(@NIGHT_ELF,@HUNTER,883,'Call Pet 1'),
+(@NIGHT_ELF,@HUNTER,982,'Revive Pet'),
+(@NIGHT_ELF,@HUNTER,76252,'Languages'),
+(@NIGHT_ELF,@HUNTER,20583,'Nature Resistance'),
+(@NIGHT_ELF,@HUNTER,20582,'Quickness'),
+(@NIGHT_ELF,@HUNTER,20585,'Wisp Spirit'),
+(@NIGHT_ELF,@HUNTER,21009,'Elusiveness'),
+(@NIGHT_ELF,@HUNTER,58984,'Shadowmeld'),
+(@NIGHT_ELF,@HUNTER,671,'Language Darnassian'),
+(@NIGHT_ELF,@HUNTER,15590,'Fist Weapons'),
+(@NIGHT_ELF,@HUNTER,200,'Polearms'),
+(@NIGHT_ELF,@HUNTER,668,'Language Common'),
+(@NIGHT_ELF,@HUNTER,227,'Staves'),
+(@NIGHT_ELF,@HUNTER,9077,'Leather'),
+(@NIGHT_ELF,@HUNTER,264,'Bows'),
+(@NIGHT_ELF,@HUNTER,266,'Guns'),
+(@NIGHT_ELF,@HUNTER,13358,'Defensive State (DND)'),
+(@NIGHT_ELF,@HUNTER,81,'Dodge'),
+(@NIGHT_ELF,@HUNTER,204,'Defense'),
+(@NIGHT_ELF,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@NIGHT_ELF,@HUNTER,9078,'Cloth'),
+(@NIGHT_ELF,@HUNTER,77442,'Focus'),
+(@NIGHT_ELF,@HUNTER,76249,'Weapon Skills'),
+(@NIGHT_ELF,@HUNTER,76250,'Armor Skills'),
+(@NIGHT_ELF,@HUNTER,87324,'Focused Aim'),
+(@NIGHT_ELF,@HUNTER,87816,'General Hunter Passives'),
+(@NIGHT_ELF,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Night Elf
+(@NIGHT_ELF,@ROGUE,196,'One-Handed Axes'),
+(@NIGHT_ELF,@ROGUE,1752,'Sinister Strike'),
+(@NIGHT_ELF,@ROGUE,5011,'Crossbows'),
+(@NIGHT_ELF,@ROGUE,3018,'Shoot'),
+(@NIGHT_ELF,@ROGUE,674,'Dual Wield'),
+(@NIGHT_ELF,@ROGUE,1180,'Daggers'),
+(@NIGHT_ELF,@ROGUE,45927,'Summon Friend'),
+(@NIGHT_ELF,@ROGUE,6478,'Opening'),
+(@NIGHT_ELF,@ROGUE,6603,'Auto Attack'),
+(@NIGHT_ELF,@ROGUE,22027,'Remove Insignia'),
+(@NIGHT_ELF,@ROGUE,22810,'Opening - No Text'),
+(@NIGHT_ELF,@ROGUE,21651,'Opening'),
+(@NIGHT_ELF,@ROGUE,21652,'Closing'),
+(@NIGHT_ELF,@ROGUE,2382,'Generic'),
+(@NIGHT_ELF,@ROGUE,3365,'Opening'),
+(@NIGHT_ELF,@ROGUE,3050,'Detect'),
+(@NIGHT_ELF,@ROGUE,9125,'Generic'),
+(@NIGHT_ELF,@ROGUE,8386,'Attacking'),
+(@NIGHT_ELF,@ROGUE,7266,'Duel'),
+(@NIGHT_ELF,@ROGUE,7267,'Grovel'),
+(@NIGHT_ELF,@ROGUE,7355,'Stuck'),
+(@NIGHT_ELF,@ROGUE,6233,'Closing'),
+(@NIGHT_ELF,@ROGUE,6246,'Closing'),
+(@NIGHT_ELF,@ROGUE,6247,'Opening'),
+(@NIGHT_ELF,@ROGUE,6477,'Opening'),
+(@NIGHT_ELF,@ROGUE,61437,'Opening'),
+(@NIGHT_ELF,@ROGUE,68398,'Opening'),
+(@NIGHT_ELF,@ROGUE,96220,'Opening'),
+(@NIGHT_ELF,@ROGUE,203,'Unarmed'),
+(@NIGHT_ELF,@ROGUE,20583,'Nature Resistance'),
+(@NIGHT_ELF,@ROGUE,20582,'Quickness'),
+(@NIGHT_ELF,@ROGUE,20585,'Elusiveness'),
+(@NIGHT_ELF,@ROGUE,21009,'Wisp Spirit'),
+(@NIGHT_ELF,@ROGUE,58984,'Shadowmeld'),
+(@NIGHT_ELF,@ROGUE,76252,'Languages'),
+(@NIGHT_ELF,@ROGUE,671,'Language Darnassian'),
+(@NIGHT_ELF,@ROGUE,15590,'Fist Weapons'),
+(@NIGHT_ELF,@ROGUE,76273,'Armor Skills'),
+(@NIGHT_ELF,@ROGUE,76297,'Weapon Skills'),
+(@NIGHT_ELF,@ROGUE,668,'Language Common'),
+(@NIGHT_ELF,@ROGUE,9077,'Leather'),
+(@NIGHT_ELF,@ROGUE,264,'Bows'),
+(@NIGHT_ELF,@ROGUE,266,'Guns'),
+(@NIGHT_ELF,@ROGUE,81,'Dodge'),
+(@NIGHT_ELF,@ROGUE,204,'Defense'),
+(@NIGHT_ELF,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@ROGUE,16092,'Defensive State (DND)'),
+(@NIGHT_ELF,@ROGUE,2764,'Throw'),
+(@NIGHT_ELF,@ROGUE,2567,'Thrown'),
+(@NIGHT_ELF,@ROGUE,9078,'Cloth'),
+(@NIGHT_ELF,@ROGUE,198,'One-Handed Maces'),
+(@NIGHT_ELF,@ROGUE,201,'One-Handed Swords'),
+-- Priest Dwarf
+(@NIGHT_ELF,@PRIEST,5009,'Wands'),
+(@NIGHT_ELF,@PRIEST,5019,'Shoot'),
+(@NIGHT_ELF,@PRIEST,1180,'Daggers'),
+(@NIGHT_ELF,@PRIEST,45927,'Summon Friend'),
+(@NIGHT_ELF,@PRIEST,6478,'Opening'),
+(@NIGHT_ELF,@PRIEST,6603,'Auto Attack'),
+(@NIGHT_ELF,@PRIEST,22027,'Remove Insignia'),
+(@NIGHT_ELF,@PRIEST,22810,'Opening - No Text'),
+(@NIGHT_ELF,@PRIEST,21651,'Opening'),
+(@NIGHT_ELF,@PRIEST,21652,'Closing'),
+(@NIGHT_ELF,@PRIEST,2382,'Generic'),
+(@NIGHT_ELF,@PRIEST,3365,'Opening'),
+(@NIGHT_ELF,@PRIEST,3050,'Detect'),
+(@NIGHT_ELF,@PRIEST,9125,'Generic'),
+(@NIGHT_ELF,@PRIEST,8386,'Attacking'),
+(@NIGHT_ELF,@PRIEST,7266,'Duel'),
+(@NIGHT_ELF,@PRIEST,7267,'Grovel'),
+(@NIGHT_ELF,@PRIEST,7355,'Stuck'),
+(@NIGHT_ELF,@PRIEST,6233,'Closing'),
+(@NIGHT_ELF,@PRIEST,6246,'Closing'),
+(@NIGHT_ELF,@PRIEST,6247,'Opening'),
+(@NIGHT_ELF,@PRIEST,6477,'Opening'),
+(@NIGHT_ELF,@PRIEST,61437,'Opening'),
+(@NIGHT_ELF,@PRIEST,68398,'Opening'),
+(@NIGHT_ELF,@PRIEST,96220,'Opening'),
+(@NIGHT_ELF,@PRIEST,203,'Unarmed'),
+(@NIGHT_ELF,@PRIEST,585,'Smite'),
+(@NIGHT_ELF,@PRIEST,84733,'Holy Focus'),
+(@NIGHT_ELF,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@NIGHT_ELF,@PRIEST,88684,'Holy Word: Serenity'),
+(@NIGHT_ELF,@PRIEST,101062,'Flash Heal'),
+(@NIGHT_ELF,@PRIEST,20583,'Nature Resistance'),
+(@NIGHT_ELF,@PRIEST,20582,'Quickness'),
+(@NIGHT_ELF,@PRIEST,20585,'Wisp Spirit'),
+(@NIGHT_ELF,@PRIEST,21009,'Elusiveness'),
+(@NIGHT_ELF,@PRIEST,58984,'Shadowmeld'),
+(@NIGHT_ELF,@PRIEST,76252,'Languages'),
+(@NIGHT_ELF,@PRIEST,671,'Language Darnassian'),
+(@NIGHT_ELF,@PRIEST,76301,'Weapon Skills'),
+(@NIGHT_ELF,@PRIEST,76279,'Armor Skills'),
+(@NIGHT_ELF,@PRIEST,84734,'Dark Thoughts'),
+(@NIGHT_ELF,@PRIEST,668,'Language Common'),
+(@NIGHT_ELF,@PRIEST,227,'Staves'),
+(@NIGHT_ELF,@PRIEST,77486,'Shadow Orb Power'),
+(@NIGHT_ELF,@PRIEST,81,'Dodge'),
+(@NIGHT_ELF,@PRIEST,204,'Defense'),
+(@NIGHT_ELF,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@PRIEST,9078,'Cloth'),
+(@NIGHT_ELF,@PRIEST,198,'One-Handed Maces'),
+-- Mage Night Elf
+(@NIGHT_ELF,@MAGE,71761,'Deep Freeze Immunity State'),
+(@NIGHT_ELF,@MAGE,5009,'Wands'),
+(@NIGHT_ELF,@MAGE,5019,'Shoot'),
+(@NIGHT_ELF,@MAGE,1180,'Daggers'),
+(@NIGHT_ELF,@MAGE,45927,'Summon Friend'),
+(@NIGHT_ELF,@MAGE,6478,'Opening'),
+(@NIGHT_ELF,@MAGE,6603,'Auto Attack'),
+(@NIGHT_ELF,@MAGE,22027,'Remove Insignia'),
+(@NIGHT_ELF,@MAGE,22810,'Opening - No Text'),
+(@NIGHT_ELF,@MAGE,21651,'Opening'),
+(@NIGHT_ELF,@MAGE,21652,'Closing'),
+(@NIGHT_ELF,@MAGE,2382,'Generic'),
+(@NIGHT_ELF,@MAGE,3365,'Opening'),
+(@NIGHT_ELF,@MAGE,3050,'Detect'),
+(@NIGHT_ELF,@MAGE,9125,'Generic'),
+(@NIGHT_ELF,@MAGE,8386,'Attacking'),
+(@NIGHT_ELF,@MAGE,7266,'Duel'),
+(@NIGHT_ELF,@MAGE,7267,'Grovel'),
+(@NIGHT_ELF,@MAGE,7355,'Stuck'),
+(@NIGHT_ELF,@MAGE,6233,'Closing'),
+(@NIGHT_ELF,@MAGE,6246,'Closing'),
+(@NIGHT_ELF,@MAGE,6247,'Opening'),
+(@NIGHT_ELF,@MAGE,6477,'Opening'),
+(@NIGHT_ELF,@MAGE,61437,'Opening'),
+(@NIGHT_ELF,@MAGE,68398,'Opening'),
+(@NIGHT_ELF,@MAGE,96220,'Opening'),
+(@NIGHT_ELF,@MAGE,79684,'Offensive State (DND)'),
+(@NIGHT_ELF,@MAGE,203,'Unarmed'),
+(@NIGHT_ELF,@MAGE,20583,'Nature Resistance'),
+(@NIGHT_ELF,@MAGE,20582,'Quickness'),
+(@NIGHT_ELF,@MAGE,20585,'Wisp Spirit'),
+(@NIGHT_ELF,@MAGE,21009,'Mace Specialization'),
+(@NIGHT_ELF,@MAGE,58984,'Shadowmeld'),
+(@NIGHT_ELF,@MAGE,76252,'Languages'),
+(@NIGHT_ELF,@MAGE,671,'Language Darnassian'),
+(@NIGHT_ELF,@MAGE,133,'Fireball'),
+(@NIGHT_ELF,@MAGE,92315,'Pyroblast!'),
+(@NIGHT_ELF,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@NIGHT_ELF,@MAGE,76298,'Weapon Skills'),
+(@NIGHT_ELF,@MAGE,76276,'Armor Skills'),
+(@NIGHT_ELF,@MAGE,668,'Language Common'),
+(@NIGHT_ELF,@MAGE,227,'Staves'),
+(@NIGHT_ELF,@MAGE,81,'Dodge'),
+(@NIGHT_ELF,@MAGE,204,'Defense'),
+(@NIGHT_ELF,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@MAGE,9078,'Cloth'),
+(@NIGHT_ELF,@MAGE,201,'One-Handed Swords'),
+-- Druid Night Elf
+(@NIGHT_ELF,@DRUID,1180,'Daggers'),
+(@NIGHT_ELF,@DRUID,45927,'Summon Friend'),
+(@NIGHT_ELF,@DRUID,6478,'Opening'),
+(@NIGHT_ELF,@DRUID,6603,'Auto Attack'),
+(@NIGHT_ELF,@DRUID,22027,'Remove Insignia'),
+(@NIGHT_ELF,@DRUID,22810,'Opening - No Text'),
+(@NIGHT_ELF,@DRUID,21651,'Opening'),
+(@NIGHT_ELF,@DRUID,21652,'Closing'),
+(@NIGHT_ELF,@DRUID,2382,'Generic'),
+(@NIGHT_ELF,@DRUID,3365,'Opening'),
+(@NIGHT_ELF,@DRUID,3050,'Detect'),
+(@NIGHT_ELF,@DRUID,9125,'Generic'),
+(@NIGHT_ELF,@DRUID,8386,'Attacking'),
+(@NIGHT_ELF,@DRUID,7266,'Duel'),
+(@NIGHT_ELF,@DRUID,7267,'Grovel'),
+(@NIGHT_ELF,@DRUID,7355,'Stuck'),
+(@NIGHT_ELF,@DRUID,6233,'Closing'),
+(@NIGHT_ELF,@DRUID,6246,'Closing'),
+(@NIGHT_ELF,@DRUID,6247,'Opening'),
+(@NIGHT_ELF,@DRUID,6477,'Opening'),
+(@NIGHT_ELF,@DRUID,61437,'Opening'),
+(@NIGHT_ELF,@DRUID,68398,'Opening'),
+(@NIGHT_ELF,@DRUID,96220,'Opening'),
+(@NIGHT_ELF,@DRUID,203,'Unarmed'),
+(@NIGHT_ELF,@DRUID,20583,'Nature Resistance'),
+(@NIGHT_ELF,@DRUID,20582,'Quickness'),
+(@NIGHT_ELF,@DRUID,20585,'Wisp Spirit'),
+(@NIGHT_ELF,@DRUID,21009,'Mace Specialization'),
+(@NIGHT_ELF,@DRUID,58984,'Shadowmeld'),
+(@NIGHT_ELF,@DRUID,76252,'Languages'),
+(@NIGHT_ELF,@DRUID,671,'Language Darnassian'),
+(@NIGHT_ELF,@DRUID,84736,"Nature's Focus"),
+(@NIGHT_ELF,@DRUID,81170,"Ravage!"),
+(@NIGHT_ELF,@DRUID,79577,"Eclipse Mastery Driver Passive"),
+(@NIGHT_ELF,@DRUID,76300,'Weapon Skills'),
+(@NIGHT_ELF,@DRUID,76275,'Armor Skills'),
+(@NIGHT_ELF,@DRUID,5176,'Wrath'),
+(@NIGHT_ELF,@DRUID,199,'Two-Handed Maces'),
+(@NIGHT_ELF,@DRUID,15590,'Fist Weapons'),
+(@NIGHT_ELF,@DRUID,84738,'Celestial Focus'),
+(@NIGHT_ELF,@DRUID,668,'Language Common'),
+(@NIGHT_ELF,@DRUID,200,'Polearms'),
+(@NIGHT_ELF,@DRUID,227,'Staves'),
+(@NIGHT_ELF,@DRUID,81,'Dodge'),
+(@NIGHT_ELF,@DRUID,204,'Defense'),
+(@NIGHT_ELF,@DRUID,522,'SPELLDEFENSE (DND)'),
+(@NIGHT_ELF,@DRUID,9077,'Leather'),
+(@NIGHT_ELF,@DRUID,9078,'Cloth'),
+(@NIGHT_ELF,@DRUID,198,'One-Handed Maces'),
+-- Undead char create:
+-- Warrior Undead
+(@UNDEAD,@WARRIOR,202,'Two-Handed Swords'),
+(@UNDEAD,@WARRIOR,196,'One-Handed Axes'),
+(@UNDEAD,@WARRIOR,2457,'Battle Stance'),
+(@UNDEAD,@WARRIOR,88161,'Strike'),
+(@UNDEAD,@WARRIOR,5011,'Crossbows'),
+(@UNDEAD,@WARRIOR,3018,'Shoot'),
+(@UNDEAD,@WARRIOR,669,'Language Orcish'),
+(@UNDEAD,@WARRIOR,197,'Two-Handed Axes'),
+(@UNDEAD,@WARRIOR,1180,'Daggers'),
+(@UNDEAD,@WARRIOR,45927,'Summon Friend'),
+(@UNDEAD,@WARRIOR,6478,'Opening'),
+(@UNDEAD,@WARRIOR,6603,'Auto Attack'),
+(@UNDEAD,@WARRIOR,22027,'Remove Insignia'),
+(@UNDEAD,@WARRIOR,22810,'Opening - No Text'),
+(@UNDEAD,@WARRIOR,21651,'Opening'),
+(@UNDEAD,@WARRIOR,21652,'Closing'),
+(@UNDEAD,@WARRIOR,2382,'Generic'),
+(@UNDEAD,@WARRIOR,3365,'Opening'),
+(@UNDEAD,@WARRIOR,3050,'Detect'),
+(@UNDEAD,@WARRIOR,9125,'Generic'),
+(@UNDEAD,@WARRIOR,8386,'Attacking'),
+(@UNDEAD,@WARRIOR,7266,'Duel'),
+(@UNDEAD,@WARRIOR,7267,'Grovel'),
+(@UNDEAD,@WARRIOR,7355,'Stuck'),
+(@UNDEAD,@WARRIOR,6233,'Closing'),
+(@UNDEAD,@WARRIOR,6246,'Closing'),
+(@UNDEAD,@WARRIOR,6247,'Opening'),
+(@UNDEAD,@WARRIOR,6477,'Opening'),
+(@UNDEAD,@WARRIOR,61437,'Opening'),
+(@UNDEAD,@WARRIOR,68398,'Opening'),
+(@UNDEAD,@WARRIOR,96220,'Opening'),
+(@UNDEAD,@WARRIOR,203,'Unarmed'),
+(@UNDEAD,@WARRIOR,49410,'Forceful Deflection'),
+(@UNDEAD,@WARRIOR,17737,'Language Gutterspeak'),
+(@UNDEAD,@WARRIOR,5227,'Underwater Breathing'),
+(@UNDEAD,@WARRIOR,7744,'Will of the Forsaken'),
+(@UNDEAD,@WARRIOR,20577,'Cannibalize'),
+(@UNDEAD,@WARRIOR,20579,'Shadow Resistance'),
+(@UNDEAD,@WARRIOR,79747,'Languages'),
+(@UNDEAD,@WARRIOR,199,'Two-Handed Maces'),
+(@UNDEAD,@WARRIOR,15590,'Fist Weapons'),
+(@UNDEAD,@WARRIOR,76268,'Armor Skills'),
+(@UNDEAD,@WARRIOR,76290,'Weapon Skills'),
+(@UNDEAD,@WARRIOR,88163,'Attack'),
+(@UNDEAD,@WARRIOR,200,'Polearms'),
+(@UNDEAD,@WARRIOR,227,'Staves'),
+(@UNDEAD,@WARRIOR,9116,'Shield'),
+(@UNDEAD,@WARRIOR,8737,'Mail'),
+(@UNDEAD,@WARRIOR,9077,'Leather'),
+(@UNDEAD,@WARRIOR,264,'Bows'),
+(@UNDEAD,@WARRIOR,266,'Guns'),
+(@UNDEAD,@WARRIOR,107,'Block'),
+(@UNDEAD,@WARRIOR,81,'Dodge'),
+(@UNDEAD,@WARRIOR,32215,'Victorious State'),
+(@UNDEAD,@WARRIOR,5301,'Defensive State (DND)'),
+(@UNDEAD,@WARRIOR,204,'Defense'),
+(@UNDEAD,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@WARRIOR,2764,'Throw'),
+(@UNDEAD,@WARRIOR,2567,'Thrown'),
+(@UNDEAD,@WARRIOR,9078,'Cloth'),
+(@UNDEAD,@WARRIOR,198,'One-Handed Maces'),
+(@UNDEAD,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Undead
+(@UNDEAD,@HUNTER,202,'Two-Handed Swords'),
+(@UNDEAD,@HUNTER,196,'One-Handed Axes'),
+(@UNDEAD,@HUNTER,3044,'Arcane Shot'),
+(@UNDEAD,@HUNTER,75,'Auto Shot'),
+(@UNDEAD,@HUNTER,82928,'Aimed Shot!'),
+(@UNDEAD,@HUNTER,5011,'Crossbows'),
+(@UNDEAD,@HUNTER,669,'Language Orcish'),
+(@UNDEAD,@HUNTER,197,'Two-Handed Axes'),
+(@UNDEAD,@HUNTER,1180,'Daggers'),
+(@UNDEAD,@HUNTER,45927,'Summon Friend'),
+(@UNDEAD,@HUNTER,6478,'Opening'),
+(@UNDEAD,@HUNTER,6603,'Auto Attack'),
+(@UNDEAD,@HUNTER,22027,'Remove Insignia'),
+(@UNDEAD,@HUNTER,22810,'Opening - No Text'),
+(@UNDEAD,@HUNTER,21651,'Opening'),
+(@UNDEAD,@HUNTER,21652,'Closing'),
+(@UNDEAD,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@UNDEAD,@HUNTER,2382,'Generic'),
+(@UNDEAD,@HUNTER,3365,'Opening'),
+(@UNDEAD,@HUNTER,3050,'Detect'),
+(@UNDEAD,@HUNTER,9125,'Generic'),
+(@UNDEAD,@HUNTER,8386,'Attacking'),
+(@UNDEAD,@HUNTER,7266,'Duel'),
+(@UNDEAD,@HUNTER,7267,'Grovel'),
+(@UNDEAD,@HUNTER,7355,'Stuck'),
+(@UNDEAD,@HUNTER,6233,'Closing'),
+(@UNDEAD,@HUNTER,6246,'Closing'),
+(@UNDEAD,@HUNTER,6247,'Opening'),
+(@UNDEAD,@HUNTER,6477,'Opening'),
+(@UNDEAD,@HUNTER,61437,'Opening'),
+(@UNDEAD,@HUNTER,68398,'Opening'),
+(@UNDEAD,@HUNTER,96220,'Opening'),
+(@UNDEAD,@HUNTER,203,'Unarmed'),
+(@UNDEAD,@HUNTER,883,'Call Pet 1'),
+(@UNDEAD,@HUNTER,982,'Revive Pet'),
+(@UNDEAD,@HUNTER,17737,'Language Gutterspeak'),
+(@UNDEAD,@HUNTER,5227,'Underwater Breathing'),
+(@UNDEAD,@HUNTER,7744,'Will of the Forsaken'),
+(@UNDEAD,@HUNTER,20577,'Cannibalize'),
+(@UNDEAD,@HUNTER,20579,'Shadow Resistance'),
+(@UNDEAD,@HUNTER,79747,'Languages'),
+(@UNDEAD,@HUNTER,15590,'Fist Weapons'),
+(@UNDEAD,@HUNTER,200,'Polearms'),
+(@UNDEAD,@HUNTER,227,'Staves'),
+(@UNDEAD,@HUNTER,9077,'Leather'),
+(@UNDEAD,@HUNTER,264,'Bows'),
+(@UNDEAD,@HUNTER,266,'Guns'),
+(@UNDEAD,@HUNTER,13358,'Defensive State (DND)'),
+(@UNDEAD,@HUNTER,81,'Dodge'),
+(@UNDEAD,@HUNTER,204,'Defense'),
+(@UNDEAD,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@UNDEAD,@HUNTER,9078,'Cloth'),
+(@UNDEAD,@HUNTER,77442,'Focus'),
+(@UNDEAD,@HUNTER,76249,'Weapon Skills'),
+(@UNDEAD,@HUNTER,76250,'Armor Skills'),
+(@UNDEAD,@HUNTER,87324,'Focused Aim'),
+(@UNDEAD,@HUNTER,87816,'General Hunter Passives'),
+(@UNDEAD,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Undead
+(@UNDEAD,@ROGUE,196,'One-Handed Axes'),
+(@UNDEAD,@ROGUE,1752,'Sinister Strike'),
+(@UNDEAD,@ROGUE,5011,'Crossbows'),
+(@UNDEAD,@ROGUE,3018,'Shoot'),
+(@UNDEAD,@ROGUE,669,'Language Orcish'),
+(@UNDEAD,@ROGUE,674,'Dual Wield'),
+(@UNDEAD,@ROGUE,1180,'Daggers'),
+(@UNDEAD,@ROGUE,45927,'Summon Friend'),
+(@UNDEAD,@ROGUE,6478,'Opening'),
+(@UNDEAD,@ROGUE,6603,'Auto Attack'),
+(@UNDEAD,@ROGUE,22027,'Remove Insignia'),
+(@UNDEAD,@ROGUE,22810,'Opening - No Text'),
+(@UNDEAD,@ROGUE,21651,'Opening'),
+(@UNDEAD,@ROGUE,21652,'Closing'),
+(@UNDEAD,@ROGUE,2382,'Generic'),
+(@UNDEAD,@ROGUE,3365,'Opening'),
+(@UNDEAD,@ROGUE,3050,'Detect'),
+(@UNDEAD,@ROGUE,9125,'Generic'),
+(@UNDEAD,@ROGUE,8386,'Attacking'),
+(@UNDEAD,@ROGUE,7266,'Duel'),
+(@UNDEAD,@ROGUE,7267,'Grovel'),
+(@UNDEAD,@ROGUE,7355,'Stuck'),
+(@UNDEAD,@ROGUE,6233,'Closing'),
+(@UNDEAD,@ROGUE,6246,'Closing'),
+(@UNDEAD,@ROGUE,6247,'Opening'),
+(@UNDEAD,@ROGUE,6477,'Opening'),
+(@UNDEAD,@ROGUE,61437,'Opening'),
+(@UNDEAD,@ROGUE,68398,'Opening'),
+(@UNDEAD,@ROGUE,96220,'Opening'),
+(@UNDEAD,@ROGUE,203,'Unarmed'),
+(@UNDEAD,@ROGUE,17737,'Language Gutterspeak'),
+(@UNDEAD,@ROGUE,5227,'Underwater Breathing'),
+(@UNDEAD,@ROGUE,7744,'Will of the Forsaken'),
+(@UNDEAD,@ROGUE,20577,'Cannibalize'),
+(@UNDEAD,@ROGUE,20579,'Shadow Resistance'),
+(@UNDEAD,@ROGUE,79747,'Languages'),
+(@UNDEAD,@ROGUE,15590,'Fist Weapons'),
+(@UNDEAD,@ROGUE,76273,'Armor Skills'),
+(@UNDEAD,@ROGUE,76297,'Weapon Skills'),
+(@UNDEAD,@ROGUE,9077,'Leather'),
+(@UNDEAD,@ROGUE,264,'Bows'),
+(@UNDEAD,@ROGUE,266,'Guns'),
+(@UNDEAD,@ROGUE,81,'Dodge'),
+(@UNDEAD,@ROGUE,204,'Defense'),
+(@UNDEAD,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@ROGUE,16092,'Defensive State (DND)'),
+(@UNDEAD,@ROGUE,2764,'Throw'),
+(@UNDEAD,@ROGUE,2567,'Thrown'),
+(@UNDEAD,@ROGUE,9078,'Cloth'),
+(@UNDEAD,@ROGUE,198,'One-Handed Maces'),
+(@UNDEAD,@ROGUE,201,'One-Handed Swords'),
+-- Priest Undead
+(@UNDEAD,@PRIEST,5009,'Wands'),
+(@UNDEAD,@PRIEST,5019,'Shoot'),
+(@UNDEAD,@PRIEST,669,'Language Orcish'),
+(@UNDEAD,@PRIEST,1180,'Daggers'),
+(@UNDEAD,@PRIEST,45927,'Summon Friend'),
+(@UNDEAD,@PRIEST,6478,'Opening'),
+(@UNDEAD,@PRIEST,6603,'Auto Attack'),
+(@UNDEAD,@PRIEST,22027,'Remove Insignia'),
+(@UNDEAD,@PRIEST,22810,'Opening - No Text'),
+(@UNDEAD,@PRIEST,21651,'Opening'),
+(@UNDEAD,@PRIEST,21652,'Closing'),
+(@UNDEAD,@PRIEST,2382,'Generic'),
+(@UNDEAD,@PRIEST,3365,'Opening'),
+(@UNDEAD,@PRIEST,3050,'Detect'),
+(@UNDEAD,@PRIEST,9125,'Generic'),
+(@UNDEAD,@PRIEST,8386,'Attacking'),
+(@UNDEAD,@PRIEST,7266,'Duel'),
+(@UNDEAD,@PRIEST,7267,'Grovel'),
+(@UNDEAD,@PRIEST,7355,'Stuck'),
+(@UNDEAD,@PRIEST,6233,'Closing'),
+(@UNDEAD,@PRIEST,6246,'Closing'),
+(@UNDEAD,@PRIEST,6247,'Opening'),
+(@UNDEAD,@PRIEST,6477,'Opening'),
+(@UNDEAD,@PRIEST,61437,'Opening'),
+(@UNDEAD,@PRIEST,68398,'Opening'),
+(@UNDEAD,@PRIEST,96220,'Opening'),
+(@UNDEAD,@PRIEST,203,'Unarmed'),
+(@UNDEAD,@PRIEST,585,'Smite'),
+(@UNDEAD,@PRIEST,84733,'Holy Focus'),
+(@UNDEAD,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@UNDEAD,@PRIEST,88684,'Holy Word: Serenity'),
+(@UNDEAD,@PRIEST,101062,'Flash Heal'),
+(@UNDEAD,@PRIEST,17737,'Language Gutterspeak'),
+(@UNDEAD,@PRIEST,5227,'Underwater Breathing'),
+(@UNDEAD,@PRIEST,7744,'Will of the Forsaken'),
+(@UNDEAD,@PRIEST,20577,'Cannibalize'),
+(@UNDEAD,@PRIEST,20579,'Shadow Resistance'),
+(@UNDEAD,@PRIEST,79747,'Languages'),
+(@UNDEAD,@PRIEST,76301,'Weapon Skills'),
+(@UNDEAD,@PRIEST,76279,'Armor Skills'),
+(@UNDEAD,@PRIEST,84734,'Dark Thoughts'),
+(@UNDEAD,@PRIEST,227,'Staves'),
+(@UNDEAD,@PRIEST,77486,'Shadow Orb Power'),
+(@UNDEAD,@PRIEST,81,'Dodge'),
+(@UNDEAD,@PRIEST,204,'Defense'),
+(@UNDEAD,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@PRIEST,9078,'Cloth'),
+(@UNDEAD,@PRIEST,198,'One-Handed Maces'),
+-- Mage Undead
+(@UNDEAD,@MAGE,71761,'Deep Freeze Immunity State'),
+(@UNDEAD,@MAGE,5009,'Wands'),
+(@UNDEAD,@MAGE,5019,'Shoot'),
+(@UNDEAD,@MAGE,669,'Language Orcish'),
+(@UNDEAD,@MAGE,1180,'Daggers'),
+(@UNDEAD,@MAGE,45927,'Summon Friend'),
+(@UNDEAD,@MAGE,6478,'Opening'),
+(@UNDEAD,@MAGE,6603,'Auto Attack'),
+(@UNDEAD,@MAGE,22027,'Remove Insignia'),
+(@UNDEAD,@MAGE,22810,'Opening - No Text'),
+(@UNDEAD,@MAGE,21651,'Opening'),
+(@UNDEAD,@MAGE,21652,'Closing'),
+(@UNDEAD,@MAGE,2382,'Generic'),
+(@UNDEAD,@MAGE,3365,'Opening'),
+(@UNDEAD,@MAGE,3050,'Detect'),
+(@UNDEAD,@MAGE,9125,'Generic'),
+(@UNDEAD,@MAGE,8386,'Attacking'),
+(@UNDEAD,@MAGE,7266,'Duel'),
+(@UNDEAD,@MAGE,7267,'Grovel'),
+(@UNDEAD,@MAGE,7355,'Stuck'),
+(@UNDEAD,@MAGE,6233,'Closing'),
+(@UNDEAD,@MAGE,6246,'Closing'),
+(@UNDEAD,@MAGE,6247,'Opening'),
+(@UNDEAD,@MAGE,6477,'Opening'),
+(@UNDEAD,@MAGE,61437,'Opening'),
+(@UNDEAD,@MAGE,68398,'Opening'),
+(@UNDEAD,@MAGE,96220,'Opening'),
+(@UNDEAD,@MAGE,79684,'Offensive State (DND)'),
+(@UNDEAD,@MAGE,203,'Unarmed'),
+(@UNDEAD,@MAGE,17737,'Language Gutterspeak'),
+(@UNDEAD,@MAGE,5227,'Underwater Breathing'),
+(@UNDEAD,@MAGE,7744,'Will of the Forsaken'),
+(@UNDEAD,@MAGE,20577,'Cannibalize'),
+(@UNDEAD,@MAGE,20579,'Shadow Resistance'),
+(@UNDEAD,@MAGE,79747,'Languages'),
+(@UNDEAD,@MAGE,133,'Fireball'),
+(@UNDEAD,@MAGE,92315,'Pyroblast!'),
+(@UNDEAD,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@UNDEAD,@MAGE,76298,'Weapon Skills'),
+(@UNDEAD,@MAGE,76276,'Armor Skills'),
+(@UNDEAD,@MAGE,227,'Staves'),
+(@UNDEAD,@MAGE,81,'Dodge'),
+(@UNDEAD,@MAGE,204,'Defense'),
+(@UNDEAD,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@MAGE,9078,'Cloth'),
+(@UNDEAD,@MAGE,201,'One-Handed Swords'),
+-- Warlock Undead
+(@UNDEAD,@WARLOCK,5009,'Wands'),
+(@UNDEAD,@WARLOCK,5019,'Shoot'),
+(@UNDEAD,@WARLOCK,669,'Language Common'),
+(@UNDEAD,@WARLOCK,1180,'Daggers'),
+(@UNDEAD,@WARLOCK,45927,'Summon Friend'),
+(@UNDEAD,@WARLOCK,6478,'Opening'),
+(@UNDEAD,@WARLOCK,6603,'Auto Attack'),
+(@UNDEAD,@WARLOCK,22027,'Remove Insignia'),
+(@UNDEAD,@WARLOCK,22810,'Opening - No Text'),
+(@UNDEAD,@WARLOCK,21651,'Opening'),
+(@UNDEAD,@WARLOCK,21652,'Closing'),
+(@UNDEAD,@WARLOCK,2382,'Generic'),
+(@UNDEAD,@WARLOCK,3365,'Opening'),
+(@UNDEAD,@WARLOCK,3050,'Detect'),
+(@UNDEAD,@WARLOCK,9125,'Generic'),
+(@UNDEAD,@WARLOCK,8386,'Attacking'),
+(@UNDEAD,@WARLOCK,7266,'Duel'),
+(@UNDEAD,@WARLOCK,7267,'Grovel'),
+(@UNDEAD,@WARLOCK,7355,'Stuck'),
+(@UNDEAD,@WARLOCK,6233,'Closing'),
+(@UNDEAD,@WARLOCK,6246,'Closing'),
+(@UNDEAD,@WARLOCK,6247,'Opening'),
+(@UNDEAD,@WARLOCK,6477,'Opening'),
+(@UNDEAD,@WARLOCK,61437,'Opening'),
+(@UNDEAD,@WARLOCK,68398,'Opening'),
+(@UNDEAD,@WARLOCK,96220,'Opening'),
+(@UNDEAD,@WARLOCK,203,'Unarmed'),
+(@UNDEAD,@WARLOCK,17747,'Language Gutterspeak'),
+(@UNDEAD,@WARLOCK,5227,'Underwater Breathing'),
+(@UNDEAD,@WARLOCK,7744,'Will of the Forsaken'),
+(@UNDEAD,@WARLOCK,20577,'Cannibalize'),
+(@UNDEAD,@WARLOCK,20579,'Shadow Resistance'),
+(@UNDEAD,@WARLOCK,79747,'Languages'),
+(@UNDEAD,@WARLOCK,688,'Summon Imp'),
+(@UNDEAD,@WARLOCK,86213,'Soul Swap Exhale'),
+(@UNDEAD,@WARLOCK,89420,'Drain Life'),
+(@UNDEAD,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@UNDEAD,@WARLOCK,76299,'Weapon Skills'),
+(@UNDEAD,@WARLOCK,76277,'Armor Skills'),
+(@UNDEAD,@WARLOCK,87330,'Suppression'),
+(@UNDEAD,@WARLOCK,227,'Staves'),
+(@UNDEAD,@WARLOCK,75445,'Demonic Immolate'),
+(@UNDEAD,@WARLOCK,686,'Shadow Bolt'),
+(@UNDEAD,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@UNDEAD,@WARLOCK,81,'Dodge'),
+(@UNDEAD,@WARLOCK,204,'Defense'),
+(@UNDEAD,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@UNDEAD,@WARLOCK,9078,'Cloth'),
+(@UNDEAD,@WARLOCK,201,'One-Handed Swords'),
+-- Tauren char create:
+-- Warrior Tauren
+(@TAUREN,@WARRIOR,202,'Two-Handed Swords'),
+(@TAUREN,@WARRIOR,196,'One-Handed Axes'),
+(@TAUREN,@WARRIOR,2457,'Battle Stance'),
+(@TAUREN,@WARRIOR,88161,'Strike'),
+(@TAUREN,@WARRIOR,5011,'Crossbows'),
+(@TAUREN,@WARRIOR,3018,'Shoot'),
+(@TAUREN,@WARRIOR,669,'Language Orcish'),
+(@TAUREN,@WARRIOR,197,'Two-Handed Axes'),
+(@TAUREN,@WARRIOR,1180,'Daggers'),
+(@TAUREN,@WARRIOR,45927,'Summon Friend'),
+(@TAUREN,@WARRIOR,6478,'Opening'),
+(@TAUREN,@WARRIOR,6603,'Auto Attack'),
+(@TAUREN,@WARRIOR,22027,'Remove Insignia'),
+(@TAUREN,@WARRIOR,22810,'Opening - No Text'),
+(@TAUREN,@WARRIOR,21651,'Opening'),
+(@TAUREN,@WARRIOR,21652,'Closing'),
+(@TAUREN,@WARRIOR,2382,'Generic'),
+(@TAUREN,@WARRIOR,3365,'Opening'),
+(@TAUREN,@WARRIOR,3050,'Detect'),
+(@TAUREN,@WARRIOR,9125,'Generic'),
+(@TAUREN,@WARRIOR,8386,'Attacking'),
+(@TAUREN,@WARRIOR,7266,'Duel'),
+(@TAUREN,@WARRIOR,7267,'Grovel'),
+(@TAUREN,@WARRIOR,7355,'Stuck'),
+(@TAUREN,@WARRIOR,6233,'Closing'),
+(@TAUREN,@WARRIOR,6246,'Closing'),
+(@TAUREN,@WARRIOR,6247,'Opening'),
+(@TAUREN,@WARRIOR,6477,'Opening'),
+(@TAUREN,@WARRIOR,61437,'Opening'),
+(@TAUREN,@WARRIOR,68398,'Opening'),
+(@TAUREN,@WARRIOR,96220,'Opening'),
+(@TAUREN,@WARRIOR,203,'Unarmed'),
+(@TAUREN,@WARRIOR,670,'Language Taurahe'),
+(@TAUREN,@WARRIOR,49410,'Forceful Deflection'),
+(@TAUREN,@WARRIOR,20549,'War Stomp'),
+(@TAUREN,@WARRIOR,20550,'Endurance'),
+(@TAUREN,@WARRIOR,20551,'Nature Resistance'),
+(@TAUREN,@WARRIOR,20552,'Cultivation'),
+(@TAUREN,@WARRIOR,79746,'Languages'),
+(@TAUREN,@WARRIOR,199,'Two-Handed Maces'),
+(@TAUREN,@WARRIOR,15590,'Fist Weapons'),
+(@TAUREN,@WARRIOR,76268,'Armor Skills'),
+(@TAUREN,@WARRIOR,76290,'Weapon Skills'),
+(@TAUREN,@WARRIOR,88163,'Attack'),
+(@TAUREN,@WARRIOR,200,'Polearms'),
+(@TAUREN,@WARRIOR,227,'Staves'),
+(@TAUREN,@WARRIOR,9116,'Shield'),
+(@TAUREN,@WARRIOR,8737,'Mail'),
+(@TAUREN,@WARRIOR,9077,'Leather'),
+(@TAUREN,@WARRIOR,264,'Bows'),
+(@TAUREN,@WARRIOR,266,'Guns'),
+(@TAUREN,@WARRIOR,107,'Block'),
+(@TAUREN,@WARRIOR,81,'Dodge'),
+(@TAUREN,@WARRIOR,32215,'Victorious State'),
+(@TAUREN,@WARRIOR,5301,'Defensive State (DND)'),
+(@TAUREN,@WARRIOR,204,'Defense'),
+(@TAUREN,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@WARRIOR,2764,'Throw'),
+(@TAUREN,@WARRIOR,2567,'Thrown'),
+(@TAUREN,@WARRIOR,9078,'Cloth'),
+(@TAUREN,@WARRIOR,198,'One-Handed Maces'),
+(@TAUREN,@WARRIOR,201,'One-Handed Swords'),
+-- Palading Tauren
+(@TAUREN,@PALADIN,202,'Two-Handed Swords'),
+(@TAUREN,@PALADIN,196,'One-Handed Axes'),
+(@TAUREN,@PALADIN,669,'Language Orcish'),
+(@TAUREN,@PALADIN,197,'Two-Handed Axes'),
+(@TAUREN,@PALADIN,45927,'Summon Friend'),
+(@TAUREN,@PALADIN,6478,'Opening'),
+(@TAUREN,@PALADIN,6603,'Auto Attack'),
+(@TAUREN,@PALADIN,22027,'Remove Insignia'),
+(@TAUREN,@PALADIN,22810,'Opening - No Text'),
+(@TAUREN,@PALADIN,21651,'Opening'),
+(@TAUREN,@PALADIN,21652,'Closing'),
+(@TAUREN,@PALADIN,2382,'Generic'),
+(@TAUREN,@PALADIN,3365,'Opening'),
+(@TAUREN,@PALADIN,3050,'Detect'),
+(@TAUREN,@PALADIN,9125,'Generic'),
+(@TAUREN,@PALADIN,8386,'Attacking'),
+(@TAUREN,@PALADIN,7266,'Duel'),
+(@TAUREN,@PALADIN,7267,'Grovel'),
+(@TAUREN,@PALADIN,7355,'Stuck'),
+(@TAUREN,@PALADIN,6233,'Closing'),
+(@TAUREN,@PALADIN,6246,'Closing'),
+(@TAUREN,@PALADIN,6247,'Opening'),
+(@TAUREN,@PALADIN,6477,'Opening'),
+(@TAUREN,@PALADIN,27762,'Relic'),
+(@TAUREN,@PALADIN,61437,'Opening'),
+(@TAUREN,@PALADIN,68398,'Opening'),
+(@TAUREN,@PALADIN,96220,'Opening'),
+(@TAUREN,@PALADIN,49410,'Forceful Deflection'),
+(@TAUREN,@PALADIN,203,'Unarmed'),
+(@TAUREN,@PALADIN,20549,'War Stomp'),
+(@TAUREN,@PALADIN,20550,'Endurance'),
+(@TAUREN,@PALADIN,20551,'Nature Resistance'),
+(@TAUREN,@PALADIN,20552,'Cultivation'),
+(@TAUREN,@PALADIN,79746,'Languages'),
+(@TAUREN,@PALADIN,199,'Two-Handed Maces'),
+(@TAUREN,@PALADIN,76271,'Armor Skills'),
+(@TAUREN,@PALADIN,76294,'Weapon Skills'),
+(@TAUREN,@PALADIN,200,'Polearms'),
+(@TAUREN,@PALADIN,670,'Language Taurahe'),
+(@TAUREN,@PALADIN,35395,'Crusader Strike'),
+(@TAUREN,@PALADIN,60091,'Judgement Anti-Parry/Dodge Passive'),
+(@TAUREN,@PALADIN,9116,'Shield'),
+(@TAUREN,@PALADIN,8737,'Mail'),
+(@TAUREN,@PALADIN,9077,'Leather'),
+(@TAUREN,@PALADIN,107,'Block'),
+(@TAUREN,@PALADIN,81,'Dodge'),
+(@TAUREN,@PALADIN,204,'Defense'),
+(@TAUREN,@PALADIN,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@PALADIN,9078,'Cloth'),
+(@TAUREN,@PALADIN,20208,'Paladin pushback resistance'),
+(@TAUREN,@PALADIN,198,'One-Handed Maces'),
+(@TAUREN,@PALADIN,201,'One-Handed Swords'),
+-- Hunter Tauren
+(@TAUREN,@HUNTER,202,'Two-Handed Swords'),
+(@TAUREN,@HUNTER,196,'One-Handed Axes'),
+(@TAUREN,@HUNTER,3044,'Arcane Shot'),
+(@TAUREN,@HUNTER,75,'Auto Shot'),
+(@TAUREN,@HUNTER,82928,'Aimed Shot!'),
+(@TAUREN,@HUNTER,5011,'Crossbows'),
+(@TAUREN,@HUNTER,669,'Language Orcish'),
+(@TAUREN,@HUNTER,197,'Two-Handed Axes'),
+(@TAUREN,@HUNTER,1180,'Daggers'),
+(@TAUREN,@HUNTER,45927,'Summon Friend'),
+(@TAUREN,@HUNTER,6478,'Opening'),
+(@TAUREN,@HUNTER,6603,'Auto Attack'),
+(@TAUREN,@HUNTER,22027,'Remove Insignia'),
+(@TAUREN,@HUNTER,22810,'Opening - No Text'),
+(@TAUREN,@HUNTER,21651,'Opening'),
+(@TAUREN,@HUNTER,21652,'Closing'),
+(@TAUREN,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@TAUREN,@HUNTER,2382,'Generic'),
+(@TAUREN,@HUNTER,3365,'Opening'),
+(@TAUREN,@HUNTER,3050,'Detect'),
+(@TAUREN,@HUNTER,9125,'Generic'),
+(@TAUREN,@HUNTER,8386,'Attacking'),
+(@TAUREN,@HUNTER,7266,'Duel'),
+(@TAUREN,@HUNTER,7267,'Grovel'),
+(@TAUREN,@HUNTER,7355,'Stuck'),
+(@TAUREN,@HUNTER,6233,'Closing'),
+(@TAUREN,@HUNTER,6246,'Closing'),
+(@TAUREN,@HUNTER,6247,'Opening'),
+(@TAUREN,@HUNTER,6477,'Opening'),
+(@TAUREN,@HUNTER,61437,'Opening'),
+(@TAUREN,@HUNTER,68398,'Opening'),
+(@TAUREN,@HUNTER,96220,'Opening'),
+(@TAUREN,@HUNTER,203,'Unarmed'),
+(@TAUREN,@HUNTER,883,'Call Pet 1'),
+(@TAUREN,@HUNTER,982,'Revive Pet'),
+(@TAUREN,@HUNTER,20549,'War Stomp'),
+(@TAUREN,@HUNTER,20550,'Endurance'),
+(@TAUREN,@HUNTER,20551,'Nature Resistance'),
+(@TAUREN,@HUNTER,20552,'Cultivation'),
+(@TAUREN,@HUNTER,79746,'Languages'),
+(@TAUREN,@HUNTER,15590,'Fist Weapons'),
+(@TAUREN,@HUNTER,200,'Polearms'),
+(@TAUREN,@HUNTER,227,'Staves'),
+(@TAUREN,@HUNTER,9077,'Leather'),
+(@TAUREN,@HUNTER,264,'Bows'),
+(@TAUREN,@HUNTER,266,'Guns'),
+(@TAUREN,@HUNTER,670,'Language Taurahe'),
+(@TAUREN,@HUNTER,13358,'Defensive State (DND)'),
+(@TAUREN,@HUNTER,81,'Dodge'),
+(@TAUREN,@HUNTER,204,'Defense'),
+(@TAUREN,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@TAUREN,@HUNTER,9078,'Cloth'),
+(@TAUREN,@HUNTER,77442,'Focus'),
+(@TAUREN,@HUNTER,76249,'Weapon Skills'),
+(@TAUREN,@HUNTER,76250,'Armor Skills'),
+(@TAUREN,@HUNTER,87324,'Focused Aim'),
+(@TAUREN,@HUNTER,87816,'General Hunter Passives'),
+(@TAUREN,@HUNTER,201,'One-Handed Swords'),
+-- Priest Tauren
+(@TAUREN,@PRIEST,5009,'Wands'),
+(@TAUREN,@PRIEST,5019,'Shoot'),
+(@TAUREN,@PRIEST,669,'Language Orcish'),
+(@TAUREN,@PRIEST,1180,'Daggers'),
+(@TAUREN,@PRIEST,45927,'Summon Friend'),
+(@TAUREN,@PRIEST,6478,'Opening'),
+(@TAUREN,@PRIEST,6603,'Auto Attack'),
+(@TAUREN,@PRIEST,22027,'Remove Insignia'),
+(@TAUREN,@PRIEST,22810,'Opening - No Text'),
+(@TAUREN,@PRIEST,21651,'Opening'),
+(@TAUREN,@PRIEST,21652,'Closing'),
+(@TAUREN,@PRIEST,2382,'Generic'),
+(@TAUREN,@PRIEST,3365,'Opening'),
+(@TAUREN,@PRIEST,3050,'Detect'),
+(@TAUREN,@PRIEST,9125,'Generic'),
+(@TAUREN,@PRIEST,8386,'Attacking'),
+(@TAUREN,@PRIEST,7266,'Duel'),
+(@TAUREN,@PRIEST,7267,'Grovel'),
+(@TAUREN,@PRIEST,7355,'Stuck'),
+(@TAUREN,@PRIEST,6233,'Closing'),
+(@TAUREN,@PRIEST,6246,'Closing'),
+(@TAUREN,@PRIEST,6247,'Opening'),
+(@TAUREN,@PRIEST,6477,'Opening'),
+(@TAUREN,@PRIEST,61437,'Opening'),
+(@TAUREN,@PRIEST,68398,'Opening'),
+(@TAUREN,@PRIEST,96220,'Opening'),
+(@TAUREN,@PRIEST,203,'Unarmed'),
+(@TAUREN,@PRIEST,585,'Smite'),
+(@TAUREN,@PRIEST,84733,'Holy Focus'),
+(@TAUREN,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@TAUREN,@PRIEST,88684,'Holy Word: Serenity'),
+(@TAUREN,@PRIEST,101062,'Flash Heal'),
+(@TAUREN,@PRIEST,20549,'War Stomp'),
+(@TAUREN,@PRIEST,20550,'Endurance'),
+(@TAUREN,@PRIEST,20551,'Nature Resistance'),
+(@TAUREN,@PRIEST,20552,'Cultivation'),
+(@TAUREN,@PRIEST,79746,'Languages'),
+(@TAUREN,@PRIEST,670,'Language Taurahe'),
+(@TAUREN,@PRIEST,76301,'Weapon Skills'),
+(@TAUREN,@PRIEST,76279,'Armor Skills'),
+(@TAUREN,@PRIEST,84734,'Dark Thoughts'),
+(@TAUREN,@PRIEST,227,'Staves'),
+(@TAUREN,@PRIEST,77486,'Shadow Orb Power'),
+(@TAUREN,@PRIEST,81,'Dodge'),
+(@TAUREN,@PRIEST,204,'Defense'),
+(@TAUREN,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@PRIEST,9078,'Cloth'),
+(@TAUREN,@PRIEST,198,'One-Handed Maces'),
+-- Mage Tauren
+(@TAUREN,@MAGE,71761,'Deep Freeze Immunity State'),
+(@TAUREN,@MAGE,5009,'Wands'),
+(@TAUREN,@MAGE,5019,'Shoot'),
+(@TAUREN,@MAGE,669,'Language Orcish'),
+(@TAUREN,@MAGE,1180,'Daggers'),
+(@TAUREN,@MAGE,45927,'Summon Friend'),
+(@TAUREN,@MAGE,6478,'Opening'),
+(@TAUREN,@MAGE,6603,'Auto Attack'),
+(@TAUREN,@MAGE,22027,'Remove Insignia'),
+(@TAUREN,@MAGE,22810,'Opening - No Text'),
+(@TAUREN,@MAGE,21651,'Opening'),
+(@TAUREN,@MAGE,21652,'Closing'),
+(@TAUREN,@MAGE,2382,'Generic'),
+(@TAUREN,@MAGE,3365,'Opening'),
+(@TAUREN,@MAGE,3050,'Detect'),
+(@TAUREN,@MAGE,9125,'Generic'),
+(@TAUREN,@MAGE,8386,'Attacking'),
+(@TAUREN,@MAGE,7266,'Duel'),
+(@TAUREN,@MAGE,7267,'Grovel'),
+(@TAUREN,@MAGE,7355,'Stuck'),
+(@TAUREN,@MAGE,6233,'Closing'),
+(@TAUREN,@MAGE,6246,'Closing'),
+(@TAUREN,@MAGE,6247,'Opening'),
+(@TAUREN,@MAGE,6477,'Opening'),
+(@TAUREN,@MAGE,61437,'Opening'),
+(@TAUREN,@MAGE,68398,'Opening'),
+(@TAUREN,@MAGE,96220,'Opening'),
+(@TAUREN,@MAGE,79684,'Offensive State (DND)'),
+(@TAUREN,@MAGE,203,'Unarmed'),
+(@TAUREN,@MAGE,670,'Language Taurahe'),
+(@TAUREN,@MAGE,20549,'War Stomp'),
+(@TAUREN,@MAGE,20550,'Endurance'),
+(@TAUREN,@MAGE,20551,'Nature Resistance'),
+(@TAUREN,@MAGE,20552,'Cultivation'),
+(@TAUREN,@MAGE,79746,'Languages'),
+(@TAUREN,@MAGE,133,'Fireball'),
+(@TAUREN,@MAGE,92315,'Pyroblast!'),
+(@TAUREN,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@TAUREN,@MAGE,76298,'Weapon Skills'),
+(@TAUREN,@MAGE,76276,'Armor Skills'),
+(@TAUREN,@MAGE,227,'Staves'),
+(@TAUREN,@MAGE,81,'Dodge'),
+(@TAUREN,@MAGE,204,'Defense'),
+(@TAUREN,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@MAGE,9078,'Cloth'),
+(@TAUREN,@MAGE,201,'One-Handed Swords'),
+-- Warlock Tauren
+(@TAUREN,@WARLOCK,5009,'Wands'),
+(@TAUREN,@WARLOCK,5019,'Shoot'),
+(@TAUREN,@WARLOCK,669,'Language Common'),
+(@TAUREN,@WARLOCK,1180,'Daggers'),
+(@TAUREN,@WARLOCK,45927,'Summon Friend'),
+(@TAUREN,@WARLOCK,6478,'Opening'),
+(@TAUREN,@WARLOCK,6603,'Auto Attack'),
+(@TAUREN,@WARLOCK,22027,'Remove Insignia'),
+(@TAUREN,@WARLOCK,22810,'Opening - No Text'),
+(@TAUREN,@WARLOCK,21651,'Opening'),
+(@TAUREN,@WARLOCK,21652,'Closing'),
+(@TAUREN,@WARLOCK,2382,'Generic'),
+(@TAUREN,@WARLOCK,3365,'Opening'),
+(@TAUREN,@WARLOCK,3050,'Detect'),
+(@TAUREN,@WARLOCK,9125,'Generic'),
+(@TAUREN,@WARLOCK,8386,'Attacking'),
+(@TAUREN,@WARLOCK,7266,'Duel'),
+(@TAUREN,@WARLOCK,7267,'Grovel'),
+(@TAUREN,@WARLOCK,7355,'Stuck'),
+(@TAUREN,@WARLOCK,6233,'Closing'),
+(@TAUREN,@WARLOCK,6246,'Closing'),
+(@TAUREN,@WARLOCK,6247,'Opening'),
+(@TAUREN,@WARLOCK,6477,'Opening'),
+(@TAUREN,@WARLOCK,61437,'Opening'),
+(@TAUREN,@WARLOCK,68398,'Opening'),
+(@TAUREN,@WARLOCK,96220,'Opening'),
+(@TAUREN,@WARLOCK,203,'Unarmed'),
+(@TAUREN,@WARLOCK,670,'Language Taurahe'),
+(@TAUREN,@WARLOCK,20549,'War Stomp'),
+(@TAUREN,@WARLOCK,20550,'Endurance'),
+(@TAUREN,@WARLOCK,20551,'Nature Resistance'),
+(@TAUREN,@WARLOCK,20552,'Cultivation'),
+(@TAUREN,@WARLOCK,79746,'Languages'),
+(@TAUREN,@WARLOCK,688,'Summon Imp'),
+(@TAUREN,@WARLOCK,86213,'Soul Swap Exhale'),
+(@TAUREN,@WARLOCK,89420,'Drain Life'),
+(@TAUREN,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@TAUREN,@WARLOCK,76299,'Weapon Skills'),
+(@TAUREN,@WARLOCK,76277,'Armor Skills'),
+(@TAUREN,@WARLOCK,87330,'Suppression'),
+(@TAUREN,@WARLOCK,227,'Staves'),
+(@TAUREN,@WARLOCK,75445,'Demonic Immolate'),
+(@TAUREN,@WARLOCK,686,'Shadow Bolt'),
+(@TAUREN,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@TAUREN,@WARLOCK,81,'Dodge'),
+(@TAUREN,@WARLOCK,204,'Defense'),
+(@TAUREN,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@WARLOCK,9078,'Cloth'),
+(@TAUREN,@WARLOCK,201,'One-Handed Swords'),
+-- Druid Tauren
+(@TAUREN,@DRUID,669,'Language Orcish'),
+(@TAUREN,@DRUID,1180,'Daggers'),
+(@TAUREN,@DRUID,45927,'Summon Friend'),
+(@TAUREN,@DRUID,6478,'Opening'),
+(@TAUREN,@DRUID,6603,'Auto Attack'),
+(@TAUREN,@DRUID,22027,'Remove Insignia'),
+(@TAUREN,@DRUID,22810,'Opening - No Text'),
+(@TAUREN,@DRUID,21651,'Opening'),
+(@TAUREN,@DRUID,21652,'Closing'),
+(@TAUREN,@DRUID,2382,'Generic'),
+(@TAUREN,@DRUID,3365,'Opening'),
+(@TAUREN,@DRUID,3050,'Detect'),
+(@TAUREN,@DRUID,9125,'Generic'),
+(@TAUREN,@DRUID,8386,'Attacking'),
+(@TAUREN,@DRUID,7266,'Duel'),
+(@TAUREN,@DRUID,7267,'Grovel'),
+(@TAUREN,@DRUID,7355,'Stuck'),
+(@TAUREN,@DRUID,6233,'Closing'),
+(@TAUREN,@DRUID,6246,'Closing'),
+(@TAUREN,@DRUID,6247,'Opening'),
+(@TAUREN,@DRUID,6477,'Opening'),
+(@TAUREN,@DRUID,61437,'Opening'),
+(@TAUREN,@DRUID,68398,'Opening'),
+(@TAUREN,@DRUID,96220,'Opening'),
+(@TAUREN,@DRUID,203,'Unarmed'),
+(@TAUREN,@DRUID,670,'Language Taurahe'),
+(@TAUREN,@DRUID,20549,'War Stomp'),
+(@TAUREN,@DRUID,20550,'Endurance'),
+(@TAUREN,@DRUID,20551,'Nature Resistance'),
+(@TAUREN,@DRUID,20552,'Cultivation'),
+(@TAUREN,@DRUID,79746,'Languages'),
+(@TAUREN,@DRUID,84736,"Nature's Focus"),
+(@TAUREN,@DRUID,81170,"Ravage!"),
+(@TAUREN,@DRUID,79577,"Eclipse Mastery Driver Passive"),
+(@TAUREN,@DRUID,76300,'Weapon Skills'),
+(@TAUREN,@DRUID,76275,'Armor Skills'),
+(@TAUREN,@DRUID,5176,'Wrath'),
+(@TAUREN,@DRUID,199,'Two-Handed Maces'),
+(@TAUREN,@DRUID,15590,'Fist Weapons'),
+(@TAUREN,@DRUID,84738,'Celestial Focus'),
+(@TAUREN,@DRUID,200,'Polearms'),
+(@TAUREN,@DRUID,227,'Staves'),
+(@TAUREN,@DRUID,81,'Dodge'),
+(@TAUREN,@DRUID,204,'Defense'),
+(@TAUREN,@DRUID,522,'SPELLDEFENSE (DND)'),
+(@TAUREN,@DRUID,9077,'Leather'),
+(@TAUREN,@DRUID,9078,'Cloth'),
+(@TAUREN,@DRUID,198,'One-Handed Maces'),
+-- Gnome char create:
+-- Warrior Gnome
+(@GNOME,@WARRIOR,202,'Two-Handed Swords'),
+(@GNOME,@WARRIOR,196,'One-Handed Axes'),
+(@GNOME,@WARRIOR,20591,'Expansive Mind'),
+(@GNOME,@WARRIOR,20593,'Engineering Specialization'),
+(@GNOME,@WARRIOR,20592,'Arcane Resistance'),
+(@GNOME,@WARRIOR,92680,'Shortblade Specialization'),
+(@GNOME,@WARRIOR,79740,'Languages'),
+(@GNOME,@WARRIOR,7340,'Language Gnomish'),
+(@GNOME,@WARRIOR,2457,'Battle Stance'),
+(@GNOME,@WARRIOR,88161,'Strike'),
+(@GNOME,@WARRIOR,5011,'Crossbows'),
+(@GNOME,@WARRIOR,3018,'Shoot'),
+(@GNOME,@WARRIOR,197,'Two-Handed Axes'),
+(@GNOME,@WARRIOR,1180,'Daggers'),
+(@GNOME,@WARRIOR,45927,'Summon Friend'),
+(@GNOME,@WARRIOR,6478,'Opening'),
+(@GNOME,@WARRIOR,6603,'Auto Attack'),
+(@GNOME,@WARRIOR,22027,'Remove Insignia'),
+(@GNOME,@WARRIOR,22810,'Opening - No Text'),
+(@GNOME,@WARRIOR,21651,'Opening'),
+(@GNOME,@WARRIOR,21652,'Closing'),
+(@GNOME,@WARRIOR,2382,'Generic'),
+(@GNOME,@WARRIOR,3365,'Opening'),
+(@GNOME,@WARRIOR,3050,'Detect'),
+(@GNOME,@WARRIOR,9125,'Generic'),
+(@GNOME,@WARRIOR,8386,'Attacking'),
+(@GNOME,@WARRIOR,7266,'Duel'),
+(@GNOME,@WARRIOR,7267,'Grovel'),
+(@GNOME,@WARRIOR,7355,'Stuck'),
+(@GNOME,@WARRIOR,6233,'Closing'),
+(@GNOME,@WARRIOR,6246,'Closing'),
+(@GNOME,@WARRIOR,6247,'Opening'),
+(@GNOME,@WARRIOR,6477,'Opening'),
+(@GNOME,@WARRIOR,61437,'Opening'),
+(@GNOME,@WARRIOR,68398,'Opening'),
+(@GNOME,@WARRIOR,96220,'Opening'),
+(@GNOME,@WARRIOR,203,'Unarmed'),
+(@GNOME,@WARRIOR,49410,'Forceful Deflection'),
+(@GNOME,@WARRIOR,199,'Two-Handed Maces'),
+(@GNOME,@WARRIOR,15590,'Fist Weapons'),
+(@GNOME,@WARRIOR,76268,'Armor Skills'),
+(@GNOME,@WARRIOR,76290,'Weapon Skills'),
+(@GNOME,@WARRIOR,88163,'Attack'),
+(@GNOME,@WARRIOR,200,'Polearms'),
+(@GNOME,@WARRIOR,668,'Language Common'),
+(@GNOME,@WARRIOR,227,'Staves'),
+(@GNOME,@WARRIOR,9116,'Shield'),
+(@GNOME,@WARRIOR,8737,'Mail'),
+(@GNOME,@WARRIOR,9077,'Leather'),
+(@GNOME,@WARRIOR,264,'Bows'),
+(@GNOME,@WARRIOR,266,'Guns'),
+(@GNOME,@WARRIOR,107,'Block'),
+(@GNOME,@WARRIOR,81,'Dodge'),
+(@GNOME,@WARRIOR,32215,'Victorious State'),
+(@GNOME,@WARRIOR,5301,'Defensive State (DND)'),
+(@GNOME,@WARRIOR,204,'Defense'),
+(@GNOME,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@GNOME,@WARRIOR,2764,'Throw'),
+(@GNOME,@WARRIOR,2567,'Thrown'),
+(@GNOME,@WARRIOR,9078,'Cloth'),
+(@GNOME,@WARRIOR,198,'One-Handed Maces'),
+(@GNOME,@WARRIOR,201,'One-Handed Swords'),
+-- Rogue Gnome
+(@GNOME,@ROGUE,196,'One-Handed Axes'),
+(@GNOME,@ROGUE,20591,'Expansive Mind'),
+(@GNOME,@ROGUE,20593,'Engineering Specialization'),
+(@GNOME,@ROGUE,20592,'Arcane Resistance'),
+(@GNOME,@ROGUE,92680,'Shortblade Specialization'),
+(@GNOME,@ROGUE,79740,'Languages'),
+(@GNOME,@ROGUE,7340,'Language Gnomish'),
+(@GNOME,@ROGUE,1752,'Sinister Strike'),
+(@GNOME,@ROGUE,5011,'Crossbows'),
+(@GNOME,@ROGUE,3018,'Shoot'),
+(@GNOME,@ROGUE,674,'Dual Wield'),
+(@GNOME,@ROGUE,1180,'Daggers'),
+(@GNOME,@ROGUE,45927,'Summon Friend'),
+(@GNOME,@ROGUE,6478,'Opening'),
+(@GNOME,@ROGUE,6603,'Auto Attack'),
+(@GNOME,@ROGUE,22027,'Remove Insignia'),
+(@GNOME,@ROGUE,22810,'Opening - No Text'),
+(@GNOME,@ROGUE,21651,'Opening'),
+(@GNOME,@ROGUE,21652,'Closing'),
+(@GNOME,@ROGUE,2382,'Generic'),
+(@GNOME,@ROGUE,3365,'Opening'),
+(@GNOME,@ROGUE,3050,'Detect'),
+(@GNOME,@ROGUE,9125,'Generic'),
+(@GNOME,@ROGUE,8386,'Attacking'),
+(@GNOME,@ROGUE,7266,'Duel'),
+(@GNOME,@ROGUE,7267,'Grovel'),
+(@GNOME,@ROGUE,7355,'Stuck'),
+(@GNOME,@ROGUE,6233,'Closing'),
+(@GNOME,@ROGUE,6246,'Closing'),
+(@GNOME,@ROGUE,6247,'Opening'),
+(@GNOME,@ROGUE,6477,'Opening'),
+(@GNOME,@ROGUE,61437,'Opening'),
+(@GNOME,@ROGUE,68398,'Opening'),
+(@GNOME,@ROGUE,96220,'Opening'),
+(@GNOME,@ROGUE,203,'Unarmed'),
+(@GNOME,@ROGUE,15590,'Fist Weapons'),
+(@GNOME,@ROGUE,76273,'Armor Skills'),
+(@GNOME,@ROGUE,76297,'Weapon Skills'),
+(@GNOME,@ROGUE,668,'Language Common'),
+(@GNOME,@ROGUE,9077,'Leather'),
+(@GNOME,@ROGUE,264,'Bows'),
+(@GNOME,@ROGUE,266,'Guns'),
+(@GNOME,@ROGUE,81,'Dodge'),
+(@GNOME,@ROGUE,204,'Defense'),
+(@GNOME,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@GNOME,@ROGUE,16092,'Defensive State (DND)'),
+(@GNOME,@ROGUE,2764,'Throw'),
+(@GNOME,@ROGUE,2567,'Thrown'),
+(@GNOME,@ROGUE,9078,'Cloth'),
+(@GNOME,@ROGUE,198,'One-Handed Maces'),
+(@GNOME,@ROGUE,201,'One-Handed Swords'),
+-- Priest Gnome
+(@GNOME,@PRIEST,20591,'Expansive Mind'),
+(@GNOME,@PRIEST,20593,'Engineering Specialization'),
+(@GNOME,@PRIEST,20592,'Arcane Resistance'),
+(@GNOME,@PRIEST,92680,'Shortblade Specialization'),
+(@GNOME,@PRIEST,79740,'Languages'),
+(@GNOME,@PRIEST,7340,'Language Gnomish'),
+(@GNOME,@PRIEST,5009,'Wands'),
+(@GNOME,@PRIEST,5019,'Shoot'),
+(@GNOME,@PRIEST,1180,'Daggers'),
+(@GNOME,@PRIEST,45927,'Summon Friend'),
+(@GNOME,@PRIEST,6478,'Opening'),
+(@GNOME,@PRIEST,6603,'Auto Attack'),
+(@GNOME,@PRIEST,22027,'Remove Insignia'),
+(@GNOME,@PRIEST,22810,'Opening - No Text'),
+(@GNOME,@PRIEST,21651,'Opening'),
+(@GNOME,@PRIEST,21652,'Closing'),
+(@GNOME,@PRIEST,2382,'Generic'),
+(@GNOME,@PRIEST,3365,'Opening'),
+(@GNOME,@PRIEST,3050,'Detect'),
+(@GNOME,@PRIEST,9125,'Generic'),
+(@GNOME,@PRIEST,8386,'Attacking'),
+(@GNOME,@PRIEST,7266,'Duel'),
+(@GNOME,@PRIEST,7267,'Grovel'),
+(@GNOME,@PRIEST,7355,'Stuck'),
+(@GNOME,@PRIEST,6233,'Closing'),
+(@GNOME,@PRIEST,6246,'Closing'),
+(@GNOME,@PRIEST,6247,'Opening'),
+(@GNOME,@PRIEST,6477,'Opening'),
+(@GNOME,@PRIEST,61437,'Opening'),
+(@GNOME,@PRIEST,68398,'Opening'),
+(@GNOME,@PRIEST,96220,'Opening'),
+(@GNOME,@PRIEST,203,'Unarmed'),
+(@GNOME,@PRIEST,585,'Smite'),
+(@GNOME,@PRIEST,84733,'Holy Focus'),
+(@GNOME,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@GNOME,@PRIEST,88684,'Holy Word: Serenity'),
+(@GNOME,@PRIEST,101062,'Flash Heal'),
+(@GNOME,@PRIEST,76301,'Weapon Skills'),
+(@GNOME,@PRIEST,76279,'Armor Skills'),
+(@GNOME,@PRIEST,84734,'Dark Thoughts'),
+(@GNOME,@PRIEST,668,'Language Common'),
+(@GNOME,@PRIEST,227,'Staves'),
+(@GNOME,@PRIEST,77486,'Shadow Orb Power'),
+(@GNOME,@PRIEST,81,'Dodge'),
+(@GNOME,@PRIEST,204,'Defense'),
+(@GNOME,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@GNOME,@PRIEST,9078,'Cloth'),
+(@GNOME,@PRIEST,198,'One-Handed Maces'),
+-- Mage Gnome
+(@GNOME,@MAGE,71761,'Deep Freeze Immunity State'),
+(@GNOME,@MAGE,20591,'Expansive Mind'),
+(@GNOME,@MAGE,20593,'Engineering Specialization'),
+(@GNOME,@MAGE,20592,'Arcane Resistance'),
+(@GNOME,@MAGE,92680,'Shortblade Specialization'),
+(@GNOME,@MAGE,79740,'Languages'),
+(@GNOME,@MAGE,7340,'Language Gnomish'),
+(@GNOME,@MAGE,5009,'Wands'),
+(@GNOME,@MAGE,5019,'Shoot'),
+(@GNOME,@MAGE,1180,'Daggers'),
+(@GNOME,@MAGE,45927,'Summon Friend'),
+(@GNOME,@MAGE,6478,'Opening'),
+(@GNOME,@MAGE,6603,'Auto Attack'),
+(@GNOME,@MAGE,22027,'Remove Insignia'),
+(@GNOME,@MAGE,22810,'Opening - No Text'),
+(@GNOME,@MAGE,21651,'Opening'),
+(@GNOME,@MAGE,21652,'Closing'),
+(@GNOME,@MAGE,2382,'Generic'),
+(@GNOME,@MAGE,3365,'Opening'),
+(@GNOME,@MAGE,3050,'Detect'),
+(@GNOME,@MAGE,9125,'Generic'),
+(@GNOME,@MAGE,8386,'Attacking'),
+(@GNOME,@MAGE,7266,'Duel'),
+(@GNOME,@MAGE,7267,'Grovel'),
+(@GNOME,@MAGE,7355,'Stuck'),
+(@GNOME,@MAGE,6233,'Closing'),
+(@GNOME,@MAGE,6246,'Closing'),
+(@GNOME,@MAGE,6247,'Opening'),
+(@GNOME,@MAGE,6477,'Opening'),
+(@GNOME,@MAGE,61437,'Opening'),
+(@GNOME,@MAGE,68398,'Opening'),
+(@GNOME,@MAGE,96220,'Opening'),
+(@GNOME,@MAGE,79684,'Offensive State (DND)'),
+(@GNOME,@MAGE,203,'Unarmed'),
+(@GNOME,@MAGE,133,'Fireball'),
+(@GNOME,@MAGE,92315,'Pyroblast!'),
+(@GNOME,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@GNOME,@MAGE,76298,'Weapon Skills'),
+(@GNOME,@MAGE,76276,'Armor Skills'),
+(@GNOME,@MAGE,668,'Language Common'),
+(@GNOME,@MAGE,227,'Staves'),
+(@GNOME,@MAGE,81,'Dodge'),
+(@GNOME,@MAGE,204,'Defense'),
+(@GNOME,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@GNOME,@MAGE,9078,'Cloth'),
+(@GNOME,@MAGE,201,'One-Handed Swords'),
+-- Warlock Gnome
+(@GNOME,@WARLOCK,20591,'Expansive Mind'),
+(@GNOME,@WARLOCK,20593,'Engineering Specialization'),
+(@GNOME,@WARLOCK,20592,'Arcane Resistance'),
+(@GNOME,@WARLOCK,92680,'Shortblade Specialization'),
+(@GNOME,@WARLOCK,79740,'Languages'),
+(@GNOME,@WARLOCK,7340,'Language Gnomish'),
+(@GNOME,@WARLOCK,5009,'Wands'),
+(@GNOME,@WARLOCK,5019,'Shoot'),
+(@GNOME,@WARLOCK,1180,'Daggers'),
+(@GNOME,@WARLOCK,45927,'Summon Friend'),
+(@GNOME,@WARLOCK,6478,'Opening'),
+(@GNOME,@WARLOCK,6603,'Auto Attack'),
+(@GNOME,@WARLOCK,22027,'Remove Insignia'),
+(@GNOME,@WARLOCK,22810,'Opening - No Text'),
+(@GNOME,@WARLOCK,21651,'Opening'),
+(@GNOME,@WARLOCK,21652,'Closing'),
+(@GNOME,@WARLOCK,2382,'Generic'),
+(@GNOME,@WARLOCK,3365,'Opening'),
+(@GNOME,@WARLOCK,3050,'Detect'),
+(@GNOME,@WARLOCK,9125,'Generic'),
+(@GNOME,@WARLOCK,8386,'Attacking'),
+(@GNOME,@WARLOCK,7266,'Duel'),
+(@GNOME,@WARLOCK,7267,'Grovel'),
+(@GNOME,@WARLOCK,7355,'Stuck'),
+(@GNOME,@WARLOCK,6233,'Closing'),
+(@GNOME,@WARLOCK,6246,'Closing'),
+(@GNOME,@WARLOCK,6247,'Opening'),
+(@GNOME,@WARLOCK,6477,'Opening'),
+(@GNOME,@WARLOCK,61437,'Opening'),
+(@GNOME,@WARLOCK,68398,'Opening'),
+(@GNOME,@WARLOCK,96220,'Opening'),
+(@GNOME,@WARLOCK,203,'Unarmed'),
+(@GNOME,@WARLOCK,688,'Summon Imp'),
+(@GNOME,@WARLOCK,86213,'Soul Swap Exhale'),
+(@GNOME,@WARLOCK,89420,'Drain Life'),
+(@GNOME,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@GNOME,@WARLOCK,76299,'Weapon Skills'),
+(@GNOME,@WARLOCK,76277,'Armor Skills'),
+(@GNOME,@WARLOCK,87330,'Suppression'),
+(@GNOME,@WARLOCK,668,'Language Common'),
+(@GNOME,@WARLOCK,227,'Staves'),
+(@GNOME,@WARLOCK,75445,'Demonic Immolate'),
+(@GNOME,@WARLOCK,686,'Shadow Bolt'),
+(@GNOME,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@GNOME,@WARLOCK,81,'Dodge'),
+(@GNOME,@WARLOCK,204,'Defense'),
+(@GNOME,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@GNOME,@WARLOCK,9078,'Cloth'),
+(@GNOME,@WARLOCK,201,'One-Handed Swords'),
+-- Troll char create:
+-- Warrior Troll
+(@TROLL,@WARRIOR,202,'Two-Handed Swords'),
+(@TROLL,@WARRIOR,7341,'Language Troll'),
+(@TROLL,@WARRIOR,26290,'Bow Specialization'),
+(@TROLL,@WARRIOR,26297,'Berserking'),
+(@TROLL,@WARRIOR,58943,'Da Voodoo Shuffle'),
+(@TROLL,@WARRIOR,20555,'Regeneration'),
+(@TROLL,@WARRIOR,20557,'Beast Slaying'),
+(@TROLL,@WARRIOR,20558,'Throwing Specialization'),
+(@TROLL,@WARRIOR,79744,'Languages'),
+(@TROLL,@WARRIOR,196,'One-Handed Axes'),
+(@TROLL,@WARRIOR,2457,'Battle Stance'),
+(@TROLL,@WARRIOR,88161,'Strike'),
+(@TROLL,@WARRIOR,5011,'Crossbows'),
+(@TROLL,@WARRIOR,3018,'Shoot'),
+(@TROLL,@WARRIOR,669,'Language Orcish'),
+(@TROLL,@WARRIOR,197,'Two-Handed Axes'),
+(@TROLL,@WARRIOR,1180,'Daggers'),
+(@TROLL,@WARRIOR,45927,'Summon Friend'),
+(@TROLL,@WARRIOR,6478,'Opening'),
+(@TROLL,@WARRIOR,6603,'Auto Attack'),
+(@TROLL,@WARRIOR,22027,'Remove Insignia'),
+(@TROLL,@WARRIOR,22810,'Opening - No Text'),
+(@TROLL,@WARRIOR,21651,'Opening'),
+(@TROLL,@WARRIOR,21652,'Closing'),
+(@TROLL,@WARRIOR,2382,'Generic'),
+(@TROLL,@WARRIOR,3365,'Opening'),
+(@TROLL,@WARRIOR,3050,'Detect'),
+(@TROLL,@WARRIOR,9125,'Generic'),
+(@TROLL,@WARRIOR,8386,'Attacking'),
+(@TROLL,@WARRIOR,7266,'Duel'),
+(@TROLL,@WARRIOR,7267,'Grovel'),
+(@TROLL,@WARRIOR,7355,'Stuck'),
+(@TROLL,@WARRIOR,6233,'Closing'),
+(@TROLL,@WARRIOR,6246,'Closing'),
+(@TROLL,@WARRIOR,6247,'Opening'),
+(@TROLL,@WARRIOR,6477,'Opening'),
+(@TROLL,@WARRIOR,61437,'Opening'),
+(@TROLL,@WARRIOR,68398,'Opening'),
+(@TROLL,@WARRIOR,96220,'Opening'),
+(@TROLL,@WARRIOR,203,'Unarmed'),
+(@TROLL,@WARRIOR,49410,'Forceful Deflection'),
+(@TROLL,@WARRIOR,199,'Two-Handed Maces'),
+(@TROLL,@WARRIOR,15590,'Fist Weapons'),
+(@TROLL,@WARRIOR,76268,'Armor Skills'),
+(@TROLL,@WARRIOR,76290,'Weapon Skills'),
+(@TROLL,@WARRIOR,88163,'Attack'),
+(@TROLL,@WARRIOR,200,'Polearms'),
+(@TROLL,@WARRIOR,227,'Staves'),
+(@TROLL,@WARRIOR,9116,'Shield'),
+(@TROLL,@WARRIOR,8737,'Mail'),
+(@TROLL,@WARRIOR,9077,'Leather'),
+(@TROLL,@WARRIOR,264,'Bows'),
+(@TROLL,@WARRIOR,266,'Guns'),
+(@TROLL,@WARRIOR,107,'Block'),
+(@TROLL,@WARRIOR,81,'Dodge'),
+(@TROLL,@WARRIOR,32215,'Victorious State'),
+(@TROLL,@WARRIOR,5301,'Defensive State (DND)'),
+(@TROLL,@WARRIOR,204,'Defense'),
+(@TROLL,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@WARRIOR,2764,'Throw'),
+(@TROLL,@WARRIOR,2567,'Thrown'),
+(@TROLL,@WARRIOR,9078,'Cloth'),
+(@TROLL,@WARRIOR,198,'One-Handed Maces'),
+(@TROLL,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Troll
+(@TROLL,@HUNTER,202,'Two-Handed Swords'),
+(@TROLL,@HUNTER,7341,'Language Troll'),
+(@TROLL,@HUNTER,26290,'Bow Specialization'),
+(@TROLL,@HUNTER,26297,'Berserking'),
+(@TROLL,@HUNTER,58943,'Da Voodoo Shuffle'),
+(@TROLL,@HUNTER,20555,'Regeneration'),
+(@TROLL,@HUNTER,20557,'Beast Slaying'),
+(@TROLL,@HUNTER,20558,'Throwing Specialization'),
+(@TROLL,@HUNTER,79744,'Languages'),
+(@TROLL,@HUNTER,196,'One-Handed Axes'),
+(@TROLL,@HUNTER,3044,'Arcane Shot'),
+(@TROLL,@HUNTER,75,'Auto Shot'),
+(@TROLL,@HUNTER,82928,'Aimed Shot!'),
+(@TROLL,@HUNTER,5011,'Crossbows'),
+(@TROLL,@HUNTER,669,'Language Orcish'),
+(@TROLL,@HUNTER,197,'Two-Handed Axes'),
+(@TROLL,@HUNTER,1180,'Daggers'),
+(@TROLL,@HUNTER,45927,'Summon Friend'),
+(@TROLL,@HUNTER,6478,'Opening'),
+(@TROLL,@HUNTER,6603,'Auto Attack'),
+(@TROLL,@HUNTER,22027,'Remove Insignia'),
+(@TROLL,@HUNTER,22810,'Opening - No Text'),
+(@TROLL,@HUNTER,21651,'Opening'),
+(@TROLL,@HUNTER,21652,'Closing'),
+(@TROLL,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@TROLL,@HUNTER,2382,'Generic'),
+(@TROLL,@HUNTER,3365,'Opening'),
+(@TROLL,@HUNTER,3050,'Detect'),
+(@TROLL,@HUNTER,9125,'Generic'),
+(@TROLL,@HUNTER,8386,'Attacking'),
+(@TROLL,@HUNTER,7266,'Duel'),
+(@TROLL,@HUNTER,7267,'Grovel'),
+(@TROLL,@HUNTER,7355,'Stuck'),
+(@TROLL,@HUNTER,6233,'Closing'),
+(@TROLL,@HUNTER,6246,'Closing'),
+(@TROLL,@HUNTER,6247,'Opening'),
+(@TROLL,@HUNTER,6477,'Opening'),
+(@TROLL,@HUNTER,61437,'Opening'),
+(@TROLL,@HUNTER,68398,'Opening'),
+(@TROLL,@HUNTER,96220,'Opening'),
+(@TROLL,@HUNTER,203,'Unarmed'),
+(@TROLL,@HUNTER,883,'Call Pet 1'),
+(@TROLL,@HUNTER,982,'Revive Pet'),
+(@TROLL,@HUNTER,15590,'Fist Weapons'),
+(@TROLL,@HUNTER,200,'Polearms'),
+(@TROLL,@HUNTER,227,'Staves'),
+(@TROLL,@HUNTER,9077,'Leather'),
+(@TROLL,@HUNTER,264,'Bows'),
+(@TROLL,@HUNTER,266,'Guns'),
+(@TROLL,@HUNTER,13358,'Defensive State (DND)'),
+(@TROLL,@HUNTER,81,'Dodge'),
+(@TROLL,@HUNTER,204,'Defense'),
+(@TROLL,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@TROLL,@HUNTER,9078,'Cloth'),
+(@TROLL,@HUNTER,77442,'Focus'),
+(@TROLL,@HUNTER,76249,'Weapon Skills'),
+(@TROLL,@HUNTER,76250,'Armor Skills'),
+(@TROLL,@HUNTER,87324,'Focused Aim'),
+(@TROLL,@HUNTER,87816,'General Hunter Passives'),
+(@TROLL,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Troll
+(@TROLL,@ROGUE,7341,'Language Troll'),
+(@TROLL,@ROGUE,26290,'Bow Specialization'),
+(@TROLL,@ROGUE,26297,'Berserking'),
+(@TROLL,@ROGUE,58943,'Da Voodoo Shuffle'),
+(@TROLL,@ROGUE,20555,'Regeneration'),
+(@TROLL,@ROGUE,20557,'Beast Slaying'),
+(@TROLL,@ROGUE,20558,'Throwing Specialization'),
+(@TROLL,@ROGUE,79744,'Languages'),
+(@TROLL,@ROGUE,196,'One-Handed Axes'),
+(@TROLL,@ROGUE,1752,'Sinister Strike'),
+(@TROLL,@ROGUE,5011,'Crossbows'),
+(@TROLL,@ROGUE,3018,'Shoot'),
+(@TROLL,@ROGUE,669,'Language Orcish'),
+(@TROLL,@ROGUE,674,'Dual Wield'),
+(@TROLL,@ROGUE,1180,'Daggers'),
+(@TROLL,@ROGUE,45927,'Summon Friend'),
+(@TROLL,@ROGUE,6478,'Opening'),
+(@TROLL,@ROGUE,6603,'Auto Attack'),
+(@TROLL,@ROGUE,22027,'Remove Insignia'),
+(@TROLL,@ROGUE,22810,'Opening - No Text'),
+(@TROLL,@ROGUE,21651,'Opening'),
+(@TROLL,@ROGUE,21652,'Closing'),
+(@TROLL,@ROGUE,2382,'Generic'),
+(@TROLL,@ROGUE,3365,'Opening'),
+(@TROLL,@ROGUE,3050,'Detect'),
+(@TROLL,@ROGUE,9125,'Generic'),
+(@TROLL,@ROGUE,8386,'Attacking'),
+(@TROLL,@ROGUE,7266,'Duel'),
+(@TROLL,@ROGUE,7267,'Grovel'),
+(@TROLL,@ROGUE,7355,'Stuck'),
+(@TROLL,@ROGUE,6233,'Closing'),
+(@TROLL,@ROGUE,6246,'Closing'),
+(@TROLL,@ROGUE,6247,'Opening'),
+(@TROLL,@ROGUE,6477,'Opening'),
+(@TROLL,@ROGUE,61437,'Opening'),
+(@TROLL,@ROGUE,68398,'Opening'),
+(@TROLL,@ROGUE,96220,'Opening'),
+(@TROLL,@ROGUE,203,'Unarmed'),
+(@TROLL,@ROGUE,15590,'Fist Weapons'),
+(@TROLL,@ROGUE,76273,'Armor Skills'),
+(@TROLL,@ROGUE,76297,'Weapon Skills'),
+(@TROLL,@ROGUE,9077,'Leather'),
+(@TROLL,@ROGUE,264,'Bows'),
+(@TROLL,@ROGUE,266,'Guns'),
+(@TROLL,@ROGUE,81,'Dodge'),
+(@TROLL,@ROGUE,204,'Defense'),
+(@TROLL,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@ROGUE,16092,'Defensive State (DND)'),
+(@TROLL,@ROGUE,2764,'Throw'),
+(@TROLL,@ROGUE,2567,'Thrown'),
+(@TROLL,@ROGUE,9078,'Cloth'),
+(@TROLL,@ROGUE,198,'One-Handed Maces'),
+(@TROLL,@ROGUE,201,'One-Handed Swords'),
+-- Priest Troll
+(@TROLL,@PRIEST,7341,'Language Troll'),
+(@TROLL,@PRIEST,26290,'Bow Specialization'),
+(@TROLL,@PRIEST,26297,'Berserking'),
+(@TROLL,@PRIEST,58943,'Da Voodoo Shuffle'),
+(@TROLL,@PRIEST,20555,'Regeneration'),
+(@TROLL,@PRIEST,20557,'Beast Slaying'),
+(@TROLL,@PRIEST,20558,'Throwing Specialization'),
+(@TROLL,@PRIEST,79744,'Languages'),
+(@TROLL,@PRIEST,5009,'Wands'),
+(@TROLL,@PRIEST,5019,'Shoot'),
+(@TROLL,@PRIEST,669,'Language Orcish'),
+(@TROLL,@PRIEST,1180,'Daggers'),
+(@TROLL,@PRIEST,45927,'Summon Friend'),
+(@TROLL,@PRIEST,6478,'Opening'),
+(@TROLL,@PRIEST,6603,'Auto Attack'),
+(@TROLL,@PRIEST,22027,'Remove Insignia'),
+(@TROLL,@PRIEST,22810,'Opening - No Text'),
+(@TROLL,@PRIEST,21651,'Opening'),
+(@TROLL,@PRIEST,21652,'Closing'),
+(@TROLL,@PRIEST,2382,'Generic'),
+(@TROLL,@PRIEST,3365,'Opening'),
+(@TROLL,@PRIEST,3050,'Detect'),
+(@TROLL,@PRIEST,9125,'Generic'),
+(@TROLL,@PRIEST,8386,'Attacking'),
+(@TROLL,@PRIEST,7266,'Duel'),
+(@TROLL,@PRIEST,7267,'Grovel'),
+(@TROLL,@PRIEST,7355,'Stuck'),
+(@TROLL,@PRIEST,6233,'Closing'),
+(@TROLL,@PRIEST,6246,'Closing'),
+(@TROLL,@PRIEST,6247,'Opening'),
+(@TROLL,@PRIEST,6477,'Opening'),
+(@TROLL,@PRIEST,61437,'Opening'),
+(@TROLL,@PRIEST,68398,'Opening'),
+(@TROLL,@PRIEST,96220,'Opening'),
+(@TROLL,@PRIEST,203,'Unarmed'),
+(@TROLL,@PRIEST,585,'Smite'),
+(@TROLL,@PRIEST,84733,'Holy Focus'),
+(@TROLL,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@TROLL,@PRIEST,88684,'Holy Word: Serenity'),
+(@TROLL,@PRIEST,101062,'Flash Heal'),
+(@TROLL,@PRIEST,76301,'Weapon Skills'),
+(@TROLL,@PRIEST,76279,'Armor Skills'),
+(@TROLL,@PRIEST,84734,'Dark Thoughts'),
+(@TROLL,@PRIEST,227,'Staves'),
+(@TROLL,@PRIEST,77486,'Shadow Orb Power'),
+(@TROLL,@PRIEST,81,'Dodge'),
+(@TROLL,@PRIEST,204,'Defense'),
+(@TROLL,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@PRIEST,9078,'Cloth'),
+(@TROLL,@PRIEST,198,'One-Handed Maces'),
+-- Shaman Troll
+(@TROLL,@SHAMAN,196,'One-Handed Axes'),
+(@TROLL,@SHAMAN,7341,'Language Troll'),
+(@TROLL,@SHAMAN,26290,'Bow Specialization'),
+(@TROLL,@SHAMAN,26297,'Berserking'),
+(@TROLL,@SHAMAN,58943,'Da Voodoo Shuffle'),
+(@TROLL,@SHAMAN,20555,'Regeneration'),
+(@TROLL,@SHAMAN,20557,'Beast Slaying'),
+(@TROLL,@SHAMAN,20558,'Throwing Specialization'),
+(@TROLL,@SHAMAN,79744,'Languages'),
+(@TROLL,@SHAMAN,669,'Language Orcish'),
+(@TROLL,@SHAMAN,197,'Two-Handed Axes'),
+(@TROLL,@SHAMAN,1180,'Daggers'),
+(@TROLL,@SHAMAN,45927,'Summon Friend'),
+(@TROLL,@SHAMAN,6478,'Opening'),
+(@TROLL,@SHAMAN,6603,'Auto Attack'),
+(@TROLL,@SHAMAN,22027,'Remove Insignia'),
+(@TROLL,@SHAMAN,22810,'Opening - No Text'),
+(@TROLL,@SHAMAN,21651,'Opening'),
+(@TROLL,@SHAMAN,21652,'Closing'),
+(@TROLL,@SHAMAN,2382,'Generic'),
+(@TROLL,@SHAMAN,3365,'Opening'),
+(@TROLL,@SHAMAN,3050,'Detect'),
+(@TROLL,@SHAMAN,9125,'Generic'),
+(@TROLL,@SHAMAN,8386,'Attacking'),
+(@TROLL,@SHAMAN,7266,'Duel'),
+(@TROLL,@SHAMAN,7267,'Grovel'),
+(@TROLL,@SHAMAN,7355,'Stuck'),
+(@TROLL,@SHAMAN,6233,'Closing'),
+(@TROLL,@SHAMAN,6246,'Closing'),
+(@TROLL,@SHAMAN,6247,'Opening'),
+(@TROLL,@SHAMAN,6477,'Opening'),
+(@TROLL,@SHAMAN,27763,'Relic'),
+(@TROLL,@SHAMAN,61437,'Opening'),
+(@TROLL,@SHAMAN,68398,'Opening'),
+(@TROLL,@SHAMAN,96220,'Opening'),
+(@TROLL,@SHAMAN,203,'Unarmed'),
+(@TROLL,@SHAMAN,199,'Two-Handed Maces'),
+(@TROLL,@SHAMAN,15590,'Fist Weapons'),
+(@TROLL,@SHAMAN,76272,'Armor Skills'),
+(@TROLL,@SHAMAN,76296,'Weapon Skills'),
+(@TROLL,@SHAMAN,89920,'Ancestral Focus'),
+(@TROLL,@SHAMAN,227,'Staves'),
+(@TROLL,@SHAMAN,9116,'Shield'),
+(@TROLL,@SHAMAN,9077,'Leather'),
+(@TROLL,@SHAMAN,107,'Block'),
+(@TROLL,@SHAMAN,81,'Dodge'),
+(@TROLL,@SHAMAN,204,'Defense'),
+(@TROLL,@SHAMAN,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@SHAMAN,403,'Lightning Bolt'),
+(@TROLL,@SHAMAN,9078,'Cloth'),
+(@TROLL,@SHAMAN,198,'One-Handed Maces'),
+-- Mage Troll
+(@TROLL,@MAGE,7341,'Language Troll'),
+(@TROLL,@MAGE,26290,'Bow Specialization'),
+(@TROLL,@MAGE,26297,'Berserking'),
+(@TROLL,@MAGE,58943,'Da Voodoo Shuffle'),
+(@TROLL,@MAGE,20555,'Regeneration'),
+(@TROLL,@MAGE,20557,'Beast Slaying'),
+(@TROLL,@MAGE,20558,'Throwing Specialization'),
+(@TROLL,@MAGE,79744,'Languages'),
+(@TROLL,@MAGE,71761,'Deep Freeze Immunity State'),
+(@TROLL,@MAGE,5009,'Wands'),
+(@TROLL,@MAGE,5019,'Shoot'),
+(@TROLL,@MAGE,669,'Language Orcish'),
+(@TROLL,@MAGE,1180,'Daggers'),
+(@TROLL,@MAGE,45927,'Summon Friend'),
+(@TROLL,@MAGE,6478,'Opening'),
+(@TROLL,@MAGE,6603,'Auto Attack'),
+(@TROLL,@MAGE,22027,'Remove Insignia'),
+(@TROLL,@MAGE,22810,'Opening - No Text'),
+(@TROLL,@MAGE,21651,'Opening'),
+(@TROLL,@MAGE,21652,'Closing'),
+(@TROLL,@MAGE,2382,'Generic'),
+(@TROLL,@MAGE,3365,'Opening'),
+(@TROLL,@MAGE,3050,'Detect'),
+(@TROLL,@MAGE,9125,'Generic'),
+(@TROLL,@MAGE,8386,'Attacking'),
+(@TROLL,@MAGE,7266,'Duel'),
+(@TROLL,@MAGE,7267,'Grovel'),
+(@TROLL,@MAGE,7355,'Stuck'),
+(@TROLL,@MAGE,6233,'Closing'),
+(@TROLL,@MAGE,6246,'Closing'),
+(@TROLL,@MAGE,6247,'Opening'),
+(@TROLL,@MAGE,6477,'Opening'),
+(@TROLL,@MAGE,61437,'Opening'),
+(@TROLL,@MAGE,68398,'Opening'),
+(@TROLL,@MAGE,96220,'Opening'),
+(@TROLL,@MAGE,79684,'Offensive State (DND)'),
+(@TROLL,@MAGE,203,'Unarmed'),
+(@TROLL,@MAGE,133,'Fireball'),
+(@TROLL,@MAGE,92315,'Pyroblast!'),
+(@TROLL,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@TROLL,@MAGE,76298,'Weapon Skills'),
+(@TROLL,@MAGE,76276,'Armor Skills'),
+(@TROLL,@MAGE,227,'Staves'),
+(@TROLL,@MAGE,81,'Dodge'),
+(@TROLL,@MAGE,204,'Defense'),
+(@TROLL,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@MAGE,9078,'Cloth'),
+(@TROLL,@MAGE,201,'One-Handed Swords'),
+-- Warlock Troll
+(@TROLL,@WARLOCK,7341,'Language Troll'),
+(@TROLL,@WARLOCK,26290,'Bow Specialization'),
+(@TROLL,@WARLOCK,26297,'Berserking'),
+(@TROLL,@WARLOCK,58943,'Da Voodoo Shuffle'),
+(@TROLL,@WARLOCK,20555,'Regeneration'),
+(@TROLL,@WARLOCK,20557,'Beast Slaying'),
+(@TROLL,@WARLOCK,20558,'Throwing Specialization'),
+(@TROLL,@WARLOCK,79744,'Languages'),
+(@TROLL,@WARLOCK,5009,'Wands'),
+(@TROLL,@WARLOCK,5019,'Shoot'),
+(@TROLL,@WARLOCK,669,'Language Common'),
+(@TROLL,@WARLOCK,1180,'Daggers'),
+(@TROLL,@WARLOCK,45927,'Summon Friend'),
+(@TROLL,@WARLOCK,6478,'Opening'),
+(@TROLL,@WARLOCK,6603,'Auto Attack'),
+(@TROLL,@WARLOCK,22027,'Remove Insignia'),
+(@TROLL,@WARLOCK,22810,'Opening - No Text'),
+(@TROLL,@WARLOCK,21651,'Opening'),
+(@TROLL,@WARLOCK,21652,'Closing'),
+(@TROLL,@WARLOCK,2382,'Generic'),
+(@TROLL,@WARLOCK,3365,'Opening'),
+(@TROLL,@WARLOCK,3050,'Detect'),
+(@TROLL,@WARLOCK,9125,'Generic'),
+(@TROLL,@WARLOCK,8386,'Attacking'),
+(@TROLL,@WARLOCK,7266,'Duel'),
+(@TROLL,@WARLOCK,7267,'Grovel'),
+(@TROLL,@WARLOCK,7355,'Stuck'),
+(@TROLL,@WARLOCK,6233,'Closing'),
+(@TROLL,@WARLOCK,6246,'Closing'),
+(@TROLL,@WARLOCK,6247,'Opening'),
+(@TROLL,@WARLOCK,6477,'Opening'),
+(@TROLL,@WARLOCK,61437,'Opening'),
+(@TROLL,@WARLOCK,68398,'Opening'),
+(@TROLL,@WARLOCK,96220,'Opening'),
+(@TROLL,@WARLOCK,203,'Unarmed'),
+(@TROLL,@WARLOCK,688,'Summon Imp'),
+(@TROLL,@WARLOCK,86213,'Soul Swap Exhale'),
+(@TROLL,@WARLOCK,89420,'Drain Life'),
+(@TROLL,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@TROLL,@WARLOCK,76299,'Weapon Skills'),
+(@TROLL,@WARLOCK,76277,'Armor Skills'),
+(@TROLL,@WARLOCK,87330,'Suppression'),
+(@TROLL,@WARLOCK,227,'Staves'),
+(@TROLL,@WARLOCK,75445,'Demonic Immolate'),
+(@TROLL,@WARLOCK,686,'Shadow Bolt'),
+(@TROLL,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@TROLL,@WARLOCK,81,'Dodge'),
+(@TROLL,@WARLOCK,204,'Defense'),
+(@TROLL,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@WARLOCK,9078,'Cloth'),
+(@TROLL,@WARLOCK,201,'One-Handed Swords'),
+-- Druid Troll
+(@TROLL,@DRUID,7341,'Language Troll'),
+(@TROLL,@DRUID,26290,'Bow Specialization'),
+(@TROLL,@DRUID,26297,'Berserking'),
+(@TROLL,@DRUID,58943,'Da Voodoo Shuffle'),
+(@TROLL,@DRUID,20555,'Regeneration'),
+(@TROLL,@DRUID,20557,'Beast Slaying'),
+(@TROLL,@DRUID,20558,'Throwing Specialization'),
+(@TROLL,@DRUID,79744,'Languages'),
+(@TROLL,@DRUID,669,'Language Orcish'),
+(@TROLL,@DRUID,1180,'Daggers'),
+(@TROLL,@DRUID,45927,'Summon Friend'),
+(@TROLL,@DRUID,6478,'Opening'),
+(@TROLL,@DRUID,6603,'Auto Attack'),
+(@TROLL,@DRUID,22027,'Remove Insignia'),
+(@TROLL,@DRUID,22810,'Opening - No Text'),
+(@TROLL,@DRUID,21651,'Opening'),
+(@TROLL,@DRUID,21652,'Closing'),
+(@TROLL,@DRUID,2382,'Generic'),
+(@TROLL,@DRUID,3365,'Opening'),
+(@TROLL,@DRUID,3050,'Detect'),
+(@TROLL,@DRUID,9125,'Generic'),
+(@TROLL,@DRUID,8386,'Attacking'),
+(@TROLL,@DRUID,7266,'Duel'),
+(@TROLL,@DRUID,7267,'Grovel'),
+(@TROLL,@DRUID,7355,'Stuck'),
+(@TROLL,@DRUID,6233,'Closing'),
+(@TROLL,@DRUID,6246,'Closing'),
+(@TROLL,@DRUID,6247,'Opening'),
+(@TROLL,@DRUID,6477,'Opening'),
+(@TROLL,@DRUID,61437,'Opening'),
+(@TROLL,@DRUID,68398,'Opening'),
+(@TROLL,@DRUID,96220,'Opening'),
+(@TROLL,@DRUID,203,'Unarmed'),
+(@TROLL,@DRUID,84736,"Nature's Focus"),
+(@TROLL,@DRUID,81170,"Ravage!"),
+(@TROLL,@DRUID,79577,"Eclipse Mastery Driver Passive"),
+(@TROLL,@DRUID,76300,'Weapon Skills'),
+(@TROLL,@DRUID,76275,'Armor Skills'),
+(@TROLL,@DRUID,5176,'Wrath'),
+(@TROLL,@DRUID,199,'Two-Handed Maces'),
+(@TROLL,@DRUID,15590,'Fist Weapons'),
+(@TROLL,@DRUID,84738,'Celestial Focus'),
+(@TROLL,@DRUID,200,'Polearms'),
+(@TROLL,@DRUID,227,'Staves'),
+(@TROLL,@DRUID,81,'Dodge'),
+(@TROLL,@DRUID,204,'Defense'),
+(@TROLL,@DRUID,522,'SPELLDEFENSE (DND)'),
+(@TROLL,@DRUID,9077,'Leather'),
+(@TROLL,@DRUID,9078,'Cloth'),
+(@TROLL,@DRUID,198,'One-Handed Maces'),
+-- Goblin char create:
+-- Warrior Goblin
+(@GOBLIN,@WARRIOR,202,'Two-Handed Swords'),
+(@GOBLIN,@WARRIOR,69269,'Language Goblin'),
+(@GOBLIN,@WARRIOR,69070,'Rocket Jump'),
+(@GOBLIN,@WARRIOR,69041,'Rocket Barrage'),
+(@GOBLIN,@WARRIOR,69044,'Best Deals Anywhere'),
+(@GOBLIN,@WARRIOR,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@WARRIOR,69042,'Time is Money'),
+(@GOBLIN,@WARRIOR,79749,'Languages'),
+(@GOBLIN,@WARRIOR,196,'One-Handed Axes'),
+(@GOBLIN,@WARRIOR,2457,'Battle Stance'),
+(@GOBLIN,@WARRIOR,88161,'Strike'),
+(@GOBLIN,@WARRIOR,5011,'Crossbows'),
+(@GOBLIN,@WARRIOR,3018,'Shoot'),
+(@GOBLIN,@WARRIOR,669,'Language Orcish'),
+(@GOBLIN,@WARRIOR,197,'Two-Handed Axes'),
+(@GOBLIN,@WARRIOR,1180,'Daggers'),
+(@GOBLIN,@WARRIOR,45927,'Summon Friend'),
+(@GOBLIN,@WARRIOR,6478,'Opening'),
+(@GOBLIN,@WARRIOR,6603,'Auto Attack'),
+(@GOBLIN,@WARRIOR,22027,'Remove Insignia'),
+(@GOBLIN,@WARRIOR,22810,'Opening - No Text'),
+(@GOBLIN,@WARRIOR,21651,'Opening'),
+(@GOBLIN,@WARRIOR,21652,'Closing'),
+(@GOBLIN,@WARRIOR,2382,'Generic'),
+(@GOBLIN,@WARRIOR,3365,'Opening'),
+(@GOBLIN,@WARRIOR,3050,'Detect'),
+(@GOBLIN,@WARRIOR,9125,'Generic'),
+(@GOBLIN,@WARRIOR,8386,'Attacking'),
+(@GOBLIN,@WARRIOR,7266,'Duel'),
+(@GOBLIN,@WARRIOR,7267,'Grovel'),
+(@GOBLIN,@WARRIOR,7355,'Stuck'),
+(@GOBLIN,@WARRIOR,6233,'Closing'),
+(@GOBLIN,@WARRIOR,6246,'Closing'),
+(@GOBLIN,@WARRIOR,6247,'Opening'),
+(@GOBLIN,@WARRIOR,6477,'Opening'),
+(@GOBLIN,@WARRIOR,61437,'Opening'),
+(@GOBLIN,@WARRIOR,68398,'Opening'),
+(@GOBLIN,@WARRIOR,96220,'Opening'),
+(@GOBLIN,@WARRIOR,203,'Unarmed'),
+(@GOBLIN,@WARRIOR,49410,'Forceful Deflection'),
+(@GOBLIN,@WARRIOR,199,'Two-Handed Maces'),
+(@GOBLIN,@WARRIOR,15590,'Fist Weapons'),
+(@GOBLIN,@WARRIOR,76268,'Armor Skills'),
+(@GOBLIN,@WARRIOR,76290,'Weapon Skills'),
+(@GOBLIN,@WARRIOR,88163,'Attack'),
+(@GOBLIN,@WARRIOR,200,'Polearms'),
+(@GOBLIN,@WARRIOR,227,'Staves'),
+(@GOBLIN,@WARRIOR,9116,'Shield'),
+(@GOBLIN,@WARRIOR,8737,'Mail'),
+(@GOBLIN,@WARRIOR,9077,'Leather'),
+(@GOBLIN,@WARRIOR,264,'Bows'),
+(@GOBLIN,@WARRIOR,266,'Guns'),
+(@GOBLIN,@WARRIOR,107,'Block'),
+(@GOBLIN,@WARRIOR,81,'Dodge'),
+(@GOBLIN,@WARRIOR,32215,'Victorious State'),
+(@GOBLIN,@WARRIOR,5301,'Defensive State (DND)'),
+(@GOBLIN,@WARRIOR,204,'Defense'),
+(@GOBLIN,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@WARRIOR,2764,'Throw'),
+(@GOBLIN,@WARRIOR,2567,'Thrown'),
+(@GOBLIN,@WARRIOR,9078,'Cloth'),
+(@GOBLIN,@WARRIOR,198,'One-Handed Maces'),
+(@GOBLIN,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Goblin
+(@GOBLIN,@HUNTER,202,'Two-Handed Swords'),
+(@GOBLIN,@HUNTER,69269,'Language Goblin'),
+(@GOBLIN,@HUNTER,69070,'Rocket Jump'),
+(@GOBLIN,@HUNTER,69041,'Rocket Barrage'),
+(@GOBLIN,@HUNTER,69044,'Best Deals Anywhere'),
+(@GOBLIN,@HUNTER,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@HUNTER,69042,'Time is Money'),
+(@GOBLIN,@HUNTER,79749,'Languages'),
+(@GOBLIN,@HUNTER,196,'One-Handed Axes'),
+(@GOBLIN,@HUNTER,3044,'Arcane Shot'),
+(@GOBLIN,@HUNTER,75,'Auto Shot'),
+(@GOBLIN,@HUNTER,82928,'Aimed Shot!'),
+(@GOBLIN,@HUNTER,5011,'Crossbows'),
+(@GOBLIN,@HUNTER,669,'Language Orcish'),
+(@GOBLIN,@HUNTER,197,'Two-Handed Axes'),
+(@GOBLIN,@HUNTER,1180,'Daggers'),
+(@GOBLIN,@HUNTER,45927,'Summon Friend'),
+(@GOBLIN,@HUNTER,6478,'Opening'),
+(@GOBLIN,@HUNTER,6603,'Auto Attack'),
+(@GOBLIN,@HUNTER,22027,'Remove Insignia'),
+(@GOBLIN,@HUNTER,22810,'Opening - No Text'),
+(@GOBLIN,@HUNTER,21651,'Opening'),
+(@GOBLIN,@HUNTER,21652,'Closing'),
+(@GOBLIN,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@GOBLIN,@HUNTER,2382,'Generic'),
+(@GOBLIN,@HUNTER,3365,'Opening'),
+(@GOBLIN,@HUNTER,3050,'Detect'),
+(@GOBLIN,@HUNTER,9125,'Generic'),
+(@GOBLIN,@HUNTER,8386,'Attacking'),
+(@GOBLIN,@HUNTER,7266,'Duel'),
+(@GOBLIN,@HUNTER,7267,'Grovel'),
+(@GOBLIN,@HUNTER,7355,'Stuck'),
+(@GOBLIN,@HUNTER,6233,'Closing'),
+(@GOBLIN,@HUNTER,6246,'Closing'),
+(@GOBLIN,@HUNTER,6247,'Opening'),
+(@GOBLIN,@HUNTER,6477,'Opening'),
+(@GOBLIN,@HUNTER,61437,'Opening'),
+(@GOBLIN,@HUNTER,68398,'Opening'),
+(@GOBLIN,@HUNTER,96220,'Opening'),
+(@GOBLIN,@HUNTER,203,'Unarmed'),
+(@GOBLIN,@HUNTER,883,'Call Pet 1'),
+(@GOBLIN,@HUNTER,982,'Revive Pet'),
+(@GOBLIN,@HUNTER,15590,'Fist Weapons'),
+(@GOBLIN,@HUNTER,200,'Polearms'),
+(@GOBLIN,@HUNTER,227,'Staves'),
+(@GOBLIN,@HUNTER,9077,'Leather'),
+(@GOBLIN,@HUNTER,264,'Bows'),
+(@GOBLIN,@HUNTER,266,'Guns'),
+(@GOBLIN,@HUNTER,13358,'Defensive State (DND)'),
+(@GOBLIN,@HUNTER,81,'Dodge'),
+(@GOBLIN,@HUNTER,204,'Defense'),
+(@GOBLIN,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@GOBLIN,@HUNTER,9078,'Cloth'),
+(@GOBLIN,@HUNTER,77442,'Focus'),
+(@GOBLIN,@HUNTER,76249,'Weapon Skills'),
+(@GOBLIN,@HUNTER,76250,'Armor Skills'),
+(@GOBLIN,@HUNTER,87324,'Focused Aim'),
+(@GOBLIN,@HUNTER,87816,'General Hunter Passives'),
+(@GOBLIN,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Goblin
+(@GOBLIN,@ROGUE,69269,'Language Goblin'),
+(@GOBLIN,@ROGUE,69070,'Rocket Jump'),
+(@GOBLIN,@ROGUE,69041,'Rocket Barrage'),
+(@GOBLIN,@ROGUE,69044,'Best Deals Anywhere'),
+(@GOBLIN,@ROGUE,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@ROGUE,69042,'Time is Money'),
+(@GOBLIN,@ROGUE,79749,'Languages'),
+(@GOBLIN,@ROGUE,196,'One-Handed Axes'),
+(@GOBLIN,@ROGUE,1752,'Sinister Strike'),
+(@GOBLIN,@ROGUE,5011,'Crossbows'),
+(@GOBLIN,@ROGUE,3018,'Shoot'),
+(@GOBLIN,@ROGUE,669,'Language Orcish'),
+(@GOBLIN,@ROGUE,674,'Dual Wield'),
+(@GOBLIN,@ROGUE,1180,'Daggers'),
+(@GOBLIN,@ROGUE,45927,'Summon Friend'),
+(@GOBLIN,@ROGUE,6478,'Opening'),
+(@GOBLIN,@ROGUE,6603,'Auto Attack'),
+(@GOBLIN,@ROGUE,22027,'Remove Insignia'),
+(@GOBLIN,@ROGUE,22810,'Opening - No Text'),
+(@GOBLIN,@ROGUE,21651,'Opening'),
+(@GOBLIN,@ROGUE,21652,'Closing'),
+(@GOBLIN,@ROGUE,2382,'Generic'),
+(@GOBLIN,@ROGUE,3365,'Opening'),
+(@GOBLIN,@ROGUE,3050,'Detect'),
+(@GOBLIN,@ROGUE,9125,'Generic'),
+(@GOBLIN,@ROGUE,8386,'Attacking'),
+(@GOBLIN,@ROGUE,7266,'Duel'),
+(@GOBLIN,@ROGUE,7267,'Grovel'),
+(@GOBLIN,@ROGUE,7355,'Stuck'),
+(@GOBLIN,@ROGUE,6233,'Closing'),
+(@GOBLIN,@ROGUE,6246,'Closing'),
+(@GOBLIN,@ROGUE,6247,'Opening'),
+(@GOBLIN,@ROGUE,6477,'Opening'),
+(@GOBLIN,@ROGUE,61437,'Opening'),
+(@GOBLIN,@ROGUE,68398,'Opening'),
+(@GOBLIN,@ROGUE,96220,'Opening'),
+(@GOBLIN,@ROGUE,203,'Unarmed'),
+(@GOBLIN,@ROGUE,15590,'Fist Weapons'),
+(@GOBLIN,@ROGUE,76273,'Armor Skills'),
+(@GOBLIN,@ROGUE,76297,'Weapon Skills'),
+(@GOBLIN,@ROGUE,9077,'Leather'),
+(@GOBLIN,@ROGUE,264,'Bows'),
+(@GOBLIN,@ROGUE,266,'Guns'),
+(@GOBLIN,@ROGUE,81,'Dodge'),
+(@GOBLIN,@ROGUE,204,'Defense'),
+(@GOBLIN,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@ROGUE,16092,'Defensive State (DND)'),
+(@GOBLIN,@ROGUE,2764,'Throw'),
+(@GOBLIN,@ROGUE,2567,'Thrown'),
+(@GOBLIN,@ROGUE,9078,'Cloth'),
+(@GOBLIN,@ROGUE,198,'One-Handed Maces'),
+(@GOBLIN,@ROGUE,201,'One-Handed Swords'),
+-- Priest Goblin
+(@GOBLIN,@PRIEST,69269,'Language Goblin'),
+(@GOBLIN,@PRIEST,69070,'Rocket Jump'),
+(@GOBLIN,@PRIEST,69041,'Rocket Barrage'),
+(@GOBLIN,@PRIEST,69044,'Best Deals Anywhere'),
+(@GOBLIN,@PRIEST,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@PRIEST,69042,'Time is Money'),
+(@GOBLIN,@PRIEST,79749,'Languages'),
+(@GOBLIN,@PRIEST,5009,'Wands'),
+(@GOBLIN,@PRIEST,5019,'Shoot'),
+(@GOBLIN,@PRIEST,669,'Language Orcish'),
+(@GOBLIN,@PRIEST,1180,'Daggers'),
+(@GOBLIN,@PRIEST,45927,'Summon Friend'),
+(@GOBLIN,@PRIEST,6478,'Opening'),
+(@GOBLIN,@PRIEST,6603,'Auto Attack'),
+(@GOBLIN,@PRIEST,22027,'Remove Insignia'),
+(@GOBLIN,@PRIEST,22810,'Opening - No Text'),
+(@GOBLIN,@PRIEST,21651,'Opening'),
+(@GOBLIN,@PRIEST,21652,'Closing'),
+(@GOBLIN,@PRIEST,2382,'Generic'),
+(@GOBLIN,@PRIEST,3365,'Opening'),
+(@GOBLIN,@PRIEST,3050,'Detect'),
+(@GOBLIN,@PRIEST,9125,'Generic'),
+(@GOBLIN,@PRIEST,8386,'Attacking'),
+(@GOBLIN,@PRIEST,7266,'Duel'),
+(@GOBLIN,@PRIEST,7267,'Grovel'),
+(@GOBLIN,@PRIEST,7355,'Stuck'),
+(@GOBLIN,@PRIEST,6233,'Closing'),
+(@GOBLIN,@PRIEST,6246,'Closing'),
+(@GOBLIN,@PRIEST,6247,'Opening'),
+(@GOBLIN,@PRIEST,6477,'Opening'),
+(@GOBLIN,@PRIEST,61437,'Opening'),
+(@GOBLIN,@PRIEST,68398,'Opening'),
+(@GOBLIN,@PRIEST,96220,'Opening'),
+(@GOBLIN,@PRIEST,203,'Unarmed'),
+(@GOBLIN,@PRIEST,585,'Smite'),
+(@GOBLIN,@PRIEST,84733,'Holy Focus'),
+(@GOBLIN,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@GOBLIN,@PRIEST,88684,'Holy Word: Serenity'),
+(@GOBLIN,@PRIEST,101062,'Flash Heal'),
+(@GOBLIN,@PRIEST,76301,'Weapon Skills'),
+(@GOBLIN,@PRIEST,76279,'Armor Skills'),
+(@GOBLIN,@PRIEST,84734,'Dark Thoughts'),
+(@GOBLIN,@PRIEST,227,'Staves'),
+(@GOBLIN,@PRIEST,77486,'Shadow Orb Power'),
+(@GOBLIN,@PRIEST,81,'Dodge'),
+(@GOBLIN,@PRIEST,204,'Defense'),
+(@GOBLIN,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@PRIEST,9078,'Cloth'),
+(@GOBLIN,@PRIEST,198,'One-Handed Maces'),
+-- Shaman Goblin
+(@GOBLIN,@SHAMAN,196,'One-Handed Axes'),
+(@GOBLIN,@SHAMAN,69269,'Language Goblin'),
+(@GOBLIN,@SHAMAN,69070,'Rocket Jump'),
+(@GOBLIN,@SHAMAN,69041,'Rocket Barrage'),
+(@GOBLIN,@SHAMAN,69044,'Best Deals Anywhere'),
+(@GOBLIN,@SHAMAN,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@SHAMAN,69042,'Time is Money'),
+(@GOBLIN,@SHAMAN,79749,'Languages'),
+(@GOBLIN,@SHAMAN,669,'Language Orcish'),
+(@GOBLIN,@SHAMAN,197,'Two-Handed Axes'),
+(@GOBLIN,@SHAMAN,1180,'Daggers'),
+(@GOBLIN,@SHAMAN,45927,'Summon Friend'),
+(@GOBLIN,@SHAMAN,6478,'Opening'),
+(@GOBLIN,@SHAMAN,6603,'Auto Attack'),
+(@GOBLIN,@SHAMAN,22027,'Remove Insignia'),
+(@GOBLIN,@SHAMAN,22810,'Opening - No Text'),
+(@GOBLIN,@SHAMAN,21651,'Opening'),
+(@GOBLIN,@SHAMAN,21652,'Closing'),
+(@GOBLIN,@SHAMAN,2382,'Generic'),
+(@GOBLIN,@SHAMAN,3365,'Opening'),
+(@GOBLIN,@SHAMAN,3050,'Detect'),
+(@GOBLIN,@SHAMAN,9125,'Generic'),
+(@GOBLIN,@SHAMAN,8386,'Attacking'),
+(@GOBLIN,@SHAMAN,7266,'Duel'),
+(@GOBLIN,@SHAMAN,7267,'Grovel'),
+(@GOBLIN,@SHAMAN,7355,'Stuck'),
+(@GOBLIN,@SHAMAN,6233,'Closing'),
+(@GOBLIN,@SHAMAN,6246,'Closing'),
+(@GOBLIN,@SHAMAN,6247,'Opening'),
+(@GOBLIN,@SHAMAN,6477,'Opening'),
+(@GOBLIN,@SHAMAN,27763,'Relic'),
+(@GOBLIN,@SHAMAN,61437,'Opening'),
+(@GOBLIN,@SHAMAN,68398,'Opening'),
+(@GOBLIN,@SHAMAN,96220,'Opening'),
+(@GOBLIN,@SHAMAN,203,'Unarmed'),
+(@GOBLIN,@SHAMAN,199,'Two-Handed Maces'),
+(@GOBLIN,@SHAMAN,15590,'Fist Weapons'),
+(@GOBLIN,@SHAMAN,76272,'Armor Skills'),
+(@GOBLIN,@SHAMAN,76296,'Weapon Skills'),
+(@GOBLIN,@SHAMAN,89920,'Ancestral Focus'),
+(@GOBLIN,@SHAMAN,227,'Staves'),
+(@GOBLIN,@SHAMAN,9116,'Shield'),
+(@GOBLIN,@SHAMAN,9077,'Leather'),
+(@GOBLIN,@SHAMAN,107,'Block'),
+(@GOBLIN,@SHAMAN,81,'Dodge'),
+(@GOBLIN,@SHAMAN,204,'Defense'),
+(@GOBLIN,@SHAMAN,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@SHAMAN,403,'Lightning Bolt'),
+(@GOBLIN,@SHAMAN,9078,'Cloth'),
+(@GOBLIN,@SHAMAN,198,'One-Handed Maces'),
+-- Mage Goblin
+(@GOBLIN,@MAGE,69269,'Language Goblin'),
+(@GOBLIN,@MAGE,69070,'Rocket Jump'),
+(@GOBLIN,@MAGE,69041,'Rocket Barrage'),
+(@GOBLIN,@MAGE,69044,'Best Deals Anywhere'),
+(@GOBLIN,@MAGE,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@MAGE,69042,'Time is Money'),
+(@GOBLIN,@MAGE,79749,'Languages'),
+(@GOBLIN,@MAGE,71761,'Deep Freeze Immunity State'),
+(@GOBLIN,@MAGE,5009,'Wands'),
+(@GOBLIN,@MAGE,5019,'Shoot'),
+(@GOBLIN,@MAGE,669,'Language Orcish'),
+(@GOBLIN,@MAGE,1180,'Daggers'),
+(@GOBLIN,@MAGE,45927,'Summon Friend'),
+(@GOBLIN,@MAGE,6478,'Opening'),
+(@GOBLIN,@MAGE,6603,'Auto Attack'),
+(@GOBLIN,@MAGE,22027,'Remove Insignia'),
+(@GOBLIN,@MAGE,22810,'Opening - No Text'),
+(@GOBLIN,@MAGE,21651,'Opening'),
+(@GOBLIN,@MAGE,21652,'Closing'),
+(@GOBLIN,@MAGE,2382,'Generic'),
+(@GOBLIN,@MAGE,3365,'Opening'),
+(@GOBLIN,@MAGE,3050,'Detect'),
+(@GOBLIN,@MAGE,9125,'Generic'),
+(@GOBLIN,@MAGE,8386,'Attacking'),
+(@GOBLIN,@MAGE,7266,'Duel'),
+(@GOBLIN,@MAGE,7267,'Grovel'),
+(@GOBLIN,@MAGE,7355,'Stuck'),
+(@GOBLIN,@MAGE,6233,'Closing'),
+(@GOBLIN,@MAGE,6246,'Closing'),
+(@GOBLIN,@MAGE,6247,'Opening'),
+(@GOBLIN,@MAGE,6477,'Opening'),
+(@GOBLIN,@MAGE,61437,'Opening'),
+(@GOBLIN,@MAGE,68398,'Opening'),
+(@GOBLIN,@MAGE,96220,'Opening'),
+(@GOBLIN,@MAGE,79684,'Offensive State (DND)'),
+(@GOBLIN,@MAGE,203,'Unarmed'),
+(@GOBLIN,@MAGE,133,'Fireball'),
+(@GOBLIN,@MAGE,92315,'Pyroblast!'),
+(@GOBLIN,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@GOBLIN,@MAGE,76298,'Weapon Skills'),
+(@GOBLIN,@MAGE,76276,'Armor Skills'),
+(@GOBLIN,@MAGE,227,'Staves'),
+(@GOBLIN,@MAGE,81,'Dodge'),
+(@GOBLIN,@MAGE,204,'Defense'),
+(@GOBLIN,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@MAGE,9078,'Cloth'),
+(@GOBLIN,@MAGE,201,'One-Handed Swords'),
+-- Warlock Goblin
+(@GOBLIN,@WARLOCK,69269,'Language Goblin'),
+(@GOBLIN,@WARLOCK,69070,'Rocket Jump'),
+(@GOBLIN,@WARLOCK,69041,'Rocket Barrage'),
+(@GOBLIN,@WARLOCK,69044,'Best Deals Anywhere'),
+(@GOBLIN,@WARLOCK,69045,'Better Living Through Chemistry'),
+(@GOBLIN,@WARLOCK,69042,'Time is Money'),
+(@GOBLIN,@WARLOCK,79749,'Languages'),
+(@GOBLIN,@WARLOCK,5009,'Wands'),
+(@GOBLIN,@WARLOCK,5019,'Shoot'),
+(@GOBLIN,@WARLOCK,669,'Language Common'),
+(@GOBLIN,@WARLOCK,1180,'Daggers'),
+(@GOBLIN,@WARLOCK,45927,'Summon Friend'),
+(@GOBLIN,@WARLOCK,6478,'Opening'),
+(@GOBLIN,@WARLOCK,6603,'Auto Attack'),
+(@GOBLIN,@WARLOCK,22027,'Remove Insignia'),
+(@GOBLIN,@WARLOCK,22810,'Opening - No Text'),
+(@GOBLIN,@WARLOCK,21651,'Opening'),
+(@GOBLIN,@WARLOCK,21652,'Closing'),
+(@GOBLIN,@WARLOCK,2382,'Generic'),
+(@GOBLIN,@WARLOCK,3365,'Opening'),
+(@GOBLIN,@WARLOCK,3050,'Detect'),
+(@GOBLIN,@WARLOCK,9125,'Generic'),
+(@GOBLIN,@WARLOCK,8386,'Attacking'),
+(@GOBLIN,@WARLOCK,7266,'Duel'),
+(@GOBLIN,@WARLOCK,7267,'Grovel'),
+(@GOBLIN,@WARLOCK,7355,'Stuck'),
+(@GOBLIN,@WARLOCK,6233,'Closing'),
+(@GOBLIN,@WARLOCK,6246,'Closing'),
+(@GOBLIN,@WARLOCK,6247,'Opening'),
+(@GOBLIN,@WARLOCK,6477,'Opening'),
+(@GOBLIN,@WARLOCK,61437,'Opening'),
+(@GOBLIN,@WARLOCK,68398,'Opening'),
+(@GOBLIN,@WARLOCK,96220,'Opening'),
+(@GOBLIN,@WARLOCK,203,'Unarmed'),
+(@GOBLIN,@WARLOCK,688,'Summon Imp'),
+(@GOBLIN,@WARLOCK,86213,'Soul Swap Exhale'),
+(@GOBLIN,@WARLOCK,89420,'Drain Life'),
+(@GOBLIN,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@GOBLIN,@WARLOCK,76299,'Weapon Skills'),
+(@GOBLIN,@WARLOCK,76277,'Armor Skills'),
+(@GOBLIN,@WARLOCK,87330,'Suppression'),
+(@GOBLIN,@WARLOCK,227,'Staves'),
+(@GOBLIN,@WARLOCK,75445,'Demonic Immolate'),
+(@GOBLIN,@WARLOCK,686,'Shadow Bolt'),
+(@GOBLIN,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@GOBLIN,@WARLOCK,81,'Dodge'),
+(@GOBLIN,@WARLOCK,204,'Defense'),
+(@GOBLIN,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@GOBLIN,@WARLOCK,9078,'Cloth'),
+(@GOBLIN,@WARLOCK,201,'One-Handed Swords'),
+-- Blood Elf char create:
+-- Warrior Blood Elf
+(@BLOOD_ELF,@WARRIOR,202,'Two-Handed Swords'),
+(@BLOOD_ELF,@WARRIOR,813,'Language Thalassian'),
+(@BLOOD_ELF,@WARRIOR,822,'Arcane Resistance'),
+(@BLOOD_ELF,@WARRIOR,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@WARRIOR,69179,'Arcane Torrent'),
+(@BLOOD_ELF,@WARRIOR,79748,'Languages'),
+(@BLOOD_ELF,@WARRIOR,196,'One-Handed Axes'),
+(@BLOOD_ELF,@WARRIOR,2457,'Battle Stance'),
+(@BLOOD_ELF,@WARRIOR,88161,'Strike'),
+(@BLOOD_ELF,@WARRIOR,5011,'Crossbows'),
+(@BLOOD_ELF,@WARRIOR,3018,'Shoot'),
+(@BLOOD_ELF,@WARRIOR,669,'Language Orcish'),
+(@BLOOD_ELF,@WARRIOR,197,'Two-Handed Axes'),
+(@BLOOD_ELF,@WARRIOR,1180,'Daggers'),
+(@BLOOD_ELF,@WARRIOR,45927,'Summon Friend'),
+(@BLOOD_ELF,@WARRIOR,6478,'Opening'),
+(@BLOOD_ELF,@WARRIOR,6603,'Auto Attack'),
+(@BLOOD_ELF,@WARRIOR,22027,'Remove Insignia'),
+(@BLOOD_ELF,@WARRIOR,22810,'Opening - No Text'),
+(@BLOOD_ELF,@WARRIOR,21651,'Opening'),
+(@BLOOD_ELF,@WARRIOR,21652,'Closing'),
+(@BLOOD_ELF,@WARRIOR,2382,'Generic'),
+(@BLOOD_ELF,@WARRIOR,3365,'Opening'),
+(@BLOOD_ELF,@WARRIOR,3050,'Detect'),
+(@BLOOD_ELF,@WARRIOR,9125,'Generic'),
+(@BLOOD_ELF,@WARRIOR,8386,'Attacking'),
+(@BLOOD_ELF,@WARRIOR,7266,'Duel'),
+(@BLOOD_ELF,@WARRIOR,7267,'Grovel'),
+(@BLOOD_ELF,@WARRIOR,7355,'Stuck'),
+(@BLOOD_ELF,@WARRIOR,6233,'Closing'),
+(@BLOOD_ELF,@WARRIOR,6246,'Closing'),
+(@BLOOD_ELF,@WARRIOR,6247,'Opening'),
+(@BLOOD_ELF,@WARRIOR,6477,'Opening'),
+(@BLOOD_ELF,@WARRIOR,61437,'Opening'),
+(@BLOOD_ELF,@WARRIOR,68398,'Opening'),
+(@BLOOD_ELF,@WARRIOR,96220,'Opening'),
+(@BLOOD_ELF,@WARRIOR,203,'Unarmed'),
+(@BLOOD_ELF,@WARRIOR,49410,'Forceful Deflection'),
+(@BLOOD_ELF,@WARRIOR,199,'Two-Handed Maces'),
+(@BLOOD_ELF,@WARRIOR,15590,'Fist Weapons'),
+(@BLOOD_ELF,@WARRIOR,76268,'Armor Skills'),
+(@BLOOD_ELF,@WARRIOR,76290,'Weapon Skills'),
+(@BLOOD_ELF,@WARRIOR,88163,'Attack'),
+(@BLOOD_ELF,@WARRIOR,200,'Polearms'),
+(@BLOOD_ELF,@WARRIOR,227,'Staves'),
+(@BLOOD_ELF,@WARRIOR,9116,'Shield'),
+(@BLOOD_ELF,@WARRIOR,8737,'Mail'),
+(@BLOOD_ELF,@WARRIOR,9077,'Leather'),
+(@BLOOD_ELF,@WARRIOR,264,'Bows'),
+(@BLOOD_ELF,@WARRIOR,266,'Guns'),
+(@BLOOD_ELF,@WARRIOR,107,'Block'),
+(@BLOOD_ELF,@WARRIOR,81,'Dodge'),
+(@BLOOD_ELF,@WARRIOR,32215,'Victorious State'),
+(@BLOOD_ELF,@WARRIOR,5301,'Defensive State (DND)'),
+(@BLOOD_ELF,@WARRIOR,204,'Defense'),
+(@BLOOD_ELF,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@WARRIOR,2764,'Throw'),
+(@BLOOD_ELF,@WARRIOR,2567,'Thrown'),
+(@BLOOD_ELF,@WARRIOR,9078,'Cloth'),
+(@BLOOD_ELF,@WARRIOR,198,'One-Handed Maces'),
+(@BLOOD_ELF,@WARRIOR,201,'One-Handed Swords'),
+-- Palading Blood Elf
+(@BLOOD_ELF,@PALADIN,202,'Two-Handed Swords'),
+(@BLOOD_ELF,@PALADIN,813,'Language Thalassian'),
+(@BLOOD_ELF,@PALADIN,822,'Arcane Resistance'),
+(@BLOOD_ELF,@PALADIN,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@PALADIN,28730,'Arcane Torrent'),
+(@BLOOD_ELF,@PALADIN,79748,'Languages'),
+(@BLOOD_ELF,@PALADIN,196,'One-Handed Axes'),
+(@BLOOD_ELF,@PALADIN,669,'Language Orcish'),
+(@BLOOD_ELF,@PALADIN,197,'Two-Handed Axes'),
+(@BLOOD_ELF,@PALADIN,45927,'Summon Friend'),
+(@BLOOD_ELF,@PALADIN,6478,'Opening'),
+(@BLOOD_ELF,@PALADIN,6603,'Auto Attack'),
+(@BLOOD_ELF,@PALADIN,22027,'Remove Insignia'),
+(@BLOOD_ELF,@PALADIN,22810,'Opening - No Text'),
+(@BLOOD_ELF,@PALADIN,21651,'Opening'),
+(@BLOOD_ELF,@PALADIN,21652,'Closing'),
+(@BLOOD_ELF,@PALADIN,2382,'Generic'),
+(@BLOOD_ELF,@PALADIN,3365,'Opening'),
+(@BLOOD_ELF,@PALADIN,3050,'Detect'),
+(@BLOOD_ELF,@PALADIN,9125,'Generic'),
+(@BLOOD_ELF,@PALADIN,8386,'Attacking'),
+(@BLOOD_ELF,@PALADIN,7266,'Duel'),
+(@BLOOD_ELF,@PALADIN,7267,'Grovel'),
+(@BLOOD_ELF,@PALADIN,7355,'Stuck'),
+(@BLOOD_ELF,@PALADIN,6233,'Closing'),
+(@BLOOD_ELF,@PALADIN,6246,'Closing'),
+(@BLOOD_ELF,@PALADIN,6247,'Opening'),
+(@BLOOD_ELF,@PALADIN,6477,'Opening'),
+(@BLOOD_ELF,@PALADIN,27762,'Relic'),
+(@BLOOD_ELF,@PALADIN,61437,'Opening'),
+(@BLOOD_ELF,@PALADIN,68398,'Opening'),
+(@BLOOD_ELF,@PALADIN,96220,'Opening'),
+(@BLOOD_ELF,@PALADIN,49410,'Forceful Deflection'),
+(@BLOOD_ELF,@PALADIN,203,'Unarmed'),
+(@BLOOD_ELF,@PALADIN,199,'Two-Handed Maces'),
+(@BLOOD_ELF,@PALADIN,76271,'Armor Skills'),
+(@BLOOD_ELF,@PALADIN,76294,'Weapon Skills'),
+(@BLOOD_ELF,@PALADIN,200,'Polearms'),
+(@BLOOD_ELF,@PALADIN,35395,'Crusader Strike'),
+(@BLOOD_ELF,@PALADIN,60091,'Judgement Anti-Parry/Dodge Passive'),
+(@BLOOD_ELF,@PALADIN,9116,'Shield'),
+(@BLOOD_ELF,@PALADIN,8737,'Mail'),
+(@BLOOD_ELF,@PALADIN,9077,'Leather'),
+(@BLOOD_ELF,@PALADIN,107,'Block'),
+(@BLOOD_ELF,@PALADIN,81,'Dodge'),
+(@BLOOD_ELF,@PALADIN,204,'Defense'),
+(@BLOOD_ELF,@PALADIN,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@PALADIN,9078,'Cloth'),
+(@BLOOD_ELF,@PALADIN,20208,'Paladin pushback resistance'),
+(@BLOOD_ELF,@PALADIN,198,'One-Handed Maces'),
+(@BLOOD_ELF,@PALADIN,201,'One-Handed Swords'),
+-- Hunter Blood Elf
+(@BLOOD_ELF,@HUNTER,202,'Two-Handed Swords'),
+(@BLOOD_ELF,@HUNTER,813,'Language Thalassian'),
+(@BLOOD_ELF,@HUNTER,822,'Arcane Resistance'),
+(@BLOOD_ELF,@HUNTER,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@HUNTER,80483,'Arcane Torrent'),
+(@BLOOD_ELF,@HUNTER,79748,'Languages'),
+(@BLOOD_ELF,@HUNTER,196,'One-Handed Axes'),
+(@BLOOD_ELF,@HUNTER,3044,'Arcane Shot'),
+(@BLOOD_ELF,@HUNTER,75,'Auto Shot'),
+(@BLOOD_ELF,@HUNTER,82928,'Aimed Shot!'),
+(@BLOOD_ELF,@HUNTER,5011,'Crossbows'),
+(@BLOOD_ELF,@HUNTER,669,'Language Orcish'),
+(@BLOOD_ELF,@HUNTER,197,'Two-Handed Axes'),
+(@BLOOD_ELF,@HUNTER,1180,'Daggers'),
+(@BLOOD_ELF,@HUNTER,45927,'Summon Friend'),
+(@BLOOD_ELF,@HUNTER,6478,'Opening'),
+(@BLOOD_ELF,@HUNTER,6603,'Auto Attack'),
+(@BLOOD_ELF,@HUNTER,22027,'Remove Insignia'),
+(@BLOOD_ELF,@HUNTER,22810,'Opening - No Text'),
+(@BLOOD_ELF,@HUNTER,21651,'Opening'),
+(@BLOOD_ELF,@HUNTER,21652,'Closing'),
+(@BLOOD_ELF,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@BLOOD_ELF,@HUNTER,2382,'Generic'),
+(@BLOOD_ELF,@HUNTER,3365,'Opening'),
+(@BLOOD_ELF,@HUNTER,3050,'Detect'),
+(@BLOOD_ELF,@HUNTER,9125,'Generic'),
+(@BLOOD_ELF,@HUNTER,8386,'Attacking'),
+(@BLOOD_ELF,@HUNTER,7266,'Duel'),
+(@BLOOD_ELF,@HUNTER,7267,'Grovel'),
+(@BLOOD_ELF,@HUNTER,7355,'Stuck'),
+(@BLOOD_ELF,@HUNTER,6233,'Closing'),
+(@BLOOD_ELF,@HUNTER,6246,'Closing'),
+(@BLOOD_ELF,@HUNTER,6247,'Opening'),
+(@BLOOD_ELF,@HUNTER,6477,'Opening'),
+(@BLOOD_ELF,@HUNTER,61437,'Opening'),
+(@BLOOD_ELF,@HUNTER,68398,'Opening'),
+(@BLOOD_ELF,@HUNTER,96220,'Opening'),
+(@BLOOD_ELF,@HUNTER,203,'Unarmed'),
+(@BLOOD_ELF,@HUNTER,883,'Call Pet 1'),
+(@BLOOD_ELF,@HUNTER,982,'Revive Pet'),
+(@BLOOD_ELF,@HUNTER,15590,'Fist Weapons'),
+(@BLOOD_ELF,@HUNTER,200,'Polearms'),
+(@BLOOD_ELF,@HUNTER,227,'Staves'),
+(@BLOOD_ELF,@HUNTER,9077,'Leather'),
+(@BLOOD_ELF,@HUNTER,264,'Bows'),
+(@BLOOD_ELF,@HUNTER,266,'Guns'),
+(@BLOOD_ELF,@HUNTER,13358,'Defensive State (DND)'),
+(@BLOOD_ELF,@HUNTER,81,'Dodge'),
+(@BLOOD_ELF,@HUNTER,204,'Defense'),
+(@BLOOD_ELF,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@BLOOD_ELF,@HUNTER,9078,'Cloth'),
+(@BLOOD_ELF,@HUNTER,77442,'Focus'),
+(@BLOOD_ELF,@HUNTER,76249,'Weapon Skills'),
+(@BLOOD_ELF,@HUNTER,76250,'Armor Skills'),
+(@BLOOD_ELF,@HUNTER,87324,'Focused Aim'),
+(@BLOOD_ELF,@HUNTER,87816,'General Hunter Passives'),
+(@BLOOD_ELF,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Blood Elf
+(@BLOOD_ELF,@ROGUE,196,'One-Handed Axes'),
+(@BLOOD_ELF,@ROGUE,813,'Language Thalassian'),
+(@BLOOD_ELF,@ROGUE,822,'Arcane Resistance'),
+(@BLOOD_ELF,@ROGUE,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@ROGUE,25046,'Arcane Torrent'),
+(@BLOOD_ELF,@ROGUE,79748,'Languages'),
+(@BLOOD_ELF,@ROGUE,1752,'Sinister Strike'),
+(@BLOOD_ELF,@ROGUE,5011,'Crossbows'),
+(@BLOOD_ELF,@ROGUE,3018,'Shoot'),
+(@BLOOD_ELF,@ROGUE,669,'Language Orcish'),
+(@BLOOD_ELF,@ROGUE,674,'Dual Wield'),
+(@BLOOD_ELF,@ROGUE,1180,'Daggers'),
+(@BLOOD_ELF,@ROGUE,45927,'Summon Friend'),
+(@BLOOD_ELF,@ROGUE,6478,'Opening'),
+(@BLOOD_ELF,@ROGUE,6603,'Auto Attack'),
+(@BLOOD_ELF,@ROGUE,22027,'Remove Insignia'),
+(@BLOOD_ELF,@ROGUE,22810,'Opening - No Text'),
+(@BLOOD_ELF,@ROGUE,21651,'Opening'),
+(@BLOOD_ELF,@ROGUE,21652,'Closing'),
+(@BLOOD_ELF,@ROGUE,2382,'Generic'),
+(@BLOOD_ELF,@ROGUE,3365,'Opening'),
+(@BLOOD_ELF,@ROGUE,3050,'Detect'),
+(@BLOOD_ELF,@ROGUE,9125,'Generic'),
+(@BLOOD_ELF,@ROGUE,8386,'Attacking'),
+(@BLOOD_ELF,@ROGUE,7266,'Duel'),
+(@BLOOD_ELF,@ROGUE,7267,'Grovel'),
+(@BLOOD_ELF,@ROGUE,7355,'Stuck'),
+(@BLOOD_ELF,@ROGUE,6233,'Closing'),
+(@BLOOD_ELF,@ROGUE,6246,'Closing'),
+(@BLOOD_ELF,@ROGUE,6247,'Opening'),
+(@BLOOD_ELF,@ROGUE,6477,'Opening'),
+(@BLOOD_ELF,@ROGUE,61437,'Opening'),
+(@BLOOD_ELF,@ROGUE,68398,'Opening'),
+(@BLOOD_ELF,@ROGUE,96220,'Opening'),
+(@BLOOD_ELF,@ROGUE,203,'Unarmed'),
+(@BLOOD_ELF,@ROGUE,15590,'Fist Weapons'),
+(@BLOOD_ELF,@ROGUE,76273,'Armor Skills'),
+(@BLOOD_ELF,@ROGUE,76297,'Weapon Skills'),
+(@BLOOD_ELF,@ROGUE,9077,'Leather'),
+(@BLOOD_ELF,@ROGUE,264,'Bows'),
+(@BLOOD_ELF,@ROGUE,266,'Guns'),
+(@BLOOD_ELF,@ROGUE,81,'Dodge'),
+(@BLOOD_ELF,@ROGUE,204,'Defense'),
+(@BLOOD_ELF,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@ROGUE,16092,'Defensive State (DND)'),
+(@BLOOD_ELF,@ROGUE,2764,'Throw'),
+(@BLOOD_ELF,@ROGUE,2567,'Thrown'),
+(@BLOOD_ELF,@ROGUE,9078,'Cloth'),
+(@BLOOD_ELF,@ROGUE,198,'One-Handed Maces'),
+(@BLOOD_ELF,@ROGUE,201,'One-Handed Swords'),
+-- Priest Blood Elf
+(@BLOOD_ELF,@PRIEST,813,'Language Thalassian'),
+(@BLOOD_ELF,@PRIEST,822,'Arcane Resistance'),
+(@BLOOD_ELF,@PRIEST,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@PRIEST,28730,'Arcane Torrent'),
+(@BLOOD_ELF,@PRIEST,79748,'Languages'),
+(@BLOOD_ELF,@PRIEST,5009,'Wands'),
+(@BLOOD_ELF,@PRIEST,5019,'Shoot'),
+(@BLOOD_ELF,@PRIEST,669,'Language Orcish'),
+(@BLOOD_ELF,@PRIEST,1180,'Daggers'),
+(@BLOOD_ELF,@PRIEST,45927,'Summon Friend'),
+(@BLOOD_ELF,@PRIEST,6478,'Opening'),
+(@BLOOD_ELF,@PRIEST,6603,'Auto Attack'),
+(@BLOOD_ELF,@PRIEST,22027,'Remove Insignia'),
+(@BLOOD_ELF,@PRIEST,22810,'Opening - No Text'),
+(@BLOOD_ELF,@PRIEST,21651,'Opening'),
+(@BLOOD_ELF,@PRIEST,21652,'Closing'),
+(@BLOOD_ELF,@PRIEST,2382,'Generic'),
+(@BLOOD_ELF,@PRIEST,3365,'Opening'),
+(@BLOOD_ELF,@PRIEST,3050,'Detect'),
+(@BLOOD_ELF,@PRIEST,9125,'Generic'),
+(@BLOOD_ELF,@PRIEST,8386,'Attacking'),
+(@BLOOD_ELF,@PRIEST,7266,'Duel'),
+(@BLOOD_ELF,@PRIEST,7267,'Grovel'),
+(@BLOOD_ELF,@PRIEST,7355,'Stuck'),
+(@BLOOD_ELF,@PRIEST,6233,'Closing'),
+(@BLOOD_ELF,@PRIEST,6246,'Closing'),
+(@BLOOD_ELF,@PRIEST,6247,'Opening'),
+(@BLOOD_ELF,@PRIEST,6477,'Opening'),
+(@BLOOD_ELF,@PRIEST,61437,'Opening'),
+(@BLOOD_ELF,@PRIEST,68398,'Opening'),
+(@BLOOD_ELF,@PRIEST,96220,'Opening'),
+(@BLOOD_ELF,@PRIEST,203,'Unarmed'),
+(@BLOOD_ELF,@PRIEST,585,'Smite'),
+(@BLOOD_ELF,@PRIEST,84733,'Holy Focus'),
+(@BLOOD_ELF,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@BLOOD_ELF,@PRIEST,88684,'Holy Word: Serenity'),
+(@BLOOD_ELF,@PRIEST,101062,'Flash Heal'),
+(@BLOOD_ELF,@PRIEST,76301,'Weapon Skills'),
+(@BLOOD_ELF,@PRIEST,76279,'Armor Skills'),
+(@BLOOD_ELF,@PRIEST,84734,'Dark Thoughts'),
+(@BLOOD_ELF,@PRIEST,227,'Staves'),
+(@BLOOD_ELF,@PRIEST,77486,'Shadow Orb Power'),
+(@BLOOD_ELF,@PRIEST,81,'Dodge'),
+(@BLOOD_ELF,@PRIEST,204,'Defense'),
+(@BLOOD_ELF,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@PRIEST,9078,'Cloth'),
+(@BLOOD_ELF,@PRIEST,198,'One-Handed Maces'),
+-- Mage Blood Elf
+(@BLOOD_ELF,@MAGE,813,'Language Thalassian'),
+(@BLOOD_ELF,@MAGE,822,'Arcane Resistance'),
+(@BLOOD_ELF,@MAGE,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@MAGE,28730,'Arcane Torrent'),
+(@BLOOD_ELF,@MAGE,79748,'Languages'),
+(@BLOOD_ELF,@MAGE,71761,'Deep Freeze Immunity State'),
+(@BLOOD_ELF,@MAGE,5009,'Wands'),
+(@BLOOD_ELF,@MAGE,5019,'Shoot'),
+(@BLOOD_ELF,@MAGE,669,'Language Orcish'),
+(@BLOOD_ELF,@MAGE,1180,'Daggers'),
+(@BLOOD_ELF,@MAGE,45927,'Summon Friend'),
+(@BLOOD_ELF,@MAGE,6478,'Opening'),
+(@BLOOD_ELF,@MAGE,6603,'Auto Attack'),
+(@BLOOD_ELF,@MAGE,22027,'Remove Insignia'),
+(@BLOOD_ELF,@MAGE,22810,'Opening - No Text'),
+(@BLOOD_ELF,@MAGE,21651,'Opening'),
+(@BLOOD_ELF,@MAGE,21652,'Closing'),
+(@BLOOD_ELF,@MAGE,2382,'Generic'),
+(@BLOOD_ELF,@MAGE,3365,'Opening'),
+(@BLOOD_ELF,@MAGE,3050,'Detect'),
+(@BLOOD_ELF,@MAGE,9125,'Generic'),
+(@BLOOD_ELF,@MAGE,8386,'Attacking'),
+(@BLOOD_ELF,@MAGE,7266,'Duel'),
+(@BLOOD_ELF,@MAGE,7267,'Grovel'),
+(@BLOOD_ELF,@MAGE,7355,'Stuck'),
+(@BLOOD_ELF,@MAGE,6233,'Closing'),
+(@BLOOD_ELF,@MAGE,6246,'Closing'),
+(@BLOOD_ELF,@MAGE,6247,'Opening'),
+(@BLOOD_ELF,@MAGE,6477,'Opening'),
+(@BLOOD_ELF,@MAGE,61437,'Opening'),
+(@BLOOD_ELF,@MAGE,68398,'Opening'),
+(@BLOOD_ELF,@MAGE,96220,'Opening'),
+(@BLOOD_ELF,@MAGE,79684,'Offensive State (DND)'),
+(@BLOOD_ELF,@MAGE,203,'Unarmed'),
+(@BLOOD_ELF,@MAGE,133,'Fireball'),
+(@BLOOD_ELF,@MAGE,92315,'Pyroblast!'),
+(@BLOOD_ELF,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@BLOOD_ELF,@MAGE,76298,'Weapon Skills'),
+(@BLOOD_ELF,@MAGE,76276,'Armor Skills'),
+(@BLOOD_ELF,@MAGE,227,'Staves'),
+(@BLOOD_ELF,@MAGE,81,'Dodge'),
+(@BLOOD_ELF,@MAGE,204,'Defense'),
+(@BLOOD_ELF,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@MAGE,9078,'Cloth'),
+(@BLOOD_ELF,@MAGE,201,'One-Handed Swords'),
+-- Warlock Blood Elf
+(@BLOOD_ELF,@WARLOCK,813,'Language Thalassian'),
+(@BLOOD_ELF,@WARLOCK,822,'Arcane Resistance'),
+(@BLOOD_ELF,@WARLOCK,28877,'Arcane Affinity'),
+(@BLOOD_ELF,@WARLOCK,28730,'Arcane Torrent'),
+(@BLOOD_ELF,@WARLOCK,79748,'Languages'),
+(@BLOOD_ELF,@WARLOCK,5009,'Wands'),
+(@BLOOD_ELF,@WARLOCK,5019,'Shoot'),
+(@BLOOD_ELF,@WARLOCK,669,'Language Common'),
+(@BLOOD_ELF,@WARLOCK,1180,'Daggers'),
+(@BLOOD_ELF,@WARLOCK,45927,'Summon Friend'),
+(@BLOOD_ELF,@WARLOCK,6478,'Opening'),
+(@BLOOD_ELF,@WARLOCK,6603,'Auto Attack'),
+(@BLOOD_ELF,@WARLOCK,22027,'Remove Insignia'),
+(@BLOOD_ELF,@WARLOCK,22810,'Opening - No Text'),
+(@BLOOD_ELF,@WARLOCK,21651,'Opening'),
+(@BLOOD_ELF,@WARLOCK,21652,'Closing'),
+(@BLOOD_ELF,@WARLOCK,2382,'Generic'),
+(@BLOOD_ELF,@WARLOCK,3365,'Opening'),
+(@BLOOD_ELF,@WARLOCK,3050,'Detect'),
+(@BLOOD_ELF,@WARLOCK,9125,'Generic'),
+(@BLOOD_ELF,@WARLOCK,8386,'Attacking'),
+(@BLOOD_ELF,@WARLOCK,7266,'Duel'),
+(@BLOOD_ELF,@WARLOCK,7267,'Grovel'),
+(@BLOOD_ELF,@WARLOCK,7355,'Stuck'),
+(@BLOOD_ELF,@WARLOCK,6233,'Closing'),
+(@BLOOD_ELF,@WARLOCK,6246,'Closing'),
+(@BLOOD_ELF,@WARLOCK,6247,'Opening'),
+(@BLOOD_ELF,@WARLOCK,6477,'Opening'),
+(@BLOOD_ELF,@WARLOCK,61437,'Opening'),
+(@BLOOD_ELF,@WARLOCK,68398,'Opening'),
+(@BLOOD_ELF,@WARLOCK,96220,'Opening'),
+(@BLOOD_ELF,@WARLOCK,203,'Unarmed'),
+(@BLOOD_ELF,@WARLOCK,688,'Summon Imp'),
+(@BLOOD_ELF,@WARLOCK,86213,'Soul Swap Exhale'),
+(@BLOOD_ELF,@WARLOCK,89420,'Drain Life'),
+(@BLOOD_ELF,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@BLOOD_ELF,@WARLOCK,76299,'Weapon Skills'),
+(@BLOOD_ELF,@WARLOCK,76277,'Armor Skills'),
+(@BLOOD_ELF,@WARLOCK,87330,'Suppression'),
+(@BLOOD_ELF,@WARLOCK,227,'Staves'),
+(@BLOOD_ELF,@WARLOCK,75445,'Demonic Immolate'),
+(@BLOOD_ELF,@WARLOCK,686,'Shadow Bolt'),
+(@BLOOD_ELF,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@BLOOD_ELF,@WARLOCK,81,'Dodge'),
+(@BLOOD_ELF,@WARLOCK,204,'Defense'),
+(@BLOOD_ELF,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@BLOOD_ELF,@WARLOCK,9078,'Cloth'),
+(@BLOOD_ELF,@WARLOCK,201,'One-Handed Swords'),
+-- Draenei char create:
+-- Warrior Draenei
+(@DRAENEI,@WARRIOR,202,'Two-Handed Swords'),
+(@DRAENEI,@WARRIOR,196,'One-Handed Axes'),
+(@DRAENEI,@WARRIOR,2457,'Battle Stance'),
+(@DRAENEI,@WARRIOR,88161,'Strike'),
+(@DRAENEI,@WARRIOR,5011,'Crossbows'),
+(@DRAENEI,@WARRIOR,3018,'Shoot'),
+(@DRAENEI,@WARRIOR,197,'Two-Handed Axes'),
+(@DRAENEI,@WARRIOR,1180,'Daggers'),
+(@DRAENEI,@WARRIOR,45927,'Summon Friend'),
+(@DRAENEI,@WARRIOR,6478,'Opening'),
+(@DRAENEI,@WARRIOR,6603,'Auto Attack'),
+(@DRAENEI,@WARRIOR,22027,'Remove Insignia'),
+(@DRAENEI,@WARRIOR,22810,'Opening - No Text'),
+(@DRAENEI,@WARRIOR,21651,'Opening'),
+(@DRAENEI,@WARRIOR,21652,'Closing'),
+(@DRAENEI,@WARRIOR,2382,'Generic'),
+(@DRAENEI,@WARRIOR,3365,'Opening'),
+(@DRAENEI,@WARRIOR,3050,'Detect'),
+(@DRAENEI,@WARRIOR,9125,'Generic'),
+(@DRAENEI,@WARRIOR,8386,'Attacking'),
+(@DRAENEI,@WARRIOR,7266,'Duel'),
+(@DRAENEI,@WARRIOR,7267,'Grovel'),
+(@DRAENEI,@WARRIOR,7355,'Stuck'),
+(@DRAENEI,@WARRIOR,6233,'Closing'),
+(@DRAENEI,@WARRIOR,6246,'Closing'),
+(@DRAENEI,@WARRIOR,6247,'Opening'),
+(@DRAENEI,@WARRIOR,6477,'Opening'),
+(@DRAENEI,@WARRIOR,61437,'Opening'),
+(@DRAENEI,@WARRIOR,68398,'Opening'),
+(@DRAENEI,@WARRIOR,96220,'Opening'),
+(@DRAENEI,@WARRIOR,203,'Unarmed'),
+(@DRAENEI,@WARRIOR,29932,'Language Draenei'),
+(@DRAENEI,@WARRIOR,79741,'Languages'),
+(@DRAENEI,@WARRIOR,49410,'Forceful Deflection'),
+(@DRAENEI,@WARRIOR,199,'Two-Handed Maces'),
+(@DRAENEI,@WARRIOR,15590,'Fist Weapons'),
+(@DRAENEI,@WARRIOR,76268,'Armor Skills'),
+(@DRAENEI,@WARRIOR,76290,'Weapon Skills'),
+(@DRAENEI,@WARRIOR,88163,'Attack'),
+(@DRAENEI,@WARRIOR,200,'Polearms'),
+(@DRAENEI,@WARRIOR,6562,'Heroic Presence'),
+(@DRAENEI,@WARRIOR,28880,'Gift of the Naaru'),
+(@DRAENEI,@WARRIOR,28875,'Gemcutting'),
+(@DRAENEI,@WARRIOR,59221,'Shadow Resistance'),
+(@DRAENEI,@WARRIOR,668,'Language Common'),
+(@DRAENEI,@WARRIOR,227,'Staves'),
+(@DRAENEI,@WARRIOR,9116,'Shield'),
+(@DRAENEI,@WARRIOR,8737,'Mail'),
+(@DRAENEI,@WARRIOR,9077,'Leather'),
+(@DRAENEI,@WARRIOR,264,'Bows'),
+(@DRAENEI,@WARRIOR,266,'Guns'),
+(@DRAENEI,@WARRIOR,107,'Block'),
+(@DRAENEI,@WARRIOR,81,'Dodge'),
+(@DRAENEI,@WARRIOR,32215,'Victorious State'),
+(@DRAENEI,@WARRIOR,5301,'Defensive State (DND)'),
+(@DRAENEI,@WARRIOR,204,'Defense'),
+(@DRAENEI,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@WARRIOR,2764,'Throw'),
+(@DRAENEI,@WARRIOR,2567,'Thrown'),
+(@DRAENEI,@WARRIOR,9078,'Cloth'),
+(@DRAENEI,@WARRIOR,198,'One-Handed Maces'),
+(@DRAENEI,@WARRIOR,201,'One-Handed Swords'),
+-- Palading Draenei
+(@DRAENEI,@PALADIN,202,'Two-Handed Swords'),
+(@DRAENEI,@PALADIN,196,'One-Handed Axes'),
+(@DRAENEI,@PALADIN,197,'Two-Handed Axes'),
+(@DRAENEI,@PALADIN,45927,'Summon Friend'),
+(@DRAENEI,@PALADIN,6478,'Opening'),
+(@DRAENEI,@PALADIN,6603,'Auto Attack'),
+(@DRAENEI,@PALADIN,22027,'Remove Insignia'),
+(@DRAENEI,@PALADIN,22810,'Opening - No Text'),
+(@DRAENEI,@PALADIN,21651,'Opening'),
+(@DRAENEI,@PALADIN,21652,'Closing'),
+(@DRAENEI,@PALADIN,2382,'Generic'),
+(@DRAENEI,@PALADIN,3365,'Opening'),
+(@DRAENEI,@PALADIN,3050,'Detect'),
+(@DRAENEI,@PALADIN,9125,'Generic'),
+(@DRAENEI,@PALADIN,8386,'Attacking'),
+(@DRAENEI,@PALADIN,7266,'Duel'),
+(@DRAENEI,@PALADIN,7267,'Grovel'),
+(@DRAENEI,@PALADIN,7355,'Stuck'),
+(@DRAENEI,@PALADIN,6233,'Closing'),
+(@DRAENEI,@PALADIN,6246,'Closing'),
+(@DRAENEI,@PALADIN,6247,'Opening'),
+(@DRAENEI,@PALADIN,6477,'Opening'),
+(@DRAENEI,@PALADIN,27762,'Relic'),
+(@DRAENEI,@PALADIN,61437,'Opening'),
+(@DRAENEI,@PALADIN,68398,'Opening'),
+(@DRAENEI,@PALADIN,96220,'Opening'),
+(@DRAENEI,@PALADIN,49410,'Forceful Deflection'),
+(@DRAENEI,@PALADIN,203,'Unarmed'),
+(@DRAENEI,@PALADIN,29932,'Language Draenei'),
+(@DRAENEI,@PALADIN,79741,'Languages'),
+(@DRAENEI,@PALADIN,59535,'Shadow Resistance'),
+(@DRAENEI,@PALADIN,6562,'Heroic Presence'),
+(@DRAENEI,@PALADIN,28875,'Gemcutting'),
+(@DRAENEI,@PALADIN,59542,'Gift of the Naaru'),
+(@DRAENEI,@PALADIN,199,'Two-Handed Maces'),
+(@DRAENEI,@PALADIN,76271,'Armor Skills'),
+(@DRAENEI,@PALADIN,76294,'Weapon Skills'),
+(@DRAENEI,@PALADIN,200,'Polearms'),
+(@DRAENEI,@PALADIN,668,'Language Common'),
+(@DRAENEI,@PALADIN,35395,'Crusader Strike'),
+(@DRAENEI,@PALADIN,60091,'Judgement Anti-Parry/Dodge Passive'),
+(@DRAENEI,@PALADIN,9116,'Shield'),
+(@DRAENEI,@PALADIN,8737,'Mail'),
+(@DRAENEI,@PALADIN,9077,'Leather'),
+(@DRAENEI,@PALADIN,107,'Block'),
+(@DRAENEI,@PALADIN,81,'Dodge'),
+(@DRAENEI,@PALADIN,204,'Defense'),
+(@DRAENEI,@PALADIN,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@PALADIN,9078,'Cloth'),
+(@DRAENEI,@PALADIN,20208,'Paladin pushback resistance'),
+(@DRAENEI,@PALADIN,198,'One-Handed Maces'),
+(@DRAENEI,@PALADIN,201,'One-Handed Swords'),
+-- Hunter Draenei
+(@DRAENEI,@HUNTER,202,'Two-Handed Swords'),
+(@DRAENEI,@HUNTER,196,'One-Handed Axes'),
+(@DRAENEI,@HUNTER,3044,'Arcane Shot'),
+(@DRAENEI,@HUNTER,75,'Auto Shot'),
+(@DRAENEI,@HUNTER,82928,'Aimed Shot!'),
+(@DRAENEI,@HUNTER,5011,'Crossbows'),
+(@DRAENEI,@HUNTER,197,'Two-Handed Axes'),
+(@DRAENEI,@HUNTER,1180,'Daggers'),
+(@DRAENEI,@HUNTER,45927,'Summon Friend'),
+(@DRAENEI,@HUNTER,6478,'Opening'),
+(@DRAENEI,@HUNTER,6603,'Auto Attack'),
+(@DRAENEI,@HUNTER,22027,'Remove Insignia'),
+(@DRAENEI,@HUNTER,22810,'Opening - No Text'),
+(@DRAENEI,@HUNTER,21651,'Opening'),
+(@DRAENEI,@HUNTER,21652,'Closing'),
+(@DRAENEI,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@DRAENEI,@HUNTER,2382,'Generic'),
+(@DRAENEI,@HUNTER,3365,'Opening'),
+(@DRAENEI,@HUNTER,3050,'Detect'),
+(@DRAENEI,@HUNTER,9125,'Generic'),
+(@DRAENEI,@HUNTER,8386,'Attacking'),
+(@DRAENEI,@HUNTER,7266,'Duel'),
+(@DRAENEI,@HUNTER,7267,'Grovel'),
+(@DRAENEI,@HUNTER,7355,'Stuck'),
+(@DRAENEI,@HUNTER,6233,'Closing'),
+(@DRAENEI,@HUNTER,6246,'Closing'),
+(@DRAENEI,@HUNTER,6247,'Opening'),
+(@DRAENEI,@HUNTER,6477,'Opening'),
+(@DRAENEI,@HUNTER,61437,'Opening'),
+(@DRAENEI,@HUNTER,68398,'Opening'),
+(@DRAENEI,@HUNTER,96220,'Opening'),
+(@DRAENEI,@HUNTER,203,'Unarmed'),
+(@DRAENEI,@HUNTER,883,'Call Pet 1'),
+(@DRAENEI,@HUNTER,982,'Revive Pet'),
+(@DRAENEI,@HUNTER,29932,'Language Draenei'),
+(@DRAENEI,@HUNTER,59543,'Gift of the Naaru'),
+(@DRAENEI,@HUNTER,6562,'Heroic Presence'),
+(@DRAENEI,@HUNTER,28875,'Gemcutting'),
+(@DRAENEI,@HUNTER,59536,'Shadow Resistance'),
+(@DRAENEI,@HUNTER,79741,'Languages'),
+(@DRAENEI,@HUNTER,15590,'Fist Weapons'),
+(@DRAENEI,@HUNTER,200,'Polearms'),
+(@DRAENEI,@HUNTER,668,'Language Common'),
+(@DRAENEI,@HUNTER,227,'Staves'),
+(@DRAENEI,@HUNTER,9077,'Leather'),
+(@DRAENEI,@HUNTER,264,'Bows'),
+(@DRAENEI,@HUNTER,266,'Guns'),
+(@DRAENEI,@HUNTER,13358,'Defensive State (DND)'),
+(@DRAENEI,@HUNTER,81,'Dodge'),
+(@DRAENEI,@HUNTER,204,'Defense'),
+(@DRAENEI,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@DRAENEI,@HUNTER,9078,'Cloth'),
+(@DRAENEI,@HUNTER,77442,'Focus'),
+(@DRAENEI,@HUNTER,76249,'Weapon Skills'),
+(@DRAENEI,@HUNTER,76250,'Armor Skills'),
+(@DRAENEI,@HUNTER,87324,'Focused Aim'),
+(@DRAENEI,@HUNTER,87816,'General Hunter Passives'),
+(@DRAENEI,@HUNTER,201,'One-Handed Swords'),
+-- Priest Draenei
+(@DRAENEI,@PRIEST,5009,'Wands'),
+(@DRAENEI,@PRIEST,5019,'Shoot'),
+(@DRAENEI,@PRIEST,1180,'Daggers'),
+(@DRAENEI,@PRIEST,45927,'Summon Friend'),
+(@DRAENEI,@PRIEST,6478,'Opening'),
+(@DRAENEI,@PRIEST,6603,'Auto Attack'),
+(@DRAENEI,@PRIEST,22027,'Remove Insignia'),
+(@DRAENEI,@PRIEST,22810,'Opening - No Text'),
+(@DRAENEI,@PRIEST,21651,'Opening'),
+(@DRAENEI,@PRIEST,21652,'Closing'),
+(@DRAENEI,@PRIEST,2382,'Generic'),
+(@DRAENEI,@PRIEST,3365,'Opening'),
+(@DRAENEI,@PRIEST,3050,'Detect'),
+(@DRAENEI,@PRIEST,9125,'Generic'),
+(@DRAENEI,@PRIEST,8386,'Attacking'),
+(@DRAENEI,@PRIEST,7266,'Duel'),
+(@DRAENEI,@PRIEST,7267,'Grovel'),
+(@DRAENEI,@PRIEST,7355,'Stuck'),
+(@DRAENEI,@PRIEST,6233,'Closing'),
+(@DRAENEI,@PRIEST,6246,'Closing'),
+(@DRAENEI,@PRIEST,6247,'Opening'),
+(@DRAENEI,@PRIEST,6477,'Opening'),
+(@DRAENEI,@PRIEST,61437,'Opening'),
+(@DRAENEI,@PRIEST,68398,'Opening'),
+(@DRAENEI,@PRIEST,96220,'Opening'),
+(@DRAENEI,@PRIEST,203,'Unarmed'),
+(@DRAENEI,@PRIEST,585,'Smite'),
+(@DRAENEI,@PRIEST,84733,'Holy Focus'),
+(@DRAENEI,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@DRAENEI,@PRIEST,88684,'Holy Word: Serenity'),
+(@DRAENEI,@PRIEST,101062,'Flash Heal'),
+(@DRAENEI,@PRIEST,29932,'Language Draenei'),
+(@DRAENEI,@PRIEST,59538,'Shadow Resistance'),
+(@DRAENEI,@PRIEST,28878,'Heroic Presence'),
+(@DRAENEI,@PRIEST,28875,'Gemcutting'),
+(@DRAENEI,@PRIEST,59544,'Gift of the Naaru'),
+(@DRAENEI,@PRIEST,79741,'Languages'),
+(@DRAENEI,@PRIEST,76301,'Weapon Skills'),
+(@DRAENEI,@PRIEST,76279,'Armor Skills'),
+(@DRAENEI,@PRIEST,84734,'Dark Thoughts'),
+(@DRAENEI,@PRIEST,668,'Language Common'),
+(@DRAENEI,@PRIEST,227,'Staves'),
+(@DRAENEI,@PRIEST,77486,'Shadow Orb Power'),
+(@DRAENEI,@PRIEST,81,'Dodge'),
+(@DRAENEI,@PRIEST,204,'Defense'),
+(@DRAENEI,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@PRIEST,9078,'Cloth'),
+(@DRAENEI,@PRIEST,198,'One-Handed Maces'),
+-- Draenei Shaman
+(@DRAENEI,@SHAMAN,196,'One-Handed Axes'),
+(@DRAENEI,@SHAMAN,197,'Two-Handed Axes'),
+(@DRAENEI,@SHAMAN,1180,'Daggers'),
+(@DRAENEI,@SHAMAN,45927,'Summon Friend'),
+(@DRAENEI,@SHAMAN,6478,'Opening'),
+(@DRAENEI,@SHAMAN,6603,'Auto Attack'),
+(@DRAENEI,@SHAMAN,22027,'Remove Insignia'),
+(@DRAENEI,@SHAMAN,22810,'Opening - No Text'),
+(@DRAENEI,@SHAMAN,21651,'Opening'),
+(@DRAENEI,@SHAMAN,21652,'Closing'),
+(@DRAENEI,@SHAMAN,2382,'Generic'),
+(@DRAENEI,@SHAMAN,3365,'Opening'),
+(@DRAENEI,@SHAMAN,3050,'Detect'),
+(@DRAENEI,@SHAMAN,9125,'Generic'),
+(@DRAENEI,@SHAMAN,8386,'Attacking'),
+(@DRAENEI,@SHAMAN,7266,'Duel'),
+(@DRAENEI,@SHAMAN,7267,'Grovel'),
+(@DRAENEI,@SHAMAN,7355,'Stuck'),
+(@DRAENEI,@SHAMAN,6233,'Closing'),
+(@DRAENEI,@SHAMAN,6246,'Closing'),
+(@DRAENEI,@SHAMAN,6247,'Opening'),
+(@DRAENEI,@SHAMAN,6477,'Opening'),
+(@DRAENEI,@SHAMAN,27763,'Relic'),
+(@DRAENEI,@SHAMAN,61437,'Opening'),
+(@DRAENEI,@SHAMAN,68398,'Opening'),
+(@DRAENEI,@SHAMAN,96220,'Opening'),
+(@DRAENEI,@SHAMAN,203,'Unarmed'),
+(@DRAENEI,@SHAMAN,29932,'Language Draenei'),
+(@DRAENEI,@SHAMAN,28878,'Heroic Presence'),
+(@DRAENEI,@SHAMAN,28875,'Gemcutting'),
+(@DRAENEI,@SHAMAN,59540,'Shadow Resistance'),
+(@DRAENEI,@SHAMAN,59547,'Gift of the Naaru'),
+(@DRAENEI,@SHAMAN,79741,'Languages'),
+(@DRAENEI,@SHAMAN,199,'Two-Handed Maces'),
+(@DRAENEI,@SHAMAN,15590,'Fist Weapons'),
+(@DRAENEI,@SHAMAN,76272,'Armor Skills'),
+(@DRAENEI,@SHAMAN,76296,'Weapon Skills'),
+(@DRAENEI,@SHAMAN,89920,'Ancestral Focus'),
+(@DRAENEI,@SHAMAN,668,'Language Common'),
+(@DRAENEI,@SHAMAN,227,'Staves'),
+(@DRAENEI,@SHAMAN,9116,'Shield'),
+(@DRAENEI,@SHAMAN,9077,'Leather'),
+(@DRAENEI,@SHAMAN,107,'Block'),
+(@DRAENEI,@SHAMAN,81,'Dodge'),
+(@DRAENEI,@SHAMAN,204,'Defense'),
+(@DRAENEI,@SHAMAN,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@SHAMAN,403,'Lightning Bolt'),
+(@DRAENEI,@SHAMAN,9078,'Cloth'),
+(@DRAENEI,@SHAMAN,198,'One-Handed Maces'),
+-- Draenei Mage
+(@DRAENEI,@MAGE,71761,'Deep Freeze Immunity State'),
+(@DRAENEI,@MAGE,5009,'Wands'),
+(@DRAENEI,@MAGE,5019,'Shoot'),
+(@DRAENEI,@MAGE,1180,'Daggers'),
+(@DRAENEI,@MAGE,45927,'Summon Friend'),
+(@DRAENEI,@MAGE,6478,'Opening'),
+(@DRAENEI,@MAGE,6603,'Auto Attack'),
+(@DRAENEI,@MAGE,22027,'Remove Insignia'),
+(@DRAENEI,@MAGE,22810,'Opening - No Text'),
+(@DRAENEI,@MAGE,21651,'Opening'),
+(@DRAENEI,@MAGE,21652,'Closing'),
+(@DRAENEI,@MAGE,2382,'Generic'),
+(@DRAENEI,@MAGE,3365,'Opening'),
+(@DRAENEI,@MAGE,3050,'Detect'),
+(@DRAENEI,@MAGE,9125,'Generic'),
+(@DRAENEI,@MAGE,8386,'Attacking'),
+(@DRAENEI,@MAGE,7266,'Duel'),
+(@DRAENEI,@MAGE,7267,'Grovel'),
+(@DRAENEI,@MAGE,7355,'Stuck'),
+(@DRAENEI,@MAGE,6233,'Closing'),
+(@DRAENEI,@MAGE,6246,'Closing'),
+(@DRAENEI,@MAGE,6247,'Opening'),
+(@DRAENEI,@MAGE,6477,'Opening'),
+(@DRAENEI,@MAGE,61437,'Opening'),
+(@DRAENEI,@MAGE,68398,'Opening'),
+(@DRAENEI,@MAGE,96220,'Opening'),
+(@DRAENEI,@MAGE,79684,'Offensive State (DND)'),
+(@DRAENEI,@MAGE,203,'Unarmed'),
+(@DRAENEI,@MAGE,29932,'Language Draenei'),
+(@DRAENEI,@MAGE,59541,'Shadow Resistance'),
+(@DRAENEI,@MAGE,28878,'Heroic Presence'),
+(@DRAENEI,@MAGE,28875,'Gemcutting'),
+(@DRAENEI,@MAGE,59548,'Gift of the Naaru'),
+(@DRAENEI,@MAGE,79741,'Languages'),
+(@DRAENEI,@MAGE,133,'Fireball'),
+(@DRAENEI,@MAGE,92315,'Pyroblast!'),
+(@DRAENEI,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@DRAENEI,@MAGE,76298,'Weapon Skills'),
+(@DRAENEI,@MAGE,76276,'Armor Skills'),
+(@DRAENEI,@MAGE,668,'Language Common'),
+(@DRAENEI,@MAGE,227,'Staves'),
+(@DRAENEI,@MAGE,81,'Dodge'),
+(@DRAENEI,@MAGE,204,'Defense'),
+(@DRAENEI,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@DRAENEI,@MAGE,9078,'Cloth'),
+(@DRAENEI,@MAGE,201,'One-Handed Swords'),
+-- Human Worgen char create:
+(@WORGEN,@WARRIOR,202,'Two-Handed Swords'),
+(@WORGEN,@WARRIOR,196,'One-Handed Axes'),
+(@WORGEN,@WARRIOR,2457,'Battle Stance'),
+(@WORGEN,@WARRIOR,88161,'Strike'),
+(@WORGEN,@WARRIOR,5011,'Crossbows'),
+(@WORGEN,@WARRIOR,3018,'Shoot'),
+(@WORGEN,@WARRIOR,197,'Two-Handed Axes'),
+(@WORGEN,@WARRIOR,1180,'Daggers'),
+(@WORGEN,@WARRIOR,45927,'Summon Friend'),
+(@WORGEN,@WARRIOR,6478,'Opening'),
+(@WORGEN,@WARRIOR,6603,'Auto Attack'),
+(@WORGEN,@WARRIOR,22027,'Remove Insignia'),
+(@WORGEN,@WARRIOR,22810,'Opening - No Text'),
+(@WORGEN,@WARRIOR,21651,'Opening'),
+(@WORGEN,@WARRIOR,21652,'Closing'),
+(@WORGEN,@WARRIOR,2382,'Generic'),
+(@WORGEN,@WARRIOR,3365,'Opening'),
+(@WORGEN,@WARRIOR,3050,'Detect'),
+(@WORGEN,@WARRIOR,9125,'Generic'),
+(@WORGEN,@WARRIOR,8386,'Attacking'),
+(@WORGEN,@WARRIOR,7266,'Duel'),
+(@WORGEN,@WARRIOR,7267,'Grovel'),
+(@WORGEN,@WARRIOR,7355,'Stuck'),
+(@WORGEN,@WARRIOR,6233,'Closing'),
+(@WORGEN,@WARRIOR,6246,'Closing'),
+(@WORGEN,@WARRIOR,6247,'Opening'),
+(@WORGEN,@WARRIOR,6477,'Opening'),
+(@WORGEN,@WARRIOR,61437,'Opening'),
+(@WORGEN,@WARRIOR,68398,'Opening'),
+(@WORGEN,@WARRIOR,96220,'Opening'),
+(@WORGEN,@WARRIOR,203,'Unarmed'),
+(@WORGEN,@WARRIOR,79742,'Languages'),
+(@WORGEN,@WARRIOR,69001,''),
+(@WORGEN,@WARRIOR,49410,'Forceful Deflection'),
+(@WORGEN,@WARRIOR,199,'Two-Handed Maces'),
+(@WORGEN,@WARRIOR,15590,'Fist Weapons'),
+(@WORGEN,@WARRIOR,76268,'Armor Skills'),
+(@WORGEN,@WARRIOR,76290,'Weapon Skills'),
+(@WORGEN,@WARRIOR,88163,'Attack'),
+(@WORGEN,@WARRIOR,200,'Polearms'),
+(@WORGEN,@WARRIOR,668,'Language Common'),
+(@WORGEN,@WARRIOR,227,'Staves'),
+(@WORGEN,@WARRIOR,9116,'Shield'),
+(@WORGEN,@WARRIOR,8737,'Mail'),
+(@WORGEN,@WARRIOR,9077,'Leather'),
+(@WORGEN,@WARRIOR,264,'Bows'),
+(@WORGEN,@WARRIOR,266,'Guns'),
+(@WORGEN,@WARRIOR,107,'Block'),
+(@WORGEN,@WARRIOR,81,'Dodge'),
+(@WORGEN,@WARRIOR,32215,'Victorious State'),
+(@WORGEN,@WARRIOR,5301,'Defensive State (DND)'),
+(@WORGEN,@WARRIOR,204,'Defense'),
+(@WORGEN,@WARRIOR,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@WARRIOR,2764,'Throw'),
+(@WORGEN,@WARRIOR,2567,'Thrown'),
+(@WORGEN,@WARRIOR,9078,'Cloth'),
+(@WORGEN,@WARRIOR,198,'One-Handed Maces'),
+(@WORGEN,@WARRIOR,201,'One-Handed Swords'),
+-- Hunter Worgen
+(@WORGEN,@HUNTER,202,'Two-Handed Swords'),
+(@WORGEN,@HUNTER,196,'One-Handed Axes'),
+(@WORGEN,@HUNTER,3044,'Arcane Shot'),
+(@WORGEN,@HUNTER,75,'Auto Shot'),
+(@WORGEN,@HUNTER,82928,'Aimed Shot!'),
+(@WORGEN,@HUNTER,5011,'Crossbows'),
+(@WORGEN,@HUNTER,197,'Two-Handed Axes'),
+(@WORGEN,@HUNTER,1180,'Daggers'),
+(@WORGEN,@HUNTER,45927,'Summon Friend'),
+(@WORGEN,@HUNTER,6478,'Opening'),
+(@WORGEN,@HUNTER,6603,'Auto Attack'),
+(@WORGEN,@HUNTER,22027,'Remove Insignia'),
+(@WORGEN,@HUNTER,22810,'Opening - No Text'),
+(@WORGEN,@HUNTER,21651,'Opening'),
+(@WORGEN,@HUNTER,21652,'Closing'),
+(@WORGEN,@HUNTER,34082,'Hunter Passive Auras (DND)'),
+(@WORGEN,@HUNTER,2382,'Generic'),
+(@WORGEN,@HUNTER,3365,'Opening'),
+(@WORGEN,@HUNTER,3050,'Detect'),
+(@WORGEN,@HUNTER,9125,'Generic'),
+(@WORGEN,@HUNTER,8386,'Attacking'),
+(@WORGEN,@HUNTER,7266,'Duel'),
+(@WORGEN,@HUNTER,7267,'Grovel'),
+(@WORGEN,@HUNTER,7355,'Stuck'),
+(@WORGEN,@HUNTER,6233,'Closing'),
+(@WORGEN,@HUNTER,6246,'Closing'),
+(@WORGEN,@HUNTER,6247,'Opening'),
+(@WORGEN,@HUNTER,6477,'Opening'),
+(@WORGEN,@HUNTER,61437,'Opening'),
+(@WORGEN,@HUNTER,68398,'Opening'),
+(@WORGEN,@HUNTER,96220,'Opening'),
+(@WORGEN,@HUNTER,203,'Unarmed'),
+(@WORGEN,@HUNTER,883,'Call Pet 1'),
+(@WORGEN,@HUNTER,982,'Revive Pet'),
+(@WORGEN,@HUNTER,79742,'Languages'),
+(@WORGEN,@HUNTER,69001,''),
+(@WORGEN,@HUNTER,15590,'Fist Weapons'),
+(@WORGEN,@HUNTER,200,'Polearms'),
+(@WORGEN,@HUNTER,668,'Language Common'),
+(@WORGEN,@HUNTER,227,'Staves'),
+(@WORGEN,@HUNTER,9077,'Leather'),
+(@WORGEN,@HUNTER,264,'Bows'),
+(@WORGEN,@HUNTER,266,'Guns'),
+(@WORGEN,@HUNTER,13358,'Defensive State (DND)'),
+(@WORGEN,@HUNTER,81,'Dodge'),
+(@WORGEN,@HUNTER,204,'Defense'),
+(@WORGEN,@HUNTER,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@HUNTER,24949,'Defensive State 2 (DND)'),
+(@WORGEN,@HUNTER,9078,'Cloth'),
+(@WORGEN,@HUNTER,77442,'Focus'),
+(@WORGEN,@HUNTER,76249,'Weapon Skills'),
+(@WORGEN,@HUNTER,76250,'Armor Skills'),
+(@WORGEN,@HUNTER,87324,'Focused Aim'),
+(@WORGEN,@HUNTER,87816,'General Hunter Passives'),
+(@WORGEN,@HUNTER,201,'One-Handed Swords'),
+-- Rogue Worgen
+(@WORGEN,@ROGUE,196,'One-Handed Axes'),
+(@WORGEN,@ROGUE,1752,'Sinister Strike'),
+(@WORGEN,@ROGUE,5011,'Crossbows'),
+(@WORGEN,@ROGUE,3018,'Shoot'),
+(@WORGEN,@ROGUE,674,'Dual Wield'),
+(@WORGEN,@ROGUE,1180,'Daggers'),
+(@WORGEN,@ROGUE,45927,'Summon Friend'),
+(@WORGEN,@ROGUE,6478,'Opening'),
+(@WORGEN,@ROGUE,6603,'Auto Attack'),
+(@WORGEN,@ROGUE,22027,'Remove Insignia'),
+(@WORGEN,@ROGUE,22810,'Opening - No Text'),
+(@WORGEN,@ROGUE,21651,'Opening'),
+(@WORGEN,@ROGUE,21652,'Closing'),
+(@WORGEN,@ROGUE,2382,'Generic'),
+(@WORGEN,@ROGUE,3365,'Opening'),
+(@WORGEN,@ROGUE,3050,'Detect'),
+(@WORGEN,@ROGUE,9125,'Generic'),
+(@WORGEN,@ROGUE,8386,'Attacking'),
+(@WORGEN,@ROGUE,7266,'Duel'),
+(@WORGEN,@ROGUE,7267,'Grovel'),
+(@WORGEN,@ROGUE,7355,'Stuck'),
+(@WORGEN,@ROGUE,6233,'Closing'),
+(@WORGEN,@ROGUE,6246,'Closing'),
+(@WORGEN,@ROGUE,6247,'Opening'),
+(@WORGEN,@ROGUE,6477,'Opening'),
+(@WORGEN,@ROGUE,61437,'Opening'),
+(@WORGEN,@ROGUE,68398,'Opening'),
+(@WORGEN,@ROGUE,96220,'Opening'),
+(@WORGEN,@ROGUE,203,'Unarmed'),
+(@WORGEN,@ROGUE,79742,'Languages'),
+(@WORGEN,@ROGUE,69001,''),
+(@WORGEN,@ROGUE,15590,'Fist Weapons'),
+(@WORGEN,@ROGUE,76273,'Armor Skills'),
+(@WORGEN,@ROGUE,76297,'Weapon Skills'),
+(@WORGEN,@ROGUE,668,'Language Common'),
+(@WORGEN,@ROGUE,9077,'Leather'),
+(@WORGEN,@ROGUE,264,'Bows'),
+(@WORGEN,@ROGUE,266,'Guns'),
+(@WORGEN,@ROGUE,81,'Dodge'),
+(@WORGEN,@ROGUE,204,'Defense'),
+(@WORGEN,@ROGUE,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@ROGUE,16092,'Defensive State (DND)'),
+(@WORGEN,@ROGUE,2764,'Throw'),
+(@WORGEN,@ROGUE,2567,'Thrown'),
+(@WORGEN,@ROGUE,9078,'Cloth'),
+(@WORGEN,@ROGUE,198,'One-Handed Maces'),
+(@WORGEN,@ROGUE,201,'One-Handed Swords'),
+-- Priest Worgen
+(@WORGEN,@PRIEST,5009,'Wands'),
+(@WORGEN,@PRIEST,5019,'Shoot'),
+(@WORGEN,@PRIEST,1180,'Daggers'),
+(@WORGEN,@PRIEST,45927,'Summon Friend'),
+(@WORGEN,@PRIEST,6478,'Opening'),
+(@WORGEN,@PRIEST,6603,'Auto Attack'),
+(@WORGEN,@PRIEST,22027,'Remove Insignia'),
+(@WORGEN,@PRIEST,22810,'Opening - No Text'),
+(@WORGEN,@PRIEST,21651,'Opening'),
+(@WORGEN,@PRIEST,21652,'Closing'),
+(@WORGEN,@PRIEST,2382,'Generic'),
+(@WORGEN,@PRIEST,3365,'Opening'),
+(@WORGEN,@PRIEST,3050,'Detect'),
+(@WORGEN,@PRIEST,9125,'Generic'),
+(@WORGEN,@PRIEST,8386,'Attacking'),
+(@WORGEN,@PRIEST,7266,'Duel'),
+(@WORGEN,@PRIEST,7267,'Grovel'),
+(@WORGEN,@PRIEST,7355,'Stuck'),
+(@WORGEN,@PRIEST,6233,'Closing'),
+(@WORGEN,@PRIEST,6246,'Closing'),
+(@WORGEN,@PRIEST,6247,'Opening'),
+(@WORGEN,@PRIEST,6477,'Opening'),
+(@WORGEN,@PRIEST,61437,'Opening'),
+(@WORGEN,@PRIEST,68398,'Opening'),
+(@WORGEN,@PRIEST,96220,'Opening'),
+(@WORGEN,@PRIEST,203,'Unarmed'),
+(@WORGEN,@PRIEST,585,'Smite'),
+(@WORGEN,@PRIEST,84733,'Holy Focus'),
+(@WORGEN,@PRIEST,88685,'Holy Word: Sanctuary'),
+(@WORGEN,@PRIEST,88684,'Holy Word: Serenity'),
+(@WORGEN,@PRIEST,101062,'Flash Heal'),
+(@WORGEN,@PRIEST,79742,'Languages'),
+(@WORGEN,@PRIEST,69001,''),
+(@WORGEN,@PRIEST,76301,'Weapon Skills'),
+(@WORGEN,@PRIEST,76279,'Armor Skills'),
+(@WORGEN,@PRIEST,84734,'Dark Thoughts'),
+(@WORGEN,@PRIEST,668,'Language Common'),
+(@WORGEN,@PRIEST,227,'Staves'),
+(@WORGEN,@PRIEST,77486,'Shadow Orb Power'),
+(@WORGEN,@PRIEST,81,'Dodge'),
+(@WORGEN,@PRIEST,204,'Defense'),
+(@WORGEN,@PRIEST,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@PRIEST,9078,'Cloth'),
+(@WORGEN,@PRIEST,198,'One-Handed Maces'),
+-- Mage Worgen
+(@WORGEN,@MAGE,71761,'Deep Freeze Immunity State'),
+(@WORGEN,@MAGE,5009,'Wands'),
+(@WORGEN,@MAGE,5019,'Shoot'),
+(@WORGEN,@MAGE,1180,'Daggers'),
+(@WORGEN,@MAGE,45927,'Summon Friend'),
+(@WORGEN,@MAGE,6478,'Opening'),
+(@WORGEN,@MAGE,6603,'Auto Attack'),
+(@WORGEN,@MAGE,22027,'Remove Insignia'),
+(@WORGEN,@MAGE,22810,'Opening - No Text'),
+(@WORGEN,@MAGE,21651,'Opening'),
+(@WORGEN,@MAGE,21652,'Closing'),
+(@WORGEN,@MAGE,2382,'Generic'),
+(@WORGEN,@MAGE,3365,'Opening'),
+(@WORGEN,@MAGE,3050,'Detect'),
+(@WORGEN,@MAGE,9125,'Generic'),
+(@WORGEN,@MAGE,8386,'Attacking'),
+(@WORGEN,@MAGE,7266,'Duel'),
+(@WORGEN,@MAGE,7267,'Grovel'),
+(@WORGEN,@MAGE,7355,'Stuck'),
+(@WORGEN,@MAGE,6233,'Closing'),
+(@WORGEN,@MAGE,6246,'Closing'),
+(@WORGEN,@MAGE,6247,'Opening'),
+(@WORGEN,@MAGE,6477,'Opening'),
+(@WORGEN,@MAGE,61437,'Opening'),
+(@WORGEN,@MAGE,68398,'Opening'),
+(@WORGEN,@MAGE,96220,'Opening'),
+(@WORGEN,@MAGE,79684,'Offensive State (DND)'),
+(@WORGEN,@MAGE,203,'Unarmed'),
+(@WORGEN,@MAGE,79742,'Languages'),
+(@WORGEN,@MAGE,69001,''),
+(@WORGEN,@MAGE,133,'Fireball'),
+(@WORGEN,@MAGE,92315,'Pyroblast!'),
+(@WORGEN,@MAGE,85801,'DPS Caster Crit Damage Bonus'),
+(@WORGEN,@MAGE,76298,'Weapon Skills'),
+(@WORGEN,@MAGE,76276,'Armor Skills'),
+(@WORGEN,@MAGE,668,'Language Common'),
+(@WORGEN,@MAGE,227,'Staves'),
+(@WORGEN,@MAGE,81,'Dodge'),
+(@WORGEN,@MAGE,204,'Defense'),
+(@WORGEN,@MAGE,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@MAGE,9078,'Cloth'),
+(@WORGEN,@MAGE,201,'One-Handed Swords'),
+-- Warlock Worgen
+(@WORGEN,@WARLOCK,5009,'Wands'),
+(@WORGEN,@WARLOCK,5019,'Shoot'),
+(@WORGEN,@WARLOCK,1180,'Daggers'),
+(@WORGEN,@WARLOCK,45927,'Summon Friend'),
+(@WORGEN,@WARLOCK,6478,'Opening'),
+(@WORGEN,@WARLOCK,6603,'Auto Attack'),
+(@WORGEN,@WARLOCK,22027,'Remove Insignia'),
+(@WORGEN,@WARLOCK,22810,'Opening - No Text'),
+(@WORGEN,@WARLOCK,21651,'Opening'),
+(@WORGEN,@WARLOCK,21652,'Closing'),
+(@WORGEN,@WARLOCK,2382,'Generic'),
+(@WORGEN,@WARLOCK,3365,'Opening'),
+(@WORGEN,@WARLOCK,3050,'Detect'),
+(@WORGEN,@WARLOCK,9125,'Generic'),
+(@WORGEN,@WARLOCK,8386,'Attacking'),
+(@WORGEN,@WARLOCK,7266,'Duel'),
+(@WORGEN,@WARLOCK,7267,'Grovel'),
+(@WORGEN,@WARLOCK,7355,'Stuck'),
+(@WORGEN,@WARLOCK,6233,'Closing'),
+(@WORGEN,@WARLOCK,6246,'Closing'),
+(@WORGEN,@WARLOCK,6247,'Opening'),
+(@WORGEN,@WARLOCK,6477,'Opening'),
+(@WORGEN,@WARLOCK,61437,'Opening'),
+(@WORGEN,@WARLOCK,68398,'Opening'),
+(@WORGEN,@WARLOCK,96220,'Opening'),
+(@WORGEN,@WARLOCK,203,'Unarmed'),
+(@WORGEN,@WARLOCK,79742,'Languages'),
+(@WORGEN,@WARLOCK,69001,''),
+(@WORGEN,@WARLOCK,688,'Summon Imp'),
+(@WORGEN,@WARLOCK,86213,'Soul Swap Exhale'),
+(@WORGEN,@WARLOCK,89420,'Drain Life'),
+(@WORGEN,@WARLOCK,85801,'DPS Caster Crit Damage Bonus'),
+(@WORGEN,@WARLOCK,76299,'Weapon Skills'),
+(@WORGEN,@WARLOCK,76277,'Armor Skills'),
+(@WORGEN,@WARLOCK,87330,'Suppression'),
+(@WORGEN,@WARLOCK,668,'Language Common'),
+(@WORGEN,@WARLOCK,227,'Staves'),
+(@WORGEN,@WARLOCK,75445,'Demonic Immolate'),
+(@WORGEN,@WARLOCK,686,'Shadow Bolt'),
+(@WORGEN,@WARLOCK,58284,'Chaos Bolt Passive'),
+(@WORGEN,@WARLOCK,81,'Dodge'),
+(@WORGEN,@WARLOCK,204,'Defense'),
+(@WORGEN,@WARLOCK,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@WARLOCK,9078,'Cloth'),
+(@WORGEN,@WARLOCK,201,'One-Handed Swords'),
+-- Druid Worgen
+(@WORGEN,@DRUID,1180,'Daggers'),
+(@WORGEN,@DRUID,45927,'Summon Friend'),
+(@WORGEN,@DRUID,6478,'Opening'),
+(@WORGEN,@DRUID,6603,'Auto Attack'),
+(@WORGEN,@DRUID,22027,'Remove Insignia'),
+(@WORGEN,@DRUID,22810,'Opening - No Text'),
+(@WORGEN,@DRUID,21651,'Opening'),
+(@WORGEN,@DRUID,21652,'Closing'),
+(@WORGEN,@DRUID,2382,'Generic'),
+(@WORGEN,@DRUID,3365,'Opening'),
+(@WORGEN,@DRUID,3050,'Detect'),
+(@WORGEN,@DRUID,9125,'Generic'),
+(@WORGEN,@DRUID,8386,'Attacking'),
+(@WORGEN,@DRUID,7266,'Duel'),
+(@WORGEN,@DRUID,7267,'Grovel'),
+(@WORGEN,@DRUID,7355,'Stuck'),
+(@WORGEN,@DRUID,6233,'Closing'),
+(@WORGEN,@DRUID,6246,'Closing'),
+(@WORGEN,@DRUID,6247,'Opening'),
+(@WORGEN,@DRUID,6477,'Opening'),
+(@WORGEN,@DRUID,61437,'Opening'),
+(@WORGEN,@DRUID,68398,'Opening'),
+(@WORGEN,@DRUID,96220,'Opening'),
+(@WORGEN,@DRUID,203,'Unarmed'),
+(@WORGEN,@DRUID,79742,'Languages'),
+(@WORGEN,@DRUID,69001,''),
+(@WORGEN,@DRUID,84736,"Nature's Focus"),
+(@WORGEN,@DRUID,81170,"Ravage!"),
+(@WORGEN,@DRUID,79577,"Eclipse Mastery Driver Passive"),
+(@WORGEN,@DRUID,76300,'Weapon Skills'),
+(@WORGEN,@DRUID,76275,'Armor Skills'),
+(@WORGEN,@DRUID,5176,'Wrath'),
+(@WORGEN,@DRUID,199,'Two-Handed Maces'),
+(@WORGEN,@DRUID,15590,'Fist Weapons'),
+(@WORGEN,@DRUID,84738,'Celestial Focus'),
+(@WORGEN,@DRUID,668,'Language Common'),
+(@WORGEN,@DRUID,200,'Polearms'),
+(@WORGEN,@DRUID,227,'Staves'),
+(@WORGEN,@DRUID,81,'Dodge'),
+(@WORGEN,@DRUID,204,'Defense'),
+(@WORGEN,@DRUID,522,'SPELLDEFENSE (DND)'),
+(@WORGEN,@DRUID,9077,'Leather'),
+(@WORGEN,@DRUID,9078,'Cloth'),
+(@WORGEN,@DRUID,198,'One-Handed Maces');
+
+-- Races:
+SET @HUMAN := 1;
+SET @ORC := 2;
+SET @DWARF := 3;
+SET @NIGHT_ELF := 4;
+SET @UNDEAD := 5;
+SET @TAUREN := 6;
+SET @GNOME := 7;
+SET @TROLL := 8;
+SET @GOBLIN := 9;
+SET @BLOOD_ELF := 10;
+SET @DRAENEI := 11;
+SET @WORGEN := 22;
+-- Classes:
+SET @WARRIOR := 1;
+SET @PALADIN := 2;
+SET @HUNTER := 3;
+SET @ROGUE := 4;
+SET @PRIEST := 5;
+SET @DK := 6;
+SET @SHAMAN := 7;
+SET @MAGE := 8;
+SET @WARLOCK := 9;
+SET @DRUID := 11;
+
+-- 4.2.0 new actions:
+TRUNCATE TABLE `playercreateinfo_action`;
+INSERT INTO `playercreateinfo_action` (`race`,`class`,`button`,`action`,`type`) VALUES
+-- Human Warrior
+(@HUMAN,@WARRIOR,72,88163,0),
+(@HUMAN,@WARRIOR,73,88161,0),
+(@HUMAN,@WARRIOR,81,59752,0),
+(@HUMAN,@WARRIOR,84,6603,0),
+(@HUMAN,@WARRIOR,96,6603,0),
+(@HUMAN,@WARRIOR,108,6603,0),
+-- Human Paladin
+(@HUMAN,@PALADIN,0,35395,0),
+(@HUMAN,@PALADIN,9,59752,0),
+-- Human Hunter
+(@HUMAN,@HUNTER,0,3044,0),
+(@HUMAN,@HUNTER,9,59752,0),
+(@HUMAN,@HUNTER,10,9,48),
+(@HUMAN,@HUNTER,11,982,0),
+-- Human Rouge
+(@HUMAN,@ROGUE,0,1752,0),
+(@HUMAN,@ROGUE,9,59752,0),
+-- Human Priest
+(@HUMAN,@PRIEST,0,585,0),
+(@HUMAN,@PRIEST,9,59752,0),
+-- Human Mage
+(@HUMAN,@MAGE,0,133,0),
+(@HUMAN,@MAGE,9,59752,0),
+-- Human Warlock
+(@HUMAN,@WARLOCK,0,686,0),
+(@HUMAN,@WARLOCK,9,59752,0),
+(@HUMAN,@WARLOCK,10,10,48),
+-- Orc:
+-- Orc Warrior
+(@ORC,@WARRIOR,72,88163,0),
+(@ORC,@WARRIOR,73,88161,0),
+(@ORC,@WARRIOR,81,20572,0),
+(@ORC,@WARRIOR,84,6603,0),
+(@ORC,@WARRIOR,96,6603,0),
+(@ORC,@WARRIOR,108,6603,0),
+-- Orc Hunter
+(@ORC,@HUNTER,0,3044,0),
+(@ORC,@HUNTER,9,20572,0),
+(@ORC,@HUNTER,10,9,48),
+(@ORC,@HUNTER,11,982,0),
+-- Orc Rogue
+(@ORC,@ROGUE,0,1752,0),
+(@ORC,@ROGUE,9,20572,0),
+-- Orc Shaman
+(@ORC,@SHAMAN,0,403,0),
+(@ORC,@SHAMAN,9,20572,0),
+(@ORC,@SHAMAN,72,403,0),
+-- Orc Mage
+(@ORC,@MAGE,0,133,0),
+(@ORC,@MAGE,9,33702,0),
+-- Orc Warlock
+(@ORC,@WARLOCK,0,686,0),
+(@ORC,@WARLOCK,9,33702,0),
+(@ORC,@WARLOCK,10,10,48),
+-- Dwarf:
+-- Dwarf Warrior
+(@DWARF,@WARRIOR,72,88163,0),
+(@DWARF,@WARRIOR,73,88161,0),
+(@DWARF,@WARRIOR,81,20594,0),
+(@DWARF,@WARRIOR,84,6603,0),
+(@DWARF,@WARRIOR,96,6603,0),
+(@DWARF,@WARRIOR,108,6603,0),
+-- Dwarf Paladin
+(@DWARF,@PALADIN,0,35395,0),
+(@DWARF,@PALADIN,9,20594,0),
+-- Dwarf Hunter
+(@DWARF,@HUNTER,0,3044,0),
+(@DWARF,@HUNTER,9,20594,0),
+(@DWARF,@HUNTER,10,9,48),
+(@DWARF,@HUNTER,11,982,0),
+(@DWARF,@HUNTER,75,20594,0),
+-- Dwarf Rogue
+(@DWARF,@ROGUE,0,1752,0),
+(@DWARF,@ROGUE,9,20594,0),
+-- Dwarf Priest
+(@DWARF,@PRIEST,0,585,0),
+(@DWARF,@PRIEST,9,20594,0),
+-- Dwarf Shaman
+(@DWARF,@SHAMAN,0,6603,0),
+(@DWARF,@SHAMAN,1,403,0),
+(@DWARF,@SHAMAN,9,20594,0),
+(@DWARF,@SHAMAN,72,403,0),
+-- Dwarf Mage
+(@DWARF,@MAGE,0,133,0),
+(@DWARF,@MAGE,9,20594,0),
+-- Dwarf Warlock
+(@DWARF,@WARLOCK,0,686,0),
+(@DWARF,@WARLOCK,9,20594,0),
+(@DWARF,@WARLOCK,10,10,48),
+-- Night Elf:
+-- Night Elf Warrior
+(@NIGHT_ELF,@WARRIOR,72,88163,0),
+(@NIGHT_ELF,@WARRIOR,73,88161,0),
+(@NIGHT_ELF,@WARRIOR,81,58984,0),
+(@NIGHT_ELF,@WARRIOR,84,6603,0),
+(@NIGHT_ELF,@WARRIOR,96,6603,0),
+(@NIGHT_ELF,@WARRIOR,108,6603,0),
+-- Night Elf Hunter
+(@NIGHT_ELF,@HUNTER,0,3044,0),
+(@NIGHT_ELF,@HUNTER,9,58984,0),
+(@NIGHT_ELF,@HUNTER,10,9,48),
+(@NIGHT_ELF,@HUNTER,11,982,0),
+(@NIGHT_ELF,@HUNTER,81,58984,0),
+-- Night Elf Rogue
+(@NIGHT_ELF,@ROGUE,0,1752,0),
+(@NIGHT_ELF,@ROGUE,9,58984,0),
+(@NIGHT_ELF,@ROGUE,81,58984,0),
+-- Night Elf Priest
+(@NIGHT_ELF,@PRIEST,0,585,0),
+(@NIGHT_ELF,@PRIEST,9,58984,0),
+(@NIGHT_ELF,@PRIEST,81,58984,0),
+-- Night Elf Mage
+(@NIGHT_ELF,@MAGE,0,133,0),
+(@NIGHT_ELF,@MAGE,9,58984,0),
+-- Night Elf Druid
+(@NIGHT_ELF,@DRUID,0,5176,0),
+(@NIGHT_ELF,@DRUID,9,58984,0),
+(@NIGHT_ELF,@DRUID,72,6603,0),
+(@NIGHT_ELF,@DRUID,74,58984,0),
+(@NIGHT_ELF,@DRUID,84,6603,0),
+(@NIGHT_ELF,@DRUID,96,6603,0),
+(@NIGHT_ELF,@DRUID,108,6603,0),
+-- Undead:
+-- Undead Warrior
+(@UNDEAD,@WARRIOR,72,88163,0),
+(@UNDEAD,@WARRIOR,73,88161,0),
+(@UNDEAD,@WARRIOR,81,20577,0),
+(@UNDEAD,@WARRIOR,84,6603,0),
+(@UNDEAD,@WARRIOR,96,6603,0),
+(@UNDEAD,@WARRIOR,108,6603,0),
+-- Undead Hunter
+(@UNDEAD,@HUNTER,0,3044,0),
+(@UNDEAD,@HUNTER,9,20577,0),
+(@UNDEAD,@HUNTER,10,9,48),
+(@UNDEAD,@HUNTER,11,982,0),
+-- Undead Rogue
+(@UNDEAD,@ROGUE,0,1752,0),
+(@UNDEAD,@ROGUE,9,20577,0),
+-- Undead Priest
+(@UNDEAD,@PRIEST,0,585,0),
+(@UNDEAD,@PRIEST,9,20577,0),
+-- Undead Mage
+(@UNDEAD,@MAGE,0,133,0),
+(@UNDEAD,@MAGE,9,20577,0),
+-- Undead Warlock
+(@UNDEAD,@WARLOCK,0,686,0),
+(@UNDEAD,@WARLOCK,9,20577,0),
+(@UNDEAD,@WARLOCK,10,10,48),
+-- Tauren:
+-- Tauren Warrior
+(@TAUREN,@WARRIOR,72,88163,0),
+(@TAUREN,@WARRIOR,73,88161,0),
+(@TAUREN,@WARRIOR,81,20549,0),
+(@TAUREN,@WARRIOR,84,6603,0),
+(@TAUREN,@WARRIOR,96,6603,0),
+(@TAUREN,@WARRIOR,108,6603,0),
+-- Tauren Paladin
+(@TAUREN,@PALADIN,0,35395,0),
+(@TAUREN,@PALADIN,9,20549,0),
+-- Tauren Hunter
+(@TAUREN,@HUNTER,0,3044,0),
+(@TAUREN,@HUNTER,9,20549,0),
+(@TAUREN,@HUNTER,10,9,48),
+(@TAUREN,@HUNTER,11,982,0),
+(@TAUREN,@HUNTER,75,20549,0),
+-- Tauren Priest
+(@TAUREN,@PRIEST,0,585,0),
+(@TAUREN,@PRIEST,9,20549,0),
+-- Tauren Shaman
+(@TAUREN,@SHAMAN,0,403,0),
+(@TAUREN,@SHAMAN,9,20549,0),
+(@TAUREN,@SHAMAN,75,20549,0),
+-- Tauren Druid
+(@TAUREN,@DRUID,0,403,0),
+(@TAUREN,@DRUID,9,20549,0),
+(@TAUREN,@DRUID,72,6603,0),
+(@TAUREN,@DRUID,75,20549,0),
+(@TAUREN,@DRUID,84,6603,0),
+(@TAUREN,@DRUID,96,6603,0),
+(@TAUREN,@DRUID,108,6603,0),
+-- Gnome:
+-- Gnome Warrior
+(@GNOME,@WARRIOR,72,88163,0),
+(@GNOME,@WARRIOR,73,88161,0),
+(@GNOME,@WARRIOR,84,6603,0),
+(@GNOME,@WARRIOR,96,6603,0),
+(@GNOME,@WARRIOR,108,6603,0),
+-- Gnome Rogue
+(@GNOME,@ROGUE,0,1752,0),
+-- Gnome Priest
+(@GNOME,@PRIEST,0,585,0),
+-- Gnome Mage
+(@GNOME,@MAGE,0,133,0),
+-- Gnome Warlock
+(@GNOME,@WARLOCK,0,686,0),
+(@GNOME,@WARLOCK,10,10,48),
+-- Troll:
+-- Troll Warrior
+(@TROLL,@WARRIOR,72,88163,0),
+(@TROLL,@WARRIOR,73,88161,0),
+(@TROLL,@WARRIOR,81,26297,0),
+(@TROLL,@WARRIOR,84,6603,0),
+(@TROLL,@WARRIOR,96,6603,0),
+(@TROLL,@WARRIOR,108,6603,0),
+-- Troll Hunter
+(@TROLL,@HUNTER,0,3044,0),
+(@TROLL,@HUNTER,9,26297,0),
+(@TROLL,@HUNTER,10,9,48),
+(@TROLL,@HUNTER,11,982,0),
+-- Troll Rogue
+(@TROLL,@ROGUE,0,1752,0),
+(@TROLL,@ROGUE,9,26297,0),
+(@TROLL,@ROGUE,76,26297,0),
+-- Troll Priest
+(@TROLL,@PRIEST,0,585,0),
+(@TROLL,@PRIEST,9,26297,0),
+-- Troll Shaman
+(@TROLL,@SHAMAN,0,403,0),
+(@TROLL,@SHAMAN,9,26297,0),
+(@TROLL,@SHAMAN,72,403,0),
+-- Troll Mage
+(@TROLL,@MAGE,0,133,0),
+(@TROLL,@MAGE,9,26297,0),
+-- Troll Warlock
+(@TROLL,@WARLOCK,0,686,0),
+(@TROLL,@WARLOCK,9,26297,0),
+(@TROLL,@WARLOCK,10,10,48),
+-- Troll Druid
+(@TROLL,@DRUID,0,5176,0),
+(@TROLL,@DRUID,9,26297,0),
+(@TROLL,@DRUID,72,6603,0),
+(@TROLL,@DRUID,84,6603,0),
+(@TROLL,@DRUID,96,6603,0),
+-- Goblin:
+-- Goblin Warrior
+(@GOBLIN,@WARRIOR,72,88163,0),
+(@GOBLIN,@WARRIOR,73,88161,0),
+(@GOBLIN,@WARRIOR,81,69070,0),
+(@GOBLIN,@WARRIOR,82,69041,0),
+-- Goblin Hunter
+(@GOBLIN,@HUNTER,0,3044,0),
+(@GOBLIN,@HUNTER,8,982,0),
+(@GOBLIN,@HUNTER,9,69070,0),
+(@GOBLIN,@HUNTER,10,69041,0),
+(@GOBLIN,@HUNTER,11,9,48),
+-- Goblin Rogue
+(@GOBLIN,@ROGUE,0,1752,0),
+(@GOBLIN,@ROGUE,9,69070,0),
+(@GOBLIN,@ROGUE,10,69041,0),
+-- Goblin Priest
+(@GOBLIN,@PRIEST,0,585,0),
+(@GOBLIN,@PRIEST,9,69070,0),
+(@GOBLIN,@PRIEST,10,69041,0),
+-- Goblin Shaman
+(@GOBLIN,@SHAMAN,0,403,0),
+(@GOBLIN,@SHAMAN,9,69070,0),
+(@GOBLIN,@SHAMAN,10,69041,0),
+(@GOBLIN,@SHAMAN,72,403,0),
+-- Goblin Mage
+(@GOBLIN,@MAGE,0,133,0),
+(@GOBLIN,@MAGE,9,69070,0),
+(@GOBLIN,@MAGE,10,69041,0),
+-- Goblin Warlock
+(@GOBLIN,@WARLOCK,0,686,0),
+(@GOBLIN,@WARLOCK,9,69070,0),
+(@GOBLIN,@WARLOCK,10,69041,0),
+(@GOBLIN,@WARLOCK,11,10,48),
+-- Blood Elf:
+-- Blood elf Warrior
+(@BLOOD_ELF,@WARRIOR,72,88163,0),
+(@BLOOD_ELF,@WARRIOR,73,88161,0),
+(@BLOOD_ELF,@WARRIOR,81,69179,0),
+-- Blood elf Paladin
+(@BLOOD_ELF,@PALADIN,0,35395,0),
+(@BLOOD_ELF,@PALADIN,9,28730,0),
+-- Blood elf Hunter
+(@BLOOD_ELF,@HUNTER,0,3044,0),
+(@BLOOD_ELF,@HUNTER,9,80483,0),
+(@BLOOD_ELF,@HUNTER,10,9,48),
+(@BLOOD_ELF,@HUNTER,11,982,0),
+-- Blood elf Rogue
+(@BLOOD_ELF,@ROGUE,0,1752,0),
+(@BLOOD_ELF,@ROGUE,9,25046,0),
+-- Blood elf Priest
+(@BLOOD_ELF,@PRIEST,0,585,0),
+(@BLOOD_ELF,@PRIEST,9,28730,0),
+-- Blood elf Mage
+(@BLOOD_ELF,@MAGE,0,133,0),
+(@BLOOD_ELF,@MAGE,9,28730,0),
+-- Blood elf Warlock
+(@BLOOD_ELF,@WARLOCK,0,686,0),
+(@BLOOD_ELF,@WARLOCK,9,28730,0),
+(@BLOOD_ELF,@WARLOCK,10,10,48),
+-- Draenei:
+-- Draenei Warrior
+(@DRAENEI,@WARRIOR,72,88163,0),
+(@DRAENEI,@WARRIOR,73,88161,0),
+(@DRAENEI,@WARRIOR,81,28880,0),
+(@DRAENEI,@WARRIOR,84,6603,0),
+(@DRAENEI,@WARRIOR,96,6603,0),
+(@DRAENEI,@WARRIOR,108,6603,0),
+-- Draenei Paladin
+(@DRAENEI,@PALADIN,0,35395,0),
+(@DRAENEI,@PALADIN,9,59542,0),
+(@DRAENEI,@PALADIN,83,4540,128),
+-- Draenei Hunter
+(@DRAENEI,@HUNTER,0,3044,0),
+(@DRAENEI,@HUNTER,9,59543,0),
+(@DRAENEI,@HUNTER,10,9,48),
+(@DRAENEI,@HUNTER,11,982,0),
+(@DRAENEI,@HUNTER,72,6603,0),
+(@DRAENEI,@HUNTER,74,75,0),
+(@DRAENEI,@HUNTER,82,159,128),
+(@DRAENEI,@HUNTER,83,4540,128),
+-- Draenei Priest
+(@DRAENEI,@PRIEST,0,585,0),
+(@DRAENEI,@PRIEST,9,59544,0),
+(@DRAENEI,@PRIEST,83,4540,128),
+-- Draenei Shaman
+(@DRAENEI,@SHAMAN,0,403,0),
+(@DRAENEI,@SHAMAN,9,59547,0),
+-- Draenei Mage
+(@DRAENEI,@MAGE,0,133,0),
+(@DRAENEI,@MAGE,9,59548,0),
+(@DRAENEI,@MAGE,83,4540,128),
+-- Human Worgen:
+-- Human Worgen Warrior
+(@WORGEN,@WARRIOR,72,88163,0),
+(@WORGEN,@WARRIOR,73,88161,0),
+-- Human Worgen Hunter
+(@WORGEN,@HUNTER,0,3044,0),
+(@WORGEN,@HUNTER,10,9,48),
+(@WORGEN,@HUNTER,11,982,0),
+-- Human Worgen Rogue
+(@WORGEN,@ROGUE,0,1752,0),
+-- Human Worgen Priest
+(@WORGEN,@PRIEST,0,585,0),
+-- Human Worgen Mage
+(@WORGEN,@MAGE,0,133,0),
+-- Human Worgen Warlock
+(@WORGEN,@WARLOCK,0,686,0),
+(@WORGEN,@WARLOCK,10,10,48),
+-- Human Worgen Druid
+(@WORGEN,@DRUID,0,5176,0),
+(@WORGEN,@DRUID,72,6603,0),
+(@WORGEN,@DRUID,84,6603,0),
+(@WORGEN,@DRUID,96,6603,0);
+
+-- Start points of Humans
+DELETE FROM `playercreateinfo` WHERE `race`=@HUMAN;
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@HUMAN,@WARRIOR,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@PALADIN,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@HUNTER,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@ROGUE,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@PRIEST,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@MAGE,0,9,-8914.57,-133.909,80.5378,0),
+(@HUMAN,@WARLOCK,0,9,-8914.57,-133.909,80.5378,0);
+
+-- Start points of Worgen and Goblin
+DELETE FROM `playercreateinfo` WHERE `race` IN (@GOBLIN,@WORGEN,@WORGEN_HUMAN);
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@WORGEN,@WARRIOR,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@HUNTER,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@ROGUE,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@PRIEST,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@MAGE,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@WARLOCK,654,4756,-1451.53,1403.35,35.5561,0),
+(@WORGEN,@DRUID,654,4756,-1451.53,1403.35,35.5561,0),
+(@GOBLIN,@WARRIOR,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@HUNTER,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@ROGUE,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@PRIEST,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@SHAMAN,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@MAGE,648,4765,-8423.81,1361.3,104.671,0),
+(@GOBLIN,@WARLOCK,648,4765,-8423.81,1361.3,104.671,0);
+
+-- Start point of Troll
+DELETE FROM `playercreateinfo` WHERE `race`=@TROLL;
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@TROLL,@WARRIOR,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@HUNTER,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@ROGUE,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@PRIEST,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@SHAMAN,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@MAGE,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@WARLOCK,1,5691,-1171.45,-5263.65,0.847728,0),
+(@TROLL,@DRUID,1,5691,-1171.45,-5263.65,0.847728,0);
+
+-- Start point of Gnome
+DELETE FROM `playercreateinfo` WHERE `race`=@GNOME;
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@GNOME,@WARRIOR,0,5495,-4983.42,877.7,274.31,0),
+(@GNOME,@ROGUE,0,5495,-4983.42,877.7,274.31,0),
+(@GNOME,@PRIEST,0,5495,-4983.42,877.7,274.31,0),
+(@GNOME,@MAGE,0,5495,-4983.42,877.7,274.31,0),
+(@GNOME,@WARLOCK,0,5495,-4983.42,877.7,274.31,0);
+
+-- Start point of Undead
+DELETE FROM `playercreateinfo` WHERE `race`=@UNDEAD;
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@UNDEAD,@WARRIOR,0,5692,1699.85,1706.56,135.928,0),
+(@UNDEAD,@HUNTER,0,5692,1699.85,1706.56,135.928,0),
+(@UNDEAD,@ROGUE,0,5692,1699.85,1706.56,135.928,0),
+(@UNDEAD,@PRIEST,0,5692,1699.85,1706.56,135.928,0),
+(@UNDEAD,@MAGE,0,5692,1699.85,1706.56,135.928,0),
+(@UNDEAD,@WARLOCK,0,5692,1699.85,1706.56,135.928,0);
+
+-- Start point of Tauren
+DELETE FROM `playercreateinfo` WHERE `race`=@TAUREN;
+INSERT INTO `playercreateinfo` (`race`,`class`,`map`,`zone`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
+(@TAUREN,@WARRIOR,1,221,-2915.55,-257.347,59.2693,0),
+(@TAUREN,@PALADIN,1,221,-2915.55,-257.347,59.2693,0),
+(@TAUREN,@HUNTER,1,221,-2915.55,-257.347,59.2693,0),
+(@TAUREN,@PRIEST,1,221,-2915.55,-257.347,59.2693,0),
+(@TAUREN,@SHAMAN,1,221,-2915.55,-257.347,59.2693,0),
+(@TAUREN,@DRUID,1,221,-2915.55,-257.347,59.2693,0);
diff --git a/sql/old/4.2.2/2011_11_26_08_world_creature_template_4x.sql b/sql/old/4.2.2/2011_11_26_08_world_creature_template_4x.sql
new file mode 100644
index 00000000000..b887038b908
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_26_08_world_creature_template_4x.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `creature_template` ADD `exp_unk` SMALLINT(2) NOT NULL DEFAULT '0' AFTER `exp`;
+ALTER TABLE `creature_template` ADD `type_flags2` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `type_flags`;
diff --git a/sql/old/4.2.2/2011_11_27_00_world_player_levelstats_4x.sql b/sql/old/4.2.2/2011_11_27_00_world_player_levelstats_4x.sql
new file mode 100644
index 00000000000..dfecacdaf07
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_27_00_world_player_levelstats_4x.sql
@@ -0,0 +1,66 @@
+-- Races:
+SET @HUMAN := 1;
+SET @ORC := 2;
+SET @DWARF := 3;
+SET @NIGHT_ELF := 4;
+SET @UNDEAD := 5;
+SET @TAUREN := 6;
+SET @GNOME := 7;
+SET @TROLL := 8;
+SET @GOBLIN := 9;
+SET @BLOOD_ELF := 10;
+SET @DRAENEI := 11;
+SET @WORGEN := 22;
+-- Classes:
+SET @WARRIOR := 1;
+SET @PALADIN := 2;
+SET @HUNTER := 3;
+SET @ROGUE := 4;
+SET @PRIEST := 5;
+SET @DK := 6;
+SET @SHAMAN := 7;
+SET @MAGE := 8;
+SET @WARLOCK := 9;
+SET @DRUID := 11;
+
+DELETE FROM `player_levelstats` WHERE
+((`class`=@WARRIOR AND `race` IN (@BLOOD_ELF, @GOBLIN, @WORGEN)) OR
+(`class`=@PALADIN AND `race` IN (@TAUREN)) OR
+(`class`=@HUNTER AND `race` IN (@HUMAN, @GOBLIN, @WORGEN, @UNDEAD)) OR
+(`class`=@ROGUE AND `race` IN (@GOBLIN, @WORGEN)) OR
+(`class`=@PRIEST AND `race` IN (@GNOME, @GOBLIN, @WORGEN, @TAUREN)) OR
+(`class`=@SHAMAN AND `race` IN (@GOBLIN, @DWARF)) OR
+(`class`=@MAGE AND `race` IN (@DWARF, @GOBLIN, @WORGEN, @NIGHT_ELF, @ORC)) OR
+(`class`=@WARLOCK AND `race` IN (@DWARF, @GOBLIN, @WORGEN, @TROLL)) OR
+(`class`=@DRUID AND `race` IN (@WORGEN, @TROLL))) AND `level`=1;
+DELETE FROM `player_levelstats` WHERE `class`=@DK AND `race` IN (@GOBLIN, @WORGEN) AND `level`=55;
+INSERT INTO `player_levelstats` (`class`, `race`, `level`, `str`, `agi`, `sta`, `inte`, `spi`) VALUES
+(@WARRIOR, @BLOOD_ELF, 1, 20, 22, 20, 24, 19),
+(@WARRIOR, @GOBLIN, 1, 20, 22, 22, 23, 18),
+(@WARRIOR, @WORGEN, 1, 26, 22, 22, 16, 19),
+(@PALADIN, @TAUREN, 1, 27, 15, 24, 15, 23),
+(@HUNTER, @HUMAN, 1, 20, 23, 21, 20, 21),
+(@HUNTER, @WORGEN, 1, 23, 25, 21, 16, 20),
+(@HUNTER, @UNDEAD, 1, 19, 21, 22, 18, 26),
+(@HUNTER, @GOBLIN, 1, 17, 25, 21, 23, 19),
+(@ROGUE, @WORGEN, 1, 23, 25, 21, 16, 19),
+(@ROGUE, @GOBLIN, 1, 18, 25, 21, 23, 18),
+(@PRIEST, @GNOME, 1, 15 ,23, 19, 25, 23),
+(@PRIEST, @WORGEN, 1, 23 ,22, 20, 18, 22),
+(@PRIEST, @GOBLIN, 1, 17 ,22, 20, 25, 21),
+(@PRIEST, @TAUREN, 1, 25 ,15, 22, 17, 25),
+(@DK, @WORGEN, 55, 111, 75, 99, 25, 41),
+(@DK, @GOBLIN, 55, 105, 75, 99, 32, 40),
+(@SHAMAN, @DWARF, 1, 22, 16, 23, 22, 21),
+(@SHAMAN, @GOBLIN, 1, 18, 22, 21, 24, 20),
+(@MAGE, @DWARF, 1, 22, 16, 23, 22, 21),
+(@MAGE, @NIGHT_ELF, 1, 17, 25, 19, 23, 22),
+(@MAGE, @WORGEN, 1, 23, 22, 20, 19, 21),
+(@MAGE, @GOBLIN, 1, 17, 22, 20, 26, 20),
+(@MAGE, @ORC, 1, 23, 17, 22, 20, 25),
+(@WARLOCK, @WORGEN, 1, 23, 22, 21, 18, 21),
+(@WARLOCK, @DWARF, 1, 22, 16, 24, 21, 21),
+(@WARLOCK, @GOBLIN, 1, 17, 22, 21, 25, 20),
+(@WARLOCK, @TROLL, 1, 21, 22, 22, 18, 23),
+(@DRUID, @WORGEN, 1, 24, 22, 20, 18, 21),
+(@DRUID, @TROLL, 1, 22, 22, 21, 18, 23);
diff --git a/sql/old/4.2.2/2011_11_28_00_world_gameobject_template_4x.sql b/sql/old/4.2.2/2011_11_28_00_world_gameobject_template_4x.sql
new file mode 100644
index 00000000000..236f6acc6ae
--- /dev/null
+++ b/sql/old/4.2.2/2011_11_28_00_world_gameobject_template_4x.sql
@@ -0,0 +1,9 @@
+ALTER TABLE `gameobject_template` ADD `data24` INT(10) NOT NULL DEFAULT '0' AFTER `data23`;
+ALTER TABLE `gameobject_template` ADD `data25` INT(10) NOT NULL DEFAULT '0' AFTER `data24`;
+ALTER TABLE `gameobject_template` ADD `data26` INT(10) NOT NULL DEFAULT '0' AFTER `data25`;
+ALTER TABLE `gameobject_template` ADD `data27` INT(10) NOT NULL DEFAULT '0' AFTER `data26`;
+ALTER TABLE `gameobject_template` ADD `data28` INT(10) NOT NULL DEFAULT '0' AFTER `data27`;
+ALTER TABLE `gameobject_template` ADD `data29` INT(10) NOT NULL DEFAULT '0' AFTER `data28`;
+ALTER TABLE `gameobject_template` ADD `data30` INT(10) NOT NULL DEFAULT '0' AFTER `data29`;
+ALTER TABLE `gameobject_template` ADD `data31` INT(10) NOT NULL DEFAULT '0' AFTER `data30`;
+ALTER TABLE `gameobject_template` ADD `unkInt32` INT(10) NOT NULL DEFAULT '0' AFTER `data31`; -- Unk size
diff --git a/sql/old/4.2.2/2011_12_18_01_world_player_classlevelstats_4x.sql b/sql/old/4.2.2/2011_12_18_01_world_player_classlevelstats_4x.sql
new file mode 100644
index 00000000000..4c3fc5a0a6e
--- /dev/null
+++ b/sql/old/4.2.2/2011_12_18_01_world_player_classlevelstats_4x.sql
@@ -0,0 +1,64 @@
+-- Classes:
+SET @WARRIOR := 1;
+SET @PALADIN := 2;
+SET @HUNTER := 3;
+SET @ROGUE := 4;
+SET @PRIEST := 5;
+SET @DK := 6;
+SET @SHAMAN := 7;
+SET @MAGE := 8;
+SET @WARLOCK := 9;
+SET @DRUID := 11;
+
+DELETE FROM `player_classlevelstats` WHERE `level` > 80;
+INSERT INTO `player_classlevelstats` VALUES
+(@WARRIOR, 81, 13277, 0),
+(@WARRIOR, 82, 20452, 0),
+(@WARRIOR, 83, 30192, 0),
+(@WARRIOR, 84, 43246, 0),
+(@WARRIOR, 85, 43285, 0),
+(@PALADIN, 81, 13345, 6141),
+(@PALADIN, 82, 19988, 8582),
+(@PALADIN, 83, 29668, 11993),
+(@PALADIN, 84, 42350, 16760),
+(@PALADIN, 85, 43285, 23422),
+(@HUNTER, 81, 12023, 0),
+(@HUNTER, 82, 18274, 0),
+(@HUNTER, 83, 27383, 0),
+(@HUNTER, 84, 39079, 0),
+(@HUNTER, 85, 39037, 0),
+(@ROGUE, 81, 12482, 0),
+(@ROGUE, 82, 18731, 0),
+(@ROGUE, 83, 28085, 0),
+(@ROGUE, 84, 39984, 0),
+(@ROGUE, 85, 40529, 0),
+(@PRIEST, 81, 11883, 5398),
+(@PRIEST, 82, 18588, 7544),
+(@PRIEST, 83, 28079, 10543),
+(@PRIEST, 84, 40612, 14734),
+(@PRIEST, 85, 43285, 20590),
+(@DK, 81, 13441, 0),
+(@DK, 82, 20013, 0),
+(@DK, 83, 29493, 0),
+(@DK, 84, 42087, 0),
+(@DK, 85, 43285, 0),
+(@SHAMAN, 81, 11595, 6143),
+(@SHAMAN, 82, 17655, 8585),
+(@SHAMAN, 83, 25662, 11997),
+(@SHAMAN, 84, 37192, 16766),
+(@SHAMAN, 85, 37097, 23430),
+(@MAGE, 81, 11659, 4567),
+(@MAGE, 82, 17508, 6382),
+(@MAGE, 83, 26172, 8919),
+(@MAGE, 84, 37638, 12464),
+(@MAGE, 85, 37113, 17418),
+(@WARLOCK, 81, 12080, 5389),
+(@WARLOCK, 82, 18408, 7531),
+(@WARLOCK, 83, 26948, 10524),
+(@WARLOCK, 84, 39580, 14707),
+(@WARLOCK, 85, 38184, 20553),
+(@DRUID, 81, 12301, 4886),
+(@DRUID, 82, 18477, 6828),
+(@DRUID, 83, 26487, 9542),
+(@DRUID, 84, 38865, 13335),
+(@DRUID, 85, 39533, 21751);
diff --git a/sql/old/4.2.2/2011_12_18_02_world_player_levelstats_4x.sql b/sql/old/4.2.2/2011_12_18_02_world_player_levelstats_4x.sql
new file mode 100644
index 00000000000..ff8456cba84
--- /dev/null
+++ b/sql/old/4.2.2/2011_12_18_02_world_player_levelstats_4x.sql
@@ -0,0 +1,1920 @@
+-- Races:
+SET @HUMAN := 1;
+SET @ORC := 2;
+SET @DWARF := 3;
+SET @NIGHT_ELF := 4;
+SET @UNDEAD := 5;
+SET @TAUREN := 6;
+SET @GNOME := 7;
+SET @TROLL := 8;
+SET @GOBLIN := 9;
+SET @BLOOD_ELF := 10;
+SET @DRAENEI := 11;
+SET @WORGEN := 22;
+-- Classes:
+SET @WARRIOR := 1;
+SET @PALADIN := 2;
+SET @HUNTER := 3;
+SET @ROGUE := 4;
+SET @PRIEST := 5;
+SET @DK := 6;
+SET @SHAMAN := 7;
+SET @MAGE := 8;
+SET @WARLOCK := 9;
+SET @DRUID := 11;
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@HUMAN;
+INSERT INTO `player_levelstats` VALUES
+(@HUMAN, @WARRIOR, 81, 177, 115, 161, 36, 60),
+(@HUMAN, @WARRIOR, 82, 189, 117, 164, 36, 60),
+(@HUMAN, @WARRIOR, 83, 192, 119, 167, 36, 61),
+(@HUMAN, @WARRIOR, 84, 195, 121, 170, 37, 62),
+(@HUMAN, @WARRIOR, 85, 198, 123, 173, 37, 63),
+(@HUMAN, @PALADIN, 81, 160, 91, 146, 99, 107),
+(@HUMAN, @PALADIN, 82, 163, 93, 148, 101, 108),
+(@HUMAN, @PALADIN, 83, 166, 94, 151, 102, 110),
+(@HUMAN, @PALADIN, 84, 170, 96, 153, 104, 112),
+(@HUMAN, @PALADIN, 85, 172, 97, 156, 106, 114),
+(@HUMAN, @HUNTER, 81, 75, 194, 130, 91, 99),
+(@HUMAN, @HUNTER, 82, 77, 197, 133, 93, 100),
+(@HUMAN, @HUNTER, 83, 78, 200, 135, 94, 102),
+(@HUMAN, @HUNTER, 84, 79, 204, 137, 96, 103),
+(@HUMAN, @HUNTER, 85, 80, 208, 139, 97, 105),
+(@HUMAN, @ROGUE, 81, 114, 202, 107, 44, 68),
+(@HUMAN, @ROGUE, 82, 116, 205, 108, 44, 68),
+(@HUMAN, @ROGUE, 83, 118, 209, 110, 45, 69),
+(@HUMAN, @ROGUE, 84, 120, 213, 112, 45, 70),
+(@HUMAN, @ROGUE, 85, 122, 216, 114, 46, 71),
+(@HUMAN, @PRIEST, 81, 44, 52, 68, 185, 185),
+(@HUMAN, @PRIEST, 82, 44, 52, 68, 189, 188),
+(@HUMAN, @PRIEST, 83, 45, 53, 69, 193, 191),
+(@HUMAN, @PRIEST, 84, 45, 54, 70, 196, 195),
+(@HUMAN, @PRIEST, 85, 46, 54, 71, 199, 198),
+(@HUMAN, @DK, 81, 178, 114, 163, 35, 60),
+(@HUMAN, @DK, 82, 178, 116, 165, 36, 60),
+(@HUMAN, @DK, 83, 185, 118, 168, 36, 61),
+(@HUMAN, @DK, 84, 185, 120, 171, 36, 62),
+(@HUMAN, @DK, 85, 191, 121, 174, 36, 63),
+(@HUMAN, @SHAMAN, 81, 122, 75, 138, 136, 146),
+(@HUMAN, @SHAMAN, 82, 124, 77, 141, 139, 148),
+(@HUMAN, @SHAMAN, 83, 127, 78, 143, 139, 151),
+(@HUMAN, @SHAMAN, 84, 129, 79, 145, 139, 153),
+(@HUMAN, @SHAMAN, 85, 131, 80, 148, 145, 156),
+(@HUMAN, @MAGE, 81, 36, 44, 60, 194, 177),
+(@HUMAN, @MAGE, 82, 36, 44, 60, 197, 180),
+(@HUMAN, @MAGE, 83, 36, 45, 61, 200, 184),
+(@HUMAN, @MAGE, 84, 37, 45, 62, 204, 187),
+(@HUMAN, @MAGE, 85, 37, 46, 63, 207, 190),
+(@HUMAN, @WARLOCK, 81, 60, 68, 91, 169, 169),
+(@HUMAN, @WARLOCK, 82, 60, 68, 92, 172, 172),
+(@HUMAN, @WARLOCK, 83, 61, 69, 94, 175, 175),
+(@HUMAN, @WARLOCK, 84, 62, 70, 95, 178, 178),
+(@HUMAN, @WARLOCK, 85, 63, 71, 96, 181, 181),
+(@HUMAN, @DRUID, 81, 91, 83, 99, 146, 161),
+(@HUMAN, @DRUID, 82, 92, 85, 101, 148, 164),
+(@HUMAN, @DRUID, 83, 94, 86, 102, 151, 167),
+(@HUMAN, @DRUID, 84, 95, 87, 104, 160, 170),
+(@HUMAN, @DRUID, 85, 96, 89, 106, 160, 173);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@ORC;
+INSERT INTO `player_levelstats` VALUES
+(@ORC, @WARRIOR, 81, 180, 112, 162, 33, 62),
+(@ORC, @WARRIOR, 82, 192, 114, 165, 33, 62),
+(@ORC, @WARRIOR, 83, 195, 116, 168, 33, 63),
+(@ORC, @WARRIOR, 84, 198, 118, 171, 34, 64),
+(@ORC, @WARRIOR, 85, 201, 120, 174, 34, 65),
+(@ORC, @PALADIN, 81, 163, 88, 147, 96, 109),
+(@ORC, @PALADIN, 82, 166, 90, 149, 98, 110),
+(@ORC, @PALADIN, 83, 169, 91, 152, 99, 112),
+(@ORC, @PALADIN, 84, 173, 93, 154, 101, 114),
+(@ORC, @PALADIN, 85, 175, 94, 157, 103, 116),
+(@ORC, @HUNTER, 81, 78, 191, 131, 88, 101),
+(@ORC, @HUNTER, 82, 80, 194, 134, 90, 102),
+(@ORC, @HUNTER, 83, 81, 197, 136, 91, 104),
+(@ORC, @HUNTER, 84, 82, 201, 138, 93, 105),
+(@ORC, @HUNTER, 85, 83, 205, 140, 94, 107),
+(@ORC, @ROGUE, 81, 117, 199, 108, 41, 70),
+(@ORC, @ROGUE, 82, 119, 202, 109, 41, 70),
+(@ORC, @ROGUE, 83, 121, 206, 111, 42, 71),
+(@ORC, @ROGUE, 84, 123, 210, 113, 42, 72),
+(@ORC, @ROGUE, 85, 125, 213, 115, 43, 73),
+(@ORC, @PRIEST, 81, 47, 49, 69, 182, 187),
+(@ORC, @PRIEST, 82, 47, 49, 69, 186, 190),
+(@ORC, @PRIEST, 83, 48, 50, 70, 190, 193),
+(@ORC, @PRIEST, 84, 48, 51, 71, 193, 197),
+(@ORC, @PRIEST, 85, 49, 51, 72, 196, 200),
+(@ORC, @DK, 81, 181, 111, 164, 32, 62),
+(@ORC, @DK, 82, 181, 113, 166, 33, 62),
+(@ORC, @DK, 83, 188, 115, 169, 33, 63),
+(@ORC, @DK, 84, 188, 117, 172, 33, 64),
+(@ORC, @DK, 85, 194, 118, 175, 33, 65),
+(@ORC, @SHAMAN, 81, 125, 72, 139, 133, 148),
+(@ORC, @SHAMAN, 82, 127, 74, 142, 136, 150),
+(@ORC, @SHAMAN, 83, 130, 75, 144, 136, 153),
+(@ORC, @SHAMAN, 84, 132, 76, 146, 136, 155),
+(@ORC, @SHAMAN, 85, 134, 77, 149, 142, 158),
+(@ORC, @MAGE, 81, 39, 41, 61, 191, 179),
+(@ORC, @MAGE, 82, 39, 41, 61, 194, 182),
+(@ORC, @MAGE, 83, 39, 42, 62, 197, 186),
+(@ORC, @MAGE, 84, 40, 42, 63, 201, 189),
+(@ORC, @MAGE, 85, 40, 43, 64, 204, 192),
+(@ORC, @WARLOCK, 81, 63, 65, 92, 166, 171),
+(@ORC, @WARLOCK, 82, 63, 65, 93, 169, 174),
+(@ORC, @WARLOCK, 83, 64, 66, 95, 172, 177),
+(@ORC, @WARLOCK, 84, 65, 67, 96, 175, 180),
+(@ORC, @WARLOCK, 85, 66, 68, 97, 178, 183),
+(@ORC, @DRUID, 81, 94, 80, 100, 143, 163),
+(@ORC, @DRUID, 82, 95, 82, 102, 145, 166),
+(@ORC, @DRUID, 83, 97, 83, 103, 148, 169),
+(@ORC, @DRUID, 84, 98, 84, 105, 157, 172),
+(@ORC, @DRUID, 85, 99, 86, 107, 157, 175);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@DWARF;
+INSERT INTO `player_levelstats` VALUES
+(@DWARF, @WARRIOR, 81, 182, 111, 162, 35, 59),
+(@DWARF, @WARRIOR, 82, 194, 113, 165, 35, 59),
+(@DWARF, @WARRIOR, 83, 197, 115, 168, 35, 60),
+(@DWARF, @WARRIOR, 84, 200, 117, 171, 36, 61),
+(@DWARF, @WARRIOR, 85, 203, 119, 174, 36, 62),
+(@DWARF, @PALADIN, 81, 165, 87, 147, 98, 106),
+(@DWARF, @PALADIN, 82, 168, 89, 149, 100, 107),
+(@DWARF, @PALADIN, 83, 171, 90, 152, 101, 109),
+(@DWARF, @PALADIN, 84, 175, 92, 154, 103, 111),
+(@DWARF, @PALADIN, 85, 177, 93, 157, 105, 113),
+(@DWARF, @HUNTER, 81, 80, 190, 131, 90, 98),
+(@DWARF, @HUNTER, 82, 82, 193, 134, 92, 99),
+(@DWARF, @HUNTER, 83, 83, 196, 136, 93, 101),
+(@DWARF, @HUNTER, 84, 84, 200, 138, 95, 102),
+(@DWARF, @HUNTER, 85, 85, 204, 140, 96, 104),
+(@DWARF, @ROGUE, 81, 119, 198, 108, 43, 67),
+(@DWARF, @ROGUE, 82, 121, 201, 109, 43, 67),
+(@DWARF, @ROGUE, 83, 123, 205, 111, 44, 68),
+(@DWARF, @ROGUE, 84, 125, 209, 113, 44, 69),
+(@DWARF, @ROGUE, 85, 127, 212, 115, 45, 70),
+(@DWARF, @PRIEST, 81, 49, 48, 69, 184, 184),
+(@DWARF, @PRIEST, 82, 49, 48, 69, 188, 187),
+(@DWARF, @PRIEST, 83, 50, 49, 70, 192, 190),
+(@DWARF, @PRIEST, 84, 50, 50, 71, 195, 194),
+(@DWARF, @PRIEST, 85, 51, 50, 72, 198, 197),
+(@DWARF, @DK, 81, 183, 110, 164, 34, 59),
+(@DWARF, @DK, 82, 183, 112, 166, 35, 59),
+(@DWARF, @DK, 83, 190, 114, 169, 35, 60),
+(@DWARF, @DK, 84, 190, 116, 172, 35, 61),
+(@DWARF, @DK, 85, 196, 117, 175, 35, 62),
+(@DWARF, @SHAMAN, 81, 127, 71, 139, 135, 145),
+(@DWARF, @SHAMAN, 82, 129, 73, 142, 138, 147),
+(@DWARF, @SHAMAN, 83, 132, 74, 144, 138, 150),
+(@DWARF, @SHAMAN, 84, 134, 75, 146, 138, 152),
+(@DWARF, @SHAMAN, 85, 136, 76, 149, 144, 155),
+(@DWARF, @MAGE, 81, 41, 40, 61, 193, 176),
+(@DWARF, @MAGE, 82, 41, 40, 61, 196, 179),
+(@DWARF, @MAGE, 83, 41, 41, 62, 199, 183),
+(@DWARF, @MAGE, 84, 42, 41, 63, 203, 186),
+(@DWARF, @MAGE, 85, 42, 42, 64, 206, 189),
+(@DWARF, @WARLOCK, 81, 65, 64, 92, 168, 168),
+(@DWARF, @WARLOCK, 82, 65, 64, 93, 171, 171),
+(@DWARF, @WARLOCK, 83, 66, 65, 95, 174, 174),
+(@DWARF, @WARLOCK, 84, 67, 66, 96, 177, 177),
+(@DWARF, @WARLOCK, 85, 68, 67, 97, 180, 180),
+(@DWARF, @DRUID, 81, 96, 79, 100, 145, 160),
+(@DWARF, @DRUID, 82, 97, 81, 102, 147, 163),
+(@DWARF, @DRUID, 83, 99, 82, 103, 150, 166),
+(@DWARF, @DRUID, 84, 100, 83, 105, 159, 169),
+(@DWARF, @DRUID, 85, 101, 85, 107, 159, 172);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@NIGHT_ELF;
+INSERT INTO `player_levelstats` VALUES
+(@NIGHT_ELF, @WARRIOR, 81, 173, 119, 161, 36, 60),
+(@NIGHT_ELF, @WARRIOR, 82, 185, 121, 164, 36, 60),
+(@NIGHT_ELF, @WARRIOR, 83, 188, 123, 167, 36, 61),
+(@NIGHT_ELF, @WARRIOR, 84, 191, 125, 170, 37, 62),
+(@NIGHT_ELF, @WARRIOR, 85, 194, 127, 173, 37, 63),
+(@NIGHT_ELF, @PALADIN, 81, 156, 95, 146, 99, 107),
+(@NIGHT_ELF, @PALADIN, 82, 159, 97, 148, 101, 108),
+(@NIGHT_ELF, @PALADIN, 83, 162, 98, 151, 102, 110),
+(@NIGHT_ELF, @PALADIN, 84, 166, 100, 153, 104, 112),
+(@NIGHT_ELF, @PALADIN, 85, 168, 101, 156, 106, 114),
+(@NIGHT_ELF, @HUNTER, 81, 71, 198, 130, 91, 99),
+(@NIGHT_ELF, @HUNTER, 82, 73, 201, 133, 93, 100),
+(@NIGHT_ELF, @HUNTER, 83, 74, 204, 135, 94, 102),
+(@NIGHT_ELF, @HUNTER, 84, 75, 208, 137, 96, 103),
+(@NIGHT_ELF, @HUNTER, 85, 76, 212, 139, 97, 105),
+(@NIGHT_ELF, @ROGUE, 81, 110, 206, 107, 44, 68),
+(@NIGHT_ELF, @ROGUE, 82, 112, 209, 108, 44, 68),
+(@NIGHT_ELF, @ROGUE, 83, 114, 213, 110, 45, 69),
+(@NIGHT_ELF, @ROGUE, 84, 116, 217, 112, 45, 70),
+(@NIGHT_ELF, @ROGUE, 85, 118, 220, 114, 46, 71),
+(@NIGHT_ELF, @PRIEST, 81, 40, 56, 68, 185, 185),
+(@NIGHT_ELF, @PRIEST, 82, 40, 56, 68, 189, 188),
+(@NIGHT_ELF, @PRIEST, 83, 41, 57, 69, 193, 191),
+(@NIGHT_ELF, @PRIEST, 84, 41, 58, 70, 196, 195),
+(@NIGHT_ELF, @PRIEST, 85, 42, 58, 71, 199, 198),
+(@NIGHT_ELF, @DK, 81, 174, 118, 163, 35, 60),
+(@NIGHT_ELF, @DK, 82, 174, 120, 165, 36, 60),
+(@NIGHT_ELF, @DK, 83, 181, 122, 168, 36, 61),
+(@NIGHT_ELF, @DK, 84, 181, 124, 171, 36, 62),
+(@NIGHT_ELF, @DK, 85, 187, 125, 174, 36, 63),
+(@NIGHT_ELF, @SHAMAN, 81, 118, 79, 138, 136, 146),
+(@NIGHT_ELF, @SHAMAN, 82, 120, 81, 141, 139, 148),
+(@NIGHT_ELF, @SHAMAN, 83, 123, 82, 143, 139, 151),
+(@NIGHT_ELF, @SHAMAN, 84, 125, 83, 145, 139, 153),
+(@NIGHT_ELF, @SHAMAN, 85, 127, 84, 148, 145, 156),
+(@NIGHT_ELF, @MAGE, 81, 32, 48, 60, 194, 177),
+(@NIGHT_ELF, @MAGE, 82, 32, 48, 60, 197, 180),
+(@NIGHT_ELF, @MAGE, 83, 32, 49, 61, 200, 184),
+(@NIGHT_ELF, @MAGE, 84, 33, 49, 62, 204, 187),
+(@NIGHT_ELF, @MAGE, 85, 33, 50, 63, 207, 190),
+(@NIGHT_ELF, @WARLOCK, 81, 56, 72, 91, 169, 169),
+(@NIGHT_ELF, @WARLOCK, 82, 56, 72, 92, 172, 172),
+(@NIGHT_ELF, @WARLOCK, 83, 57, 73, 94, 175, 175),
+(@NIGHT_ELF, @WARLOCK, 84, 58, 74, 95, 178, 178),
+(@NIGHT_ELF, @WARLOCK, 85, 59, 75, 96, 181, 181),
+(@NIGHT_ELF, @DRUID, 81, 87, 87, 99, 146, 161),
+(@NIGHT_ELF, @DRUID, 82, 88, 89, 101, 148, 164),
+(@NIGHT_ELF, @DRUID, 83, 90, 90, 102, 151, 167),
+(@NIGHT_ELF, @DRUID, 84, 91, 91, 104, 160, 170),
+(@NIGHT_ELF, @DRUID, 85, 92, 93, 106, 160, 173);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@UNDEAD;
+INSERT INTO `player_levelstats` VALUES
+(@UNDEAD, @WARRIOR, 81, 176, 113, 161, 34, 65),
+(@UNDEAD, @WARRIOR, 82, 188, 115, 164, 34, 65),
+(@UNDEAD, @WARRIOR, 83, 191, 117, 167, 34, 66),
+(@UNDEAD, @WARRIOR, 84, 194, 119, 170, 35, 67),
+(@UNDEAD, @WARRIOR, 85, 197, 121, 173, 35, 68),
+(@UNDEAD, @PALADIN, 81, 159, 89, 146, 97, 112),
+(@UNDEAD, @PALADIN, 82, 162, 91, 148, 99, 113),
+(@UNDEAD, @PALADIN, 83, 165, 92, 151, 100, 115),
+(@UNDEAD, @PALADIN, 84, 169, 94, 153, 102, 117),
+(@UNDEAD, @PALADIN, 85, 171, 95, 156, 104, 119),
+(@UNDEAD, @HUNTER, 81, 74, 192, 130, 89, 104),
+(@UNDEAD, @HUNTER, 82, 76, 195, 133, 91, 105),
+(@UNDEAD, @HUNTER, 83, 77, 198, 135, 92, 107),
+(@UNDEAD, @HUNTER, 84, 78, 202, 137, 94, 108),
+(@UNDEAD, @HUNTER, 85, 79, 206, 139, 95, 110),
+(@UNDEAD, @ROGUE, 81, 113, 200, 107, 42, 73),
+(@UNDEAD, @ROGUE, 82, 115, 203, 108, 42, 73),
+(@UNDEAD, @ROGUE, 83, 117, 207, 110, 43, 74),
+(@UNDEAD, @ROGUE, 84, 119, 211, 112, 43, 75),
+(@UNDEAD, @ROGUE, 85, 121, 214, 114, 44, 76),
+(@UNDEAD, @PRIEST, 81, 43, 50, 68, 183, 190),
+(@UNDEAD, @PRIEST, 82, 43, 50, 68, 187, 193),
+(@UNDEAD, @PRIEST, 83, 44, 51, 69, 191, 196),
+(@UNDEAD, @PRIEST, 84, 44, 52, 70, 194, 200),
+(@UNDEAD, @PRIEST, 85, 45, 52, 71, 197, 203),
+(@UNDEAD, @DK, 81, 177, 112, 163, 33, 65),
+(@UNDEAD, @DK, 82, 177, 114, 165, 34, 65),
+(@UNDEAD, @DK, 83, 184, 116, 168, 34, 66),
+(@UNDEAD, @DK, 84, 184, 118, 171, 34, 67),
+(@UNDEAD, @DK, 85, 190, 119, 174, 34, 68),
+(@UNDEAD, @SHAMAN, 81, 121, 73, 138, 134, 151),
+(@UNDEAD, @SHAMAN, 82, 123, 75, 141, 137, 153),
+(@UNDEAD, @SHAMAN, 83, 126, 76, 143, 137, 156),
+(@UNDEAD, @SHAMAN, 84, 128, 77, 145, 137, 158),
+(@UNDEAD, @SHAMAN, 85, 130, 78, 148, 143, 161),
+(@UNDEAD, @MAGE, 81, 35, 42, 60, 192, 182),
+(@UNDEAD, @MAGE, 82, 35, 42, 60, 195, 185),
+(@UNDEAD, @MAGE, 83, 35, 43, 61, 198, 189),
+(@UNDEAD, @MAGE, 84, 36, 43, 62, 202, 192),
+(@UNDEAD, @MAGE, 85, 36, 44, 63, 205, 195),
+(@UNDEAD, @WARLOCK, 81, 59, 66, 91, 167, 174),
+(@UNDEAD, @WARLOCK, 82, 59, 66, 92, 170, 177),
+(@UNDEAD, @WARLOCK, 83, 60, 67, 94, 173, 180),
+(@UNDEAD, @WARLOCK, 84, 61, 68, 95, 176, 183),
+(@UNDEAD, @WARLOCK, 85, 62, 69, 96, 179, 186),
+(@UNDEAD, @DRUID, 81, 90, 81, 99, 144, 166),
+(@UNDEAD, @DRUID, 82, 91, 83, 101, 146, 169),
+(@UNDEAD, @DRUID, 83, 93, 84, 102, 149, 172),
+(@UNDEAD, @DRUID, 84, 94, 85, 104, 158, 175),
+(@UNDEAD, @DRUID, 85, 95, 87, 106, 158, 178);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@TAUREN;
+INSERT INTO `player_levelstats` VALUES
+(@TAUREN, @WARRIOR, 81, 182, 111, 162, 32, 62),
+(@TAUREN, @WARRIOR, 82, 194, 113, 165, 32, 62),
+(@TAUREN, @WARRIOR, 83, 197, 115, 168, 32, 63),
+(@TAUREN, @WARRIOR, 84, 200, 117, 171, 33, 64),
+(@TAUREN, @WARRIOR, 85, 203, 119, 174, 33, 65),
+(@TAUREN, @PALADIN, 81, 165, 87, 147, 95, 109),
+(@TAUREN, @PALADIN, 82, 168, 89, 149, 97, 110),
+(@TAUREN, @PALADIN, 83, 171, 90, 152, 98, 112),
+(@TAUREN, @PALADIN, 84, 175, 92, 154, 100, 114),
+(@TAUREN, @PALADIN, 85, 177, 93, 157, 102, 116),
+(@TAUREN, @HUNTER, 81, 80, 190, 131, 87, 101),
+(@TAUREN, @HUNTER, 82, 82, 193, 134, 89, 102),
+(@TAUREN, @HUNTER, 83, 83, 196, 136, 90, 104),
+(@TAUREN, @HUNTER, 84, 84, 200, 138, 92, 105),
+(@TAUREN, @HUNTER, 85, 85, 204, 140, 93, 107),
+(@TAUREN, @ROGUE, 81, 119, 198, 108, 40, 70),
+(@TAUREN, @ROGUE, 82, 121, 201, 109, 40, 70),
+(@TAUREN, @ROGUE, 83, 123, 205, 111, 41, 71),
+(@TAUREN, @ROGUE, 84, 125, 209, 113, 41, 72),
+(@TAUREN, @ROGUE, 85, 127, 212, 115, 42, 73),
+(@TAUREN, @PRIEST, 81, 49, 48, 69, 181, 187),
+(@TAUREN, @PRIEST, 82, 49, 48, 69, 185, 190),
+(@TAUREN, @PRIEST, 83, 50, 49, 70, 189, 193),
+(@TAUREN, @PRIEST, 84, 50, 50, 71, 192, 197),
+(@TAUREN, @PRIEST, 85, 51, 50, 72, 195, 200),
+(@TAUREN, @DK, 81, 183, 110, 164, 31, 62),
+(@TAUREN, @DK, 82, 183, 112, 166, 32, 62),
+(@TAUREN, @DK, 83, 190, 114, 169, 32, 63),
+(@TAUREN, @DK, 84, 190, 116, 172, 32, 64),
+(@TAUREN, @DK, 85, 196, 117, 175, 32, 65),
+(@TAUREN, @SHAMAN, 81, 127, 71, 139, 132, 148),
+(@TAUREN, @SHAMAN, 82, 129, 73, 142, 135, 150),
+(@TAUREN, @SHAMAN, 83, 132, 74, 144, 135, 153),
+(@TAUREN, @SHAMAN, 84, 134, 75, 146, 135, 155),
+(@TAUREN, @SHAMAN, 85, 136, 76, 149, 141, 158),
+(@TAUREN, @MAGE, 81, 41, 40, 61, 190, 179),
+(@TAUREN, @MAGE, 82, 41, 40, 61, 193, 182),
+(@TAUREN, @MAGE, 83, 41, 41, 62, 196, 186),
+(@TAUREN, @MAGE, 84, 42, 41, 63, 200, 189),
+(@TAUREN, @MAGE, 85, 42, 42, 64, 203, 192),
+(@TAUREN, @WARLOCK, 81, 65, 64, 92, 165, 171),
+(@TAUREN, @WARLOCK, 82, 65, 64, 93, 168, 174),
+(@TAUREN, @WARLOCK, 83, 66, 65, 95, 171, 177),
+(@TAUREN, @WARLOCK, 84, 67, 66, 96, 174, 180),
+(@TAUREN, @WARLOCK, 85, 68, 67, 97, 177, 183),
+(@TAUREN, @DRUID, 81, 96, 79, 100, 142, 163),
+(@TAUREN, @DRUID, 82, 97, 81, 102, 144, 166),
+(@TAUREN, @DRUID, 83, 99, 82, 103, 147, 169),
+(@TAUREN, @DRUID, 84, 100, 83, 105, 156, 172),
+(@TAUREN, @DRUID, 85, 101, 85, 107, 156, 175);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@GNOME;
+INSERT INTO `player_levelstats` VALUES
+(@GNOME, @WARRIOR, 81, 172, 117, 161, 39, 60),
+(@GNOME, @WARRIOR, 82, 184, 119, 164, 39, 60),
+(@GNOME, @WARRIOR, 83, 187, 121, 167, 39, 61),
+(@GNOME, @WARRIOR, 84, 190, 123, 170, 40, 62),
+(@GNOME, @WARRIOR, 85, 193, 125, 173, 40, 63),
+(@GNOME, @PALADIN, 81, 155, 93, 146, 102, 107),
+(@GNOME, @PALADIN, 82, 158, 95, 148, 104, 108),
+(@GNOME, @PALADIN, 83, 161, 96, 151, 105, 110),
+(@GNOME, @PALADIN, 84, 165, 98, 153, 107, 112),
+(@GNOME, @PALADIN, 85, 167, 99, 156, 109, 114),
+(@GNOME, @HUNTER, 81, 70, 196, 130, 94, 99),
+(@GNOME, @HUNTER, 82, 72, 199, 133, 96, 100),
+(@GNOME, @HUNTER, 83, 73, 202, 135, 97, 102),
+(@GNOME, @HUNTER, 84, 74, 206, 137, 99, 103),
+(@GNOME, @HUNTER, 85, 75, 210, 139, 100, 105),
+(@GNOME, @ROGUE, 81, 109, 204, 107, 47, 68),
+(@GNOME, @ROGUE, 82, 111, 207, 108, 47, 68),
+(@GNOME, @ROGUE, 83, 113, 211, 110, 48, 69),
+(@GNOME, @ROGUE, 84, 115, 215, 112, 48, 70),
+(@GNOME, @ROGUE, 85, 117, 218, 114, 49, 71),
+(@GNOME, @PRIEST, 81, 39, 54, 68, 188, 185),
+(@GNOME, @PRIEST, 82, 39, 54, 68, 192, 188),
+(@GNOME, @PRIEST, 83, 40, 55, 69, 196, 191),
+(@GNOME, @PRIEST, 84, 40, 56, 70, 199, 195),
+(@GNOME, @PRIEST, 85, 41, 56, 71, 202, 198),
+(@GNOME, @DK, 81, 173, 116, 163, 38, 60),
+(@GNOME, @DK, 82, 173, 118, 165, 39, 60),
+(@GNOME, @DK, 83, 180, 120, 168, 39, 61),
+(@GNOME, @DK, 84, 180, 122, 171, 39, 62),
+(@GNOME, @DK, 85, 186, 123, 174, 39, 63),
+(@GNOME, @SHAMAN, 81, 117, 77, 138, 139, 146),
+(@GNOME, @SHAMAN, 82, 119, 79, 141, 142, 148),
+(@GNOME, @SHAMAN, 83, 122, 80, 143, 142, 151),
+(@GNOME, @SHAMAN, 84, 124, 81, 145, 142, 153),
+(@GNOME, @SHAMAN, 85, 126, 82, 148, 148, 156),
+(@GNOME, @MAGE, 81, 31, 46, 60, 197, 177),
+(@GNOME, @MAGE, 82, 31, 46, 60, 200, 180),
+(@GNOME, @MAGE, 83, 31, 47, 61, 203, 184),
+(@GNOME, @MAGE, 84, 32, 47, 62, 207, 187),
+(@GNOME, @MAGE, 85, 32, 48, 63, 210, 190),
+(@GNOME, @WARLOCK, 81, 55, 70, 91, 172, 169),
+(@GNOME, @WARLOCK, 82, 55, 70, 92, 175, 172),
+(@GNOME, @WARLOCK, 83, 56, 71, 94, 178, 175),
+(@GNOME, @WARLOCK, 84, 57, 72, 95, 181, 178),
+(@GNOME, @WARLOCK, 85, 58, 73, 96, 184, 181),
+(@GNOME, @DRUID, 81, 86, 85, 99, 149, 161),
+(@GNOME, @DRUID, 82, 87, 87, 101, 151, 164),
+(@GNOME, @DRUID, 83, 89, 88, 102, 154, 167),
+(@GNOME, @DRUID, 84, 90, 89, 104, 163, 170),
+(@GNOME, @DRUID, 85, 91, 91, 106, 163, 173);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@TROLL;
+INSERT INTO `player_levelstats` VALUES
+(@TROLL, @WARRIOR, 81, 178, 117, 161, 32, 61),
+(@TROLL, @WARRIOR, 82, 190, 119, 164, 32, 61),
+(@TROLL, @WARRIOR, 83, 193, 121, 167, 32, 62),
+(@TROLL, @WARRIOR, 84, 196, 123, 170, 33, 63),
+(@TROLL, @WARRIOR, 85, 199, 125, 173, 33, 64),
+(@TROLL, @PALADIN, 81, 161, 93, 146, 95, 108),
+(@TROLL, @PALADIN, 82, 164, 95, 148, 97, 109),
+(@TROLL, @PALADIN, 83, 167, 96, 151, 98, 111),
+(@TROLL, @PALADIN, 84, 171, 98, 153, 100, 113),
+(@TROLL, @PALADIN, 85, 173, 99, 156, 102, 115),
+(@TROLL, @HUNTER, 81, 76, 196, 130, 87, 100),
+(@TROLL, @HUNTER, 82, 78, 199, 133, 89, 101),
+(@TROLL, @HUNTER, 83, 79, 202, 135, 90, 103),
+(@TROLL, @HUNTER, 84, 80, 206, 137, 92, 104),
+(@TROLL, @HUNTER, 85, 81, 210, 139, 93, 106),
+(@TROLL, @ROGUE, 81, 115, 204, 107, 40, 69),
+(@TROLL, @ROGUE, 82, 117, 207, 108, 40, 69),
+(@TROLL, @ROGUE, 83, 119, 211, 110, 41, 70),
+(@TROLL, @ROGUE, 84, 121, 215, 112, 41, 71),
+(@TROLL, @ROGUE, 85, 123, 218, 114, 42, 72),
+(@TROLL, @PRIEST, 81, 45, 54, 68, 181, 186),
+(@TROLL, @PRIEST, 82, 45, 54, 68, 185, 189),
+(@TROLL, @PRIEST, 83, 46, 55, 69, 189, 192),
+(@TROLL, @PRIEST, 84, 46, 56, 70, 192, 196),
+(@TROLL, @PRIEST, 85, 47, 56, 71, 195, 199),
+(@TROLL, @DK, 81, 179, 116, 163, 31, 61),
+(@TROLL, @DK, 82, 179, 118, 165, 32, 61),
+(@TROLL, @DK, 83, 186, 120, 168, 32, 62),
+(@TROLL, @DK, 84, 186, 122, 171, 32, 63),
+(@TROLL, @DK, 85, 192, 123, 174, 32, 64),
+(@TROLL, @SHAMAN, 81, 123, 77, 138, 132, 147),
+(@TROLL, @SHAMAN, 82, 125, 79, 141, 135, 149),
+(@TROLL, @SHAMAN, 83, 128, 80, 143, 135, 152),
+(@TROLL, @SHAMAN, 84, 130, 81, 145, 135, 154),
+(@TROLL, @SHAMAN, 85, 132, 82, 148, 141, 157),
+(@TROLL, @MAGE, 81, 37, 46, 60, 190, 178),
+(@TROLL, @MAGE, 82, 37, 46, 60, 193, 181),
+(@TROLL, @MAGE, 83, 37, 47, 61, 196, 185),
+(@TROLL, @MAGE, 84, 38, 47, 62, 200, 188),
+(@TROLL, @MAGE, 85, 38, 48, 63, 203, 191),
+(@TROLL, @WARLOCK, 81, 61, 70, 91, 165, 170),
+(@TROLL, @WARLOCK, 82, 61, 70, 92, 168, 173),
+(@TROLL, @WARLOCK, 83, 62, 71, 94, 171, 176),
+(@TROLL, @WARLOCK, 84, 63, 72, 95, 174, 179),
+(@TROLL, @WARLOCK, 85, 64, 73, 96, 177, 182),
+(@TROLL, @DRUID, 81, 92, 85, 99, 142, 162),
+(@TROLL, @DRUID, 82, 93, 87, 101, 144, 165),
+(@TROLL, @DRUID, 83, 95, 88, 102, 147, 168),
+(@TROLL, @DRUID, 84, 96, 89, 104, 156, 171),
+(@TROLL, @DRUID, 85, 97, 91, 106, 156, 174);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@BLOOD_ELF;
+INSERT INTO `player_levelstats` VALUES
+(@BLOOD_ELF, @WARRIOR, 81, 174, 117, 161, 39, 58),
+(@BLOOD_ELF, @WARRIOR, 82, 186, 119, 164, 39, 58),
+(@BLOOD_ELF, @WARRIOR, 83, 189, 121, 167, 39, 59),
+(@BLOOD_ELF, @WARRIOR, 84, 192, 123, 170, 40, 60),
+(@BLOOD_ELF, @WARRIOR, 85, 195, 125, 173, 40, 61),
+(@BLOOD_ELF, @PALADIN, 81, 157, 93, 146, 102, 105),
+(@BLOOD_ELF, @PALADIN, 82, 160, 95, 148, 104, 106),
+(@BLOOD_ELF, @PALADIN, 83, 163, 96, 151, 105, 108),
+(@BLOOD_ELF, @PALADIN, 84, 167, 98, 153, 107, 110),
+(@BLOOD_ELF, @PALADIN, 85, 169, 99, 156, 109, 112),
+(@BLOOD_ELF, @HUNTER, 81, 72, 196, 130, 94, 97),
+(@BLOOD_ELF, @HUNTER, 82, 74, 199, 133, 96, 98),
+(@BLOOD_ELF, @HUNTER, 83, 75, 202, 135, 97, 100),
+(@BLOOD_ELF, @HUNTER, 84, 76, 206, 137, 99, 101),
+(@BLOOD_ELF, @HUNTER, 85, 77, 210, 139, 100, 103),
+(@BLOOD_ELF, @ROGUE, 81, 111, 204, 107, 47, 66),
+(@BLOOD_ELF, @ROGUE, 82, 113, 207, 108, 47, 66),
+(@BLOOD_ELF, @ROGUE, 83, 115, 211, 110, 48, 67),
+(@BLOOD_ELF, @ROGUE, 84, 117, 215, 112, 48, 68),
+(@BLOOD_ELF, @ROGUE, 85, 119, 218, 114, 49, 69),
+(@BLOOD_ELF, @PRIEST, 81, 41, 54, 68, 188, 183),
+(@BLOOD_ELF, @PRIEST, 82, 41, 54, 68, 192, 186),
+(@BLOOD_ELF, @PRIEST, 83, 42, 55, 69, 196, 189),
+(@BLOOD_ELF, @PRIEST, 84, 42, 56, 70, 199, 193),
+(@BLOOD_ELF, @PRIEST, 85, 43, 56, 71, 202, 196),
+(@BLOOD_ELF, @DK, 81, 175, 116, 163, 38, 58),
+(@BLOOD_ELF, @DK, 82, 175, 118, 165, 39, 58),
+(@BLOOD_ELF, @DK, 83, 182, 120, 168, 39, 59),
+(@BLOOD_ELF, @DK, 84, 182, 122, 171, 39, 60),
+(@BLOOD_ELF, @DK, 85, 188, 123, 174, 39, 61),
+(@BLOOD_ELF, @SHAMAN, 81, 119, 77, 138, 139, 144),
+(@BLOOD_ELF, @SHAMAN, 82, 121, 79, 141, 142, 146),
+(@BLOOD_ELF, @SHAMAN, 83, 124, 80, 143, 142, 149),
+(@BLOOD_ELF, @SHAMAN, 84, 126, 81, 145, 142, 151),
+(@BLOOD_ELF, @SHAMAN, 85, 128, 82, 148, 148, 154),
+(@BLOOD_ELF, @MAGE, 81, 33, 46, 60, 197, 175),
+(@BLOOD_ELF, @MAGE, 82, 33, 46, 60, 200, 178),
+(@BLOOD_ELF, @MAGE, 83, 33, 47, 61, 203, 182),
+(@BLOOD_ELF, @MAGE, 84, 34, 47, 62, 207, 185),
+(@BLOOD_ELF, @MAGE, 85, 34, 48, 63, 210, 188),
+(@BLOOD_ELF, @WARLOCK, 81, 57, 70, 91, 172, 167),
+(@BLOOD_ELF, @WARLOCK, 82, 57, 70, 92, 175, 170),
+(@BLOOD_ELF, @WARLOCK, 83, 58, 71, 94, 178, 173),
+(@BLOOD_ELF, @WARLOCK, 84, 59, 72, 95, 181, 176),
+(@BLOOD_ELF, @WARLOCK, 85, 60, 73, 96, 184, 179),
+(@BLOOD_ELF, @DRUID, 81, 88, 85, 99, 149, 159),
+(@BLOOD_ELF, @DRUID, 82, 89, 87, 101, 151, 162),
+(@BLOOD_ELF, @DRUID, 83, 91, 88, 102, 154, 165),
+(@BLOOD_ELF, @DRUID, 84, 92, 89, 104, 163, 168),
+(@BLOOD_ELF, @DRUID, 85, 93, 91, 106, 163, 171);
+
+DELETE FROM `player_levelstats` WHERE `level` > 80 AND `race`=@DRAENEI;
+INSERT INTO `player_levelstats` VALUES
+(@DRAENEI, @WARRIOR, 81, 178, 112, 161, 36, 62),
+(@DRAENEI, @WARRIOR, 82, 190, 114, 164, 36, 62),
+(@DRAENEI, @WARRIOR, 83, 193, 116, 167, 36, 63),
+(@DRAENEI, @WARRIOR, 84, 196, 118, 170, 37, 64),
+(@DRAENEI, @WARRIOR, 85, 199, 120, 173, 37, 65),
+(@DRAENEI, @PALADIN, 81, 161, 88, 146, 99, 109),
+(@DRAENEI, @PALADIN, 82, 164, 90, 148, 101, 110),
+(@DRAENEI, @PALADIN, 83, 167, 91, 151, 102, 112),
+(@DRAENEI, @PALADIN, 84, 171, 93, 153, 104, 114),
+(@DRAENEI, @PALADIN, 85, 173, 94, 156, 106, 116),
+(@DRAENEI, @HUNTER, 81, 76, 191, 130, 91, 101),
+(@DRAENEI, @HUNTER, 82, 78, 194, 133, 93, 102),
+(@DRAENEI, @HUNTER, 83, 79, 197, 135, 94, 104),
+(@DRAENEI, @HUNTER, 84, 80, 201, 137, 96, 105),
+(@DRAENEI, @HUNTER, 85, 81, 205, 139, 97, 107),
+(@DRAENEI, @ROGUE, 81, 115, 199, 107, 44, 70),
+(@DRAENEI, @ROGUE, 82, 117, 202, 108, 44, 70),
+(@DRAENEI, @ROGUE, 83, 119, 206, 110, 45, 71),
+(@DRAENEI, @ROGUE, 84, 121, 210, 112, 45, 72),
+(@DRAENEI, @ROGUE, 85, 123, 213, 114, 46, 73),
+(@DRAENEI, @PRIEST, 81, 45, 49, 68, 185, 187),
+(@DRAENEI, @PRIEST, 82, 45, 49, 68, 189, 190),
+(@DRAENEI, @PRIEST, 83, 46, 50, 69, 193, 193),
+(@DRAENEI, @PRIEST, 84, 46, 51, 70, 196, 197),
+(@DRAENEI, @PRIEST, 85, 47, 51, 71, 199, 200),
+(@DRAENEI, @DK, 81, 179, 111, 163, 35, 62),
+(@DRAENEI, @DK, 82, 179, 113, 165, 36, 62),
+(@DRAENEI, @DK, 83, 186, 115, 168, 36, 63),
+(@DRAENEI, @DK, 84, 186, 117, 171, 36, 64),
+(@DRAENEI, @DK, 85, 192, 118, 174, 36, 65),
+(@DRAENEI, @SHAMAN, 81, 123, 72, 138, 136, 148),
+(@DRAENEI, @SHAMAN, 82, 125, 74, 141, 139, 150),
+(@DRAENEI, @SHAMAN, 83, 128, 75, 143, 139, 153),
+(@DRAENEI, @SHAMAN, 84, 130, 76, 145, 139, 155),
+(@DRAENEI, @SHAMAN, 85, 132, 77, 148, 145, 158),
+(@DRAENEI, @MAGE, 81, 37, 41, 60, 194, 179),
+(@DRAENEI, @MAGE, 82, 37, 41, 60, 197, 182),
+(@DRAENEI, @MAGE, 83, 37, 42, 61, 200, 186),
+(@DRAENEI, @MAGE, 84, 38, 42, 62, 204, 189),
+(@DRAENEI, @MAGE, 85, 38, 43, 63, 207, 192),
+(@DRAENEI, @WARLOCK, 81, 61, 65, 91, 169, 171),
+(@DRAENEI, @WARLOCK, 82, 61, 65, 92, 172, 174),
+(@DRAENEI, @WARLOCK, 83, 62, 66, 94, 175, 177),
+(@DRAENEI, @WARLOCK, 84, 63, 67, 95, 178, 180),
+(@DRAENEI, @WARLOCK, 85, 64, 68, 96, 181, 183),
+(@DRAENEI, @DRUID, 81, 92, 80, 99, 146, 163),
+(@DRAENEI, @DRUID, 82, 93, 82, 101, 148, 166),
+(@DRAENEI, @DRUID, 83, 95, 83, 102, 151, 169),
+(@DRAENEI, @DRUID, 84, 96, 84, 104, 160, 172),
+(@DRAENEI, @DRUID, 85, 97, 86, 106, 160, 175);
+
+DELETE FROM `player_levelstats` WHERE `race`=@GOBLIN;
+INSERT INTO `player_levelstats` VALUES
+(@GOBLIN, @WARRIOR, 1, 23, 20, 22, 20, 20),
+(@GOBLIN, @WARRIOR, 2, 24, 21, 23, 20, 20),
+(@GOBLIN, @WARRIOR, 3, 26, 22, 24, 20, 21),
+(@GOBLIN, @WARRIOR, 4, 27, 22, 26, 20, 21),
+(@GOBLIN, @WARRIOR, 5, 28, 23, 27, 20, 21),
+(@GOBLIN, @WARRIOR, 6, 30, 24, 28, 20, 21),
+(@GOBLIN, @WARRIOR, 7, 31, 25, 29, 21, 22),
+(@GOBLIN, @WARRIOR, 8, 32, 26, 30, 21, 22),
+(@GOBLIN, @WARRIOR, 9, 34, 26, 32, 21, 22),
+(@GOBLIN, @WARRIOR, 10, 35, 27, 33, 21, 23),
+(@GOBLIN, @WARRIOR, 11, 36, 28, 34, 21, 23),
+(@GOBLIN, @WARRIOR, 12, 38, 29, 35, 21, 23),
+(@GOBLIN, @WARRIOR, 13, 39, 30, 37, 21, 24),
+(@GOBLIN, @WARRIOR, 14, 41, 31, 38, 21, 24),
+(@GOBLIN, @WARRIOR, 15, 42, 32, 39, 21, 24),
+(@GOBLIN, @WARRIOR, 16, 44, 33, 41, 21, 25),
+(@GOBLIN, @WARRIOR, 17, 45, 34, 42, 22, 25),
+(@GOBLIN, @WARRIOR, 18, 47, 34, 43, 22, 25),
+(@GOBLIN, @WARRIOR, 19, 48, 35, 45, 22, 26),
+(@GOBLIN, @WARRIOR, 20, 50, 36, 46, 22, 26),
+(@GOBLIN, @WARRIOR, 21, 51, 37, 48, 22, 26),
+(@GOBLIN, @WARRIOR, 22, 53, 38, 49, 22, 27),
+(@GOBLIN, @WARRIOR, 23, 54, 39, 51, 22, 27),
+(@GOBLIN, @WARRIOR, 24, 56, 40, 52, 23, 28),
+(@GOBLIN, @WARRIOR, 25, 58, 41, 53, 23, 28),
+(@GOBLIN, @WARRIOR, 26, 59, 42, 55, 23, 28),
+(@GOBLIN, @WARRIOR, 27, 61, 43, 56, 23, 29),
+(@GOBLIN, @WARRIOR, 28, 63, 44, 58, 23, 29),
+(@GOBLIN, @WARRIOR, 29, 64, 45, 59, 23, 30),
+(@GOBLIN, @WARRIOR, 30, 66, 46, 61, 24, 30),
+(@GOBLIN, @WARRIOR, 31, 68, 47, 62, 24, 30),
+(@GOBLIN, @WARRIOR, 32, 69, 48, 64, 24, 31),
+(@GOBLIN, @WARRIOR, 33, 71, 50, 66, 24, 31),
+(@GOBLIN, @WARRIOR, 34, 73, 51, 67, 24, 32),
+(@GOBLIN, @WARRIOR, 35, 74, 52, 69, 24, 32),
+(@GOBLIN, @WARRIOR, 36, 76, 53, 70, 25, 33),
+(@GOBLIN, @WARRIOR, 37, 78, 54, 72, 25, 33),
+(@GOBLIN, @WARRIOR, 38, 80, 55, 74, 25, 34),
+(@GOBLIN, @WARRIOR, 39, 82, 56, 75, 25, 34),
+(@GOBLIN, @WARRIOR, 40, 83, 57, 77, 25, 35),
+(@GOBLIN, @WARRIOR, 41, 85, 58, 79, 26, 35),
+(@GOBLIN, @WARRIOR, 42, 87, 60, 80, 26, 35),
+(@GOBLIN, @WARRIOR, 43, 89, 61, 82, 26, 36),
+(@GOBLIN, @WARRIOR, 44, 91, 62, 84, 26, 36),
+(@GOBLIN, @WARRIOR, 45, 93, 63, 85, 26, 37),
+(@GOBLIN, @WARRIOR, 46, 95, 64, 87, 27, 37),
+(@GOBLIN, @WARRIOR, 47, 97, 66, 89, 27, 38),
+(@GOBLIN, @WARRIOR, 48, 99, 67, 91, 27, 38),
+(@GOBLIN, @WARRIOR, 49, 101, 68, 93, 27, 39),
+(@GOBLIN, @WARRIOR, 50, 103, 69, 94, 28, 40),
+(@GOBLIN, @WARRIOR, 51, 105, 71, 96, 28, 40),
+(@GOBLIN, @WARRIOR, 52, 107, 72, 98, 28, 41),
+(@GOBLIN, @WARRIOR, 53, 109, 73, 100, 28, 41),
+(@GOBLIN, @WARRIOR, 54, 111, 74, 102, 29, 42),
+(@GOBLIN, @WARRIOR, 55, 113, 76, 103, 29, 42),
+(@GOBLIN, @WARRIOR, 56, 115, 77, 105, 29, 43),
+(@GOBLIN, @WARRIOR, 57, 117, 78, 107, 29, 43),
+(@GOBLIN, @WARRIOR, 58, 119, 79, 109, 30, 44),
+(@GOBLIN, @WARRIOR, 59, 121, 81, 111, 30, 44),
+(@GOBLIN, @WARRIOR, 60, 123, 82, 113, 30, 45),
+(@GOBLIN, @WARRIOR, 61, 125, 83, 115, 30, 46),
+(@GOBLIN, @WARRIOR, 62, 127, 85, 117, 31, 46),
+(@GOBLIN, @WARRIOR, 63, 129, 86, 119, 31, 47),
+(@GOBLIN, @WARRIOR, 64, 132, 88, 121, 31, 47),
+(@GOBLIN, @WARRIOR, 65, 134, 89, 123, 32, 48),
+(@GOBLIN, @WARRIOR, 66, 136, 90, 125, 32, 49),
+(@GOBLIN, @WARRIOR, 67, 138, 92, 127, 32, 49),
+(@GOBLIN, @WARRIOR, 68, 140, 93, 129, 32, 50),
+(@GOBLIN, @WARRIOR, 69, 143, 95, 131, 33, 50),
+(@GOBLIN, @WARRIOR, 70, 145, 96, 133, 33, 51),
+(@GOBLIN, @WARRIOR, 71, 148, 97, 140, 33, 53),
+(@GOBLIN, @WARRIOR, 72, 156, 99, 143, 33, 54),
+(@GOBLIN, @WARRIOR, 73, 162, 101, 148, 33, 55),
+(@GOBLIN, @WARRIOR, 74, 162, 102, 148, 34, 55),
+(@GOBLIN, @WARRIOR, 75, 165, 104, 150, 34, 56),
+(@GOBLIN, @WARRIOR, 76, 171, 106, 156, 34, 57),
+(@GOBLIN, @WARRIOR, 77, 171, 108, 157, 35, 58),
+(@GOBLIN, @WARRIOR, 78, 174, 109, 159, 35, 58),
+(@GOBLIN, @WARRIOR, 79, 181, 111, 165, 35, 59),
+(@GOBLIN, @WARRIOR, 80, 184, 113, 168, 36, 60),
+(@GOBLIN, @WARRIOR, 81, 194, 123, 178, 46, 70),
+(@GOBLIN, @WARRIOR, 82, 204, 133, 188, 56, 80),
+(@GOBLIN, @WARRIOR, 83, 214, 143, 198, 66, 90),
+(@GOBLIN, @WARRIOR, 84, 224, 153, 208, 76, 100),
+(@GOBLIN, @WARRIOR, 85, 234, 163, 218, 86, 110),
+(@GOBLIN, @HUNTER, 1, 22, 20, 22, 20, 21),
+(@GOBLIN, @HUNTER, 2, 23, 21, 23, 21, 22),
+(@GOBLIN, @HUNTER, 3, 24, 21, 24, 21, 22),
+(@GOBLIN, @HUNTER, 4, 25, 22, 25, 22, 23),
+(@GOBLIN, @HUNTER, 5, 26, 22, 26, 23, 24),
+(@GOBLIN, @HUNTER, 6, 28, 23, 27, 23, 25),
+(@GOBLIN, @HUNTER, 7, 29, 24, 28, 24, 25),
+(@GOBLIN, @HUNTER, 8, 30, 24, 29, 25, 26),
+(@GOBLIN, @HUNTER, 9, 31, 25, 30, 25, 27),
+(@GOBLIN, @HUNTER, 10, 32, 25, 32, 26, 27),
+(@GOBLIN, @HUNTER, 11, 33, 26, 33, 27, 28),
+(@GOBLIN, @HUNTER, 12, 35, 27, 34, 27, 29),
+(@GOBLIN, @HUNTER, 13, 36, 27, 35, 28, 30),
+(@GOBLIN, @HUNTER, 14, 37, 28, 36, 29, 31),
+(@GOBLIN, @HUNTER, 15, 38, 29, 37, 30, 31),
+(@GOBLIN, @HUNTER, 16, 40, 29, 38, 30, 32),
+(@GOBLIN, @HUNTER, 17, 41, 30, 40, 31, 33),
+(@GOBLIN, @HUNTER, 18, 42, 31, 41, 32, 34),
+(@GOBLIN, @HUNTER, 19, 43, 31, 42, 33, 35),
+(@GOBLIN, @HUNTER, 20, 45, 32, 43, 33, 35),
+(@GOBLIN, @HUNTER, 21, 46, 33, 45, 34, 36),
+(@GOBLIN, @HUNTER, 22, 47, 33, 46, 35, 37),
+(@GOBLIN, @HUNTER, 23, 49, 34, 47, 36, 38),
+(@GOBLIN, @HUNTER, 24, 50, 35, 48, 37, 39),
+(@GOBLIN, @HUNTER, 25, 51, 36, 50, 37, 40),
+(@GOBLIN, @HUNTER, 26, 53, 36, 51, 38, 41),
+(@GOBLIN, @HUNTER, 27, 54, 37, 52, 39, 42),
+(@GOBLIN, @HUNTER, 28, 56, 38, 54, 40, 43),
+(@GOBLIN, @HUNTER, 29, 57, 39, 55, 41, 43),
+(@GOBLIN, @HUNTER, 30, 58, 39, 56, 42, 44),
+(@GOBLIN, @HUNTER, 31, 60, 40, 58, 43, 45),
+(@GOBLIN, @HUNTER, 32, 61, 41, 59, 43, 46),
+(@GOBLIN, @HUNTER, 33, 63, 42, 60, 44, 47),
+(@GOBLIN, @HUNTER, 34, 64, 43, 62, 45, 48),
+(@GOBLIN, @HUNTER, 35, 66, 44, 63, 46, 49),
+(@GOBLIN, @HUNTER, 36, 67, 44, 65, 47, 50),
+(@GOBLIN, @HUNTER, 37, 69, 45, 66, 48, 51),
+(@GOBLIN, @HUNTER, 38, 70, 46, 67, 49, 52),
+(@GOBLIN, @HUNTER, 39, 72, 47, 69, 50, 53),
+(@GOBLIN, @HUNTER, 40, 73, 48, 70, 51, 54),
+(@GOBLIN, @HUNTER, 41, 75, 49, 72, 52, 55),
+(@GOBLIN, @HUNTER, 42, 77, 49, 73, 53, 56),
+(@GOBLIN, @HUNTER, 43, 78, 50, 75, 54, 57),
+(@GOBLIN, @HUNTER, 44, 80, 51, 76, 55, 58),
+(@GOBLIN, @HUNTER, 45, 81, 52, 78, 56, 59),
+(@GOBLIN, @HUNTER, 46, 83, 53, 79, 57, 61),
+(@GOBLIN, @HUNTER, 47, 85, 54, 81, 58, 62),
+(@GOBLIN, @HUNTER, 48, 86, 55, 83, 59, 63),
+(@GOBLIN, @HUNTER, 49, 88, 56, 84, 60, 64),
+(@GOBLIN, @HUNTER, 50, 90, 57, 86, 61, 65),
+(@GOBLIN, @HUNTER, 51, 91, 58, 87, 62, 66),
+(@GOBLIN, @HUNTER, 52, 93, 59, 89, 63, 67),
+(@GOBLIN, @HUNTER, 53, 95, 60, 91, 64, 68),
+(@GOBLIN, @HUNTER, 54, 97, 61, 92, 65, 69),
+(@GOBLIN, @HUNTER, 55, 98, 61, 94, 66, 71),
+(@GOBLIN, @HUNTER, 56, 100, 62, 95, 67, 72),
+(@GOBLIN, @HUNTER, 57, 102, 63, 97, 68, 73),
+(@GOBLIN, @HUNTER, 58, 104, 64, 99, 69, 74),
+(@GOBLIN, @HUNTER, 59, 105, 65, 101, 70, 75),
+(@GOBLIN, @HUNTER, 60, 107, 66, 102, 71, 77),
+(@GOBLIN, @HUNTER, 61, 109, 67, 104, 73, 78),
+(@GOBLIN, @HUNTER, 62, 111, 69, 106, 74, 79),
+(@GOBLIN, @HUNTER, 63, 113, 70, 107, 75, 80),
+(@GOBLIN, @HUNTER, 64, 115, 71, 109, 76, 81),
+(@GOBLIN, @HUNTER, 65, 116, 72, 111, 77, 83),
+(@GOBLIN, @HUNTER, 66, 118, 73, 113, 78, 84),
+(@GOBLIN, @HUNTER, 67, 120, 74, 115, 79, 85),
+(@GOBLIN, @HUNTER, 68, 122, 75, 116, 81, 86),
+(@GOBLIN, @HUNTER, 69, 124, 76, 118, 82, 88),
+(@GOBLIN, @HUNTER, 70, 126, 77, 120, 83, 89),
+(@GOBLIN, @HUNTER, 71, 148, 78, 122, 84, 92),
+(@GOBLIN, @HUNTER, 72, 150, 79, 125, 86, 94),
+(@GOBLIN, @HUNTER, 73, 152, 80, 127, 87, 96),
+(@GOBLIN, @HUNTER, 74, 156, 82, 129, 89, 97),
+(@GOBLIN, @HUNTER, 75, 158, 83, 131, 90, 99),
+(@GOBLIN, @HUNTER, 76, 162, 84, 134, 92, 100),
+(@GOBLIN, @HUNTER, 77, 164, 86, 136, 93, 103),
+(@GOBLIN, @HUNTER, 78, 167, 87, 138, 95, 105),
+(@GOBLIN, @HUNTER, 79, 170, 88, 153, 96, 106),
+(@GOBLIN, @HUNTER, 80, 173, 90, 160, 98, 108),
+(@GOBLIN, @HUNTER, 81, 183, 100, 170, 108, 118),
+(@GOBLIN, @HUNTER, 82, 193, 110, 180, 118, 128),
+(@GOBLIN, @HUNTER, 83, 203, 120, 190, 128, 138),
+(@GOBLIN, @HUNTER, 84, 213, 130, 200, 138, 148),
+(@GOBLIN, @HUNTER, 85, 223, 140, 210, 148, 158),
+(@GOBLIN, @ROGUE, 1, 21, 23, 21, 20, 20),
+(@GOBLIN, @ROGUE, 2, 22, 24, 22, 20, 20),
+(@GOBLIN, @ROGUE, 3, 23, 26, 22, 20, 21),
+(@GOBLIN, @ROGUE, 4, 23, 27, 23, 20, 21),
+(@GOBLIN, @ROGUE, 5, 24, 29, 24, 21, 21),
+(@GOBLIN, @ROGUE, 6, 25, 30, 25, 21, 22),
+(@GOBLIN, @ROGUE, 7, 26, 32, 25, 21, 22),
+(@GOBLIN, @ROGUE, 8, 26, 33, 26, 21, 23),
+(@GOBLIN, @ROGUE, 9, 27, 35, 27, 21, 23),
+(@GOBLIN, @ROGUE, 10, 28, 36, 27, 21, 23),
+(@GOBLIN, @ROGUE, 11, 29, 38, 28, 22, 24),
+(@GOBLIN, @ROGUE, 12, 30, 39, 29, 22, 24),
+(@GOBLIN, @ROGUE, 13, 31, 41, 30, 22, 25),
+(@GOBLIN, @ROGUE, 14, 31, 43, 31, 22, 25),
+(@GOBLIN, @ROGUE, 15, 32, 44, 31, 22, 25),
+(@GOBLIN, @ROGUE, 16, 33, 46, 32, 23, 26),
+(@GOBLIN, @ROGUE, 17, 34, 48, 33, 23, 26),
+(@GOBLIN, @ROGUE, 18, 35, 49, 34, 23, 27),
+(@GOBLIN, @ROGUE, 19, 36, 51, 35, 23, 27),
+(@GOBLIN, @ROGUE, 20, 37, 53, 35, 23, 28),
+(@GOBLIN, @ROGUE, 21, 38, 54, 36, 24, 28),
+(@GOBLIN, @ROGUE, 22, 39, 56, 37, 24, 29),
+(@GOBLIN, @ROGUE, 23, 40, 58, 38, 24, 29),
+(@GOBLIN, @ROGUE, 24, 41, 60, 39, 24, 30),
+(@GOBLIN, @ROGUE, 25, 42, 61, 40, 25, 30),
+(@GOBLIN, @ROGUE, 26, 43, 63, 41, 25, 31),
+(@GOBLIN, @ROGUE, 27, 44, 65, 42, 25, 31),
+(@GOBLIN, @ROGUE, 28, 45, 67, 43, 25, 32),
+(@GOBLIN, @ROGUE, 29, 46, 69, 43, 25, 32),
+(@GOBLIN, @ROGUE, 30, 47, 71, 44, 26, 33),
+(@GOBLIN, @ROGUE, 31, 48, 72, 45, 26, 33),
+(@GOBLIN, @ROGUE, 32, 49, 74, 46, 26, 34),
+(@GOBLIN, @ROGUE, 33, 50, 76, 47, 27, 34),
+(@GOBLIN, @ROGUE, 34, 51, 78, 48, 27, 35),
+(@GOBLIN, @ROGUE, 35, 52, 80, 49, 27, 35),
+(@GOBLIN, @ROGUE, 36, 53, 82, 50, 27, 36),
+(@GOBLIN, @ROGUE, 37, 54, 84, 51, 28, 36),
+(@GOBLIN, @ROGUE, 38, 55, 86, 52, 28, 37),
+(@GOBLIN, @ROGUE, 39, 56, 88, 53, 28, 38),
+(@GOBLIN, @ROGUE, 40, 57, 90, 54, 28, 38),
+(@GOBLIN, @ROGUE, 41, 58, 92, 55, 29, 39),
+(@GOBLIN, @ROGUE, 42, 60, 94, 56, 29, 39),
+(@GOBLIN, @ROGUE, 43, 61, 96, 57, 29, 40),
+(@GOBLIN, @ROGUE, 44, 62, 98, 58, 30, 40),
+(@GOBLIN, @ROGUE, 45, 63, 100, 59, 30, 41),
+(@GOBLIN, @ROGUE, 46, 64, 103, 61, 30, 42),
+(@GOBLIN, @ROGUE, 47, 65, 105, 62, 31, 42),
+(@GOBLIN, @ROGUE, 48, 66, 107, 63, 31, 43),
+(@GOBLIN, @ROGUE, 49, 68, 109, 64, 31, 44),
+(@GOBLIN, @ROGUE, 50, 69, 111, 65, 32, 44),
+(@GOBLIN, @ROGUE, 51, 70, 113, 66, 32, 45),
+(@GOBLIN, @ROGUE, 52, 71, 116, 67, 32, 45),
+(@GOBLIN, @ROGUE, 53, 73, 118, 68, 33, 46),
+(@GOBLIN, @ROGUE, 54, 74, 120, 69, 33, 47),
+(@GOBLIN, @ROGUE, 55, 75, 122, 71, 33, 47),
+(@GOBLIN, @ROGUE, 56, 76, 125, 72, 34, 48),
+(@GOBLIN, @ROGUE, 57, 78, 127, 73, 34, 49),
+(@GOBLIN, @ROGUE, 58, 79, 129, 74, 34, 49),
+(@GOBLIN, @ROGUE, 59, 80, 131, 75, 35, 50),
+(@GOBLIN, @ROGUE, 60, 81, 134, 77, 35, 51),
+(@GOBLIN, @ROGUE, 61, 83, 136, 78, 35, 51),
+(@GOBLIN, @ROGUE, 62, 84, 138, 79, 36, 52),
+(@GOBLIN, @ROGUE, 63, 85, 141, 80, 36, 53),
+(@GOBLIN, @ROGUE, 64, 87, 143, 81, 37, 54),
+(@GOBLIN, @ROGUE, 65, 88, 146, 83, 37, 54),
+(@GOBLIN, @ROGUE, 66, 89, 148, 84, 37, 55),
+(@GOBLIN, @ROGUE, 67, 91, 151, 85, 38, 56),
+(@GOBLIN, @ROGUE, 68, 92, 153, 86, 38, 57),
+(@GOBLIN, @ROGUE, 69, 94, 156, 88, 39, 57),
+(@GOBLIN, @ROGUE, 70, 95, 158, 89, 39, 58),
+(@GOBLIN, @ROGUE, 71, 97, 161, 90, 39, 60),
+(@GOBLIN, @ROGUE, 72, 99, 164, 92, 40, 60),
+(@GOBLIN, @ROGUE, 73, 100, 167, 94, 40, 61),
+(@GOBLIN, @ROGUE, 74, 102, 170, 95, 41, 62),
+(@GOBLIN, @ROGUE, 75, 104, 173, 97, 41, 63),
+(@GOBLIN, @ROGUE, 76, 105, 176, 98, 41, 64),
+(@GOBLIN, @ROGUE, 77, 107, 179, 100, 42, 65),
+(@GOBLIN, @ROGUE, 78, 109, 183, 106, 42, 66),
+(@GOBLIN, @ROGUE, 79, 111, 186, 107, 43, 67),
+(@GOBLIN, @ROGUE, 80, 113, 189, 109, 43, 69),
+(@GOBLIN, @ROGUE, 81, 123, 199, 119, 53, 79),
+(@GOBLIN, @ROGUE, 82, 133, 209, 129, 63, 89),
+(@GOBLIN, @ROGUE, 83, 143, 219, 139, 73, 99),
+(@GOBLIN, @ROGUE, 84, 153, 229, 149, 83, 109),
+(@GOBLIN, @ROGUE, 85, 163, 239, 159, 93, 119),
+(@GOBLIN, @PRIEST, 1, 20, 20, 20, 22, 23),
+(@GOBLIN, @PRIEST, 2, 20, 20, 20, 23, 24),
+(@GOBLIN, @PRIEST, 3, 20, 20, 21, 25, 26),
+(@GOBLIN, @PRIEST, 4, 20, 21, 21, 26, 27),
+(@GOBLIN, @PRIEST, 5, 21, 21, 21, 27, 28),
+(@GOBLIN, @PRIEST, 6, 21, 21, 22, 29, 30),
+(@GOBLIN, @PRIEST, 7, 21, 21, 22, 30, 31),
+(@GOBLIN, @PRIEST, 8, 21, 22, 23, 31, 33),
+(@GOBLIN, @PRIEST, 9, 21, 22, 23, 33, 34),
+(@GOBLIN, @PRIEST, 10, 21, 22, 23, 34, 36),
+(@GOBLIN, @PRIEST, 11, 22, 22, 24, 36, 37),
+(@GOBLIN, @PRIEST, 12, 22, 23, 24, 37, 39),
+(@GOBLIN, @PRIEST, 13, 22, 23, 25, 38, 40),
+(@GOBLIN, @PRIEST, 14, 22, 23, 25, 40, 42),
+(@GOBLIN, @PRIEST, 15, 22, 23, 25, 41, 43),
+(@GOBLIN, @PRIEST, 16, 23, 24, 26, 43, 45),
+(@GOBLIN, @PRIEST, 17, 23, 24, 26, 44, 46),
+(@GOBLIN, @PRIEST, 18, 23, 24, 27, 46, 48),
+(@GOBLIN, @PRIEST, 19, 23, 24, 27, 47, 49),
+(@GOBLIN, @PRIEST, 20, 23, 25, 28, 49, 51),
+(@GOBLIN, @PRIEST, 21, 24, 25, 28, 51, 53),
+(@GOBLIN, @PRIEST, 22, 24, 25, 29, 52, 54),
+(@GOBLIN, @PRIEST, 23, 24, 26, 29, 54, 56),
+(@GOBLIN, @PRIEST, 24, 24, 26, 30, 55, 58),
+(@GOBLIN, @PRIEST, 25, 25, 26, 30, 57, 59),
+(@GOBLIN, @PRIEST, 26, 25, 27, 31, 59, 61),
+(@GOBLIN, @PRIEST, 27, 25, 27, 31, 60, 63),
+(@GOBLIN, @PRIEST, 28, 25, 27, 32, 62, 65),
+(@GOBLIN, @PRIEST, 29, 25, 28, 32, 64, 66),
+(@GOBLIN, @PRIEST, 30, 26, 28, 33, 65, 68),
+(@GOBLIN, @PRIEST, 31, 26, 28, 33, 67, 70),
+(@GOBLIN, @PRIEST, 32, 26, 29, 34, 69, 72),
+(@GOBLIN, @PRIEST, 33, 27, 29, 34, 70, 73),
+(@GOBLIN, @PRIEST, 34, 27, 29, 35, 72, 75),
+(@GOBLIN, @PRIEST, 35, 27, 30, 35, 74, 77),
+(@GOBLIN, @PRIEST, 36, 27, 30, 36, 76, 79),
+(@GOBLIN, @PRIEST, 37, 28, 30, 36, 78, 81),
+(@GOBLIN, @PRIEST, 38, 28, 31, 37, 79, 83),
+(@GOBLIN, @PRIEST, 39, 28, 31, 38, 81, 85),
+(@GOBLIN, @PRIEST, 40, 28, 31, 38, 83, 87),
+(@GOBLIN, @PRIEST, 41, 29, 32, 39, 85, 88),
+(@GOBLIN, @PRIEST, 42, 29, 32, 39, 87, 90),
+(@GOBLIN, @PRIEST, 43, 29, 33, 40, 89, 92),
+(@GOBLIN, @PRIEST, 44, 30, 33, 40, 91, 94),
+(@GOBLIN, @PRIEST, 45, 30, 33, 41, 92, 96),
+(@GOBLIN, @PRIEST, 46, 30, 34, 42, 94, 98),
+(@GOBLIN, @PRIEST, 47, 31, 34, 42, 96, 100),
+(@GOBLIN, @PRIEST, 48, 31, 35, 43, 98, 102),
+(@GOBLIN, @PRIEST, 49, 31, 35, 44, 100, 104),
+(@GOBLIN, @PRIEST, 50, 32, 36, 44, 102, 106),
+(@GOBLIN, @PRIEST, 51, 32, 36, 45, 104, 109),
+(@GOBLIN, @PRIEST, 52, 32, 36, 45, 106, 111),
+(@GOBLIN, @PRIEST, 53, 33, 37, 46, 108, 113),
+(@GOBLIN, @PRIEST, 54, 33, 37, 47, 110, 115),
+(@GOBLIN, @PRIEST, 55, 33, 38, 47, 112, 117),
+(@GOBLIN, @PRIEST, 56, 34, 38, 48, 114, 119),
+(@GOBLIN, @PRIEST, 57, 34, 39, 49, 117, 121),
+(@GOBLIN, @PRIEST, 58, 34, 39, 49, 119, 124),
+(@GOBLIN, @PRIEST, 59, 35, 40, 50, 121, 126),
+(@GOBLIN, @PRIEST, 60, 35, 40, 51, 123, 128),
+(@GOBLIN, @PRIEST, 61, 35, 41, 51, 125, 130),
+(@GOBLIN, @PRIEST, 62, 36, 41, 52, 127, 132),
+(@GOBLIN, @PRIEST, 63, 36, 41, 53, 129, 135),
+(@GOBLIN, @PRIEST, 64, 37, 42, 54, 132, 137),
+(@GOBLIN, @PRIEST, 65, 37, 42, 54, 134, 139),
+(@GOBLIN, @PRIEST, 66, 37, 43, 55, 136, 142),
+(@GOBLIN, @PRIEST, 67, 38, 43, 56, 138, 144),
+(@GOBLIN, @PRIEST, 68, 38, 44, 57, 140, 146),
+(@GOBLIN, @PRIEST, 69, 39, 44, 57, 143, 149),
+(@GOBLIN, @PRIEST, 70, 39, 45, 58, 145, 151),
+(@GOBLIN, @PRIEST, 71, 39, 46, 59, 148, 158),
+(@GOBLIN, @PRIEST, 72, 40, 46, 59, 151, 161),
+(@GOBLIN, @PRIEST, 73, 40, 47, 60, 154, 164),
+(@GOBLIN, @PRIEST, 74, 41, 47, 61, 156, 167),
+(@GOBLIN, @PRIEST, 75, 41, 48, 62, 159, 170),
+(@GOBLIN, @PRIEST, 76, 41, 49, 63, 162, 174),
+(@GOBLIN, @PRIEST, 77, 42, 49, 64, 165, 177),
+(@GOBLIN, @PRIEST, 78, 42, 50, 65, 168, 180),
+(@GOBLIN, @PRIEST, 79, 43, 50, 66, 171, 183),
+(@GOBLIN, @PRIEST, 80, 43, 51, 67, 174, 186),
+(@GOBLIN, @PRIEST, 81, 53, 61, 77, 184, 196),
+(@GOBLIN, @PRIEST, 82, 63, 71, 87, 194, 206),
+(@GOBLIN, @PRIEST, 83, 73, 81, 97, 204, 216),
+(@GOBLIN, @PRIEST, 84, 83, 91, 107, 214, 226),
+(@GOBLIN, @PRIEST, 85, 93, 101, 117, 224, 236),
+(@GOBLIN, @DK, 1, 23, 20, 22, 20, 20),
+(@GOBLIN, @DK, 2, 24, 21, 23, 20, 20),
+(@GOBLIN, @DK, 3, 26, 22, 24, 20, 21),
+(@GOBLIN, @DK, 4, 27, 22, 26, 20, 21),
+(@GOBLIN, @DK, 5, 28, 23, 27, 20, 21),
+(@GOBLIN, @DK, 6, 30, 24, 28, 20, 21),
+(@GOBLIN, @DK, 7, 31, 25, 29, 21, 22),
+(@GOBLIN, @DK, 8, 32, 26, 30, 21, 22),
+(@GOBLIN, @DK, 9, 34, 26, 32, 21, 22),
+(@GOBLIN, @DK, 10, 35, 27, 33, 21, 23),
+(@GOBLIN, @DK, 11, 36, 28, 34, 21, 23),
+(@GOBLIN, @DK, 12, 38, 29, 35, 21, 23),
+(@GOBLIN, @DK, 13, 39, 30, 37, 21, 24),
+(@GOBLIN, @DK, 14, 41, 31, 38, 21, 24),
+(@GOBLIN, @DK, 15, 42, 32, 39, 21, 24),
+(@GOBLIN, @DK, 16, 44, 33, 41, 21, 25),
+(@GOBLIN, @DK, 17, 45, 34, 42, 22, 25),
+(@GOBLIN, @DK, 18, 47, 34, 43, 22, 25),
+(@GOBLIN, @DK, 19, 48, 35, 45, 22, 26),
+(@GOBLIN, @DK, 20, 50, 36, 46, 22, 26),
+(@GOBLIN, @DK, 21, 51, 37, 48, 22, 26),
+(@GOBLIN, @DK, 22, 53, 38, 49, 22, 27),
+(@GOBLIN, @DK, 23, 54, 39, 51, 22, 27),
+(@GOBLIN, @DK, 24, 56, 40, 52, 23, 28),
+(@GOBLIN, @DK, 25, 58, 41, 53, 23, 28),
+(@GOBLIN, @DK, 26, 59, 42, 55, 23, 28),
+(@GOBLIN, @DK, 27, 61, 43, 56, 23, 29),
+(@GOBLIN, @DK, 28, 63, 44, 58, 23, 29),
+(@GOBLIN, @DK, 29, 64, 45, 59, 23, 30),
+(@GOBLIN, @DK, 30, 66, 46, 61, 24, 30),
+(@GOBLIN, @DK, 31, 68, 47, 62, 24, 30),
+(@GOBLIN, @DK, 32, 69, 48, 64, 24, 31),
+(@GOBLIN, @DK, 33, 71, 50, 66, 24, 31),
+(@GOBLIN, @DK, 34, 73, 51, 67, 24, 32),
+(@GOBLIN, @DK, 35, 74, 52, 69, 24, 32),
+(@GOBLIN, @DK, 36, 76, 53, 70, 25, 33),
+(@GOBLIN, @DK, 37, 78, 54, 72, 25, 33),
+(@GOBLIN, @DK, 38, 80, 55, 74, 25, 34),
+(@GOBLIN, @DK, 39, 82, 56, 75, 25, 34),
+(@GOBLIN, @DK, 40, 83, 57, 77, 25, 35),
+(@GOBLIN, @DK, 41, 85, 58, 79, 26, 35),
+(@GOBLIN, @DK, 42, 87, 60, 80, 26, 35),
+(@GOBLIN, @DK, 43, 89, 61, 82, 26, 36),
+(@GOBLIN, @DK, 44, 91, 62, 84, 26, 36),
+(@GOBLIN, @DK, 45, 93, 63, 85, 26, 37),
+(@GOBLIN, @DK, 46, 95, 64, 87, 27, 37),
+(@GOBLIN, @DK, 47, 97, 66, 89, 27, 38),
+(@GOBLIN, @DK, 48, 99, 67, 91, 27, 38),
+(@GOBLIN, @DK, 49, 101, 68, 93, 27, 39),
+(@GOBLIN, @DK, 50, 103, 69, 94, 28, 40),
+(@GOBLIN, @DK, 51, 105, 71, 96, 28, 40),
+(@GOBLIN, @DK, 52, 106, 72, 97, 28, 41),
+(@GOBLIN, @DK, 53, 107, 72, 98, 28, 41),
+(@GOBLIN, @DK, 54, 107, 73, 98, 29, 42),
+(@GOBLIN, @DK, 55, 108, 73, 99, 29, 43),
+(@GOBLIN, @DK, 56, 111, 75, 102, 29, 44),
+(@GOBLIN, @DK, 57, 113, 76, 104, 29, 44),
+(@GOBLIN, @DK, 58, 118, 77, 106, 30, 45),
+(@GOBLIN, @DK, 59, 118, 79, 108, 30, 45),
+(@GOBLIN, @DK, 60, 123, 80, 110, 30, 46),
+(@GOBLIN, @DK, 61, 125, 81, 112, 30, 47),
+(@GOBLIN, @DK, 62, 128, 83, 114, 30, 47),
+(@GOBLIN, @DK, 63, 130, 84, 117, 31, 48),
+(@GOBLIN, @DK, 64, 130, 86, 119, 31, 48),
+(@GOBLIN, @DK, 65, 140, 87, 128, 31, 49),
+(@GOBLIN, @DK, 66, 143, 89, 131, 31, 50),
+(@GOBLIN, @DK, 67, 146, 90, 133, 32, 50),
+(@GOBLIN, @DK, 68, 148, 92, 135, 32, 51),
+(@GOBLIN, @DK, 69, 151, 93, 138, 32, 52),
+(@GOBLIN, @DK, 70, 154, 95, 140, 32, 52),
+(@GOBLIN, @DK, 71, 162, 97, 144, 33, 53),
+(@GOBLIN, @DK, 72, 164, 98, 146, 33, 54),
+(@GOBLIN, @DK, 73, 165, 100, 148, 33, 55),
+(@GOBLIN, @DK, 74, 166, 102, 151, 33, 55),
+(@GOBLIN, @DK, 75, 169, 103, 154, 34, 56),
+(@GOBLIN, @DK, 76, 172, 105, 157, 34, 57),
+(@GOBLIN, @DK, 77, 175, 107, 157, 34, 58),
+(@GOBLIN, @DK, 78, 176, 108, 157, 34, 58),
+(@GOBLIN, @DK, 79, 177, 110, 157, 35, 59),
+(@GOBLIN, @DK, 80, 180, 112, 160, 35, 60),
+(@GOBLIN, @DK, 81, 190, 122, 170, 45, 70),
+(@GOBLIN, @DK, 82, 200, 132, 180, 55, 80),
+(@GOBLIN, @DK, 83, 210, 142, 190, 65, 90),
+(@GOBLIN, @DK, 84, 220, 152, 200, 75, 100),
+(@GOBLIN, @DK, 85, 230, 162, 210, 85, 110),
+(@GOBLIN, @SHAMAN, 1, 24, 17, 23, 18, 25),
+(@GOBLIN, @SHAMAN, 2, 25, 17, 24, 19, 26),
+(@GOBLIN, @SHAMAN, 3, 26, 18, 25, 20, 27),
+(@GOBLIN, @SHAMAN, 4, 26, 18, 26, 21, 28),
+(@GOBLIN, @SHAMAN, 5, 27, 19, 27, 22, 29),
+(@GOBLIN, @SHAMAN, 6, 28, 19, 28, 23, 30),
+(@GOBLIN, @SHAMAN, 7, 29, 20, 29, 24, 31),
+(@GOBLIN, @SHAMAN, 8, 30, 20, 30, 25, 32),
+(@GOBLIN, @SHAMAN, 9, 31, 21, 31, 26, 33),
+(@GOBLIN, @SHAMAN, 10, 32, 21, 32, 27, 34),
+(@GOBLIN, @SHAMAN, 11, 33, 22, 33, 28, 36),
+(@GOBLIN, @SHAMAN, 12, 34, 22, 34, 29, 37),
+(@GOBLIN, @SHAMAN, 13, 34, 23, 35, 30, 38),
+(@GOBLIN, @SHAMAN, 14, 35, 23, 36, 31, 39),
+(@GOBLIN, @SHAMAN, 15, 36, 24, 37, 32, 40),
+(@GOBLIN, @SHAMAN, 16, 37, 24, 39, 33, 41),
+(@GOBLIN, @SHAMAN, 17, 38, 25, 40, 34, 43),
+(@GOBLIN, @SHAMAN, 18, 39, 25, 41, 35, 44),
+(@GOBLIN, @SHAMAN, 19, 40, 26, 42, 36, 45),
+(@GOBLIN, @SHAMAN, 20, 41, 26, 43, 37, 46),
+(@GOBLIN, @SHAMAN, 21, 42, 27, 44, 38, 47),
+(@GOBLIN, @SHAMAN, 22, 43, 27, 45, 39, 49),
+(@GOBLIN, @SHAMAN, 23, 44, 28, 47, 40, 50),
+(@GOBLIN, @SHAMAN, 24, 45, 28, 48, 41, 51),
+(@GOBLIN, @SHAMAN, 25, 47, 29, 49, 43, 52),
+(@GOBLIN, @SHAMAN, 26, 48, 30, 50, 44, 54),
+(@GOBLIN, @SHAMAN, 27, 49, 30, 52, 45, 55),
+(@GOBLIN, @SHAMAN, 28, 50, 31, 53, 46, 56),
+(@GOBLIN, @SHAMAN, 29, 51, 31, 54, 47, 58),
+(@GOBLIN, @SHAMAN, 30, 52, 32, 55, 48, 59),
+(@GOBLIN, @SHAMAN, 31, 53, 33, 57, 50, 60),
+(@GOBLIN, @SHAMAN, 32, 54, 33, 58, 51, 62),
+(@GOBLIN, @SHAMAN, 33, 55, 34, 59, 52, 63),
+(@GOBLIN, @SHAMAN, 34, 57, 34, 61, 53, 65),
+(@GOBLIN, @SHAMAN, 35, 58, 35, 62, 55, 66),
+(@GOBLIN, @SHAMAN, 36, 59, 36, 63, 56, 67),
+(@GOBLIN, @SHAMAN, 37, 60, 36, 65, 57, 69),
+(@GOBLIN, @SHAMAN, 38, 61, 37, 66, 58, 70),
+(@GOBLIN, @SHAMAN, 39, 62, 38, 67, 60, 72),
+(@GOBLIN, @SHAMAN, 40, 64, 38, 69, 61, 73),
+(@GOBLIN, @SHAMAN, 41, 65, 39, 70, 62, 75),
+(@GOBLIN, @SHAMAN, 42, 66, 40, 72, 64, 76),
+(@GOBLIN, @SHAMAN, 43, 67, 40, 73, 65, 78),
+(@GOBLIN, @SHAMAN, 44, 69, 41, 74, 66, 79),
+(@GOBLIN, @SHAMAN, 45, 70, 42, 76, 68, 81),
+(@GOBLIN, @SHAMAN, 46, 71, 42, 77, 69, 82),
+(@GOBLIN, @SHAMAN, 47, 72, 43, 79, 70, 84),
+(@GOBLIN, @SHAMAN, 48, 74, 44, 80, 72, 85),
+(@GOBLIN, @SHAMAN, 49, 75, 45, 82, 73, 87),
+(@GOBLIN, @SHAMAN, 50, 76, 45, 83, 75, 89),
+(@GOBLIN, @SHAMAN, 51, 78, 46, 85, 76, 90),
+(@GOBLIN, @SHAMAN, 52, 79, 47, 86, 77, 92),
+(@GOBLIN, @SHAMAN, 53, 80, 47, 88, 79, 93),
+(@GOBLIN, @SHAMAN, 54, 82, 48, 90, 80, 95),
+(@GOBLIN, @SHAMAN, 55, 83, 49, 91, 82, 97),
+(@GOBLIN, @SHAMAN, 56, 85, 50, 93, 83, 98),
+(@GOBLIN, @SHAMAN, 57, 86, 50, 94, 85, 100),
+(@GOBLIN, @SHAMAN, 58, 87, 51, 96, 86, 102),
+(@GOBLIN, @SHAMAN, 59, 89, 52, 97, 88, 103),
+(@GOBLIN, @SHAMAN, 60, 90, 53, 99, 89, 105),
+(@GOBLIN, @SHAMAN, 61, 92, 54, 101, 91, 107),
+(@GOBLIN, @SHAMAN, 62, 93, 54, 102, 92, 109),
+(@GOBLIN, @SHAMAN, 63, 95, 55, 104, 94, 110),
+(@GOBLIN, @SHAMAN, 64, 96, 56, 106, 95, 112),
+(@GOBLIN, @SHAMAN, 65, 97, 57, 107, 97, 114),
+(@GOBLIN, @SHAMAN, 66, 99, 58, 109, 99, 116),
+(@GOBLIN, @SHAMAN, 67, 100, 58, 111, 100, 118),
+(@GOBLIN, @SHAMAN, 68, 102, 59, 113, 102, 119),
+(@GOBLIN, @SHAMAN, 69, 103, 60, 114, 103, 121),
+(@GOBLIN, @SHAMAN, 70, 105, 61, 116, 105, 123),
+(@GOBLIN, @SHAMAN, 71, 106, 62, 118, 117, 125),
+(@GOBLIN, @SHAMAN, 72, 108, 63, 120, 119, 128),
+(@GOBLIN, @SHAMAN, 73, 110, 64, 122, 122, 130),
+(@GOBLIN, @SHAMAN, 74, 112, 65, 125, 124, 132),
+(@GOBLIN, @SHAMAN, 75, 114, 66, 127, 126, 134),
+(@GOBLIN, @SHAMAN, 76, 116, 67, 129, 128, 137),
+(@GOBLIN, @SHAMAN, 77, 117, 68, 131, 128, 139),
+(@GOBLIN, @SHAMAN, 78, 119, 69, 133, 133, 141),
+(@GOBLIN, @SHAMAN, 79, 121, 70, 136, 135, 144),
+(@GOBLIN, @SHAMAN, 80, 123, 71, 138, 137, 146),
+(@GOBLIN, @SHAMAN, 81, 133, 81, 148, 147, 156),
+(@GOBLIN, @SHAMAN, 82, 143, 91, 158, 157, 166),
+(@GOBLIN, @SHAMAN, 83, 153, 101, 168, 167, 176),
+(@GOBLIN, @SHAMAN, 84, 163, 111, 178, 177, 186),
+(@GOBLIN, @SHAMAN, 85, 173, 121, 188, 187, 196),
+(@GOBLIN, @MAGE, 1, 20, 20, 20, 23, 22),
+(@GOBLIN, @MAGE, 2, 20, 20, 20, 24, 23),
+(@GOBLIN, @MAGE, 3, 20, 20, 21, 26, 25),
+(@GOBLIN, @MAGE, 4, 20, 20, 21, 27, 26),
+(@GOBLIN, @MAGE, 5, 20, 21, 21, 28, 27),
+(@GOBLIN, @MAGE, 6, 20, 21, 21, 30, 29),
+(@GOBLIN, @MAGE, 7, 21, 21, 22, 31, 30),
+(@GOBLIN, @MAGE, 8, 21, 21, 22, 33, 31),
+(@GOBLIN, @MAGE, 9, 21, 21, 22, 34, 33),
+(@GOBLIN, @MAGE, 10, 21, 21, 23, 36, 34),
+(@GOBLIN, @MAGE, 11, 21, 22, 23, 37, 36),
+(@GOBLIN, @MAGE, 12, 21, 22, 23, 39, 37),
+(@GOBLIN, @MAGE, 13, 21, 22, 24, 40, 38),
+(@GOBLIN, @MAGE, 14, 21, 22, 24, 42, 40),
+(@GOBLIN, @MAGE, 15, 21, 22, 24, 43, 41),
+(@GOBLIN, @MAGE, 16, 21, 23, 25, 45, 43),
+(@GOBLIN, @MAGE, 17, 22, 23, 25, 46, 44),
+(@GOBLIN, @MAGE, 18, 22, 23, 25, 48, 46),
+(@GOBLIN, @MAGE, 19, 22, 23, 26, 49, 47),
+(@GOBLIN, @MAGE, 20, 22, 23, 26, 51, 49),
+(@GOBLIN, @MAGE, 21, 22, 24, 26, 53, 51),
+(@GOBLIN, @MAGE, 22, 22, 24, 27, 54, 52),
+(@GOBLIN, @MAGE, 23, 22, 24, 27, 56, 54),
+(@GOBLIN, @MAGE, 24, 23, 24, 28, 58, 55),
+(@GOBLIN, @MAGE, 25, 23, 25, 28, 59, 57),
+(@GOBLIN, @MAGE, 26, 23, 25, 28, 61, 59),
+(@GOBLIN, @MAGE, 27, 23, 25, 29, 63, 60),
+(@GOBLIN, @MAGE, 28, 23, 25, 29, 65, 62),
+(@GOBLIN, @MAGE, 29, 23, 25, 30, 66, 64),
+(@GOBLIN, @MAGE, 30, 24, 26, 30, 68, 65),
+(@GOBLIN, @MAGE, 31, 24, 26, 30, 70, 67),
+(@GOBLIN, @MAGE, 32, 24, 26, 31, 72, 69),
+(@GOBLIN, @MAGE, 33, 24, 27, 31, 73, 70),
+(@GOBLIN, @MAGE, 34, 24, 27, 32, 75, 72),
+(@GOBLIN, @MAGE, 35, 24, 27, 32, 77, 74),
+(@GOBLIN, @MAGE, 36, 25, 27, 33, 79, 76),
+(@GOBLIN, @MAGE, 37, 25, 28, 33, 81, 78),
+(@GOBLIN, @MAGE, 38, 25, 28, 34, 83, 79),
+(@GOBLIN, @MAGE, 39, 25, 28, 34, 85, 81),
+(@GOBLIN, @MAGE, 40, 25, 28, 35, 87, 83),
+(@GOBLIN, @MAGE, 41, 26, 29, 35, 88, 85),
+(@GOBLIN, @MAGE, 42, 26, 29, 35, 90, 87),
+(@GOBLIN, @MAGE, 43, 26, 29, 36, 92, 89),
+(@GOBLIN, @MAGE, 44, 26, 30, 36, 94, 91),
+(@GOBLIN, @MAGE, 45, 26, 30, 37, 96, 92),
+(@GOBLIN, @MAGE, 46, 27, 30, 37, 98, 94),
+(@GOBLIN, @MAGE, 47, 27, 31, 38, 100, 96),
+(@GOBLIN, @MAGE, 48, 27, 31, 38, 102, 98),
+(@GOBLIN, @MAGE, 49, 27, 31, 39, 104, 100),
+(@GOBLIN, @MAGE, 50, 28, 32, 40, 106, 102),
+(@GOBLIN, @MAGE, 51, 28, 32, 40, 109, 104),
+(@GOBLIN, @MAGE, 52, 28, 32, 41, 111, 106),
+(@GOBLIN, @MAGE, 53, 28, 33, 41, 113, 108),
+(@GOBLIN, @MAGE, 54, 29, 33, 42, 115, 110),
+(@GOBLIN, @MAGE, 55, 29, 33, 42, 117, 112),
+(@GOBLIN, @MAGE, 56, 29, 34, 43, 119, 114),
+(@GOBLIN, @MAGE, 57, 29, 34, 43, 121, 117),
+(@GOBLIN, @MAGE, 58, 30, 34, 44, 124, 119),
+(@GOBLIN, @MAGE, 59, 30, 35, 44, 126, 121),
+(@GOBLIN, @MAGE, 60, 30, 35, 45, 128, 123),
+(@GOBLIN, @MAGE, 61, 30, 35, 46, 130, 125),
+(@GOBLIN, @MAGE, 62, 31, 36, 46, 132, 127),
+(@GOBLIN, @MAGE, 63, 31, 36, 47, 135, 129),
+(@GOBLIN, @MAGE, 64, 31, 37, 47, 137, 132),
+(@GOBLIN, @MAGE, 65, 32, 37, 48, 139, 134),
+(@GOBLIN, @MAGE, 66, 32, 37, 49, 142, 136),
+(@GOBLIN, @MAGE, 67, 32, 38, 49, 144, 138),
+(@GOBLIN, @MAGE, 68, 32, 38, 50, 146, 140),
+(@GOBLIN, @MAGE, 69, 33, 39, 50, 149, 143),
+(@GOBLIN, @MAGE, 70, 33, 39, 51, 151, 145),
+(@GOBLIN, @MAGE, 71, 33, 39, 52, 154, 152),
+(@GOBLIN, @MAGE, 72, 33, 40, 53, 160, 155),
+(@GOBLIN, @MAGE, 73, 33, 40, 54, 160, 158),
+(@GOBLIN, @MAGE, 74, 34, 41, 54, 163, 160),
+(@GOBLIN, @MAGE, 75, 34, 41, 55, 166, 163),
+(@GOBLIN, @MAGE, 76, 34, 41, 56, 169, 166),
+(@GOBLIN, @MAGE, 77, 35, 42, 57, 172, 169),
+(@GOBLIN, @MAGE, 78, 35, 42, 57, 175, 173),
+(@GOBLIN, @MAGE, 79, 35, 43, 58, 178, 176),
+(@GOBLIN, @MAGE, 80, 36, 43, 59, 181, 179),
+(@GOBLIN, @MAGE, 81, 46, 53, 69, 191, 189),
+(@GOBLIN, @MAGE, 82, 56, 63, 79, 201, 199),
+(@GOBLIN, @MAGE, 83, 66, 73, 89, 211, 209),
+(@GOBLIN, @MAGE, 84, 76, 83, 99, 221, 219),
+(@GOBLIN, @MAGE, 85, 86, 93, 109, 231, 229),
+(@GOBLIN, @WARLOCK, 1, 20, 20, 21, 22, 22),
+(@GOBLIN, @WARLOCK, 2, 20, 20, 22, 23, 23),
+(@GOBLIN, @WARLOCK, 3, 21, 21, 22, 24, 24),
+(@GOBLIN, @WARLOCK, 4, 21, 21, 23, 26, 25),
+(@GOBLIN, @WARLOCK, 5, 21, 21, 23, 27, 27),
+(@GOBLIN, @WARLOCK, 6, 21, 22, 24, 28, 28),
+(@GOBLIN, @WARLOCK, 7, 22, 22, 24, 29, 29),
+(@GOBLIN, @WARLOCK, 8, 22, 23, 25, 30, 30),
+(@GOBLIN, @WARLOCK, 9, 22, 23, 26, 32, 31),
+(@GOBLIN, @WARLOCK, 10, 23, 23, 26, 33, 33),
+(@GOBLIN, @WARLOCK, 11, 23, 24, 27, 34, 34),
+(@GOBLIN, @WARLOCK, 12, 23, 24, 27, 35, 35),
+(@GOBLIN, @WARLOCK, 13, 24, 25, 28, 37, 36),
+(@GOBLIN, @WARLOCK, 14, 24, 25, 29, 38, 38),
+(@GOBLIN, @WARLOCK, 15, 24, 25, 29, 39, 39),
+(@GOBLIN, @WARLOCK, 16, 25, 26, 30, 41, 40),
+(@GOBLIN, @WARLOCK, 17, 25, 26, 31, 42, 42),
+(@GOBLIN, @WARLOCK, 18, 25, 27, 31, 43, 43),
+(@GOBLIN, @WARLOCK, 19, 26, 27, 32, 45, 44),
+(@GOBLIN, @WARLOCK, 20, 26, 28, 33, 46, 46),
+(@GOBLIN, @WARLOCK, 21, 26, 28, 33, 48, 47),
+(@GOBLIN, @WARLOCK, 22, 27, 29, 34, 49, 49),
+(@GOBLIN, @WARLOCK, 23, 27, 29, 35, 51, 50),
+(@GOBLIN, @WARLOCK, 24, 28, 30, 35, 52, 51),
+(@GOBLIN, @WARLOCK, 25, 28, 30, 36, 53, 53),
+(@GOBLIN, @WARLOCK, 26, 28, 31, 37, 55, 54),
+(@GOBLIN, @WARLOCK, 27, 29, 31, 37, 56, 56),
+(@GOBLIN, @WARLOCK, 28, 29, 32, 38, 58, 57),
+(@GOBLIN, @WARLOCK, 29, 30, 32, 39, 59, 59),
+(@GOBLIN, @WARLOCK, 30, 30, 33, 40, 61, 60),
+(@GOBLIN, @WARLOCK, 31, 30, 33, 40, 62, 62),
+(@GOBLIN, @WARLOCK, 32, 31, 34, 41, 64, 63),
+(@GOBLIN, @WARLOCK, 33, 31, 34, 42, 66, 65),
+(@GOBLIN, @WARLOCK, 34, 32, 35, 43, 67, 66),
+(@GOBLIN, @WARLOCK, 35, 32, 35, 44, 69, 68),
+(@GOBLIN, @WARLOCK, 36, 33, 36, 44, 70, 69),
+(@GOBLIN, @WARLOCK, 37, 33, 36, 45, 72, 71),
+(@GOBLIN, @WARLOCK, 38, 34, 37, 46, 74, 73),
+(@GOBLIN, @WARLOCK, 39, 34, 38, 47, 75, 74),
+(@GOBLIN, @WARLOCK, 40, 35, 38, 48, 77, 76),
+(@GOBLIN, @WARLOCK, 41, 35, 39, 48, 79, 78),
+(@GOBLIN, @WARLOCK, 42, 35, 39, 49, 80, 79),
+(@GOBLIN, @WARLOCK, 43, 36, 40, 50, 82, 81),
+(@GOBLIN, @WARLOCK, 44, 36, 40, 51, 84, 83),
+(@GOBLIN, @WARLOCK, 45, 37, 41, 52, 85, 84),
+(@GOBLIN, @WARLOCK, 46, 37, 42, 53, 87, 86),
+(@GOBLIN, @WARLOCK, 47, 38, 42, 54, 89, 88),
+(@GOBLIN, @WARLOCK, 48, 38, 43, 55, 91, 89),
+(@GOBLIN, @WARLOCK, 49, 39, 44, 55, 93, 91),
+(@GOBLIN, @WARLOCK, 50, 40, 44, 56, 94, 93),
+(@GOBLIN, @WARLOCK, 51, 40, 45, 57, 96, 95),
+(@GOBLIN, @WARLOCK, 52, 41, 45, 58, 98, 97),
+(@GOBLIN, @WARLOCK, 53, 41, 46, 59, 100, 98),
+(@GOBLIN, @WARLOCK, 54, 42, 47, 60, 102, 100),
+(@GOBLIN, @WARLOCK, 55, 42, 47, 61, 103, 102),
+(@GOBLIN, @WARLOCK, 56, 43, 48, 62, 105, 104),
+(@GOBLIN, @WARLOCK, 57, 43, 49, 63, 107, 106),
+(@GOBLIN, @WARLOCK, 58, 44, 49, 64, 109, 108),
+(@GOBLIN, @WARLOCK, 59, 44, 50, 65, 111, 109),
+(@GOBLIN, @WARLOCK, 60, 45, 51, 66, 113, 111),
+(@GOBLIN, @WARLOCK, 61, 46, 51, 67, 115, 113),
+(@GOBLIN, @WARLOCK, 62, 46, 52, 68, 117, 115),
+(@GOBLIN, @WARLOCK, 63, 47, 53, 69, 119, 117),
+(@GOBLIN, @WARLOCK, 64, 47, 54, 70, 121, 119),
+(@GOBLIN, @WARLOCK, 65, 48, 54, 71, 123, 121),
+(@GOBLIN, @WARLOCK, 66, 49, 55, 72, 125, 123),
+(@GOBLIN, @WARLOCK, 67, 49, 56, 73, 127, 125),
+(@GOBLIN, @WARLOCK, 68, 50, 57, 74, 129, 127),
+(@GOBLIN, @WARLOCK, 69, 50, 57, 75, 131, 129),
+(@GOBLIN, @WARLOCK, 70, 51, 58, 76, 133, 131),
+(@GOBLIN, @WARLOCK, 71, 52, 59, 78, 135, 146),
+(@GOBLIN, @WARLOCK, 72, 53, 59, 79, 138, 148),
+(@GOBLIN, @WARLOCK, 73, 54, 60, 80, 140, 151),
+(@GOBLIN, @WARLOCK, 74, 54, 61, 89, 143, 154),
+(@GOBLIN, @WARLOCK, 75, 55, 62, 91, 145, 156),
+(@GOBLIN, @WARLOCK, 76, 56, 63, 92, 148, 159),
+(@GOBLIN, @WARLOCK, 77, 57, 64, 93, 151, 162),
+(@GOBLIN, @WARLOCK, 78, 57, 65, 95, 153, 165),
+(@GOBLIN, @WARLOCK, 79, 58, 66, 96, 156, 168),
+(@GOBLIN, @WARLOCK, 80, 59, 67, 97, 159, 170),
+(@GOBLIN, @WARLOCK, 81, 69, 77, 107, 169, 180),
+(@GOBLIN, @WARLOCK, 82, 79, 87, 117, 179, 190),
+(@GOBLIN, @WARLOCK, 83, 89, 97, 127, 189, 200),
+(@GOBLIN, @WARLOCK, 84, 99, 107, 137, 199, 210),
+(@GOBLIN, @WARLOCK, 85, 109, 117, 147, 209, 220);
+
+DELETE FROM `player_levelstats` WHERE `race`=@WORGEN;
+INSERT INTO `player_levelstats` VALUES
+(@WORGEN, @WARRIOR, 1, 23, 20, 22, 20, 20),
+(@WORGEN, @WARRIOR, 2, 24, 21, 23, 20, 20),
+(@WORGEN, @WARRIOR, 3, 26, 22, 24, 20, 21),
+(@WORGEN, @WARRIOR, 4, 27, 22, 26, 20, 21),
+(@WORGEN, @WARRIOR, 5, 28, 23, 27, 20, 21),
+(@WORGEN, @WARRIOR, 6, 30, 24, 28, 20, 21),
+(@WORGEN, @WARRIOR, 7, 31, 25, 29, 21, 22),
+(@WORGEN, @WARRIOR, 8, 32, 26, 30, 21, 22),
+(@WORGEN, @WARRIOR, 9, 34, 26, 32, 21, 22),
+(@WORGEN, @WARRIOR, 10, 35, 27, 33, 21, 23),
+(@WORGEN, @WARRIOR, 11, 36, 28, 34, 21, 23),
+(@WORGEN, @WARRIOR, 12, 38, 29, 35, 21, 23),
+(@WORGEN, @WARRIOR, 13, 39, 30, 37, 21, 24),
+(@WORGEN, @WARRIOR, 14, 41, 31, 38, 21, 24),
+(@WORGEN, @WARRIOR, 15, 42, 32, 39, 21, 24),
+(@WORGEN, @WARRIOR, 16, 44, 33, 41, 21, 25),
+(@WORGEN, @WARRIOR, 17, 45, 34, 42, 22, 25),
+(@WORGEN, @WARRIOR, 18, 47, 34, 43, 22, 25),
+(@WORGEN, @WARRIOR, 19, 48, 35, 45, 22, 26),
+(@WORGEN, @WARRIOR, 20, 50, 36, 46, 22, 26),
+(@WORGEN, @WARRIOR, 21, 51, 37, 48, 22, 26),
+(@WORGEN, @WARRIOR, 22, 53, 38, 49, 22, 27),
+(@WORGEN, @WARRIOR, 23, 54, 39, 51, 22, 27),
+(@WORGEN, @WARRIOR, 24, 56, 40, 52, 23, 28),
+(@WORGEN, @WARRIOR, 25, 58, 41, 53, 23, 28),
+(@WORGEN, @WARRIOR, 26, 59, 42, 55, 23, 28),
+(@WORGEN, @WARRIOR, 27, 61, 43, 56, 23, 29),
+(@WORGEN, @WARRIOR, 28, 63, 44, 58, 23, 29),
+(@WORGEN, @WARRIOR, 29, 64, 45, 59, 23, 30),
+(@WORGEN, @WARRIOR, 30, 66, 46, 61, 24, 30),
+(@WORGEN, @WARRIOR, 31, 68, 47, 62, 24, 30),
+(@WORGEN, @WARRIOR, 32, 69, 48, 64, 24, 31),
+(@WORGEN, @WARRIOR, 33, 71, 50, 66, 24, 31),
+(@WORGEN, @WARRIOR, 34, 73, 51, 67, 24, 32),
+(@WORGEN, @WARRIOR, 35, 74, 52, 69, 24, 32),
+(@WORGEN, @WARRIOR, 36, 76, 53, 70, 25, 33),
+(@WORGEN, @WARRIOR, 37, 78, 54, 72, 25, 33),
+(@WORGEN, @WARRIOR, 38, 80, 55, 74, 25, 34),
+(@WORGEN, @WARRIOR, 39, 82, 56, 75, 25, 34),
+(@WORGEN, @WARRIOR, 40, 83, 57, 77, 25, 35),
+(@WORGEN, @WARRIOR, 41, 85, 58, 79, 26, 35),
+(@WORGEN, @WARRIOR, 42, 87, 60, 80, 26, 35),
+(@WORGEN, @WARRIOR, 43, 89, 61, 82, 26, 36),
+(@WORGEN, @WARRIOR, 44, 91, 62, 84, 26, 36),
+(@WORGEN, @WARRIOR, 45, 93, 63, 85, 26, 37),
+(@WORGEN, @WARRIOR, 46, 95, 64, 87, 27, 37),
+(@WORGEN, @WARRIOR, 47, 97, 66, 89, 27, 38),
+(@WORGEN, @WARRIOR, 48, 99, 67, 91, 27, 38),
+(@WORGEN, @WARRIOR, 49, 101, 68, 93, 27, 39),
+(@WORGEN, @WARRIOR, 50, 103, 69, 94, 28, 40),
+(@WORGEN, @WARRIOR, 51, 105, 71, 96, 28, 40),
+(@WORGEN, @WARRIOR, 52, 107, 72, 98, 28, 41),
+(@WORGEN, @WARRIOR, 53, 109, 73, 100, 28, 41),
+(@WORGEN, @WARRIOR, 54, 111, 74, 102, 29, 42),
+(@WORGEN, @WARRIOR, 55, 113, 76, 103, 29, 42),
+(@WORGEN, @WARRIOR, 56, 115, 77, 105, 29, 43),
+(@WORGEN, @WARRIOR, 57, 117, 78, 107, 29, 43),
+(@WORGEN, @WARRIOR, 58, 119, 79, 109, 30, 44),
+(@WORGEN, @WARRIOR, 59, 121, 81, 111, 30, 44),
+(@WORGEN, @WARRIOR, 60, 123, 82, 113, 30, 45),
+(@WORGEN, @WARRIOR, 61, 125, 83, 115, 30, 46),
+(@WORGEN, @WARRIOR, 62, 127, 85, 117, 31, 46),
+(@WORGEN, @WARRIOR, 63, 129, 86, 119, 31, 47),
+(@WORGEN, @WARRIOR, 64, 132, 88, 121, 31, 47),
+(@WORGEN, @WARRIOR, 65, 134, 89, 123, 32, 48),
+(@WORGEN, @WARRIOR, 66, 136, 90, 125, 32, 49),
+(@WORGEN, @WARRIOR, 67, 138, 92, 127, 32, 49),
+(@WORGEN, @WARRIOR, 68, 140, 93, 129, 32, 50),
+(@WORGEN, @WARRIOR, 69, 143, 95, 131, 33, 50),
+(@WORGEN, @WARRIOR, 70, 145, 96, 133, 33, 51),
+(@WORGEN, @WARRIOR, 71, 148, 97, 140, 33, 53),
+(@WORGEN, @WARRIOR, 72, 156, 99, 143, 33, 54),
+(@WORGEN, @WARRIOR, 73, 162, 101, 148, 33, 55),
+(@WORGEN, @WARRIOR, 74, 162, 102, 148, 34, 55),
+(@WORGEN, @WARRIOR, 75, 165, 104, 150, 34, 56),
+(@WORGEN, @WARRIOR, 76, 171, 106, 156, 34, 57),
+(@WORGEN, @WARRIOR, 77, 171, 108, 157, 35, 58),
+(@WORGEN, @WARRIOR, 78, 174, 109, 159, 35, 58),
+(@WORGEN, @WARRIOR, 79, 181, 111, 165, 35, 59),
+(@WORGEN, @WARRIOR, 80, 184, 113, 168, 36, 60),
+(@WORGEN, @WARRIOR, 81, 194, 123, 178, 46, 70),
+(@WORGEN, @WARRIOR, 82, 204, 133, 188, 56, 80),
+(@WORGEN, @WARRIOR, 83, 214, 143, 198, 66, 90),
+(@WORGEN, @WARRIOR, 84, 224, 153, 208, 76, 100),
+(@WORGEN, @WARRIOR, 85, 234, 163, 218, 86, 110),
+(@WORGEN, @HUNTER, 1, 22, 20, 22, 20, 21),
+(@WORGEN, @HUNTER, 2, 23, 21, 23, 21, 22),
+(@WORGEN, @HUNTER, 3, 24, 21, 24, 21, 22),
+(@WORGEN, @HUNTER, 4, 25, 22, 25, 22, 23),
+(@WORGEN, @HUNTER, 5, 26, 22, 26, 23, 24),
+(@WORGEN, @HUNTER, 6, 28, 23, 27, 23, 25),
+(@WORGEN, @HUNTER, 7, 29, 24, 28, 24, 25),
+(@WORGEN, @HUNTER, 8, 30, 24, 29, 25, 26),
+(@WORGEN, @HUNTER, 9, 31, 25, 30, 25, 27),
+(@WORGEN, @HUNTER, 10, 32, 25, 32, 26, 27),
+(@WORGEN, @HUNTER, 11, 33, 26, 33, 27, 28),
+(@WORGEN, @HUNTER, 12, 35, 27, 34, 27, 29),
+(@WORGEN, @HUNTER, 13, 36, 27, 35, 28, 30),
+(@WORGEN, @HUNTER, 14, 37, 28, 36, 29, 31),
+(@WORGEN, @HUNTER, 15, 38, 29, 37, 30, 31),
+(@WORGEN, @HUNTER, 16, 40, 29, 38, 30, 32),
+(@WORGEN, @HUNTER, 17, 41, 30, 40, 31, 33),
+(@WORGEN, @HUNTER, 18, 42, 31, 41, 32, 34),
+(@WORGEN, @HUNTER, 19, 43, 31, 42, 33, 35),
+(@WORGEN, @HUNTER, 20, 45, 32, 43, 33, 35),
+(@WORGEN, @HUNTER, 21, 46, 33, 45, 34, 36),
+(@WORGEN, @HUNTER, 22, 47, 33, 46, 35, 37),
+(@WORGEN, @HUNTER, 23, 49, 34, 47, 36, 38),
+(@WORGEN, @HUNTER, 24, 50, 35, 48, 37, 39),
+(@WORGEN, @HUNTER, 25, 51, 36, 50, 37, 40),
+(@WORGEN, @HUNTER, 26, 53, 36, 51, 38, 41),
+(@WORGEN, @HUNTER, 27, 54, 37, 52, 39, 42),
+(@WORGEN, @HUNTER, 28, 56, 38, 54, 40, 43),
+(@WORGEN, @HUNTER, 29, 57, 39, 55, 41, 43),
+(@WORGEN, @HUNTER, 30, 58, 39, 56, 42, 44),
+(@WORGEN, @HUNTER, 31, 60, 40, 58, 43, 45),
+(@WORGEN, @HUNTER, 32, 61, 41, 59, 43, 46),
+(@WORGEN, @HUNTER, 33, 63, 42, 60, 44, 47),
+(@WORGEN, @HUNTER, 34, 64, 43, 62, 45, 48),
+(@WORGEN, @HUNTER, 35, 66, 44, 63, 46, 49),
+(@WORGEN, @HUNTER, 36, 67, 44, 65, 47, 50),
+(@WORGEN, @HUNTER, 37, 69, 45, 66, 48, 51),
+(@WORGEN, @HUNTER, 38, 70, 46, 67, 49, 52),
+(@WORGEN, @HUNTER, 39, 72, 47, 69, 50, 53),
+(@WORGEN, @HUNTER, 40, 73, 48, 70, 51, 54),
+(@WORGEN, @HUNTER, 41, 75, 49, 72, 52, 55),
+(@WORGEN, @HUNTER, 42, 77, 49, 73, 53, 56),
+(@WORGEN, @HUNTER, 43, 78, 50, 75, 54, 57),
+(@WORGEN, @HUNTER, 44, 80, 51, 76, 55, 58),
+(@WORGEN, @HUNTER, 45, 81, 52, 78, 56, 59),
+(@WORGEN, @HUNTER, 46, 83, 53, 79, 57, 61),
+(@WORGEN, @HUNTER, 47, 85, 54, 81, 58, 62),
+(@WORGEN, @HUNTER, 48, 86, 55, 83, 59, 63),
+(@WORGEN, @HUNTER, 49, 88, 56, 84, 60, 64),
+(@WORGEN, @HUNTER, 50, 90, 57, 86, 61, 65),
+(@WORGEN, @HUNTER, 51, 91, 58, 87, 62, 66),
+(@WORGEN, @HUNTER, 52, 93, 59, 89, 63, 67),
+(@WORGEN, @HUNTER, 53, 95, 60, 91, 64, 68),
+(@WORGEN, @HUNTER, 54, 97, 61, 92, 65, 69),
+(@WORGEN, @HUNTER, 55, 98, 61, 94, 66, 71),
+(@WORGEN, @HUNTER, 56, 100, 62, 95, 67, 72),
+(@WORGEN, @HUNTER, 57, 102, 63, 97, 68, 73),
+(@WORGEN, @HUNTER, 58, 104, 64, 99, 69, 74),
+(@WORGEN, @HUNTER, 59, 105, 65, 101, 70, 75),
+(@WORGEN, @HUNTER, 60, 107, 66, 102, 71, 77),
+(@WORGEN, @HUNTER, 61, 109, 67, 104, 73, 78),
+(@WORGEN, @HUNTER, 62, 111, 69, 106, 74, 79),
+(@WORGEN, @HUNTER, 63, 113, 70, 107, 75, 80),
+(@WORGEN, @HUNTER, 64, 115, 71, 109, 76, 81),
+(@WORGEN, @HUNTER, 65, 116, 72, 111, 77, 83),
+(@WORGEN, @HUNTER, 66, 118, 73, 113, 78, 84),
+(@WORGEN, @HUNTER, 67, 120, 74, 115, 79, 85),
+(@WORGEN, @HUNTER, 68, 122, 75, 116, 81, 86),
+(@WORGEN, @HUNTER, 69, 124, 76, 118, 82, 88),
+(@WORGEN, @HUNTER, 70, 126, 77, 120, 83, 89),
+(@WORGEN, @HUNTER, 71, 148, 78, 122, 84, 92),
+(@WORGEN, @HUNTER, 72, 150, 79, 125, 86, 94),
+(@WORGEN, @HUNTER, 73, 152, 80, 127, 87, 96),
+(@WORGEN, @HUNTER, 74, 156, 82, 129, 89, 97),
+(@WORGEN, @HUNTER, 75, 158, 83, 131, 90, 99),
+(@WORGEN, @HUNTER, 76, 162, 84, 134, 92, 100),
+(@WORGEN, @HUNTER, 77, 164, 86, 136, 93, 103),
+(@WORGEN, @HUNTER, 78, 167, 87, 138, 95, 105),
+(@WORGEN, @HUNTER, 79, 170, 88, 153, 96, 106),
+(@WORGEN, @HUNTER, 80, 173, 90, 160, 98, 108),
+(@WORGEN, @HUNTER, 81, 183, 100, 170, 108, 118),
+(@WORGEN, @HUNTER, 82, 193, 110, 180, 118, 128),
+(@WORGEN, @HUNTER, 83, 203, 120, 190, 128, 138),
+(@WORGEN, @HUNTER, 84, 213, 130, 200, 138, 148),
+(@WORGEN, @HUNTER, 85, 223, 140, 210, 148, 158),
+(@WORGEN, @ROGUE, 1, 21, 23, 21, 20, 20),
+(@WORGEN, @ROGUE, 2, 22, 24, 22, 20, 20),
+(@WORGEN, @ROGUE, 3, 23, 26, 22, 20, 21),
+(@WORGEN, @ROGUE, 4, 23, 27, 23, 20, 21),
+(@WORGEN, @ROGUE, 5, 24, 29, 24, 21, 21),
+(@WORGEN, @ROGUE, 6, 25, 30, 25, 21, 22),
+(@WORGEN, @ROGUE, 7, 26, 32, 25, 21, 22),
+(@WORGEN, @ROGUE, 8, 26, 33, 26, 21, 23),
+(@WORGEN, @ROGUE, 9, 27, 35, 27, 21, 23),
+(@WORGEN, @ROGUE, 10, 28, 36, 27, 21, 23),
+(@WORGEN, @ROGUE, 11, 29, 38, 28, 22, 24),
+(@WORGEN, @ROGUE, 12, 30, 39, 29, 22, 24),
+(@WORGEN, @ROGUE, 13, 31, 41, 30, 22, 25),
+(@WORGEN, @ROGUE, 14, 31, 43, 31, 22, 25),
+(@WORGEN, @ROGUE, 15, 32, 44, 31, 22, 25),
+(@WORGEN, @ROGUE, 16, 33, 46, 32, 23, 26),
+(@WORGEN, @ROGUE, 17, 34, 48, 33, 23, 26),
+(@WORGEN, @ROGUE, 18, 35, 49, 34, 23, 27),
+(@WORGEN, @ROGUE, 19, 36, 51, 35, 23, 27),
+(@WORGEN, @ROGUE, 20, 37, 53, 35, 23, 28),
+(@WORGEN, @ROGUE, 21, 38, 54, 36, 24, 28),
+(@WORGEN, @ROGUE, 22, 39, 56, 37, 24, 29),
+(@WORGEN, @ROGUE, 23, 40, 58, 38, 24, 29),
+(@WORGEN, @ROGUE, 24, 41, 60, 39, 24, 30),
+(@WORGEN, @ROGUE, 25, 42, 61, 40, 25, 30),
+(@WORGEN, @ROGUE, 26, 43, 63, 41, 25, 31),
+(@WORGEN, @ROGUE, 27, 44, 65, 42, 25, 31),
+(@WORGEN, @ROGUE, 28, 45, 67, 43, 25, 32),
+(@WORGEN, @ROGUE, 29, 46, 69, 43, 25, 32),
+(@WORGEN, @ROGUE, 30, 47, 71, 44, 26, 33),
+(@WORGEN, @ROGUE, 31, 48, 72, 45, 26, 33),
+(@WORGEN, @ROGUE, 32, 49, 74, 46, 26, 34),
+(@WORGEN, @ROGUE, 33, 50, 76, 47, 27, 34),
+(@WORGEN, @ROGUE, 34, 51, 78, 48, 27, 35),
+(@WORGEN, @ROGUE, 35, 52, 80, 49, 27, 35),
+(@WORGEN, @ROGUE, 36, 53, 82, 50, 27, 36),
+(@WORGEN, @ROGUE, 37, 54, 84, 51, 28, 36),
+(@WORGEN, @ROGUE, 38, 55, 86, 52, 28, 37),
+(@WORGEN, @ROGUE, 39, 56, 88, 53, 28, 38),
+(@WORGEN, @ROGUE, 40, 57, 90, 54, 28, 38),
+(@WORGEN, @ROGUE, 41, 58, 92, 55, 29, 39),
+(@WORGEN, @ROGUE, 42, 60, 94, 56, 29, 39),
+(@WORGEN, @ROGUE, 43, 61, 96, 57, 29, 40),
+(@WORGEN, @ROGUE, 44, 62, 98, 58, 30, 40),
+(@WORGEN, @ROGUE, 45, 63, 100, 59, 30, 41),
+(@WORGEN, @ROGUE, 46, 64, 103, 61, 30, 42),
+(@WORGEN, @ROGUE, 47, 65, 105, 62, 31, 42),
+(@WORGEN, @ROGUE, 48, 66, 107, 63, 31, 43),
+(@WORGEN, @ROGUE, 49, 68, 109, 64, 31, 44),
+(@WORGEN, @ROGUE, 50, 69, 111, 65, 32, 44),
+(@WORGEN, @ROGUE, 51, 70, 113, 66, 32, 45),
+(@WORGEN, @ROGUE, 52, 71, 116, 67, 32, 45),
+(@WORGEN, @ROGUE, 53, 73, 118, 68, 33, 46),
+(@WORGEN, @ROGUE, 54, 74, 120, 69, 33, 47),
+(@WORGEN, @ROGUE, 55, 75, 122, 71, 33, 47),
+(@WORGEN, @ROGUE, 56, 76, 125, 72, 34, 48),
+(@WORGEN, @ROGUE, 57, 78, 127, 73, 34, 49),
+(@WORGEN, @ROGUE, 58, 79, 129, 74, 34, 49),
+(@WORGEN, @ROGUE, 59, 80, 131, 75, 35, 50),
+(@WORGEN, @ROGUE, 60, 81, 134, 77, 35, 51),
+(@WORGEN, @ROGUE, 61, 83, 136, 78, 35, 51),
+(@WORGEN, @ROGUE, 62, 84, 138, 79, 36, 52),
+(@WORGEN, @ROGUE, 63, 85, 141, 80, 36, 53),
+(@WORGEN, @ROGUE, 64, 87, 143, 81, 37, 54),
+(@WORGEN, @ROGUE, 65, 88, 146, 83, 37, 54),
+(@WORGEN, @ROGUE, 66, 89, 148, 84, 37, 55),
+(@WORGEN, @ROGUE, 67, 91, 151, 85, 38, 56),
+(@WORGEN, @ROGUE, 68, 92, 153, 86, 38, 57),
+(@WORGEN, @ROGUE, 69, 94, 156, 88, 39, 57),
+(@WORGEN, @ROGUE, 70, 95, 158, 89, 39, 58),
+(@WORGEN, @ROGUE, 71, 97, 161, 90, 39, 60),
+(@WORGEN, @ROGUE, 72, 99, 164, 92, 40, 60),
+(@WORGEN, @ROGUE, 73, 100, 167, 94, 40, 61),
+(@WORGEN, @ROGUE, 74, 102, 170, 95, 41, 62),
+(@WORGEN, @ROGUE, 75, 104, 173, 97, 41, 63),
+(@WORGEN, @ROGUE, 76, 105, 176, 98, 41, 64),
+(@WORGEN, @ROGUE, 77, 107, 179, 100, 42, 65),
+(@WORGEN, @ROGUE, 78, 109, 183, 106, 42, 66),
+(@WORGEN, @ROGUE, 79, 111, 186, 107, 43, 67),
+(@WORGEN, @ROGUE, 80, 113, 189, 109, 43, 69),
+(@WORGEN, @ROGUE, 81, 123, 199, 119, 53, 79),
+(@WORGEN, @ROGUE, 82, 133, 209, 129, 63, 89),
+(@WORGEN, @ROGUE, 83, 143, 219, 139, 73, 99),
+(@WORGEN, @ROGUE, 84, 153, 229, 149, 83, 109),
+(@WORGEN, @ROGUE, 85, 163, 239, 159, 93, 119),
+(@WORGEN, @PRIEST, 1, 20, 20, 20, 22, 23),
+(@WORGEN, @PRIEST, 2, 20, 20, 20, 23, 24),
+(@WORGEN, @PRIEST, 3, 20, 20, 21, 25, 26),
+(@WORGEN, @PRIEST, 4, 20, 21, 21, 26, 27),
+(@WORGEN, @PRIEST, 5, 21, 21, 21, 27, 28),
+(@WORGEN, @PRIEST, 6, 21, 21, 22, 29, 30),
+(@WORGEN, @PRIEST, 7, 21, 21, 22, 30, 31),
+(@WORGEN, @PRIEST, 8, 21, 22, 23, 31, 33),
+(@WORGEN, @PRIEST, 9, 21, 22, 23, 33, 34),
+(@WORGEN, @PRIEST, 10, 21, 22, 23, 34, 36),
+(@WORGEN, @PRIEST, 11, 22, 22, 24, 36, 37),
+(@WORGEN, @PRIEST, 12, 22, 23, 24, 37, 39),
+(@WORGEN, @PRIEST, 13, 22, 23, 25, 38, 40),
+(@WORGEN, @PRIEST, 14, 22, 23, 25, 40, 42),
+(@WORGEN, @PRIEST, 15, 22, 23, 25, 41, 43),
+(@WORGEN, @PRIEST, 16, 23, 24, 26, 43, 45),
+(@WORGEN, @PRIEST, 17, 23, 24, 26, 44, 46),
+(@WORGEN, @PRIEST, 18, 23, 24, 27, 46, 48),
+(@WORGEN, @PRIEST, 19, 23, 24, 27, 47, 49),
+(@WORGEN, @PRIEST, 20, 23, 25, 28, 49, 51),
+(@WORGEN, @PRIEST, 21, 24, 25, 28, 51, 53),
+(@WORGEN, @PRIEST, 22, 24, 25, 29, 52, 54),
+(@WORGEN, @PRIEST, 23, 24, 26, 29, 54, 56),
+(@WORGEN, @PRIEST, 24, 24, 26, 30, 55, 58),
+(@WORGEN, @PRIEST, 25, 25, 26, 30, 57, 59),
+(@WORGEN, @PRIEST, 26, 25, 27, 31, 59, 61),
+(@WORGEN, @PRIEST, 27, 25, 27, 31, 60, 63),
+(@WORGEN, @PRIEST, 28, 25, 27, 32, 62, 65),
+(@WORGEN, @PRIEST, 29, 25, 28, 32, 64, 66),
+(@WORGEN, @PRIEST, 30, 26, 28, 33, 65, 68),
+(@WORGEN, @PRIEST, 31, 26, 28, 33, 67, 70),
+(@WORGEN, @PRIEST, 32, 26, 29, 34, 69, 72),
+(@WORGEN, @PRIEST, 33, 27, 29, 34, 70, 73),
+(@WORGEN, @PRIEST, 34, 27, 29, 35, 72, 75),
+(@WORGEN, @PRIEST, 35, 27, 30, 35, 74, 77),
+(@WORGEN, @PRIEST, 36, 27, 30, 36, 76, 79),
+(@WORGEN, @PRIEST, 37, 28, 30, 36, 78, 81),
+(@WORGEN, @PRIEST, 38, 28, 31, 37, 79, 83),
+(@WORGEN, @PRIEST, 39, 28, 31, 38, 81, 85),
+(@WORGEN, @PRIEST, 40, 28, 31, 38, 83, 87),
+(@WORGEN, @PRIEST, 41, 29, 32, 39, 85, 88),
+(@WORGEN, @PRIEST, 42, 29, 32, 39, 87, 90),
+(@WORGEN, @PRIEST, 43, 29, 33, 40, 89, 92),
+(@WORGEN, @PRIEST, 44, 30, 33, 40, 91, 94),
+(@WORGEN, @PRIEST, 45, 30, 33, 41, 92, 96),
+(@WORGEN, @PRIEST, 46, 30, 34, 42, 94, 98),
+(@WORGEN, @PRIEST, 47, 31, 34, 42, 96, 100),
+(@WORGEN, @PRIEST, 48, 31, 35, 43, 98, 102),
+(@WORGEN, @PRIEST, 49, 31, 35, 44, 100, 104),
+(@WORGEN, @PRIEST, 50, 32, 36, 44, 102, 106),
+(@WORGEN, @PRIEST, 51, 32, 36, 45, 104, 109),
+(@WORGEN, @PRIEST, 52, 32, 36, 45, 106, 111),
+(@WORGEN, @PRIEST, 53, 33, 37, 46, 108, 113),
+(@WORGEN, @PRIEST, 54, 33, 37, 47, 110, 115),
+(@WORGEN, @PRIEST, 55, 33, 38, 47, 112, 117),
+(@WORGEN, @PRIEST, 56, 34, 38, 48, 114, 119),
+(@WORGEN, @PRIEST, 57, 34, 39, 49, 117, 121),
+(@WORGEN, @PRIEST, 58, 34, 39, 49, 119, 124),
+(@WORGEN, @PRIEST, 59, 35, 40, 50, 121, 126),
+(@WORGEN, @PRIEST, 60, 35, 40, 51, 123, 128),
+(@WORGEN, @PRIEST, 61, 35, 41, 51, 125, 130),
+(@WORGEN, @PRIEST, 62, 36, 41, 52, 127, 132),
+(@WORGEN, @PRIEST, 63, 36, 41, 53, 129, 135),
+(@WORGEN, @PRIEST, 64, 37, 42, 54, 132, 137),
+(@WORGEN, @PRIEST, 65, 37, 42, 54, 134, 139),
+(@WORGEN, @PRIEST, 66, 37, 43, 55, 136, 142),
+(@WORGEN, @PRIEST, 67, 38, 43, 56, 138, 144),
+(@WORGEN, @PRIEST, 68, 38, 44, 57, 140, 146),
+(@WORGEN, @PRIEST, 69, 39, 44, 57, 143, 149),
+(@WORGEN, @PRIEST, 70, 39, 45, 58, 145, 151),
+(@WORGEN, @PRIEST, 71, 39, 46, 59, 148, 158),
+(@WORGEN, @PRIEST, 72, 40, 46, 59, 151, 161),
+(@WORGEN, @PRIEST, 73, 40, 47, 60, 154, 164),
+(@WORGEN, @PRIEST, 74, 41, 47, 61, 156, 167),
+(@WORGEN, @PRIEST, 75, 41, 48, 62, 159, 170),
+(@WORGEN, @PRIEST, 76, 41, 49, 63, 162, 174),
+(@WORGEN, @PRIEST, 77, 42, 49, 64, 165, 177),
+(@WORGEN, @PRIEST, 78, 42, 50, 65, 168, 180),
+(@WORGEN, @PRIEST, 79, 43, 50, 66, 171, 183),
+(@WORGEN, @PRIEST, 80, 43, 51, 67, 174, 186),
+(@WORGEN, @PRIEST, 81, 53, 61, 77, 184, 196),
+(@WORGEN, @PRIEST, 82, 63, 71, 87, 194, 206),
+(@WORGEN, @PRIEST, 83, 73, 81, 97, 204, 216),
+(@WORGEN, @PRIEST, 84, 83, 91, 107, 214, 226),
+(@WORGEN, @PRIEST, 85, 93, 101, 117, 224, 236),
+(@WORGEN, @DK, 1, 23, 20, 22, 20, 20),
+(@WORGEN, @DK, 2, 24, 21, 23, 20, 20),
+(@WORGEN, @DK, 3, 26, 22, 24, 20, 21),
+(@WORGEN, @DK, 4, 27, 22, 26, 20, 21),
+(@WORGEN, @DK, 5, 28, 23, 27, 20, 21),
+(@WORGEN, @DK, 6, 30, 24, 28, 20, 21),
+(@WORGEN, @DK, 7, 31, 25, 29, 21, 22),
+(@WORGEN, @DK, 8, 32, 26, 30, 21, 22),
+(@WORGEN, @DK, 9, 34, 26, 32, 21, 22),
+(@WORGEN, @DK, 10, 35, 27, 33, 21, 23),
+(@WORGEN, @DK, 11, 36, 28, 34, 21, 23),
+(@WORGEN, @DK, 12, 38, 29, 35, 21, 23),
+(@WORGEN, @DK, 13, 39, 30, 37, 21, 24),
+(@WORGEN, @DK, 14, 41, 31, 38, 21, 24),
+(@WORGEN, @DK, 15, 42, 32, 39, 21, 24),
+(@WORGEN, @DK, 16, 44, 33, 41, 21, 25),
+(@WORGEN, @DK, 17, 45, 34, 42, 22, 25),
+(@WORGEN, @DK, 18, 47, 34, 43, 22, 25),
+(@WORGEN, @DK, 19, 48, 35, 45, 22, 26),
+(@WORGEN, @DK, 20, 50, 36, 46, 22, 26),
+(@WORGEN, @DK, 21, 51, 37, 48, 22, 26),
+(@WORGEN, @DK, 22, 53, 38, 49, 22, 27),
+(@WORGEN, @DK, 23, 54, 39, 51, 22, 27),
+(@WORGEN, @DK, 24, 56, 40, 52, 23, 28),
+(@WORGEN, @DK, 25, 58, 41, 53, 23, 28),
+(@WORGEN, @DK, 26, 59, 42, 55, 23, 28),
+(@WORGEN, @DK, 27, 61, 43, 56, 23, 29),
+(@WORGEN, @DK, 28, 63, 44, 58, 23, 29),
+(@WORGEN, @DK, 29, 64, 45, 59, 23, 30),
+(@WORGEN, @DK, 30, 66, 46, 61, 24, 30),
+(@WORGEN, @DK, 31, 68, 47, 62, 24, 30),
+(@WORGEN, @DK, 32, 69, 48, 64, 24, 31),
+(@WORGEN, @DK, 33, 71, 50, 66, 24, 31),
+(@WORGEN, @DK, 34, 73, 51, 67, 24, 32),
+(@WORGEN, @DK, 35, 74, 52, 69, 24, 32),
+(@WORGEN, @DK, 36, 76, 53, 70, 25, 33),
+(@WORGEN, @DK, 37, 78, 54, 72, 25, 33),
+(@WORGEN, @DK, 38, 80, 55, 74, 25, 34),
+(@WORGEN, @DK, 39, 82, 56, 75, 25, 34),
+(@WORGEN, @DK, 40, 83, 57, 77, 25, 35),
+(@WORGEN, @DK, 41, 85, 58, 79, 26, 35),
+(@WORGEN, @DK, 42, 87, 60, 80, 26, 35),
+(@WORGEN, @DK, 43, 89, 61, 82, 26, 36),
+(@WORGEN, @DK, 44, 91, 62, 84, 26, 36),
+(@WORGEN, @DK, 45, 93, 63, 85, 26, 37),
+(@WORGEN, @DK, 46, 95, 64, 87, 27, 37),
+(@WORGEN, @DK, 47, 97, 66, 89, 27, 38),
+(@WORGEN, @DK, 48, 99, 67, 91, 27, 38),
+(@WORGEN, @DK, 49, 101, 68, 93, 27, 39),
+(@WORGEN, @DK, 50, 103, 69, 94, 28, 40),
+(@WORGEN, @DK, 51, 105, 71, 96, 28, 40),
+(@WORGEN, @DK, 52, 106, 72, 97, 28, 41),
+(@WORGEN, @DK, 53, 107, 72, 98, 28, 41),
+(@WORGEN, @DK, 54, 107, 73, 98, 29, 42),
+(@WORGEN, @DK, 55, 108, 73, 99, 29, 43),
+(@WORGEN, @DK, 56, 111, 75, 102, 29, 44),
+(@WORGEN, @DK, 57, 113, 76, 104, 29, 44),
+(@WORGEN, @DK, 58, 118, 77, 106, 30, 45),
+(@WORGEN, @DK, 59, 118, 79, 108, 30, 45),
+(@WORGEN, @DK, 60, 123, 80, 110, 30, 46),
+(@WORGEN, @DK, 61, 125, 81, 112, 30, 47),
+(@WORGEN, @DK, 62, 128, 83, 114, 30, 47),
+(@WORGEN, @DK, 63, 130, 84, 117, 31, 48),
+(@WORGEN, @DK, 64, 130, 86, 119, 31, 48),
+(@WORGEN, @DK, 65, 140, 87, 128, 31, 49),
+(@WORGEN, @DK, 66, 143, 89, 131, 31, 50),
+(@WORGEN, @DK, 67, 146, 90, 133, 32, 50),
+(@WORGEN, @DK, 68, 148, 92, 135, 32, 51),
+(@WORGEN, @DK, 69, 151, 93, 138, 32, 52),
+(@WORGEN, @DK, 70, 154, 95, 140, 32, 52),
+(@WORGEN, @DK, 71, 162, 97, 144, 33, 53),
+(@WORGEN, @DK, 72, 164, 98, 146, 33, 54),
+(@WORGEN, @DK, 73, 165, 100, 148, 33, 55),
+(@WORGEN, @DK, 74, 166, 102, 151, 33, 55),
+(@WORGEN, @DK, 75, 169, 103, 154, 34, 56),
+(@WORGEN, @DK, 76, 172, 105, 157, 34, 57),
+(@WORGEN, @DK, 77, 175, 107, 157, 34, 58),
+(@WORGEN, @DK, 78, 176, 108, 157, 34, 58),
+(@WORGEN, @DK, 79, 177, 110, 157, 35, 59),
+(@WORGEN, @DK, 80, 180, 112, 160, 35, 60),
+(@WORGEN, @DK, 81, 190, 122, 170, 45, 70),
+(@WORGEN, @DK, 82, 200, 132, 180, 55, 80),
+(@WORGEN, @DK, 83, 210, 142, 190, 65, 90),
+(@WORGEN, @DK, 84, 220, 152, 200, 75, 100),
+(@WORGEN, @DK, 85, 230, 162, 210, 85, 110),
+(@WORGEN, @MAGE, 1, 20, 20, 20, 23, 22),
+(@WORGEN, @MAGE, 2, 20, 20, 20, 24, 23),
+(@WORGEN, @MAGE, 3, 20, 20, 21, 26, 25),
+(@WORGEN, @MAGE, 4, 20, 20, 21, 27, 26),
+(@WORGEN, @MAGE, 5, 20, 21, 21, 28, 27),
+(@WORGEN, @MAGE, 6, 20, 21, 21, 30, 29),
+(@WORGEN, @MAGE, 7, 21, 21, 22, 31, 30),
+(@WORGEN, @MAGE, 8, 21, 21, 22, 33, 31),
+(@WORGEN, @MAGE, 9, 21, 21, 22, 34, 33),
+(@WORGEN, @MAGE, 10, 21, 21, 23, 36, 34),
+(@WORGEN, @MAGE, 11, 21, 22, 23, 37, 36),
+(@WORGEN, @MAGE, 12, 21, 22, 23, 39, 37),
+(@WORGEN, @MAGE, 13, 21, 22, 24, 40, 38),
+(@WORGEN, @MAGE, 14, 21, 22, 24, 42, 40),
+(@WORGEN, @MAGE, 15, 21, 22, 24, 43, 41),
+(@WORGEN, @MAGE, 16, 21, 23, 25, 45, 43),
+(@WORGEN, @MAGE, 17, 22, 23, 25, 46, 44),
+(@WORGEN, @MAGE, 18, 22, 23, 25, 48, 46),
+(@WORGEN, @MAGE, 19, 22, 23, 26, 49, 47),
+(@WORGEN, @MAGE, 20, 22, 23, 26, 51, 49),
+(@WORGEN, @MAGE, 21, 22, 24, 26, 53, 51),
+(@WORGEN, @MAGE, 22, 22, 24, 27, 54, 52),
+(@WORGEN, @MAGE, 23, 22, 24, 27, 56, 54),
+(@WORGEN, @MAGE, 24, 23, 24, 28, 58, 55),
+(@WORGEN, @MAGE, 25, 23, 25, 28, 59, 57),
+(@WORGEN, @MAGE, 26, 23, 25, 28, 61, 59),
+(@WORGEN, @MAGE, 27, 23, 25, 29, 63, 60),
+(@WORGEN, @MAGE, 28, 23, 25, 29, 65, 62),
+(@WORGEN, @MAGE, 29, 23, 25, 30, 66, 64),
+(@WORGEN, @MAGE, 30, 24, 26, 30, 68, 65),
+(@WORGEN, @MAGE, 31, 24, 26, 30, 70, 67),
+(@WORGEN, @MAGE, 32, 24, 26, 31, 72, 69),
+(@WORGEN, @MAGE, 33, 24, 27, 31, 73, 70),
+(@WORGEN, @MAGE, 34, 24, 27, 32, 75, 72),
+(@WORGEN, @MAGE, 35, 24, 27, 32, 77, 74),
+(@WORGEN, @MAGE, 36, 25, 27, 33, 79, 76),
+(@WORGEN, @MAGE, 37, 25, 28, 33, 81, 78),
+(@WORGEN, @MAGE, 38, 25, 28, 34, 83, 79),
+(@WORGEN, @MAGE, 39, 25, 28, 34, 85, 81),
+(@WORGEN, @MAGE, 40, 25, 28, 35, 87, 83),
+(@WORGEN, @MAGE, 41, 26, 29, 35, 88, 85),
+(@WORGEN, @MAGE, 42, 26, 29, 35, 90, 87),
+(@WORGEN, @MAGE, 43, 26, 29, 36, 92, 89),
+(@WORGEN, @MAGE, 44, 26, 30, 36, 94, 91),
+(@WORGEN, @MAGE, 45, 26, 30, 37, 96, 92),
+(@WORGEN, @MAGE, 46, 27, 30, 37, 98, 94),
+(@WORGEN, @MAGE, 47, 27, 31, 38, 100, 96),
+(@WORGEN, @MAGE, 48, 27, 31, 38, 102, 98),
+(@WORGEN, @MAGE, 49, 27, 31, 39, 104, 100),
+(@WORGEN, @MAGE, 50, 28, 32, 40, 106, 102),
+(@WORGEN, @MAGE, 51, 28, 32, 40, 109, 104),
+(@WORGEN, @MAGE, 52, 28, 32, 41, 111, 106),
+(@WORGEN, @MAGE, 53, 28, 33, 41, 113, 108),
+(@WORGEN, @MAGE, 54, 29, 33, 42, 115, 110),
+(@WORGEN, @MAGE, 55, 29, 33, 42, 117, 112),
+(@WORGEN, @MAGE, 56, 29, 34, 43, 119, 114),
+(@WORGEN, @MAGE, 57, 29, 34, 43, 121, 117),
+(@WORGEN, @MAGE, 58, 30, 34, 44, 124, 119),
+(@WORGEN, @MAGE, 59, 30, 35, 44, 126, 121),
+(@WORGEN, @MAGE, 60, 30, 35, 45, 128, 123),
+(@WORGEN, @MAGE, 61, 30, 35, 46, 130, 125),
+(@WORGEN, @MAGE, 62, 31, 36, 46, 132, 127),
+(@WORGEN, @MAGE, 63, 31, 36, 47, 135, 129),
+(@WORGEN, @MAGE, 64, 31, 37, 47, 137, 132),
+(@WORGEN, @MAGE, 65, 32, 37, 48, 139, 134),
+(@WORGEN, @MAGE, 66, 32, 37, 49, 142, 136),
+(@WORGEN, @MAGE, 67, 32, 38, 49, 144, 138),
+(@WORGEN, @MAGE, 68, 32, 38, 50, 146, 140),
+(@WORGEN, @MAGE, 69, 33, 39, 50, 149, 143),
+(@WORGEN, @MAGE, 70, 33, 39, 51, 151, 145),
+(@WORGEN, @MAGE, 71, 33, 39, 52, 154, 152),
+(@WORGEN, @MAGE, 72, 33, 40, 53, 160, 155),
+(@WORGEN, @MAGE, 73, 33, 40, 54, 160, 158),
+(@WORGEN, @MAGE, 74, 34, 41, 54, 163, 160),
+(@WORGEN, @MAGE, 75, 34, 41, 55, 166, 163),
+(@WORGEN, @MAGE, 76, 34, 41, 56, 169, 166),
+(@WORGEN, @MAGE, 77, 35, 42, 57, 172, 169),
+(@WORGEN, @MAGE, 78, 35, 42, 57, 175, 173),
+(@WORGEN, @MAGE, 79, 35, 43, 58, 178, 176),
+(@WORGEN, @MAGE, 80, 36, 43, 59, 181, 179),
+(@WORGEN, @MAGE, 81, 46, 53, 69, 191, 189),
+(@WORGEN, @MAGE, 82, 56, 63, 79, 201, 199),
+(@WORGEN, @MAGE, 83, 66, 73, 89, 211, 209),
+(@WORGEN, @MAGE, 84, 76, 83, 99, 221, 219),
+(@WORGEN, @MAGE, 85, 86, 93, 109, 231, 229),
+(@WORGEN, @WARLOCK, 1, 20, 20, 21, 22, 22),
+(@WORGEN, @WARLOCK, 2, 20, 20, 22, 23, 23),
+(@WORGEN, @WARLOCK, 3, 21, 21, 22, 24, 24),
+(@WORGEN, @WARLOCK, 4, 21, 21, 23, 26, 25),
+(@WORGEN, @WARLOCK, 5, 21, 21, 23, 27, 27),
+(@WORGEN, @WARLOCK, 6, 21, 22, 24, 28, 28),
+(@WORGEN, @WARLOCK, 7, 22, 22, 24, 29, 29),
+(@WORGEN, @WARLOCK, 8, 22, 23, 25, 30, 30),
+(@WORGEN, @WARLOCK, 9, 22, 23, 26, 32, 31),
+(@WORGEN, @WARLOCK, 10, 23, 23, 26, 33, 33),
+(@WORGEN, @WARLOCK, 11, 23, 24, 27, 34, 34),
+(@WORGEN, @WARLOCK, 12, 23, 24, 27, 35, 35),
+(@WORGEN, @WARLOCK, 13, 24, 25, 28, 37, 36),
+(@WORGEN, @WARLOCK, 14, 24, 25, 29, 38, 38),
+(@WORGEN, @WARLOCK, 15, 24, 25, 29, 39, 39),
+(@WORGEN, @WARLOCK, 16, 25, 26, 30, 41, 40),
+(@WORGEN, @WARLOCK, 17, 25, 26, 31, 42, 42),
+(@WORGEN, @WARLOCK, 18, 25, 27, 31, 43, 43),
+(@WORGEN, @WARLOCK, 19, 26, 27, 32, 45, 44),
+(@WORGEN, @WARLOCK, 20, 26, 28, 33, 46, 46),
+(@WORGEN, @WARLOCK, 21, 26, 28, 33, 48, 47),
+(@WORGEN, @WARLOCK, 22, 27, 29, 34, 49, 49),
+(@WORGEN, @WARLOCK, 23, 27, 29, 35, 51, 50),
+(@WORGEN, @WARLOCK, 24, 28, 30, 35, 52, 51),
+(@WORGEN, @WARLOCK, 25, 28, 30, 36, 53, 53),
+(@WORGEN, @WARLOCK, 26, 28, 31, 37, 55, 54),
+(@WORGEN, @WARLOCK, 27, 29, 31, 37, 56, 56),
+(@WORGEN, @WARLOCK, 28, 29, 32, 38, 58, 57),
+(@WORGEN, @WARLOCK, 29, 30, 32, 39, 59, 59),
+(@WORGEN, @WARLOCK, 30, 30, 33, 40, 61, 60),
+(@WORGEN, @WARLOCK, 31, 30, 33, 40, 62, 62),
+(@WORGEN, @WARLOCK, 32, 31, 34, 41, 64, 63),
+(@WORGEN, @WARLOCK, 33, 31, 34, 42, 66, 65),
+(@WORGEN, @WARLOCK, 34, 32, 35, 43, 67, 66),
+(@WORGEN, @WARLOCK, 35, 32, 35, 44, 69, 68),
+(@WORGEN, @WARLOCK, 36, 33, 36, 44, 70, 69),
+(@WORGEN, @WARLOCK, 37, 33, 36, 45, 72, 71),
+(@WORGEN, @WARLOCK, 38, 34, 37, 46, 74, 73),
+(@WORGEN, @WARLOCK, 39, 34, 38, 47, 75, 74),
+(@WORGEN, @WARLOCK, 40, 35, 38, 48, 77, 76),
+(@WORGEN, @WARLOCK, 41, 35, 39, 48, 79, 78),
+(@WORGEN, @WARLOCK, 42, 35, 39, 49, 80, 79),
+(@WORGEN, @WARLOCK, 43, 36, 40, 50, 82, 81),
+(@WORGEN, @WARLOCK, 44, 36, 40, 51, 84, 83),
+(@WORGEN, @WARLOCK, 45, 37, 41, 52, 85, 84),
+(@WORGEN, @WARLOCK, 46, 37, 42, 53, 87, 86),
+(@WORGEN, @WARLOCK, 47, 38, 42, 54, 89, 88),
+(@WORGEN, @WARLOCK, 48, 38, 43, 55, 91, 89),
+(@WORGEN, @WARLOCK, 49, 39, 44, 55, 93, 91),
+(@WORGEN, @WARLOCK, 50, 40, 44, 56, 94, 93),
+(@WORGEN, @WARLOCK, 51, 40, 45, 57, 96, 95),
+(@WORGEN, @WARLOCK, 52, 41, 45, 58, 98, 97),
+(@WORGEN, @WARLOCK, 53, 41, 46, 59, 100, 98),
+(@WORGEN, @WARLOCK, 54, 42, 47, 60, 102, 100),
+(@WORGEN, @WARLOCK, 55, 42, 47, 61, 103, 102),
+(@WORGEN, @WARLOCK, 56, 43, 48, 62, 105, 104),
+(@WORGEN, @WARLOCK, 57, 43, 49, 63, 107, 106),
+(@WORGEN, @WARLOCK, 58, 44, 49, 64, 109, 108),
+(@WORGEN, @WARLOCK, 59, 44, 50, 65, 111, 109),
+(@WORGEN, @WARLOCK, 60, 45, 51, 66, 113, 111),
+(@WORGEN, @WARLOCK, 61, 46, 51, 67, 115, 113),
+(@WORGEN, @WARLOCK, 62, 46, 52, 68, 117, 115),
+(@WORGEN, @WARLOCK, 63, 47, 53, 69, 119, 117),
+(@WORGEN, @WARLOCK, 64, 47, 54, 70, 121, 119),
+(@WORGEN, @WARLOCK, 65, 48, 54, 71, 123, 121),
+(@WORGEN, @WARLOCK, 66, 49, 55, 72, 125, 123),
+(@WORGEN, @WARLOCK, 67, 49, 56, 73, 127, 125),
+(@WORGEN, @WARLOCK, 68, 50, 57, 74, 129, 127),
+(@WORGEN, @WARLOCK, 69, 50, 57, 75, 131, 129),
+(@WORGEN, @WARLOCK, 70, 51, 58, 76, 133, 131),
+(@WORGEN, @WARLOCK, 71, 52, 59, 78, 135, 146),
+(@WORGEN, @WARLOCK, 72, 53, 59, 79, 138, 148),
+(@WORGEN, @WARLOCK, 73, 54, 60, 80, 140, 151),
+(@WORGEN, @WARLOCK, 74, 54, 61, 89, 143, 154),
+(@WORGEN, @WARLOCK, 75, 55, 62, 91, 145, 156),
+(@WORGEN, @WARLOCK, 76, 56, 63, 92, 148, 159),
+(@WORGEN, @WARLOCK, 77, 57, 64, 93, 151, 162),
+(@WORGEN, @WARLOCK, 78, 57, 65, 95, 153, 165),
+(@WORGEN, @WARLOCK, 79, 58, 66, 96, 156, 168),
+(@WORGEN, @WARLOCK, 80, 59, 67, 97, 159, 170),
+(@WORGEN, @WARLOCK, 81, 69, 77, 107, 169, 180),
+(@WORGEN, @WARLOCK, 82, 79, 87, 117, 179, 190),
+(@WORGEN, @WARLOCK, 83, 89, 97, 127, 189, 200),
+(@WORGEN, @WARLOCK, 84, 99, 107, 137, 199, 210),
+(@WORGEN, @WARLOCK, 85, 109, 117, 147, 209, 220),
+(@WORGEN, @DRUID, 1, 26, 15, 22, 17, 24),
+(@WORGEN, @DRUID, 2, 27, 16, 23, 18, 25),
+(@WORGEN, @DRUID, 3, 27, 16, 23, 19, 26),
+(@WORGEN, @DRUID, 4, 28, 17, 24, 20, 27),
+(@WORGEN, @DRUID, 5, 28, 17, 25, 21, 29),
+(@WORGEN, @DRUID, 6, 29, 18, 25, 22, 30),
+(@WORGEN, @DRUID, 7, 29, 18, 26, 23, 31),
+(@WORGEN, @DRUID, 8, 30, 19, 27, 24, 32),
+(@WORGEN, @DRUID, 9, 30, 19, 27, 26, 34),
+(@WORGEN, @DRUID, 10, 31, 20, 28, 27, 35),
+(@WORGEN, @DRUID, 11, 32, 20, 29, 28, 36),
+(@WORGEN, @DRUID, 12, 32, 21, 29, 29, 37),
+(@WORGEN, @DRUID, 13, 33, 21, 30, 30, 39),
+(@WORGEN, @DRUID, 14, 33, 22, 31, 31, 40),
+(@WORGEN, @DRUID, 15, 34, 23, 32, 32, 41),
+(@WORGEN, @DRUID, 16, 35, 23, 32, 34, 43),
+(@WORGEN, @DRUID, 17, 35, 24, 33, 35, 44),
+(@WORGEN, @DRUID, 18, 36, 24, 34, 36, 45),
+(@WORGEN, @DRUID, 19, 37, 25, 35, 37, 47),
+(@WORGEN, @DRUID, 20, 37, 26, 35, 39, 48),
+(@WORGEN, @DRUID, 21, 38, 26, 36, 40, 50),
+(@WORGEN, @DRUID, 22, 39, 27, 37, 41, 51),
+(@WORGEN, @DRUID, 23, 39, 28, 38, 42, 52),
+(@WORGEN, @DRUID, 24, 40, 28, 39, 44, 54),
+(@WORGEN, @DRUID, 25, 41, 29, 39, 45, 55),
+(@WORGEN, @DRUID, 26, 41, 30, 40, 46, 57),
+(@WORGEN, @DRUID, 27, 42, 30, 41, 47, 58),
+(@WORGEN, @DRUID, 28, 43, 31, 42, 49, 60),
+(@WORGEN, @DRUID, 29, 44, 32, 43, 50, 61),
+(@WORGEN, @DRUID, 30, 44, 32, 44, 52, 63),
+(@WORGEN, @DRUID, 31, 45, 33, 44, 53, 64),
+(@WORGEN, @DRUID, 32, 46, 34, 45, 54, 66),
+(@WORGEN, @DRUID, 33, 47, 34, 46, 56, 67),
+(@WORGEN, @DRUID, 34, 47, 35, 47, 57, 69),
+(@WORGEN, @DRUID, 35, 48, 36, 48, 58, 71),
+(@WORGEN, @DRUID, 36, 49, 36, 49, 60, 72),
+(@WORGEN, @DRUID, 37, 50, 37, 50, 61, 74),
+(@WORGEN, @DRUID, 38, 51, 38, 51, 63, 76),
+(@WORGEN, @DRUID, 39, 52, 39, 52, 64, 77),
+(@WORGEN, @DRUID, 40, 52, 39, 53, 66, 79),
+(@WORGEN, @DRUID, 41, 53, 40, 54, 67, 81),
+(@WORGEN, @DRUID, 42, 54, 41, 55, 69, 82),
+(@WORGEN, @DRUID, 43, 55, 42, 56, 70, 84),
+(@WORGEN, @DRUID, 44, 56, 43, 57, 72, 86),
+(@WORGEN, @DRUID, 45, 57, 43, 57, 73, 87),
+(@WORGEN, @DRUID, 46, 57, 44, 58, 75, 89),
+(@WORGEN, @DRUID, 47, 58, 45, 60, 76, 91),
+(@WORGEN, @DRUID, 48, 59, 46, 61, 78, 93),
+(@WORGEN, @DRUID, 49, 60, 47, 62, 79, 94),
+(@WORGEN, @DRUID, 50, 61, 47, 63, 81, 96),
+(@WORGEN, @DRUID, 51, 62, 48, 64, 83, 98),
+(@WORGEN, @DRUID, 52, 63, 49, 65, 84, 100),
+(@WORGEN, @DRUID, 53, 64, 50, 66, 86, 102),
+(@WORGEN, @DRUID, 54, 65, 51, 67, 87, 104),
+(@WORGEN, @DRUID, 55, 66, 51, 68, 89, 105),
+(@WORGEN, @DRUID, 56, 67, 52, 69, 91, 107),
+(@WORGEN, @DRUID, 57, 68, 53, 70, 92, 109),
+(@WORGEN, @DRUID, 58, 69, 54, 71, 94, 111),
+(@WORGEN, @DRUID, 59, 70, 55, 72, 96, 113),
+(@WORGEN, @DRUID, 60, 71, 56, 73, 97, 115),
+(@WORGEN, @DRUID, 61, 72, 57, 74, 99, 117),
+(@WORGEN, @DRUID, 62, 73, 58, 76, 101, 119),
+(@WORGEN, @DRUID, 63, 74, 59, 77, 103, 121),
+(@WORGEN, @DRUID, 64, 75, 59, 78, 104, 123),
+(@WORGEN, @DRUID, 65, 76, 60, 79, 106, 125),
+(@WORGEN, @DRUID, 66, 77, 61, 80, 108, 127),
+(@WORGEN, @DRUID, 67, 78, 62, 81, 110, 129),
+(@WORGEN, @DRUID, 68, 79, 63, 83, 111, 131),
+(@WORGEN, @DRUID, 69, 80, 64, 84, 113, 133),
+(@WORGEN, @DRUID, 70, 81, 65, 85, 115, 135),
+(@WORGEN, @DRUID, 71, 83, 66, 86, 117, 137),
+(@WORGEN, @DRUID, 72, 84, 68, 88, 120, 140),
+(@WORGEN, @DRUID, 73, 85, 69, 89, 122, 142),
+(@WORGEN, @DRUID, 74, 86, 70, 91, 124, 145),
+(@WORGEN, @DRUID, 75, 88, 71, 92, 126, 147),
+(@WORGEN, @DRUID, 76, 89, 72, 94, 128, 150),
+(@WORGEN, @DRUID, 77, 90, 73, 95, 131, 153),
+(@WORGEN, @DRUID, 78, 92, 75, 97, 133, 155),
+(@WORGEN, @DRUID, 79, 93, 76, 98, 136, 158),
+(@WORGEN, @DRUID, 80, 94, 77, 100, 138, 185),
+(@WORGEN, @DRUID, 81, 104, 87, 110, 148, 195),
+(@WORGEN, @DRUID, 82, 114, 97, 120, 158, 205),
+(@WORGEN, @DRUID, 83, 124, 107, 130, 168, 215),
+(@WORGEN, @DRUID, 84, 134, 117, 140, 178, 225),
+(@WORGEN, @DRUID, 85, 144, 127, 150, 188, 235);
diff --git a/sql/old/4.2.2/2011_12_21_00_world_locales_quest_4x.sql b/sql/old/4.2.2/2011_12_21_00_world_locales_quest_4x.sql
new file mode 100644
index 00000000000..2a6cc73ebdc
--- /dev/null
+++ b/sql/old/4.2.2/2011_12_21_00_world_locales_quest_4x.sql
@@ -0,0 +1,34 @@
+ALTER TABLE `locales_quest`
+ ADD `QuestGiverTextWindow_loc1` TEXT NULL DEFAULT NULL AFTER `ObjectiveText4_loc8`,
+ ADD `QuestGiverTextWindow_loc2` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc1`,
+ ADD `QuestGiverTextWindow_loc3` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc2`,
+ ADD `QuestGiverTextWindow_loc4` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc3`,
+ ADD `QuestGiverTextWindow_loc5` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc4`,
+ ADD `QuestGiverTextWindow_loc6` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc5`,
+ ADD `QuestGiverTextWindow_loc7` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc6`,
+ ADD `QuestGiverTextWindow_loc8` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc7`,
+ ADD `QuestGiverTargetName_loc1` TEXT NULL DEFAULT NULL AFTER `QuestGiverTextWindow_loc8`,
+ ADD `QuestGiverTargetName_loc2` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc1`,
+ ADD `QuestGiverTargetName_loc3` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc2`,
+ ADD `QuestGiverTargetName_loc4` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc3`,
+ ADD `QuestGiverTargetName_loc5` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc4`,
+ ADD `QuestGiverTargetName_loc6` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc5`,
+ ADD `QuestGiverTargetName_loc7` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc6`,
+ ADD `QuestGiverTargetName_loc8` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc7`,
+ ADD `QuestTurnTextWindow_loc1` TEXT NULL DEFAULT NULL AFTER `QuestGiverTargetName_loc8`,
+ ADD `QuestTurnTextWindow_loc2` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc1`,
+ ADD `QuestTurnTextWindow_loc3` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc2`,
+ ADD `QuestTurnTextWindow_loc4` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc3`,
+ ADD `QuestTurnTextWindow_loc5` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc4`,
+ ADD `QuestTurnTextWindow_loc6` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc5`,
+ ADD `QuestTurnTextWindow_loc7` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc6`,
+ ADD `QuestTurnTextWindow_loc8` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc7`,
+ ADD `QuestTurnTargetName_loc1` TEXT NULL DEFAULT NULL AFTER `QuestTurnTextWindow_loc8`,
+ ADD `QuestTurnTargetName_loc2` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc1`,
+ ADD `QuestTurnTargetName_loc3` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc2`,
+ ADD `QuestTurnTargetName_loc4` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc3`,
+ ADD `QuestTurnTargetName_loc5` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc4`,
+ ADD `QuestTurnTargetName_loc6` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc5`,
+ ADD `QuestTurnTargetName_loc7` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc6`,
+ ADD `QuestTurnTargetName_loc8` TEXT NULL DEFAULT NULL AFTER `QuestTurnTargetName_loc7`;
+ \ No newline at end of file
diff --git a/sql/old/4.2.2/2011_12_26_00_world_achievement_criteria_data_4x.sql b/sql/old/4.2.2/2011_12_26_00_world_achievement_criteria_data_4x.sql
new file mode 100644
index 00000000000..0f2936634fb
--- /dev/null
+++ b/sql/old/4.2.2/2011_12_26_00_world_achievement_criteria_data_4x.sql
@@ -0,0 +1,3 @@
+-- Remove unneeded achievement criteria datas for implemented DBC conditions:
+-- TYPE_T_PLAYER_DEAD 4, TYPE_S_AREA 6, TYPE_MAP_DIFFICULTY 12, TYPE_MAP_ID 20
+DELETE FROM achievement_criteria_data WHERE `type` IN (4, 6, 12, 20);
diff --git a/sql/old/4.2.2/2012_01_10_00_auth_account_4x.sql b/sql/old/4.2.2/2012_01_10_00_auth_account_4x.sql
new file mode 100644
index 00000000000..1e9016575fc
--- /dev/null
+++ b/sql/old/4.2.2/2012_01_10_00_auth_account_4x.sql
@@ -0,0 +1 @@
+ALTER TABLE `account` CHANGE COLUMN `expansion` `expansion` tinyint(3) unsigned NOT NULL DEFAULT '3';
diff --git a/sql/old/4.2.2/2012_01_29_00_characters_characters_4x.sql b/sql/old/4.2.2/2012_01_29_00_characters_characters_4x.sql
new file mode 100644
index 00000000000..baaf37ac467
--- /dev/null
+++ b/sql/old/4.2.2/2012_01_29_00_characters_characters_4x.sql
@@ -0,0 +1 @@
+ALTER TABLE `characters` ADD `talentTree` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `resettalents_time`;
diff --git a/sql/old/4.2.2/2012_01_29_01_characters_characters_4x.sql b/sql/old/4.2.2/2012_01_29_01_characters_characters_4x.sql
new file mode 100644
index 00000000000..ae8aefc75b6
--- /dev/null
+++ b/sql/old/4.2.2/2012_01_29_01_characters_characters_4x.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `characters` CHANGE `talentTree` `talentTree` varchar(10) NOT NULL DEFAULT '0 0 ' AFTER `resettalents_time`;
+UPDATE `characters` SET `talentTree`='0 0 ';
diff --git a/sql/old/4.2.2/2012_01_31_01_world_hotfix_data_4x.sql b/sql/old/4.2.2/2012_01_31_01_world_hotfix_data_4x.sql
new file mode 100644
index 00000000000..8c941ea7038
--- /dev/null
+++ b/sql/old/4.2.2/2012_01_31_01_world_hotfix_data_4x.sql
@@ -0,0 +1,42 @@
+DROP TABLE IF EXISTS `hotfix_data`;
+CREATE TABLE `hotfix_data` (
+ `entry` int(10) unsigned NOT NULL,
+ `type` int(10) unsigned NOT NULL DEFAULT '0',
+ `unk` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`entry`,`type`,`unk`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `hotfix_data`
+--
+
+INSERT INTO `hotfix_data` VALUES
+(6948,1344507586,1322022853),
+(44623,1344507586,1322022844),
+(44625,1344507586,1322022844),
+(44626,1344507586,1322022844),
+(44632,1344507586,1322022844),
+(44812,1344507586,1322022840),
+(44834,1344507586,1322022840),
+(44835,1344507586,1322022840),
+(44836,1344507586,1322022840),
+(44837,1344507586,1322022840),
+(44838,1344507586,1322022840),
+(44839,1344507586,1322022840),
+(44840,1344507586,1322022840),
+(44844,1344507586,1322022840),
+(44853,1344507586,1322022840),
+(44854,1344507586,1322022840),
+(44855,1344507586,1322022840),
+(44856,1344507586,1322022840),
+(46784,1344507586,1322022840),
+(46793,1344507586,1322022840),
+(46796,1344507586,1322022840),
+(46797,1344507586,1322022840),
+(46887,1344507586,1322022840),
+(46888,1344507586,1322022840),
+(64488,1344507586,1322022853),
+(69847,1344507586,1322022843),
+(69847,1344507586,1322022846),
+(72068,1344507586,1322022843),
+(72068,1344507586,1322022846);
diff --git a/sql/old/4.2.2/2012_01_31_02_world_hotfix_data_4x.sql b/sql/old/4.2.2/2012_01_31_02_world_hotfix_data_4x.sql
new file mode 100644
index 00000000000..ce45feed943
--- /dev/null
+++ b/sql/old/4.2.2/2012_01_31_02_world_hotfix_data_4x.sql
@@ -0,0 +1,5 @@
+ALTER TABLE hotfix_data ADD `hotfixDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `unk`;
+UPDATE `hotfix_data` SET `hotfixDate`=FROM_UNIXTIME(`unk`);
+ALTER TABLE `hotfix_data` DROP PRIMARY KEY;
+ALTER TABLE `hotfix_data` ADD PRIMARY KEY (`entry`,`type`,`hotfixDate`);
+ALTER TABLE `hotfix_data` DROP `unk`;
diff --git a/sql/old/4.2.2/2012_05_30_00_characters_characters_4x.sql b/sql/old/4.2.2/2012_05_30_00_characters_characters_4x.sql
new file mode 100644
index 00000000000..9336e826580
--- /dev/null
+++ b/sql/old/4.2.2/2012_05_30_00_characters_characters_4x.sql
@@ -0,0 +1,2 @@
+-- Remove unused flag
+UPDATE `characters` SET `extra_flags`=`extra_flags`&~0x40;
diff --git a/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_4x.sql b/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_4x.sql
new file mode 100644
index 00000000000..fffe375b464
--- /dev/null
+++ b/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_4x.sql
@@ -0,0 +1,24 @@
+--
+-- Table structure for table `guild_achievement`
+--
+
+DROP TABLE IF EXISTS `guild_achievement`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_achievement` (
+ `guildId` int(10) unsigned NOT NULL,
+ `achievement` smallint(5) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ `guids` text NOT NULL DEFAULT '',
+ PRIMARY KEY (`guildId`,`achievement`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_achievement`
+--
+
+LOCK TABLES `guild_achievement` WRITE;
+/*!40000 ALTER TABLE `guild_achievement` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_achievement` ENABLE KEYS */;
+UNLOCK TABLES;
diff --git a/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_progress_4x.sql b/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_progress_4x.sql
new file mode 100644
index 00000000000..c69e41a4ad4
--- /dev/null
+++ b/sql/old/4.2.2/2012_07_09_00_characters_guild_achievement_progress_4x.sql
@@ -0,0 +1,25 @@
+--
+-- Table structure for table `guild_achievement_progress`
+--
+
+DROP TABLE IF EXISTS `guild_achievement_progress`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `guild_achievement_progress` (
+ `guildId` int(10) unsigned NOT NULL,
+ `criteria` smallint(5) unsigned NOT NULL,
+ `counter` int(10) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ `completedGuid` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`guildId`,`criteria`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `guild_achievement_progress`
+--
+
+LOCK TABLES `guild_achievement_progress` WRITE;
+/*!40000 ALTER TABLE `guild_achievement_progress` DISABLE KEYS */;
+/*!40000 ALTER TABLE `guild_achievement_progress` ENABLE KEYS */;
+UNLOCK TABLES;
diff --git a/sql/old/4.2.2/2012_07_14_00_world_item_template_4x.sql b/sql/old/4.2.2/2012_07_14_00_world_item_template_4x.sql
new file mode 100644
index 00000000000..cf0749243ce
--- /dev/null
+++ b/sql/old/4.2.2/2012_07_14_00_world_item_template_4x.sql
@@ -0,0 +1,4 @@
+ALTER TABLE `item_template`
+ ADD `Unk430_1` float unsigned NOT NULL DEFAULT '1' AFTER `FlagsExtra`,
+ ADD `Unk430_2` float NOT NULL DEFAULT '1' AFTER `Unk430_1`,
+ ADD `BuyCount` tinyint(3) unsigned NOT NULL DEFAULT '1' AFTER `Unk430_2`;
diff --git a/sql/old/4.2.2/2012_07_19_00_world_item_template_4x.sql b/sql/old/4.2.2/2012_07_19_00_world_item_template_4x.sql
new file mode 100644
index 00000000000..fc0540da182
--- /dev/null
+++ b/sql/old/4.2.2/2012_07_19_00_world_item_template_4x.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `item_template`
+ CHANGE `Field130` `CurrencySubstitutionId` int(10) unsigned NOT NULL DEFAULT '0',
+ CHANGE `Field131` `CurrencySubstitutionCount` int(10) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_07_03_00_world_item_template_addon_434.sql b/sql/old/4.3.4/2012_07_03_00_world_item_template_addon_434.sql
new file mode 100644
index 00000000000..6cc5b547867
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_03_00_world_item_template_addon_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `item_template_addon` DROP `BuyCount`;
diff --git a/sql/old/4.3.4/2012_07_05_00_world_item_template_addon_434.sql b/sql/old/4.3.4/2012_07_05_00_world_item_template_addon_434.sql
new file mode 100644
index 00000000000..140fc3a9940
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_05_00_world_item_template_addon_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `item_template_addon` ADD `FlagsCu` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `Id`;
diff --git a/sql/old/4.3.4/2012_07_10_00_characters_character_glyphs_434.sql b/sql/old/4.3.4/2012_07_10_00_characters_character_glyphs_434.sql
new file mode 100644
index 00000000000..b8aba4d7798
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_10_00_characters_character_glyphs_434.sql
@@ -0,0 +1,4 @@
+ALTER TABLE `character_glyphs`
+ ADD `glyph7` smallint(5) unsigned DEFAULT '0' AFTER `glyph6`,
+ ADD `glyph8` smallint(5) unsigned DEFAULT '0' AFTER `glyph7`,
+ ADD `glyph9` smallint(5) unsigned DEFAULT '0' AFTER `glyph8`;
diff --git a/sql/old/4.3.4/2012_07_18_00_characters_characters_434.sql b/sql/old/4.3.4/2012_07_18_00_characters_characters_434.sql
new file mode 100644
index 00000000000..159c3d85703
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_18_00_characters_characters_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `characters` DROP `guildId`;
diff --git a/sql/old/4.3.4/2012_07_23_00_auth_realmlist_434.sql b/sql/old/4.3.4/2012_07_23_00_auth_realmlist_434.sql
new file mode 100644
index 00000000000..121e97f5837
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_23_00_auth_realmlist_434.sql
@@ -0,0 +1 @@
+UPDATE `realmlist` SET `gamebuild`=15595 WHERE `id`=1;
diff --git a/sql/old/4.3.4/2012_07_24_00_characters_various_434.sql b/sql/old/4.3.4/2012_07_24_00_characters_various_434.sql
new file mode 100644
index 00000000000..8b2bfd4f131
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_24_00_characters_various_434.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `characters` CHANGE `money` `money` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `mail` CHANGE `money` `money` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `mail` CHANGE `cod` `cod` bigint(20) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_07_30_00_characters_void_storage_434.sql b/sql/old/4.3.4/2012_07_30_00_characters_void_storage_434.sql
new file mode 100644
index 00000000000..e8a47c5f91c
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_30_00_characters_void_storage_434.sql
@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `void_storage`;
+CREATE TABLE IF NOT EXISTS `void_storage` (
+ `itemId` bigint(20) unsigned NOT NULL,
+ `playerGuid` int(10) unsigned NOT NULL,
+ `itemEntry` mediumint(8) unsigned NOT NULL,
+ `slot` tinyint(3) unsigned NOT NULL,
+ `creatorGuid` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`itemId`),
+ UNIQUE KEY `idx_player_slot` (`playerGuid`,`slot`),
+ KEY `idx_player` (`playerGuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/old/4.3.4/2012_07_30_01_characters_void_storage_434.sql b/sql/old/4.3.4/2012_07_30_01_characters_void_storage_434.sql
new file mode 100644
index 00000000000..cd2cb0f0b9e
--- /dev/null
+++ b/sql/old/4.3.4/2012_07_30_01_characters_void_storage_434.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `void_storage` ADD `randomProperty` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `void_storage` ADD `suffixFactor` int(10) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_01_00_characters_item_instance_434.sql b/sql/old/4.3.4/2012_08_01_00_characters_item_instance_434.sql
new file mode 100644
index 00000000000..b87b781e293
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_01_00_characters_item_instance_434.sql
@@ -0,0 +1,11 @@
+UPDATE `item_instance` SET `enchantments` = REPLACE(`enchantments`,' ',' ');
+UPDATE `item_instance` SET `enchantments` = CONCAT(TRIM(`enchantments`),' ');
+
+UPDATE `item_instance` SET `enchantments` = CONCAT(
+ SUBSTRING_INDEX(`enchantments`, ' ', 7*3),
+ ' 0 0 0 0 0 0 0 0 0 ',
+ SUBSTRING_INDEX(`enchantments`, ' ', -(12-7)*3 - 1))
+WHERE (LENGTH(`enchantments`) - LENGTH(REPLACE(`enchantments`, ' ', ''))) = 12*3;
+
+UPDATE `item_instance` SET `enchantments` = REPLACE(`enchantments`,' ',' ');
+UPDATE `item_instance` SET `enchantments` = CONCAT(TRIM(`enchantments`),' ');
diff --git a/sql/old/4.3.4/2012_08_04_01_world_player_classlevelstats_434.sql b/sql/old/4.3.4/2012_08_04_01_world_player_classlevelstats_434.sql
new file mode 100644
index 00000000000..9b2bcb6d6ca
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_04_01_world_player_classlevelstats_434.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `player_classlevelstats`; \ No newline at end of file
diff --git a/sql/old/4.3.4/2012_08_05_01_world_item_set_names_434.sql b/sql/old/4.3.4/2012_08_05_01_world_item_set_names_434.sql
new file mode 100644
index 00000000000..6e7cd5dbc61
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_05_01_world_item_set_names_434.sql
@@ -0,0 +1,2 @@
+DROP TABLE IF EXISTS `locales_item_set_names`;
+DROP TABLE IF EXISTS `item_set_names`;
diff --git a/sql/old/4.3.4/2012_08_05_02_world_command_434.sql b/sql/old/4.3.4/2012_08_05_02_world_command_434.sql
new file mode 100644
index 00000000000..69fd621c457
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_05_02_world_command_434.sql
@@ -0,0 +1,2 @@
+DELETE FROM `command` WHERE `name` = 'reload locales_item_set_name';
+DELETE FROM `command` WHERE `name` = 'reload item_set_names';
diff --git a/sql/old/4.3.4/2012_08_06_00_world_classlevelstats_434.sql b/sql/old/4.3.4/2012_08_06_00_world_classlevelstats_434.sql
new file mode 100644
index 00000000000..e6038374508
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_06_00_world_classlevelstats_434.sql
@@ -0,0 +1,7 @@
+ALTER TABLE `creature_classlevelstats` ADD `basehp3` smallint(6) NOT NULL DEFAULT '1' AFTER `basehp2`;
+
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp0` `basehp0` smallint(6) NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp1` `basehp1` smallint(6) NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp2` `basehp2` smallint(6) NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basemana` `basemana` smallint(6) NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basearmor` `basearmor` smallint(6) NOT NULL DEFAULT '1';
diff --git a/sql/old/4.3.4/2012_08_06_00_world_command_434.sql b/sql/old/4.3.4/2012_08_06_00_world_command_434.sql
new file mode 100644
index 00000000000..50628aaa589
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_06_00_world_command_434.sql
@@ -0,0 +1,4 @@
+DELETE FROM `command` WHERE `name` IN ('server togglequerylog', 'server set loglevel');
+
+INSERT INTO `command` (`name`,`security`,`help`) VALUES
+('server set loglevel',4,'Syntax: .server set loglevel $facility $name $loglevel. $facility can take the values: appender (a) or logger (l). $loglevel can take the values: disabled (0), trace (1), debug (2), info (3), warn (4), error (5) or fatal (6)');
diff --git a/sql/old/4.3.4/2012_08_06_01_world_classlevelstats_434.sql b/sql/old/4.3.4/2012_08_06_01_world_classlevelstats_434.sql
new file mode 100644
index 00000000000..6fe7ad67994
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_06_01_world_classlevelstats_434.sql
@@ -0,0 +1,6 @@
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp0` `basehp0` mediumint(8) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp1` `basehp1` mediumint(8) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp2` `basehp2` mediumint(8) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basehp3` `basehp3` mediumint(8) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basemana` `basemana` mediumint(8) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `creature_classlevelstats` CHANGE `basearmor` `basearmor` mediumint(8) unsigned NOT NULL DEFAULT '1';
diff --git a/sql/old/4.3.4/2012_08_07_00_characters_characters_434.sql b/sql/old/4.3.4/2012_08_07_00_characters_characters_434.sql
new file mode 100644
index 00000000000..e9bea82ad4b
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_07_00_characters_characters_434.sql
@@ -0,0 +1,2 @@
+UPDATE characters SET drunk = (drunk / 256) & 0xFF;
+ALTER TABLE characters CHANGE drunk drunk tinyint(3) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_07_01_characters_void_storage_434.sql b/sql/old/4.3.4/2012_08_07_01_characters_void_storage_434.sql
new file mode 100644
index 00000000000..8a68ba3740d
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_07_01_characters_void_storage_434.sql
@@ -0,0 +1 @@
+RENAME TABLE `void_storage` TO `character_void_storage`;
diff --git a/sql/old/4.3.4/2012_08_08_00_world_creature_template_434.sql b/sql/old/4.3.4/2012_08_08_00_world_creature_template_434.sql
new file mode 100644
index 00000000000..1e934b9f612
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_08_00_world_creature_template_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `creature_template` ADD `Mana_mod_extra` float NOT NULL DEFAULT '1' AFTER `Mana_mod`;
diff --git a/sql/old/4.3.4/2012_08_12_00_world_misc_434.sql b/sql/old/4.3.4/2012_08_12_00_world_misc_434.sql
new file mode 100644
index 00000000000..740b9c3582c
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_12_00_world_misc_434.sql
@@ -0,0 +1,59 @@
+UPDATE `creature_template` SET `ScriptName`='' WHERE `ScriptName` IN (
+'mobs_spitelashes',
+'npc_loramus_thalipedes',
+'mob_rizzle_sprysprocket',
+'mob_depth_charge',
+'npc_geezle',
+'boss_azuregos',
+'npc_kerlonian',
+'npc_prospector_remtravel',
+'npc_threshwackonator',
+'go_iruxos',
+'npc_dalinda',
+'npc_tiger_matriarch_credit',
+'npc_tiger_matriarch',
+'npc_troll_volunteer',
+'mobs_risen_husk_spirit',
+'npc_lady_jaina_proudmoore',
+'npc_nat_pagle',
+'npc_private_hendel',
+'npc_zelfrax',
+'npc_theramore_guard',
+'npcs_riverbreeze_and_silversky',
+'npc_gregan_brewspewer',
+'npc_oox22fe',
+'npc_screecher_spirit',
+'npc_bunthen_plainswind',
+'npc_great_bear_spirit',
+'npc_silva_filnaveth',
+'npc_clintar_dreamwalker',
+'npc_clintar_spirit',
+'npc_plains_vision',
+'npc_shenthul',
+'npc_thrall_warchief',
+'go_crystalline_tear',
+'npc_anachronos_quest_trigger',
+'npc_anachronos_the_ancient',
+'mob_qiraj_war_spawn',
+'npc_braug_dimspirit',
+'npc_kaya_flathoof',
+'mob_aquementas',
+'npc_marin_noggenfogger',
+'npc_stone_watcher_of_norgannon',
+'npc_tooga',
+'npc_beaten_corpse',
+'npc_gilthares',
+'npc_sputtervalve',
+'npc_taskmaster_fizzule',
+'npc_twiggy_flathead',
+'npc_kanati',
+'npc_lakota_windsong',
+'npc_paoka_swiftmountain',
+'npc_plucky',
+'npc_enraged_panther',
+'go_panther_cage',
+'npc_ame',
+'npc_ringo'
+);
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_mount_check','spell_voljin_war_drums');
diff --git a/sql/old/4.3.4/2012_08_12_03_world_misc_434.sql b/sql/old/4.3.4/2012_08_12_03_world_misc_434.sql
new file mode 100644
index 00000000000..aa6c11ee1f8
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_12_03_world_misc_434.sql
@@ -0,0 +1,38 @@
+DELETE FROM `creature_text` WHERE `entry`=2768;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(2768,0,0,'Ok, $N. Follow me to the cave where I''ll attempt to harness the power of the rune stone into these goggles.',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_1'),
+(2768,1,0,'I discovered this cave on our first day here. I believe the energy in the stone can be used to our advantage.',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_2'),
+(2768,2,0,'I''ll begin drawing energy from the stone. Your job, $N, is to defend me. This place is cursed... trust me.',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_3'),
+(2768,3,0,'%s begins tinkering with the goggles before the stone.',16,0,100,0,0,0,'Professor Phizzlethorpe - EMOTE_PROGRESS_4'),
+(2768,4,0,'Help!!! Get these things off me so I can get my work done!',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_AGGRO'),
+(2768,5,0,'Almost done! Just a little longer!',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_5'),
+(2768,6,0,'I''ve done it! I have harnessed the power of the stone into the goggles! Let''s get out of here!',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_6'),
+(2768,7,0,'Phew! Glad to be back from that creepy cave.',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_7'),
+(2768,8,0,'%s hands one glowing goggles over to Doctor Draxlegauge.',16,0,100,0,0,0,'Professor Phizzlethorpe - EMOTE_PROGRESS_8'),
+(2768,9,0,'Doctor Draxlegauge will give you further instructions, $N. Many thanks for your help!',12,0,100,0,0,0,'Professor Phizzlethorpe - SAY_PROGRESS_9');
+
+DELETE FROM `script_waypoint` WHERE `entry`=2768;
+INSERT INTO `script_waypoint` (`entry`, `pointid`, `location_x`, `location_y`, `location_z`, `waittime`, `point_comment`) VALUES
+(2768,1,-2072.32,-2089.59,9.14603,0,''),
+(2768,2,-2078.18,-2096.31,10.8916,0,''),
+(2768,3,-2079.21,-2105.22,13.3174,0,''),
+(2768,4,-2074.81,-2108.72,14.1485,0,''),
+(2768,5,-2076,-2116.21,16.3934,0,''),
+(2768,6,-2073.31,-2123.92,18.6202,4000,''),
+(2768,7,-2064.41,-2133.33,21.5776,0,''),
+(2768,8,-2044.08,-2153.12,20.121,18000,''),
+(2768,9,-2044.08,-2153.12,20.121,3000,''),
+(2768,10,-2044.08,-2153.12,20.121,0,''),
+(2768,11,-2044.08,-2153.12,20.121,14000,''),
+(2768,12,-2063.89,-2133.33,21.5648,0,''),
+(2768,13,-2075,-2121.98,17.8443,0,''),
+(2768,14,-2074.83,-2108.53,14.1036,0,''),
+(2768,15,-2079.59,-2091.61,9.80862,0,''),
+(2768,16,-2071.29,-2086.44,8.5181,0,''),
+(2768,17,-2066.46,-2085.97,8.9241,7000,'');
+
+DELETE FROM `creature_questrelation` WHERE `id`=2768 AND `quest`=26050;
+INSERT INTO `creature_questrelation` (`id`, `quest`)
+VALUES (2768, 26050);
+
+UPDATE `creature_template` SET `ScriptName`='npc_professor_phizzlethorpe' WHERE `entry`=2768; \ No newline at end of file
diff --git a/sql/old/4.3.4/2012_08_13_00_world_quest_template_434.sql b/sql/old/4.3.4/2012_08_13_00_world_quest_template_434.sql
new file mode 100644
index 00000000000..d4a0960e044
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_13_00_world_quest_template_434.sql
@@ -0,0 +1,2 @@
+-- ALTER TABLE `quest_template` CHANGE `MinLevel` `MinLevel` tinyint(4) NOT NULL DEFAULT '0';
+-- Properly fixed in 53a2b8622812f365ca7d31fdbf75fe9a1707ac7
diff --git a/sql/old/4.3.4/2012_08_14_00_world_event_ai_434.sql b/sql/old/4.3.4/2012_08_14_00_world_event_ai_434.sql
new file mode 100644
index 00000000000..3fe49aa4059
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_14_00_world_event_ai_434.sql
@@ -0,0 +1,3 @@
+DROP TABLE `creature_ai_scripts`;
+DROP TABLE `creature_ai_summons`;
+DROP TABLE `creature_ai_texts`;
diff --git a/sql/old/4.3.4/2012_08_14_00_world_reputation_spillover_template_434.sql b/sql/old/4.3.4/2012_08_14_00_world_reputation_spillover_template_434.sql
new file mode 100644
index 00000000000..afce8209afa
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_14_00_world_reputation_spillover_template_434.sql
@@ -0,0 +1,13 @@
+ALTER TABLE `reputation_spillover_template`
+ADD COLUMN `faction5` SMALLINT(6) UNSIGNED DEFAULT '0' NOT NULL AFTER `rank_4`,
+ADD COLUMN `rate_5` FLOAT DEFAULT '0' NOT NULL AFTER `faction5`,
+ADD COLUMN `rank_5` TINYINT(3) UNSIGNED DEFAULT '0' NOT NULL AFTER `rate_5`;
+
+UPDATE `reputation_spillover_template` SET `faction5`=1134,`rate_5`=0.25,`rank_5`=7 WHERE `faction` IN (72,47,54,930,69);
+UPDATE `reputation_spillover_template` SET `faction5`=1133,`rate_5`=0.25,`rank_5`=7 WHERE `faction` IN (76,530,911,81,68);
+
+DELETE FROM `reputation_spillover_template` WHERE `faction` IN (1134,1133);
+INSERT INTO `reputation_spillover_template`(`faction`,`faction1`,`rate_1`,`rank_1`,`faction2`,`rate_2`,`rank_2`,`faction3`,`rate_3`,`rank_3`,`faction4`,`rate_4`,`rank_4`,`faction5`,`rate_5`,`rank_5`) VALUES
+(1134,72,0.25,7,47,0.27,7,54,0.25,7,930,0.25,7,69,0.25,7),
+(1133,76,0.25,7,530,0.27,7,911,0.25,7,81,0.25,7,68,0.25,7);
+
diff --git a/sql/old/4.3.4/2012_08_14_01_world_commands_434.sql b/sql/old/4.3.4/2012_08_14_01_world_commands_434.sql
new file mode 100644
index 00000000000..aa030e01adb
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_14_01_world_commands_434.sql
@@ -0,0 +1 @@
+DELETE FROM `command` WHERE `name`='reload all eventai';
diff --git a/sql/old/4.3.4/2012_08_14_02_world_npc_vendor_434.sql b/sql/old/4.3.4/2012_08_14_02_world_npc_vendor_434.sql
new file mode 100644
index 00000000000..de00be694fc
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_14_02_world_npc_vendor_434.sql
@@ -0,0 +1,6 @@
+ALTER TABLE `npc_vendor` ADD `type` tinyint(3) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `game_event_npc_vendor` ADD `type` tinyint(3) unsigned NOT NULL DEFAULT '1';
+ALTER TABLE `npc_vendor` CHANGE `maxcount` `maxcount` mediumint(8) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `game_event_npc_vendor` CHANGE `maxcount` `maxcount` mediumint(8) unsigned NOT NULL DEFAULT '0';
+UPDATE `trinity_string` SET `content_default` = 'Item \'%u\' (type %u) not found in database.' WHERE `entry`=207;
+UPDATE `trinity_string` SET `content_default` = 'Item \'%u\' (with extended cost %u, type %u) already in vendor list' WHERE `entry`=210;
diff --git a/sql/old/4.3.4/2012_08_15_00_world_quest_template_434.sql b/sql/old/4.3.4/2012_08_15_00_world_quest_template_434.sql
new file mode 100644
index 00000000000..423edb1c77b
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_15_00_world_quest_template_434.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `quest_template` CHANGE `MinLevel` `MinLevel` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `quest_template` CHANGE `MaxLevel` `MaxLevel` smallint(6) NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_15_01_world_misc_434.sql b/sql/old/4.3.4/2012_08_15_01_world_misc_434.sql
new file mode 100644
index 00000000000..dae8500479b
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_15_01_world_misc_434.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `quest_poi` DROP INDEX `idx`;
+ALTER TABLE `game_event_npc_vendor` DROP INDEX `PRIMARY`, ADD PRIMARY KEY (`guid`, `item`, `ExtendedCost`, `type`);
+ALTER TABLE `npc_vendor` DROP INDEX `PRIMARY`, ADD PRIMARY KEY (`entry`, `item`, `ExtendedCost`, `type`);
diff --git a/sql/old/4.3.4/2012_08_15_01_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_08_15_01_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..b280367c811
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_15_01_world_spell_script_names_434.sql
@@ -0,0 +1,5 @@
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (2912,5176,78674);
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(2912, 'spell_dru_eclipse_energize'),
+(5176, 'spell_dru_eclipse_energize'),
+(78674, 'spell_dru_eclipse_energize');
diff --git a/sql/old/4.3.4/2012_08_15_02_world_quest_template_434.sql b/sql/old/4.3.4/2012_08_15_02_world_quest_template_434.sql
new file mode 100644
index 00000000000..a435f54e639
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_15_02_world_quest_template_434.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `quest_template` CHANGE `RewardFactionValueIdOverride1` `RewardFactionValueIdOverride1` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `quest_template` CHANGE `RewardFactionValueIdOverride2` `RewardFactionValueIdOverride2` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `quest_template` CHANGE `RewardFactionValueIdOverride3` `RewardFactionValueIdOverride3` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `quest_template` CHANGE `RewardFactionValueIdOverride4` `RewardFactionValueIdOverride4` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `quest_template` CHANGE `RewardFactionValueIdOverride5` `RewardFactionValueIdOverride5` int(11) NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_15_03_world_rep_spillover_template_434.sql b/sql/old/4.3.4/2012_08_15_03_world_rep_spillover_template_434.sql
new file mode 100644
index 00000000000..08469f1b59e
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_15_03_world_rep_spillover_template_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `reputation_spillover_template` CHANGE `faction5` `faction5` smallint(5) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_20_00_world_quest_template_434.sql b/sql/old/4.3.4/2012_08_20_00_world_quest_template_434.sql
new file mode 100644
index 00000000000..ddd447acc50
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_20_00_world_quest_template_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `quest_template` CHANGE `RequiredRaces` `RequiredRaces` mediumint(8) unsigned NOT NULL DEFAULT '0';
diff --git a/sql/old/4.3.4/2012_08_22_00_characters_characters_434.sql b/sql/old/4.3.4/2012_08_22_00_characters_characters_434.sql
new file mode 100644
index 00000000000..087f6f894eb
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_22_00_characters_characters_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `characters` ADD `slot` TINYINT UNSIGNED NOT NULL DEFAULT '0' AFTER `name`;
diff --git a/sql/old/4.3.4/2012_08_23_00_characters_guild_member434.sql b/sql/old/4.3.4/2012_08_23_00_characters_guild_member434.sql
new file mode 100644
index 00000000000..cdd4781c0c0
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_23_00_characters_guild_member434.sql
@@ -0,0 +1,4 @@
+ALTER TABLE guild_member ADD BankResetTimeTab6 INT(10) unsigned DEFAULT '0' AFTER BankRemSlotsTab5;
+ALTER TABLE guild_member ADD BankRemSlotsTab6 INT(10) unsigned DEFAULT '0' AFTER BankResetTimeTab6;
+ALTER TABLE guild_member ADD BankResetTimeTab7 INT(10) unsigned DEFAULT '0' AFTER BankRemSlotsTab6;
+ALTER TABLE guild_member ADD BankRemSlotsTab7 INT(10) unsigned DEFAULT '0' AFTER BankResetTimeTab7;
diff --git a/sql/old/4.3.4/2012_08_26_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_08_26_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..d9bb921bf8a
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_26_00_world_spell_script_names_434.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_script_names` WHERE `spell_id`=15473;
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(15473,'spell_pri_shadowform');
diff --git a/sql/old/4.3.4/2012_08_27_00_characters_guild_bank_eventlog.sql b/sql/old/4.3.4/2012_08_27_00_characters_guild_bank_eventlog.sql
new file mode 100644
index 00000000000..c019bc81504
--- /dev/null
+++ b/sql/old/4.3.4/2012_08_27_00_characters_guild_bank_eventlog.sql
@@ -0,0 +1 @@
+DELETE FROM `guild_bank_eventlog` WHERE `EventType` IN (3,7) AND `TabId`=`DestTabId`; -- delete log entries of item moves within one tab
diff --git a/sql/old/4.3.4/2012_09_03_00_characters_currency_434.sql b/sql/old/4.3.4/2012_09_03_00_characters_currency_434.sql
new file mode 100644
index 00000000000..fd6b3aaff10
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_03_00_characters_currency_434.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `character_currency`;
+CREATE TABLE `character_currency` (
+ `guid` int(10) unsigned NOT NULL,
+ `currency` smallint(5) unsigned NOT NULL,
+ `total_count` int(10) unsigned NOT NULL,
+ `week_count` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`guid`,`currency`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/old/4.3.4/2012_09_03_01_characters_currency_434.sql b/sql/old/4.3.4/2012_09_03_01_characters_currency_434.sql
new file mode 100644
index 00000000000..8b44fa43bd3
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_03_01_characters_currency_434.sql
@@ -0,0 +1,3 @@
+-- porting from characters table
+INSERT INTO `character_currency` (`guid`, `currency`, `total_count`, `week_count`) SELECT `characters`.`guid`, 392, `characters`.`totalHonorPoints`, 0 FROM `characters` WHERE `characters`.`totalHonorPoints` > 0;
+INSERT INTO `character_currency` (`guid`, `currency`, `total_count`, `week_count`) SELECT `characters`.`guid`, 390, `characters`.`conquestPoints`, 0 FROM `characters` WHERE `characters`.`conquestPoints` > 0;
diff --git a/sql/old/4.3.4/2012_09_03_02_characters_characters_434.sql b/sql/old/4.3.4/2012_09_03_02_characters_characters_434.sql
new file mode 100644
index 00000000000..db61cbb1c88
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_03_02_characters_characters_434.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `characters` DROP `conquestPoints`;
+ALTER TABLE `characters` DROP `totalHonorPoints`;
diff --git a/sql/old/4.3.4/2012_09_04_00_characters_character_cuf_profiles_434.sql b/sql/old/4.3.4/2012_09_04_00_characters_character_cuf_profiles_434.sql
new file mode 100644
index 00000000000..394c0912601
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_04_00_characters_character_cuf_profiles_434.sql
@@ -0,0 +1,19 @@
+DROP TABLE IF EXISTS `character_cuf_profiles`;
+CREATE TABLE IF NOT EXISTS `character_cuf_profiles` (
+ `guid` int(10) unsigned NOT NULL COMMENT 'Character Guid',
+ `id` tinyint(3) unsigned NOT NULL COMMENT 'Profile Id (0-4)',
+ `name` varchar(12) NOT NULL COMMENT 'Profile Name',
+ `frameHeight` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Height',
+ `frameWidth` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Frame Width',
+ `sortBy` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Sort By',
+ `healthText` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Frame Health Text',
+ `boolOptions` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Many Configurable Bool Options',
+ `unk146` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk147` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk148` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int8',
+ `unk150` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk152` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ `unk154` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Profile Unk Int16',
+ PRIMARY KEY (`guid`,`id`),
+ KEY `index` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/old/4.3.4/2012_09_07_00_characters_guild_434.sql b/sql/old/4.3.4/2012_09_07_00_characters_guild_434.sql
new file mode 100644
index 00000000000..31695bab93f
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_07_00_characters_guild_434.sql
@@ -0,0 +1,3 @@
+ALTER TABLE guild ADD `level` INT(10) unsigned DEFAULT '1' AFTER `BankMoney`;
+ALTER TABLE guild ADD `experience` BIGINT(20) unsigned DEFAULT '0' AFTER `level`;
+ALTER TABLE guild ADD `todayExperience` BIGINT(20) unsigned DEFAULT '0' AFTER `experience`;
diff --git a/sql/old/4.3.4/2012_09_09_00_characters_guild_news_434.sql b/sql/old/4.3.4/2012_09_09_00_characters_guild_news_434.sql
new file mode 100644
index 00000000000..78fa817678b
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_09_00_characters_guild_news_434.sql
@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `guild_news_log`;
+CREATE TABLE `guild_news_log` (
+ `guild` int(10) unsigned NOT NULL,
+ `id` int(10) unsigned NOT NULL,
+ `eventType` int(10) unsigned NOT NULL,
+ `playerGuid` bigint(20) unsigned NOT NULL,
+ `data` int(10) unsigned NOT NULL,
+ `flags` int(10) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`guild`,`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/old/4.3.4/2012_09_09_00_world_guild_xp_for_level.sql b/sql/old/4.3.4/2012_09_09_00_world_guild_xp_for_level.sql
new file mode 100644
index 00000000000..aa2ee143d53
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_09_00_world_guild_xp_for_level.sql
@@ -0,0 +1,33 @@
+DROP TABLE IF EXISTS `guild_xp_for_level`;
+CREATE TABLE `guild_xp_for_level` (
+ `lvl` int(11) unsigned NOT NULL,
+ `xp_for_next_level` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`lvl`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO `guild_xp_for_level` VALUES
+(1,16580000),
+(2,18240000),
+(3,19900000),
+(4,21550000),
+(5,23220000),
+(6,24880000),
+(7,26530000),
+(8,28190000),
+(9,29850000),
+(10,31510000),
+(11,33170000),
+(12,34820000),
+(13,36490000),
+(14,38140000),
+(15,39800000),
+(16,41450000),
+(17,43120000),
+(18,44780000),
+(19,46430000),
+(20,48090000),
+(21,49750000),
+(22,51410000),
+(23,53060000),
+(24,54730000),
+(25,56390000);
diff --git a/sql/old/4.3.4/2012_09_09_01_world_spell_script_names.sql b/sql/old/4.3.4/2012_09_09_01_world_spell_script_names.sql
new file mode 100644
index 00000000000..5c1701e45bd
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_09_01_world_spell_script_names.sql
@@ -0,0 +1,5 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warr_improved_spell_reflection', 'spell_warr_vigilance', 'spell_warr_charge', 'spell_warr_slam', 'spell_warr_execute', 'spell_warr_overpower');
+INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES
+(100,'spell_warr_charge'),
+(1464,'spell_warr_slam'),
+(5308,'spell_warr_execute');
diff --git a/sql/old/4.3.4/2012_09_09_02_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_09_09_02_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..a4304663d9c
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_09_02_world_spell_script_names_434.sql
@@ -0,0 +1,4 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warl_banish','spell_warl_create_healthstone','spell_warl_ritual_of_doom_effect');
+INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES
+(710,'spell_warl_banish'),
+(6201,'spell_warl_create_healthstone');
diff --git a/sql/old/4.3.4/2012_09_09_05_world_guild_rewards_434.sql b/sql/old/4.3.4/2012_09_09_05_world_guild_rewards_434.sql
new file mode 100644
index 00000000000..b05b9d959c7
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_09_05_world_guild_rewards_434.sql
@@ -0,0 +1,53 @@
+DROP TABLE IF EXISTS `guild_rewards`;
+CREATE TABLE `guild_rewards` (
+ `entry` int(10) unsigned NOT NULL DEFAULT '0',
+ `standing` tinyint(3) unsigned DEFAULT '0',
+ `racemask` int(11) DEFAULT '0',
+ `price` bigint(20) unsigned DEFAULT '0',
+ `achievement` int(10) unsigned DEFAULT '0',
+ PRIMARY KEY (`entry`)
+) engine=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO `guild_rewards` values
+(69209, 4, -1, 1250000, 0),
+(69210, 5, -1, 2500000, 0),
+(63353, 5, 946, 1500000, 4989),
+(63352, 5, 2098253, 1500000, 4989),
+(63207, 5, 946, 3000000, 4945),
+(63206, 5, 2098253, 3000000, 4945),
+(65274, 6, 946, 5000000, 5035),
+(65360, 6, 2098253, 5000000, 5035),
+(65362, 5, 946, 3000000, 5179),
+(65364, 6, 946, 5000000, 5201),
+(65361, 5, 2098253, 3000000, 5031),
+(65363, 6, 2098253, 5000000, 5201),
+(63138, 7, -1, 3000000, 5812),
+(63398, 6, 0, 3000000, 5144),
+(63359, 5, 2098253, 1500000, 4860),
+(64398, 5, 2098253, 2000000, 5143),
+(64399, 5, 2098253, 3000000, 5422),
+(64400, 5, 946, 1500000, 4860),
+(64401, 5, 946, 2000000, 5143),
+(64402, 5, 946, 3000000, 5422),
+(62800, 5, 0, 1500000, 5036),
+(62799, 5, 0, 1500000, 5467),
+(65435, 5, 0, 1500000, 5465),
+(65498, 5, 0, 1500000, 5024),
+(62286, 4, 0, 100000000, 4943),
+(68136, 6, 2098253, 200000000, 5152),
+(62287, 6, 946, 200000000, 5158),
+(69892, 5, 0, 12000000, 4944),
+(62038, 5, 0, 12000000, 4944),
+(62039, 5, 0, 12000000, 4944),
+(62040, 5, 0, 12000000, 4944),
+(69887, 5, 0, 15000000, 4946),
+(61958, 5, 0, 15000000, 4946),
+(61942, 5, 0, 15000000, 4946),
+(61937, 5, 0, 15000000, 4946),
+(61936, 5, 0, 15000000, 4946),
+(61935, 5, 0, 15000000, 4946),
+(61931, 5, 0, 15000000, 4946),
+(67107, 7, 946, 15000000, 5492),
+(62298, 7, 2098253, 15000000, 4912),
+(63125, 7, 0, 30000000, 4988),
+(71033, 7, 0, 15000000, 5840);
diff --git a/sql/old/4.3.4/2012_09_10_00_characters_guild_finder_434.sql b/sql/old/4.3.4/2012_09_10_00_characters_guild_finder_434.sql
new file mode 100644
index 00000000000..d4d524e0bef
--- /dev/null
+++ b/sql/old/4.3.4/2012_09_10_00_characters_guild_finder_434.sql
@@ -0,0 +1,40 @@
+/*!40101 SET NAMES utf8 */;
+
+/*!40101 SET SQL_MODE=''*/;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+/* Table structure for table `guild_finder_applicant` */
+
+DROP TABLE IF EXISTS `guild_finder_applicant`;
+
+CREATE TABLE `guild_finder_applicant` (
+ `guildId` int(10) unsigned DEFAULT NULL,
+ `playerGuid` int(10) unsigned DEFAULT NULL,
+ `availability` tinyint(3) unsigned DEFAULT '0',
+ `classRole` tinyint(3) unsigned DEFAULT '0',
+ `interests` tinyint(3) unsigned DEFAULT '0',
+ `comment` varchar(255) DEFAULT NULL,
+ `submitTime` int(10) unsigned DEFAULT NULL,
+ UNIQUE KEY `guildId` (`guildId`,`playerGuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+/* Table structure for table `guild_finder_guild_settings` */
+
+DROP TABLE IF EXISTS `guild_finder_guild_settings`;
+
+CREATE TABLE `guild_finder_guild_settings` (
+ `guildId` int(10) unsigned NOT NULL,
+ `availability` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `classRoles` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `interests` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `level` tinyint(3) unsigned NOT NULL DEFAULT '1',
+ `listed` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `comment` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`guildId`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
diff --git a/sql/old/4.3.4/2012_10_15_00_world_phase_definitions_434.sql b/sql/old/4.3.4/2012_10_15_00_world_phase_definitions_434.sql
new file mode 100644
index 00000000000..b8e97278eb5
--- /dev/null
+++ b/sql/old/4.3.4/2012_10_15_00_world_phase_definitions_434.sql
@@ -0,0 +1,66 @@
+DROP TABLE IF EXISTS `phase_definitions`;
+CREATE TABLE `phase_definitions` (
+ `zoneId` mediumint(7) unsigned NOT NULL DEFAULT '0',
+ `entry` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
+ `phasemask` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `phaseId` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `terrainswapmap` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `flags` tinyint(3) unsigned DEFAULT '0',
+ `comment` text,
+ PRIMARY KEY (`zoneId`, `entry`)
+)
+AUTO_INCREMENT=1
+ENGINE=MyISAM
+COLLATE='utf8_general_ci';
+
+INSERT INTO `phase_definitions` (`zoneId`, `entry`, `phasemask`, `phaseId`, `terrainswapmap`, `flags`, `comment`) VALUES
+(1519, 1, 129, 0, 0, 0, 'Stormwind: [A] Heros Call: Vashj''ir'),
+(1519, 2, 257, 0, 0, 0, 'Stormwind: [A] Heros Call: Hyjal'),
+(1519, 3, 513, 0, 0, 0, 'Stormwind: [A] Heros Call: Deepholm'),
+(1519, 4, 1025, 0, 0, 0, 'Stormwind: [A] Heros Call: Uldum'),
+(1519, 5, 2049, 0, 0, 0, 'Stormwind: [A] Heros Call: Twilight Highlands'),
+(1637, 1, 129, 0, 0, 0, 'Orgrimmar: [H] Warchiefs Command: Vashj''ir'),
+(1637, 2, 257, 0, 0, 0, 'Orgrimmar: [H] Warchiefs Command: Hyjal'),
+(1637, 3, 513, 0, 0, 0, 'Orgrimmar: [H] Warchiefs Command: Deepholm'),
+(1637, 4, 1025, 0, 0, 0, 'Orgrimmar: [H] Warchiefs Command: Uldum'),
+(1637, 5, 2049, 0, 0, 0, 'Orgrimmar: [H] Warchiefs Command: Twilight Highlands'),
+(616 , 1, 0 , 165, 719, 0, 'Mount Hyjal: Default Terrainswap');
+
+DROP TABLE IF EXISTS `spell_phase`;
+CREATE TABLE `spell_phase` (
+ `id` mediumint(7) unsigned NOT NULL DEFAULT '0',
+ `phasemask` bigint(20) unsigned NOT NULL DEFAULT '1',
+ `terrainswapmap` smallint(5) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`)
+)
+AUTO_INCREMENT=1
+ENGINE=MyISAM
+COLLATE='utf8_general_ci';
+
+DELETE FROM `trinity_string` WHERE `entry` BETWEEN 176 AND 182;
+INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES
+(176, '|cff0099FFPhaseMgr: Report for player: %s, zoneId: %u, level: %u, team: %u, phaseupdateflag: %u|r'),
+(177, '|cff663399PhaseMgr: There are no definitions defined for zoneId %u.|r'),
+(178, '|cff0066FFPhaseMgr: Success (entry: %u) - added %s %u to the players phase.|r'),
+(179, '|cffFF0000PhaseMgr: Condition for phase %u (entry: %u, zoneId: %u) failed.|r'),
+(180, '|cffFF0000PhaseMgr: Condition for phase %u (entry: %u, zoneId: %u) has last phasemask flag. Skipped other definitions.|r'),
+(181, '|cff6699FFPhaseMgr: The player gets phasemask %u through definitions, %u through phasing auras, and phase %u through custom phase.|r'),
+(182, '|cff0099FFPhaseMgr: The player has phasemask %u (real: %u).|r');
+
+DELETE FROM `command` WHERE `name` IN('debug phase', 'debug send setphaseshift');
+INSERT INTO `command` (`name`, `security`, `help`) VALUES
+('debug phase', 1, 'Syntax: .debug phase\r\n\r\nSends a phase debug report of a player to you.');
+
+/*
+Conditions (SourceGroup -> ZoneId, SourceEntry -> Entry)
+
+If you visit the Gm Island as a alliance race you are automatically phased into phase 2.
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=23 AND `SourceGroup`=876 AND `SourceEntry`=1;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(23, 876, 1, 0, 0, 6, 0, 469, 0, 0, 0, 0, '', 'Phase Definitions Example: Phase is only visible for Alliance Members');
+
+DELETE FROM `phase_definitions` WHERE `zoneId`=876 AND `entry`=1;
+INSERT INTO `phase_definitions` (`zoneId`, `entry`, `phasemask`, `phaseId`, `terrainswapmap`, `flags`, `comment`) VALUES
+(876, 1, 2, 0, 0, 0, '[Example] Gm Island');
+*/
diff --git a/sql/old/4.3.4/2012_10_15_01_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_10_15_01_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..c3390573bc2
--- /dev/null
+++ b/sql/old/4.3.4/2012_10_15_01_world_spell_script_names_434.sql
@@ -0,0 +1,2 @@
+UPDATE `spell_script_names` SET `spell_id`=755 WHERE `spell_id`=-755;
+UPDATE `spell_script_names` SET `spell_id`=1535 WHERE `spell_id`=-1535;
diff --git a/sql/old/4.3.4/2012_10_15_02_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_10_15_02_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..d0876fa3cc6
--- /dev/null
+++ b/sql/old/4.3.4/2012_10_15_02_world_spell_script_names_434.sql
@@ -0,0 +1 @@
+DELETE FROM `spell_script_names` WHERE `scriptname`='spell_sha_astral_shift';
diff --git a/sql/old/4.3.4/2012_11_07_00_characters_guild_newslog_434.sql b/sql/old/4.3.4/2012_11_07_00_characters_guild_newslog_434.sql
new file mode 100644
index 00000000000..1504bd3b6e5
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_07_00_characters_guild_newslog_434.sql
@@ -0,0 +1,21 @@
+-- Rename table and column to fit the other guild_*log tables and columns and create indexes
+RENAME TABLE `guild_news_log` TO `guild_newslog`;
+
+ALTER TABLE `guild_newslog`
+CHANGE COLUMN `guild` `guildid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Guild Identificator',
+CHANGE COLUMN `id` `LogGuid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Log record identificator - auxiliary column',
+CHANGE COLUMN `eventType` `EventType` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Event type',
+CHANGE COLUMN `playerGuid` `PlayerGuid` int(10) unsigned NOT NULL DEFAULT '0',
+CHANGE COLUMN `data` `Value` int(10) unsigned NOT NULL DEFAULT '0',
+CHANGE COLUMN `flags` `Flags` int(10) unsigned NOT NULL DEFAULT '0' AFTER `PlayerGuid`,
+CHANGE COLUMN `date` `TimeStamp` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Event UNIX time',
+ADD KEY `guildid_key` (`guildid`),
+ADD KEY `Idx_PlayerGuid` (`PlayerGuid`),
+ADD KEY `Idx_LogGuid` (`LogGuid`);
+
+-- Create missing tabs
+
+ALTER TABLE `guild_member_withdraw`
+ADD COLUMN `tab6` int(10) unsigned NOT NULL DEFAULT '0' AFTER `tab5`,
+ADD COLUMN `tab7` int(10) unsigned NOT NULL DEFAULT '0' AFTER `tab6`;
+
diff --git a/sql/old/4.3.4/2012_11_17_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_11_17_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..13eac8b301e
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_17_00_world_spell_script_names_434.sql
@@ -0,0 +1,4 @@
+-- 120 Cone of Cold
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (120);
+INSERT INTO `spell_script_names` VALUES
+(120, "spell_mage_cone_of_cold");
diff --git a/sql/old/4.3.4/2012_11_20_00_world_misc_434.sql b/sql/old/4.3.4/2012_11_20_00_world_misc_434.sql
new file mode 100644
index 00000000000..c0a95134b0a
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_20_00_world_misc_434.sql
@@ -0,0 +1,39 @@
+-- Mark of the Wild
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=1126;
+DELETE FROM `spell_script_names` WHERE `spell_id`=1126 OR `ScriptName`='spell_dru_mark_of_the_wild';
+INSERT INTO `spell_script_names` VALUES
+(1126,'spell_dru_mark_of_the_wild');
+
+-- Arcane Brilliance
+DELETE FROM `spell_script_names` WHERE `spell_id`=1459 OR `ScriptName`='spell_mage_arcane_brilliance';
+INSERT INTO `spell_script_names` VALUES
+(1459,'spell_mage_arcane_brilliance');
+
+-- Dalaran Brilliance
+DELETE FROM `spell_script_names` WHERE `spell_id`=61316 OR `ScriptName`='spell_mage_dalaran_brilliance';
+INSERT INTO `spell_script_names` VALUES
+(61316,'spell_mage_dalaran_brilliance');
+
+-- Blessing of Kings
+DELETE FROM `spell_script_names` WHERE `spell_id`=20217 OR `ScriptName`='spell_pal_blessing_of_kings';
+INSERT INTO `spell_script_names` VALUES
+(20217,'spell_pal_blessing_of_kings');
+
+-- Blessing of Might
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=19740;
+DELETE FROM `spell_script_names` WHERE `spell_id`=19740 OR `ScriptName`='spell_pal_blessing_of_might';
+INSERT INTO `spell_script_names` VALUES
+(19740,'spell_pal_blessing_of_might');
+
+-- Power Word: Fortitude
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=21562;
+DELETE FROM `spell_script_names` WHERE `spell_id`=21562 OR `ScriptName`='spell_pri_power_word_fortitude';
+INSERT INTO `spell_script_names` VALUES
+(21562,'spell_pri_power_word_fortitude');
+
+-- Shadow Protection
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=27683;
+DELETE FROM `spell_scripts` WHERE `id`=27683;
+DELETE FROM `spell_script_names` WHERE `spell_id`=27683 OR `ScriptName`='spell_pri_shadow_protection';
+INSERT INTO `spell_script_names` VALUES
+(27683,'spell_pri_shadow_protection');
diff --git a/sql/old/4.3.4/2012_11_21_00_characters_worldstates_434.sql b/sql/old/4.3.4/2012_11_21_00_characters_worldstates_434.sql
new file mode 100644
index 00000000000..14e9ffb6834
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_21_00_characters_worldstates_434.sql
@@ -0,0 +1 @@
+UPDATE `worldstates` SET `comment` = 'NextCurrencyDistributionTime' WHERE `entry` =20001;
diff --git a/sql/old/4.3.4/2012_11_21_00_world_misc_434.sql b/sql/old/4.3.4/2012_11_21_00_world_misc_434.sql
new file mode 100644
index 00000000000..131dd94585d
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_21_00_world_misc_434.sql
@@ -0,0 +1,3 @@
+-- --------
+DELETE FROM `command` WHERE `name`='flusharenapoints';
+DELETE FROM `trinity_string` WHERE `entry` IN ('741','742','743','744','745','746');
diff --git a/sql/old/4.3.4/2012_11_22_00_world_command_434.sql b/sql/old/4.3.4/2012_11_22_00_world_command_434.sql
new file mode 100644
index 00000000000..41da2d208b7
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_22_00_world_command_434.sql
@@ -0,0 +1,6 @@
+-- --------
+DELETE FROM `command` WHERE `name` = 'modify arenapoints';
+
+DELETE FROM `command` WHERE `name` = 'modify currency';
+INSERT INTO `command` (`name`, `security`, `help`) VALUES
+('modify currency', 2, 'Syntax: .modify currency #id #value\nAdd $amount (without precision) of $currency to the selected player.');
diff --git a/sql/old/4.3.4/2012_11_25_02_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_11_25_02_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..f0dd277cc96
--- /dev/null
+++ b/sql/old/4.3.4/2012_11_25_02_world_spell_script_names_434.sql
@@ -0,0 +1,9 @@
+DELETE FROM spell_linked_spell WHERE spell_trigger = 73325;
+INSERT INTO spell_linked_spell (spell_trigger, spell_effect, type, comment) VALUES
+(73325, 92833, 0, "Priest - Leap of Faith");
+
+DELETE FROM spell_script_names WHERE spell_id = 92833;
+DELETE FROM spell_script_names WHERE spell_id = -139;
+INSERT INTO spell_script_names (spell_id, ScriptName) VALUES
+(92833, "spell_pri_leap_of_faith_effect_trigger"),
+(139, "spell_pri_renew"); -- Minus doesnt matter, theres no rank any more
diff --git a/sql/old/4.3.4/2012_12_01_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_12_01_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..bd13cb8ef9d
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_01_00_world_spell_script_names_434.sql
@@ -0,0 +1,16 @@
+-- Conjure Refreshment
+DELETE FROM `spell_script_names` WHERE `spell_id`=42955;
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(42955, 'spell_mage_conjure_refreshment');
+
+-- Sacred Shield
+DELETE FROM spell_proc_event WHERE entry=85285;
+INSERT INTO spell_proc_event (entry, Cooldown) VALUES(85285, 60);
+DELETE FROM spell_script_names WHERE spell_id=85285;
+INSERT INTO spell_script_names (spell_id, ScriptName) VALUES
+(85285, 'spell_pal_sacred_shield');
+
+-- Recuperate
+DELETE FROM spell_script_names WHERE spell_id=73651;
+INSERT INTO spell_script_names (spell_id, ScriptName) VALUES
+(73651, "spell_rog_recuperate");
diff --git a/sql/old/4.3.4/2012_12_02_00_world_spell_group_misc_434.sql b/sql/old/4.3.4/2012_12_02_00_world_spell_group_misc_434.sql
new file mode 100644
index 00000000000..52e6a041f2e
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_02_00_world_spell_group_misc_434.sql
@@ -0,0 +1,22 @@
+SET @GROUP = 1121;
+DELETE FROM `spell_group_stack_rules` WHERE `group_id`=@GROUP;
+INSERT INTO `spell_group_stack_rules` (`group_id`,`stack_rule`) VALUES
+(@GROUP, 1); -- SPEL_GROUP_STACK_RULE_EXCLUSIVE
+
+DELETE FROM `spell_group` WHERE `id`=@GROUP;
+INSERT INTO `spell_group` (`id`,`spell_id`) VALUES
+(@GROUP, 73413), -- Inner will
+(@GROUP, 588); -- Inner fire
+
+-- Adding missing proc event for Fingers of Frost (Rank 3)
+DELETE FROM `spell_proc_event` WHERE `entry`=83074;
+INSERT INTO `spell_proc_event` (`entry`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`procFlags`,`procEx`,`ppmRate`,`CustomChance`,`Cooldown`) VALUES
+(83074, 0, 3, 1049120, 4096, 0, 65536, 0, 0, 20, 0);
+
+-- Updating spell_learn_spell's spell IDs range...
+ALTER TABLE `spell_learn_spell` MODIFY `entry` MEDIUMINT(8) NOT NULL;
+ALTER TABLE `spell_learn_spell` MODIFY `SpellID` MEDIUMINT(8) NOT NULL;
+-- ...So we can have sinister strike's combo point enabler.
+DELETE FROM `spell_learn_spell` WHERE `SpellID`=79327 AND `entry`=2098;
+INSERT INTO `spell_learn_spell` (`entry`,`SpellID`,`Active`) VALUES
+(2098, 79327, 0);
diff --git a/sql/old/4.3.4/2012_12_24_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_12_24_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..d95da8f3239
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_24_00_world_spell_script_names_434.sql
@@ -0,0 +1 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_damage_reduction_aura';
diff --git a/sql/old/4.3.4/2012_12_24_09_world_halls_of_origination_434.sql b/sql/old/4.3.4/2012_12_24_09_world_halls_of_origination_434.sql
new file mode 100644
index 00000000000..940f3407f23
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_24_09_world_halls_of_origination_434.sql
@@ -0,0 +1,50 @@
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=76599;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 76599, 0, 0, 31, 0, 5, 207218, 0, 0, 0, 0, '', 'Activate Beacons - Beacon of Light'),
+(13, 1, 76599, 0, 1, 31, 0, 5, 207219, 0, 0, 0, 0, '', 'Activate Beacons - Beacon of Light'),
+(13, 1, 76599, 0, 2, 31, 0, 5, 203133, 0, 0, 0, 0, '', 'Activate Beacons - Beacon of Light'),
+(13, 1, 76599, 0, 3, 31, 0, 5, 203136, 0, 0, 0, 0, '', 'Activate Beacons - Beacon of Light');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=75194;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 75194, 0, 0, 31, 0, 3, 40283, 0, 0, 0, 0, '', 'Burning Light - Searing Light');
+
+UPDATE `creature_template` SET `ScriptName`='boss_temple_guardian_anhuur' WHERE `entry`=39425;
+UPDATE `creature_template` SET `ScriptName`='',`unit_flags`=`unit_flags`|0x00000040|0x00008000 WHERE `entry`=40183;
+
+DELETE FROM `spell_target_position` WHERE `id`=74969;
+INSERT INTO `spell_target_position` (`id`,`target_map`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation`) VALUES
+(74969, 644, -640.437, 335.306, 77.7573, 1.52073);
+
+UPDATE `instance_template` SET `script`='instance_halls_of_origination' WHERE `map`=644;
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (76573,74930);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 2, 74930, 0, 0, 31, 0, 3, 40183, 0, 0, 0, 0, '', 'Shield of Light - Cave In Stalker'),
+(13, 2, 76573, 0, 0, 31, 0, 3, 40183, 0, 0, 0, 0, '', 'Shield of Light - Cave In Stalker');
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (74930,76573,76599,76606,76608);
+INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUES
+(74930, 'spell_anhuur_shield_of_light'),
+(76573, 'spell_anhuur_shield_of_light'),
+(76599, 'spell_anhuur_activate_beacons'),
+(76606, 'spell_anhuur_disable_beacon_beams'),
+(76608, 'spell_anhuur_disable_beacon_beams'),
+(75592, 'spell_anhuur_divine_reckoning');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (76606,76608);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(13,1,76606,0,0,31,0,3,40183,0,0,0,'','Disable Beacon Beams L - Cave In Stalker'),
+(13,1,76608,0,0,31,0,3,40183,0,0,0,'','Disable Beacon Beams R - Cave In Stalker');
+
+DELETE FROM `creature_text` WHERE `entry`=39425;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(39425, 0, 0, 'Turn back, intruders! These halls must not be disturbed!', 14, 0, 100, 0, 0, 18580, 'Temple Guardian Anhuur - SAY_AGGRO'),
+(39425, 1, 0, 'Beacons of light, bestow upon me your aegis!', 14, 0, 100, 0, 0, 18581, 'Temple Guardian Anhuur - SAY_SHIELD'),
+(39425, 2, 0, '%s becomes protected by his defense beacons! Disable them by pulling the levers below!', 41, 0, 100, 0, 0, 0, 'Temple Guardian Anhuur - EMOTE_SHIELD'),
+(39425, 3, 0, '%s is no longer protected by the beacons!', 41, 0, 100, 0, 0, 0, 'Temple Guardian Anhuur'),
+(39425, 4, 0, 'I regret nothing.', 14, 0, 100, 0, 0, 18582, 'Temple Guardian Anhuur'),
+(39425, 5, 0, 'What... have you... done?', 14, 0, 100, 0, 0, 18579, 'Temple Guardian Anhuur - SAY_DEATH');
+
+-- Template updates for creature 40283 (Searing Light)
+UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`minlevel`=80,`maxlevel`=80,`baseattacktime`=2000,`unit_flags`=`unit_flags`|33555008 WHERE `entry`=40283; -- Searing Light
diff --git a/sql/old/4.3.4/2012_12_25_01_world_halls_of_origination_434.sql b/sql/old/4.3.4/2012_12_25_01_world_halls_of_origination_434.sql
new file mode 100644
index 00000000000..7b2cd1a7245
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_25_01_world_halls_of_origination_434.sql
@@ -0,0 +1,55 @@
+DELETE FROM `creature_text` WHERE `entry`=39428;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(39428, 0, 0, 'More carrion for the swarm...', 14, 0, 100, 0, 0, 18906, 'Earthrager Ptah - SAY_AGGRO'),
+(39428, 1, 0, 'Ptah... is... no more...', 14, 0, 100, 0, 0, 18905, 'Earthrager Ptah - SAY_DEATH');
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (75540,89881,94974,75519);
+INSERT INTO `spell_script_names` VALUES
+(75540,'spell_earthrager_ptah_flame_bolt'),
+(89881,'spell_earthrager_ptah_flame_bolt'),
+(75519 ,'spell_earthrager_ptah_explosion'),
+(94974,'spell_earthrager_ptah_earth_spike');
+
+UPDATE `creature_template` SET `ScriptName`='boss_earthrager_ptah' WHERE `Entry`=39428;
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=89398;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 6, 89398, 0, 0, 31, 0, 3, 39443, 0, 0, 0, 0, '', 'Earth Spike - Camel');
+
+DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=39443;
+INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES
+(39443,89397,1,0);
+
+-- Jeweled Scarab SAI
+SET @ENTRY := 40458;
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,1,54,0,100,0,0,0,0,0,91,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jeweled Scarab - On just summoned - Remove field byte for submerged'),
+(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,11,65982,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jeweled Scarab - Linked - Cast emerge'),
+(@ENTRY,0,2,0,1,0,100,1,2500,2500,2500,2500,49,0,0,0,0,0,0,21,100,0,0,0,0,0,0, 'Jeweled Scarab - OOC (one time) - Attack player in 100 yards'),
+(@ENTRY,0,3,4,6,0,100,0,0,0,0,0,45,0,1,0,0,0,0,11,39428,100,0,0,0,0,0, 'Jeweled Scarab - On death - Set data 0 - 1'),
+(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,90,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jeweled Scarab - Linked - Add again byte for submerged');
+
+-- Dustbone Horror SAI
+SET @ENTRY := 40450;
+SET @SPELL := 75453; -- Smash
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,54,0,100,0,0,0,0,0,91,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dustbone Horror - On just summoned - Remove field byte 1 for submerged'),
+(@ENTRY,0,1,0,1,0,100,1,2500,2500,2500,2500,49,0,0,0,0,0,0,21,100,0,0,0,0,0,0, 'Dustbone Horror - OOC (one time) - Attack player in 100 yards'),
+(@ENTRY,0,2,0,0,0,100,0,10000,12000,10000,12000,11,@SPELL,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Dustbone Horror - Combat - Cast Smash'),
+(@ENTRY,0,3,4,6,0,100,0,0,0,0,0,45,0,1,0,0,0,0,11,39428,100,0,0,0,0,0, 'Dustbone Horror - On death - Set data 0 - 1'),
+(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,90,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dustbone Horror - Linked - Add again byte for submerged');
+
+-- Add creature_addon data
+DELETE FROM `creature_template_addon` WHERE `entry` IN (40458,40450);
+INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
+(40458,0,0,9,1,0,NULL),
+(40450,0,0,9,1,0,NULL);
+
+SET @QUICKSAND := 75548;
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@QUICKSAND;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@QUICKSAND,0,0,0,54,0,100,0,0,0,0,0,11,40503,0,0,0,0,0,1,0,0,0,0,0,0,0,'Quicksand - On summoned (spawned) - Cast spell');
diff --git a/sql/old/4.3.4/2012_12_26_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2012_12_26_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..c1c7a8db271
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_26_00_world_spell_script_names_434.sql
@@ -0,0 +1,39 @@
+-- Blast Wave
+DELETE FROM `spell_script_names` WHERE `spell_id`=11113 OR `ScriptName`='spell_mage_blast_wave';
+INSERT INTO `spell_script_names` VALUES
+(11113,'spell_mage_blast_wave');
+
+-- Blizzard
+DELETE FROM `spell_script_names` WHERE `spell_id`=42208 OR `ScriptName`='spell_mage_blizzard';
+INSERT INTO `spell_script_names` VALUES
+(42208,'spell_mage_blizzard');
+
+-- Frostbolt
+DELETE FROM `spell_script_names` WHERE `spell_id`=116 OR `ScriptName`='spell_mage_frostbolt';
+INSERT INTO `spell_script_names` VALUES
+(116,'spell_mage_frostbolt');
+
+-- Ice Barrier
+DELETE FROM `spell_script_names` WHERE `spell_id`=11426 OR `ScriptName`='spell_mage_ice_barrier';
+INSERT INTO `spell_script_names` VALUES
+(11426,'spell_mage_ice_barrier');
+
+-- Mana Shield
+DELETE FROM `spell_script_names` WHERE `spell_id`=1463 OR `ScriptName`='spell_mage_mana_shield' OR `ScriptName`='spell_mage_incanters_absorbtion_manashield';
+INSERT INTO `spell_script_names` VALUES
+(1463,'spell_mage_mana_shield');
+
+-- Mage Ward
+DELETE FROM `spell_script_names` WHERE `spell_id`=543 OR `ScriptName`='spell_mage_mage_ward' OR `ScriptName`='spell_mage_incanters_absorbtion_absorb';
+INSERT INTO `spell_script_names` VALUES
+(543,'spell_mage_mage_ward');
+
+-- Replenish Mana (Mana Gem)
+DELETE FROM `spell_script_names` WHERE `spell_id`=5405 OR `ScriptName`='spell_mage_replenish_mana';
+INSERT INTO `spell_script_names` VALUES
+(5405,'spell_mage_replenish_mana');
+
+-- Water Elemental's Freeze
+DELETE FROM `spell_script_names` WHERE `spell_id`=33395 OR `ScriptName`='spell_mage_water_elemental_freeze';
+INSERT INTO `spell_script_names` VALUES
+(33395,'spell_mage_water_elemental_freeze');
diff --git a/sql/old/4.3.4/2012_12_27_00_world_spelldifficulty_dbc_434.sql b/sql/old/4.3.4/2012_12_27_00_world_spelldifficulty_dbc_434.sql
new file mode 100644
index 00000000000..569e6eb7178
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_27_00_world_spelldifficulty_dbc_434.sql
@@ -0,0 +1 @@
+DELETE FROM `spelldifficulty_dbc` WHERE `id` IN(3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3049,3050,3051,3052,3053,3054,3062,3064,3065,3066,3067,3068,3069,3070,3071,3072,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3108,3109,3111,3112,3113,3114,3115,3116,3117,3118,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3133,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3200,3201,3202,3203,3204,3205,3206,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,3269,3270);
diff --git a/sql/old/4.3.4/2012_12_27_01_world_achievement_dbc_434.sql b/sql/old/4.3.4/2012_12_27_01_world_achievement_dbc_434.sql
new file mode 100644
index 00000000000..8229f489add
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_27_01_world_achievement_dbc_434.sql
@@ -0,0 +1,418 @@
+TRUNCATE TABLE `achievement_dbc`;
+INSERT INTO `achievement_dbc` (`ID`, `flags`, `count`) VALUES
+(3376,0x2,1),
+(3377,0x2,1),
+(3378,0x2,1),
+(3379,0x2,1),
+(3380,0x2,1),
+(3381,0x2,1),
+(3382,0x2,1),
+(3383,0x2,1),
+(3384,0x2,1),
+(3385,0x2,1),
+(3386,0x2,1),
+(3387,0x2,1),
+(3388,0x2,1),
+(3390,0x2,1),
+(3389,0x2,1),
+(3391,0x2,1),
+(3392,0x2,1),
+(3393,0x2,1),
+(3394,0x2,1),
+(3396,0x2,1),
+(3398,0x2,1),
+(3395,0x2,1),
+(3397,0x2,1),
+(3399,0x2,1),
+(3400,0x2,1),
+(3401,0x2,1),
+(3402,0x2,1),
+(3403,0x2,1),
+(3404,0x2,1),
+(3405,0x2,1),
+(3406,0x2,1),
+(3407,0x2,1),
+(3408,0x2,1),
+(3409,0x2,1),
+(3410,0x2,1),
+(3411,0x2,1),
+(3696,0x2,1),
+(4056,0x2,1),
+(4276,0x2,1),
+(4277,0x2,1),
+(4278,0x2,1),
+(4279,0x2,1),
+(4280,0x2,1),
+(4281,0x2,1),
+(4282,0x2,1),
+(4283,0x2,1),
+(4284,0x2,1),
+(4285,0x2,1),
+(4057,0x2,1),
+(4058,0x2,1),
+(4059,0x2,1),
+(4060,0x2,1),
+(4061,0x2,1),
+(4063,0x2,1),
+(4062,0x2,1),
+(4064,0x2,1),
+(4065,0x2,1),
+(4066,0x2,1),
+(4067,0x2,1),
+(4068,0x2,1),
+(4070,0x2,1),
+(4069,0x2,1),
+(4071,0x2,1),
+(4072,0x2,1),
+(4073,0x2,1),
+(4076,0x2,1),
+(4077,0x2,1),
+(4376,0x2,1),
+(4416,0x2,1),
+(4417,0x2,1),
+(4689,0x2,1),
+(4690,0x2,1),
+(4691,0x2,1),
+(4692,0x2,1),
+(4693,0x2,1),
+(4694,0x2,1),
+(4695,0x2,1),
+(4696,0x2,1),
+(4697,0x2,1),
+(4698,0x2,1),
+(4699,0x2,1),
+(4700,0x2,1),
+(4701,0x2,1),
+(4702,0x2,1),
+(4703,0x2,1),
+(4704,0x2,1),
+(4705,0x2,1),
+(4706,0x2,1),
+(4707,0x2,1),
+(4708,0x2,1),
+(4709,0x2,1),
+(4712,0x2,1),
+(4710,0x2,1),
+(4711,0x2,1),
+(4731,0x2,1),
+(4732,0x2,1),
+(4733,0x2,1),
+(4734,0x2,1),
+(4735,0x2,1),
+(4736,0x2,1),
+(4737,0x2,1),
+(4738,0x2,1),
+(4739,0x2,1),
+(4740,0x2,1),
+(4741,0x2,1),
+(4742,0x2,1),
+(4743,0x2,1),
+(4744,0x2,1),
+(4745,0x2,1),
+(4746,0x2,1),
+(4747,0x2,1),
+(4748,0x2,1),
+(4749,0x2,1),
+(4750,0x2,1),
+(4751,0x2,1),
+(4752,0x2,1),
+(4753,0x2,1),
+(4754,0x2,1),
+(4755,0x2,1),
+(4756,0x2,1),
+(4757,0x2,1),
+(4758,0x2,1),
+(4759,0x2,1),
+(4760,0x2,1),
+(4761,0x2,1),
+(4762,0x2,1),
+(4763,0x2,1),
+(4764,0x2,1),
+(4765,0x2,1),
+(4766,0x2,1),
+(4767,0x2,1),
+(4768,0x2,1),
+(4769,0x2,1),
+(4770,0x2,1),
+(4771,0x2,1),
+(4772,0x2,1),
+(4773,0x2,1),
+(4774,0x2,1),
+(4775,0x2,1),
+(4776,0x2,1),
+(4788,0x2,1),
+(4789,0x2,1),
+(4791,0x2,1),
+(4792,0x2,1),
+(4793,0x2,1),
+(4794,0x2,1),
+(4795,0x2,1),
+(5544,0x2,1),
+(5545,0x2,1),
+(5579,0x2,1),
+(5580,0x2,1),
+(5581,0x2,1),
+(5582,0x2,1),
+(5583,0x2,1),
+(5584,0x2,1),
+(5585,0x2,1),
+(5586,0x2,1),
+(5587,0x2,1),
+(5588,0x2,1),
+(5589,0x2,1),
+(5590,0x2,1),
+(5591,0x2,1),
+(5593,0x2,1),
+(5592,0x2,1),
+(5594,0x2,1),
+(5595,0x2,1),
+(5596,0x2,1),
+(5597,0x2,1),
+(5598,0x2,1),
+(5599,0x2,1),
+(5601,0x2,1),
+(5600,0x2,1),
+(5602,0x2,1),
+(5603,0x2,1),
+(5604,0x2,1),
+(5605,0x2,1),
+(5606,0x2,1),
+(5607,0x2,1),
+(5608,0x2,1),
+(5609,0x2,1),
+(5610,0x2,1),
+(5611,0x2,1),
+(5612,0x2,1),
+(5613,0x2,1),
+(5614,0x2,1),
+(5615,0x2,1),
+(5616,0x2,1),
+(5618,0x2,1),
+(5617,0x2,1),
+(5619,0x2,1),
+(5620,0x2,1),
+(5621,0x2,1),
+(5622,0x2,1),
+(5623,0x2,1),
+(5624,0x2,1),
+(5625,0x2,1),
+(5626,0x2,1),
+(5627,0x2,1),
+(5629,0x2,1),
+(5628,0x2,1),
+(5630,0x2,1),
+(5651,0x2,1),
+(5652,0x2,1),
+(5653,0x2,1),
+(5654,0x2,1),
+(5655,0x2,1),
+(5656,0x2,1),
+(5657,0x2,1),
+(5658,0x2,1),
+(5659,0x2,1),
+(5660,0x2,1),
+(5661,0x2,1),
+(5662,0x2,1),
+(5663,0x2,1),
+(5664,0x2,1),
+(5665,0x2,1),
+(5666,0x2,1),
+(5667,0x2,1),
+(5668,0x2,1),
+(5669,0x2,1),
+(5670,0x2,1),
+(5671,0x2,1),
+(5672,0x2,1),
+(5673,0x2,1),
+(5674,0x2,1),
+(5675,0x2,1),
+(5676,0x2,1),
+(5677,0x2,1),
+(5678,0x2,1),
+(5679,0x2,1),
+(5680,0x2,1),
+(5681,0x2,1),
+(5682,0x2,1),
+(5683,0x2,1),
+(5684,0x2,1),
+(5685,0x2,1),
+(5686,0x2,1),
+(5687,0x2,1),
+(5688,0x2,1),
+(5689,0x2,1),
+(5690,0x2,1),
+(5691,0x2,1),
+(5696,0x2,1),
+(5697,0x2,1),
+(5698,0x2,1),
+(5699,0x2,1),
+(5700,0x2,1),
+(5701,0x2,1),
+(5702,0x2,1),
+(5703,0x2,1),
+(5704,0x2,1),
+(5705,0x2,1),
+(5706,0x2,1),
+(5707,0x2,1),
+(5763,0x2,1),
+(5775,0x2,1),
+(5776,0x2,1),
+(5777,0x2,1),
+(5778,0x2,1),
+(5792,0x2,1),
+(5125,0x2,1),
+(5825,0x2,1),
+(5826,0x2,1),
+(5831,0x2,1),
+(5832,0x2,1),
+(5893,0x2,1),
+(5894,0x2,1),
+(5895,0x2,1),
+(5896,0x2,1),
+(5897,0x2,1),
+(5898,0x2,1),
+(5899,0x2,1),
+(5900,0x2,1),
+(5909,0x2,1),
+(5910,0x2,1),
+(5911,0x2,1),
+(5912,0x2,1),
+(5913,0x2,1),
+(5914,0x2,1),
+(5915,0x2,1),
+(5916,0x2,1),
+(5917,0x2,1),
+(5918,0x2,1),
+(5919,0x2,1),
+(5920,0x2,1),
+(5921,0x2,1),
+(5922,0x2,1),
+(5923,0x2,1),
+(5924,0x2,1),
+(5925,0x2,1),
+(5926,0x2,1),
+(5927,0x2,1),
+(5928,0x2,1),
+(5929,0x2,1),
+(5930,0x2,1),
+(5931,0x2,1),
+(5932,0x2,1),
+(5933,0x2,1),
+(5934,0x2,1),
+(5935,0x2,1),
+(5936,0x2,1),
+(5937,0x2,1),
+(5938,0x2,1),
+(5939,0x2,1),
+(5940,0x2,1),
+(5941,0x2,1),
+(5942,0x2,1),
+(5943,0x2,1),
+(5944,0x2,1),
+(5945,0x2,1),
+(5946,0x2,1),
+(5947,0x2,1),
+(5948,0x2,1),
+(5949,0x2,1),
+(5950,0x2,1),
+(5951,0x2,1),
+(5952,0x2,1),
+(5953,0x2,1),
+(5954,0x2,1),
+(5955,0x2,1),
+(5956,0x2,1),
+(5957,0x2,1),
+(5958,0x2,1),
+(5959,0x2,1),
+(5960,0x2,1),
+(5961,0x2,1),
+(5962,0x2,1),
+(5963,0x2,1),
+(5986,0x2,1),
+(5987,0x2,1),
+(6186,0x2,1),
+(6187,0x2,1),
+(6188,0x2,1),
+(6189,0x2,1),
+(6190,0x2,1),
+(6191,0x2,1),
+(6192,0x2,1),
+(6195,0x2,1),
+(6196,0x2,1),
+(6197,0x2,1),
+(6198,0x2,1),
+(6194,0x2,1),
+(6199,0x2,1),
+(6200,0x2,1),
+(6201,0x2,1),
+(6202,0x2,1),
+(6203,0x2,1),
+(6204,0x2,1),
+(6205,0x2,1),
+(6206,0x2,1),
+(6207,0x2,1),
+(6208,0x2,1),
+(6209,0x2,1),
+(6210,0x2,1),
+(6211,0x2,1),
+(6212,0x2,1),
+(6213,0x2,1),
+(6214,0x2,1),
+(6215,0x2,1),
+(6220,0x2,1),
+(6216,0x2,1),
+(6217,0x2,1),
+(6218,0x2,1),
+(6219,0x2,1),
+(6221,0x2,1),
+(6222,0x2,1),
+(6223,0x2,1),
+(6224,0x2,1),
+(6225,0x2,1),
+(6226,0x2,1),
+(6227,0x2,1),
+(6228,0x2,1),
+(6229,0x2,1),
+(6230,0x2,1),
+(6231,0x2,1),
+(6232,0x2,1),
+(6233,0x2,1),
+(6234,0x2,1),
+(6235,0x2,1),
+(6236,0x2,1),
+(6237,0x2,1),
+(6238,0x2,1),
+(6239,0x2,1),
+(6240,0x2,1),
+(6243,0x2,1),
+(6241,0x2,1),
+(6242,0x2,1),
+(6244,0x2,1),
+(6245,0x2,1),
+(6246,0x2,1),
+(6247,0x2,1),
+(6248,0x2,1),
+(6249,0x2,1),
+(6250,0x2,1),
+(6251,0x2,1),
+(6252,0x2,1),
+(6253,0x2,1),
+(6254,0x2,1),
+(6255,0x2,1),
+(6256,0x2,1),
+(6257,0x2,1),
+(6258,0x2,1),
+(6259,0x2,1),
+(6260,0x2,1),
+(6261,0x2,1),
+(6262,0x2,1),
+(6263,0x2,1),
+(6264,0x2,1),
+(6265,0x2,1),
+(6266,0x2,1),
+(6267,0x2,1),
+(6268,0x2,1),
+(6269,0x2,1),
+(6270,0x2,1),
+(6271,0x2,1),
+(6313,0x2,1);
diff --git a/sql/old/4.3.4/2012_12_30_00_world_zul_gurub_434.sql b/sql/old/4.3.4/2012_12_30_00_world_zul_gurub_434.sql
new file mode 100644
index 00000000000..5b4e31636db
--- /dev/null
+++ b/sql/old/4.3.4/2012_12_30_00_world_zul_gurub_434.sql
@@ -0,0 +1,26 @@
+UPDATE `creature_template` SET `ScriptName`='npc_chained_spirit' WHERE `entry`=52156;
+UPDATE `creature_template` SET `ScriptName`='npc_ohgan' WHERE `entry`=52157;
+
+DELETE FROM `creature` WHERE `id`=52156;
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (96682,96776,96761,96821,96721,96722,96724,96740,28471);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(96682,'spell_mandokir_decapitate'),
+(96776,'spell_mandokir_bloodletting'),
+(96761,'spell_mandokir_devastating_slam'),
+(96821,'spell_mandokir_spirit_vengeance_cancel'),
+(96721,'spell_mandokir_ohgan_orders'),
+(96722,'spell_mandokir_ohgan_orders_trigger'),
+(96724,'spell_mandokir_reanimate_ohgan'),
+(96740,'spell_mandokir_devastating_slam_damage'),
+(28471,'spell_clear_all');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`IN (96724,96721);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 3, 96724, 0, 0, 31, 0, 3, 52157, 0, 0, 0, 0, '', 'Earth Spike - Ohgan'),
+(13, 1, 96721, 0, 0, 31, 0, 3, 52156, 0, 0, 0, 0, '', 'Ohgan''s Orders - Chained Spirit');
+
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id`=16848;
+INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
+(16848,11,0,0,'achievement_ohganot_so_fast'),
+(16848,12,1,0,'');
diff --git a/sql/old/4.3.4/2013_01_03_00_world_spell_area_434.sql b/sql/old/4.3.4/2013_01_03_00_world_spell_area_434.sql
new file mode 100644
index 00000000000..207b51f9f7b
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_03_00_world_spell_area_434.sql
@@ -0,0 +1 @@
+DELETE FROM `spell_area` WHERE `spell`=58600; -- Restricted Flight Area (Dalaran)
diff --git a/sql/old/4.3.4/2013_01_03_01_world_spell_area_434.sql b/sql/old/4.3.4/2013_01_03_01_world_spell_area_434.sql
new file mode 100644
index 00000000000..2eb36926193
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_03_01_world_spell_area_434.sql
@@ -0,0 +1,13 @@
+DELETE FROM `spell_area` WHERE `spell`=91604;
+INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES
+(91604, 4197, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4538, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4539, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4575, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4577, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4581, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4582, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4583, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4585, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4589, 0, 0, 0, 0, 2, 1, 64, 11),
+(91604, 4612, 0, 0, 0, 0, 2, 1, 64, 11);
diff --git a/sql/old/4.3.4/2013_01_04_00_world_halls_of_origination_434.sql b/sql/old/4.3.4/2013_01_04_00_world_halls_of_origination_434.sql
new file mode 100644
index 00000000000..36df0da72ca
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_04_00_world_halls_of_origination_434.sql
@@ -0,0 +1,51 @@
+UPDATE `creature_template` SET `ScriptName`="npc_brann_bronzebeard_anraphet" WHERE `entry`=39908;
+DELETE FROM `creature_text` WHERE `entry`=39908;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(39908, 0, 0, 'Right, let''s go! Just need to input the final entry sequence into the door mechanism... and...', 12, 0, 100, 5, 0, 20897, 'Brann Bronzebeard'),
+(39908, 1, 0, 'That did the trick! The control room should be right behind this... oh... wow...', 12, 0, 100, 5, 0, 20898, 'Brann Bronzebeard'),
+(39908, 2, 0, 'What? This isn''t the control room! There''s another entire defense mechanism in place, and the blasted Rock Troggs broke into here somehow. Troggs. Why did it have to be Troggs!', 12, 0, 100, 5, 0, 20899, 'Brann Bronzebeard'),
+(39908, 3, 0, 'Ok, let me think a moment.', 12, 0, 100, 1, 0, 20900, 'Brann Bronzebeard'),
+(39908, 4, 0, 'Mirrors pointing all over the place.', 12, 0, 100, 25, 0, 20902, 'Brann Bronzebeard'),
+(39908, 5, 0, 'Four platforms with huge elementals.', 12, 0, 100, 25, 0, 20901, 'Brann Bronzebeard'),
+(39908, 6, 0, 'I got it! I saw a tablet that mentioned this chamber. This is the Vault of Lights! Ok, simple enough. I need you adventurers to take out each of the four elementals to trigger the opening sequence for the far door!', 12, 0, 100, 5, 0, 20903, 'Brann Bronzebeard'),
+(39908, 7, 0, 'One down!', 14, 0, 100, 5, 0, 20904, 'Brann Bronzebeard'),
+(39908, 8, 0, 'Another one down! Just look at those light beams! They seem to be connecting to the far door!', 14, 0, 100, 5, 0, 20905, 'Brann Bronzebeard'),
+(39908, 9, 0, 'One more elemental to go! The door is almost open!', 14, 0, 100, 5, 0, 20906, 'Brann Bronzebeard'),
+(39908, 10, 0, 'That''s it, you''ve done it! The vault door is opening! Now we can... oh, no!', 14, 0, 100, 5, 0, 20907, 'Brann Bronzebeard'),
+(39908, 11, 0, 'We''ve done it! The control room is breached!', 14, 0, 100, 5, 0, 23709, 'Brann Bronzebeard'),
+(39908, 12, 0, 'Here we go! Now this should only take a moment...', 14, 0, 100, 5, 0, 23710, 'Brann Bronzebeard');
+
+UPDATE `creature_template` SET `ScriptName`="boss_anraphet" WHERE `entry`=39788;
+DELETE FROM `creature_text` WHERE `entry`=39788;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(39788, 0, 0, 'This unit has been activated outside normal operating protocols. Downloading new operational parameters. Download complete. Full unit self defense routines are now active. Destruction of foreign units in the system shall now commence.', 14, 0, 100, 0, 0, 20857, 'Anraphet - SAY_INTRO'),
+(39788, 1, 0, 'Purge of unauthorized entities commencing.', 14, 0, 100, 0, 0, 20862, 'Anraphet - SAY_AGGRO'),
+(39788, 2, 0, 'Omega Stance activated. Annihilation of foreign unit is now imminent.', 14, 0, 100, 0, 0, 20861, 'Anraphet - SAY_OMEGA_STANCE'),
+(39788, 3, 0, 'Purge Complete.', 14, 0, 100, 0, 0, 20859, 'Anraphet - SAY_PLAYER_KILL'),
+(39788, 3, 1, 'Target Annihilated.', 14, 0, 100, 0, 0, 20858, 'Anraphet - SAY_PLAYER_KILL'),
+(39788, 4, 0, 'Anraphet unit shutting down...', 14, 0, 100, 0, 0, 20856, 'Anraphet - SAY_DEATH');
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (76904,77106,77127);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(76904,'spell_anraphet_alpha_beams'),
+(77106,'spell_anraphet_omega_stance_summon'),
+(77127,'spell_omega_stance_spider_effect');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup` IN (11339,11348,12512);
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=11339;
+INSERT INTO `conditions`(`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(14, 11339, 15794, 0, 0, 13, 1, 2, 3, 2, 1, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_VAULT_OF_LIGHTS is not done'),
+(14, 11348, 15815, 0, 0, 13, 1, 18, 4, 0, 1, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_DEAD_ELEMENTALS is less than 4'),
+(14, 12512, 17600, 0, 0, 13, 1, 18, 4, 0, 0, 0, 0, '', 'Brann Bronzebeard gossip menu - Show only if DATA_DEAD_ELEMENTALS is 4'),
+(15, 11339, 0, 0, 0, 13, 1, 2, 3, 2, 1, 0, 0, '', 'Brann Bronzebeard gossip menu option - Show only if DATA_VAULT_OF_LIGHTS is not done');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=77437;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 6, 77437, 0, 0, 31, 0, 3, 39804, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Pillager'),
+(13, 6, 77437, 0, 1, 31, 0, 3, 40252, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Rock Flinger'),
+(13, 6, 77437, 0, 2, 31, 0, 3, 40251, 0, 0, 0, 0, '', 'Destruction Protocol - Stone Trogg Brute');
+
+UPDATE `creature_template` SET `ScriptName`='npc_alpha_beam' WHERE `entry`=41144;
+UPDATE `creature_template` SET `ScriptName`='npc_omega_stance' WHERE `entry`=41194;
+
+DELETE FROM `spell_script_names` WHERE `spell_id`=94974;
diff --git a/sql/old/4.3.4/2013_01_05_00_world_firelands_434.sql b/sql/old/4.3.4/2013_01_05_00_world_firelands_434.sql
new file mode 100644
index 00000000000..fa20d425209
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_05_00_world_firelands_434.sql
@@ -0,0 +1,113 @@
+DELETE FROM `creature` WHERE `id` IN (53520,53375,53698,53693,53487,53691,52530,53369,53680,53734,53896,53900) AND `map`=720;
+DELETE FROM `gameobject` WHERE `id` IN (209036,208966,201722,209035) AND `map`=720;
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x80 WHERE `entry` IN (53723,53154,53789,53792,53787,53788);
+
+UPDATE `creature_template` SET `minlevel`=88,`maxlevel`=88,`exp`=3,`faction_A`=16,`faction_H`=16,`speed_walk`=3.2,`speed_run`=2,`baseattacktime`=2000,`rangeattacktime`=2000,`unit_class`=2,`unit_flags`=0x2008140,`unit_flags2`=0x8000800,`VehicleId`=1673,`HoverHeight`=14,`mana_mod_extra`=1.72414 WHERE `entry` IN (52530,54044,54045,54046);
+UPDATE `creature_template` SET `minlevel`=87,`maxlevel`=87,`exp`=3,`faction_A`=16,`faction_H`=16,`speed_walk`=3.2,`speed_run`=2,`baseattacktime`=2000,`rangeattacktime`=2000,`unit_flags`=0x8000,`unit_flags2`=0x800,`VehicleId`=1695 WHERE `entry` IN (54056,54057); -- Blazing Monstrosity
+UPDATE `creature_template` SET `minlevel`=87,`maxlevel`=87,`exp`=3,`faction_A`=16,`faction_H`=16,`speed_walk`=1,`speed_run`=1,`baseattacktime`=2000,`rangeattacktime`=2000,`unit_flags`=0x8000,`unit_flags2`=0x8800 WHERE `entry` IN (53795,54059); -- Egg Pile
+UPDATE `creature_template` SET `spell1`=100076,`spell2`=100080,`spell3`=100078,`spell4`=100082 WHERE `entry`=53789;
+UPDATE `creature_template` SET `spell1`=100090,`spell2`=100089,`spell3`=100091,`spell4`=100092 WHERE `entry`=53792;
+UPDATE `creature_template` SET `minlevel`=85,`maxlevel`=85,`exp`=3,`faction_A`=14,`faction_H`=14,`speed_walk`=1.2,`speed_run`=0.428571,`unit_flags`=0x2000000,`unit_flags2`=0x2000800 WHERE `entry` IN (53787,53788); -- Molten Barrage
+UPDATE `creature_template` SET `minlevel`=85,`maxlevel`=85,`exp`=3,`faction_A`=16,`faction_H`=16,`speed_walk`=3.2,`speed_run`=2,`unit_flags`=0x8000,`unit_flags2`=0x800,`baseattacktime`=2000,`rangeattacktime`=2000 WHERE `entry` IN (53794,54058); -- Smouldering Hatchling
+UPDATE `creature_template` SET `minlevel`=86,`maxlevel`=86,`exp`=3,`faction_A`=16,`faction_H`=16,`speed_walk`=1,`speed_run`=1.14286,`unit_flags`=0,`unit_flags2`=0x800,`baseattacktime`=2000,`rangeattacktime`=2000,`unit_class`=8,`dynamicflags`=0 WHERE `entry` IN (53793,53973); -- Harbinger of Flame
+
+UPDATE `creature_template` SET `difficulty_entry_1`=54044,`difficulty_entry_2`=54045,`difficulty_entry_3`=54046 WHERE `entry`=52530; -- Alysrazor
+UPDATE `creature_template` SET `difficulty_entry_1`=54056 WHERE `entry`=53786; -- Blazing Monstrosity
+UPDATE `creature_template` SET `difficulty_entry_1`=54057 WHERE `entry`=53791; -- Blazing Monstrosity
+UPDATE `creature_template` SET `difficulty_entry_1`=54059 WHERE `entry`=53795; -- Egg Pile
+UPDATE `creature_template` SET `difficulty_entry_1`=54058 WHERE `entry`=53794; -- Smouldering Hatchling
+UPDATE `creature_template` SET `difficulty_entry_1`=53973 WHERE `entry`=53793; -- Harbinger of Flame
+
+DELETE FROM `creature_template_addon` WHERE `entry` IN (53786,53791,54056,54057,53794,54058,54276,54019,53224,53102,52530,54044,54045,54046,53900,53680,53520,53693,53698);
+INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES
+(53786, 0, 0x0, 0x1, '100712 99480'), -- Blazing Monstrosity - Fire Hawk Smoke Cosmetic, Sleep (Ultra-High Priority)
+(53791, 0, 0x0, 0x1, '100712 99480'), -- Blazing Monstrosity - Fire Hawk Smoke Cosmetic, Sleep (Ultra-High Priority)
+(54056, 0, 0x0, 0x1, '100712 99480'), -- Blazing Monstrosity - Fire Hawk Smoke Cosmetic, Sleep (Ultra-High Priority)
+(54057, 0, 0x0, 0x1, '100712 99480'), -- Blazing Monstrosity - Fire Hawk Smoke Cosmetic, Sleep (Ultra-High Priority)
+(53794, 0, 0x0, 0x1, '100712'), -- Smouldering Hatchling - Fire Hawk Smoke Cosmetic
+(54058, 0, 0x0, 0x1, '100712'), -- Smouldering Hatchling - Fire Hawk Smoke Cosmetic
+(54276, 0, 0x0, 0x1, '101112'), -- Cinderslither Snake - Cinderslither Aura
+(54019, 0, 0x0, 0x1, '100556'), -- Captive Druid of the Talon - Smouldering Roots
+(53224, 0, 0x0, 0x1, '100743'), -- Flamewaker Taskmaster - Aura of Indomitability
+(53102, 0, 0x3000000, 0x1, '100712'), -- Inferno Hawk - Fire Hawk Smoke Cosmetic
+(52530, 0, 0x0, 0x1, '100712'), -- Alysrazor - Fire Hawk Smoke Cosmetic
+(54044, 0, 0x0, 0x1, '100712'), -- Alysrazor - Fire Hawk Smoke Cosmetic
+(54045, 0, 0x0, 0x1, '100712'), -- Alysrazor - Fire Hawk Smoke Cosmetic
+(54046, 0, 0x0, 0x1, '100712'), -- Alysrazor - Fire Hawk Smoke Cosmetic
+(53900, 0, 0x3000000, 0x1, '100712'), -- Blazing Broodmother - Fire Hawk Smoke Cosmetic
+(53680, 0, 0x3000000, 0x1, '100712'), -- Blazing Broodmother - Fire Hawk Smoke Cosmetic
+(53520, 0, 0x0, 0x1, '99327'), -- Plump Lava Worm - Fire Worm Cosmetic
+(53693, 0, 0x0, 0x1, '99793'), -- Fiery Vortex - Fiery Vortex
+(53698, 0, 0x0, 0x1, '99817'); -- Fiery Tornado - Fiery Tornado
+
+DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (53786,53791);
+INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `minion`, `description`, `summontype`, `summontimer`) VALUES
+(53786,53789,1,'Blazing Monstrosity',5,0),
+(53791,53792,1,'Blazing Monstrosity',5,0);
+
+DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (53786,53791,53789,53792);
+INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`) VALUES
+(53786,98509,1),
+(53791,98509,1),
+(53789,93970,1),
+(53792,93970,1);
+
+DELETE FROM `creature_text` WHERE `entry`=53795;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(53795, 0, 0, 'The Molten Eggs begin to crack and splinter!', 41, 0, 100, 0, 0, 0, 'Molten Egg - EMOTE_CRACKING_EGGS');
+
+-- ScriptNames and conditions
+UPDATE `instance_template` SET `script`='instance_firelands' WHERE `map`=720;
+UPDATE `creature_template` SET `ScriptName`='npc_harbinger_of_flame' WHERE `entry`=53793;
+UPDATE `creature_template` SET `ScriptName`='npc_blazing_monstrosity' WHERE `entry` IN (53786,53791);
+UPDATE `creature_template` SET `ScriptName`='npc_molten_barrage' WHERE `entry` IN (53787,53788);
+UPDATE `creature_template` SET `ScriptName`='npc_egg_pile' WHERE `entry`=53795;
+
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_alysrazor_cosmetic_egg_xplosion';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_alysrazor_turn_monstrosity';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_alysrazor_aggro_closest';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_alysrazor_fieroblast';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(100099,'spell_alysrazor_cosmetic_egg_xplosion'),
+(100076,'spell_alysrazor_turn_monstrosity'),
+(100078,'spell_alysrazor_turn_monstrosity'),
+(100080,'spell_alysrazor_turn_monstrosity'),
+(100082,'spell_alysrazor_turn_monstrosity'),
+(100089,'spell_alysrazor_turn_monstrosity'),
+(100090,'spell_alysrazor_turn_monstrosity'),
+(100091,'spell_alysrazor_turn_monstrosity'),
+(100092,'spell_alysrazor_turn_monstrosity'),
+(100462,'spell_alysrazor_aggro_closest'),
+(100094,'spell_alysrazor_fieroblast'),
+(101223,'spell_alysrazor_fieroblast'),
+(101294,'spell_alysrazor_fieroblast'),
+(101295,'spell_alysrazor_fieroblast'),
+(101296,'spell_alysrazor_fieroblast');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (100558,100071,100074,100070,100076,100078,100080,100082,100089,100090,100091,100092);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(13,3,100558,0,0,31,0,3,54019,0,0,0,0,'','Sacrifice to the Flame - Captive Druid of the Talon'),
+(13,1,100071,0,0,31,0,3,53787,0,0,0,0,'','Molten Barrage'),
+(13,1,100074,0,0,31,0,3,53788,0,0,0,0,'','Molten Barrage'),
+(13,2,100070,0,0,31,0,3,53786,0,0,0,0,'','Molten Barrage - Blazing Monstrosity'),
+(13,2,100070,0,1,31,0,3,53791,0,0,0,0,'','Molten Barrage - Blazing Monstrosity'),
+(13,2,100070,0,2,31,0,3,53793,0,0,0,0,'','Molten Barrage - Harbinger of Flame'),
+(13,2,100070,0,3,31,0,3,53795,0,0,0,0,'','Molten Barrage - Egg Pile'),
+(13,2,100070,0,4,31,0,3,53794,0,0,0,0,'','Molten Barrage - Smouldering Hatchling'),
+(13,1,100076,0,0,31,0,3,53787,0,0,0,0,'','Left-Side Smack - Molten Barrage'),
+(13,2,100076,0,1,31,0,3,53786,0,0,0,0,'','Left-Side Smack - Blazing Monstrosity'),
+(13,1,100078,0,0,31,0,3,53787,0,0,0,0,'','Right-Side Smack - Molten Barrage'),
+(13,2,100078,0,1,31,0,3,53786,0,0,0,0,'','Right-Side Smack - Blazing Monstrosity'),
+(13,1,100080,0,0,31,0,3,53787,0,0,0,0,'','Head Bonk - Molten Barrage'),
+(13,2,100080,0,1,31,0,3,53786,0,0,0,0,'','Head Bonk - Blazing Monstrosity'),
+(13,1,100082,0,0,31,0,3,53787,0,0,0,0,'','Tickle - Molten Barrage'),
+(13,2,100082,0,1,31,0,3,53786,0,0,0,0,'','Tickle - Blazing Monstrosity'),
+(13,1,100089,0,0,31,0,3,53788,0,0,0,0,'','Head Bonk - Molten Barrage'),
+(13,2,100089,0,1,31,0,3,53791,0,0,0,0,'','Head Bonk - Blazing Monstrosity'),
+(13,1,100090,0,0,31,0,3,53788,0,0,0,0,'','Left-Side Smack - Molten Barrage'),
+(13,2,100090,0,1,31,0,3,53791,0,0,0,0,'','Left-Side Smack - Blazing Monstrosity'),
+(13,1,100091,0,0,31,0,3,53788,0,0,0,0,'','Right-Side Smack - Molten Barrage'),
+(13,2,100091,0,1,31,0,3,53791,0,0,0,0,'','Right-Side Smack - Blazing Monstrosity'),
+(13,1,100092,0,0,31,0,3,53788,0,0,0,0,'','Tickle - Molten Barrage'),
+(13,2,100092,0,1,31,0,3,53791,0,0,0,0,'','Tickle - Blazing Monstrosity');
diff --git a/sql/old/4.3.4/2013_01_21_00_world_misc_434.sql b/sql/old/4.3.4/2013_01_21_00_world_misc_434.sql
new file mode 100644
index 00000000000..058a574ca93
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_21_00_world_misc_434.sql
@@ -0,0 +1,22 @@
+-- Intro Areatrigger
+DELETE FROM `areatrigger_scripts` WHERE `entry`=7246;
+INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
+(7246, 'at_alizabal_intro');
+
+UPDATE `creature_template` SET `scriptname` = 'boss_alizabal' WHERE `entry`=55869;
+
+-- Todo: Find the Rest of the Texts and their meanings
+DELETE FROM `creature_text` WHERE `entry`=55869;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
+(55869, 1, 0, 'How I HATE this place. My captors may be long-dead, but don\'t think I won\'t take it all out on you miserable treasure-hunters.', 14, 0, 100, 0, 0, 25779, 'Alizabal - Intro'),
+(55869, 2, 0, 'I hate adventurers.', 14, 0, 100, 0, 0, 25777, 'Alizabal - Aggro'),
+(55869, 3, 0, 'I hate martyrs.', 14, 0, 100, 0, 0, 25786, 'Alizabal - Seething Hate'),
+(55869, 4, 0, 'I hate armor.', 14, 0, 100, 0, 0, 25785, 'Alizabal - Skewer'),
+(55869, 5, 0, 'Alizabal nailed $N firmly on the ground.', 41, 0, 100, 0, 0, 0, 'Alizabal - Skewer Announce'),
+(55869, 6, 0, 'I hate standing still.', 14, 0, 100, 0, 0, 25791, 'Alizabal - Blade Dance'),
+(55869, 7, 0, 'Feel my hatred!', 14, 0, 100, 0, 0, 25787, 'Alizabal - ???'),
+(55869, 8, 0, 'My hate will consume you!', 14, 0, 100, 0, 0, 25789, 'Alizabal - ???'),
+(55869, 9, 0, 'I hate you all.', 14, 0, 100, 0, 0, 25790, 'Alizabal - ???'),
+(55869, 10, 0, 'I hate mercy.', 14, 0, 100, 0, 0, 25783, 'Alizabal - Slay 1'),
+(55869, 11, 0, 'My hatred burns!', 14, 0, 100, 0, 0, 25788, 'Alizabal - ???'),
+(55869, 12, 0, 'I hate... every one of you...', 14, 0, 100, 0, 0, 25778, 'Alizabal - Death');
diff --git a/sql/old/4.3.4/2013_01_21_01_world_misc_434.sql b/sql/old/4.3.4/2013_01_21_01_world_misc_434.sql
new file mode 100644
index 00000000000..dcf058b44e0
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_21_01_world_misc_434.sql
@@ -0,0 +1,4 @@
+-- NPC Hira Snowdawn no longer sells Tome of Cold Weather Flight
+UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=31238;
+DELETE FROM `gossip_menu_option` WHERE `menu_id`=10723 AND `id`=1;
+DELETE FROM `npc_vendor` WHERE `entry`=31238 AND `item`=49177;
diff --git a/sql/old/4.3.4/2013_01_22_00_world_spell_proc_event_434.sql b/sql/old/4.3.4/2013_01_22_00_world_spell_proc_event_434.sql
new file mode 100644
index 00000000000..036864683ea
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_22_00_world_spell_proc_event_434.sql
@@ -0,0 +1,6 @@
+-- Malfurion's Gift
+DELETE FROM `spell_proc_event` WHERE `entry` IN ('92363', '92364');
+INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `procFlags`, `procEx`, `ppmRate`, `CustomChance`, `Cooldown`)
+VALUES
+(92363, 0, 7, 0, 16, 0, 278528, 0, 0, 2, 0),
+(92364, 0, 7, 0, 16, 0, 278528, 0, 0, 4, 0);
diff --git a/sql/old/4.3.4/2013_01_22_01_world_spell_script_names_434.sql b/sql/old/4.3.4/2013_01_22_01_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..cc74d504e94
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_22_01_world_spell_script_names_434.sql
@@ -0,0 +1,4 @@
+-- 85256 - Templar's Verdict
+DELETE FROM `spell_script_names` WHERE `spell_id`=85256;
+INSERT INTO `spell_script_names` VALUES
+(85256,'spell_pal_templar_s_verdict');
diff --git a/sql/old/4.3.4/2013_01_24_00_world_instance_template_434.sql b/sql/old/4.3.4/2013_01_24_00_world_instance_template_434.sql
new file mode 100644
index 00000000000..23a0ffb04b8
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_24_00_world_instance_template_434.sql
@@ -0,0 +1 @@
+UPDATE `instance_template` SET `script`='instance_baradin_hold' WHERE `map`=757;
diff --git a/sql/old/4.3.4/2013_01_25_00_world_spell_linked_spell_434.sql b/sql/old/4.3.4/2013_01_25_00_world_spell_linked_spell_434.sql
new file mode 100644
index 00000000000..5eb29aa4de1
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_25_00_world_spell_linked_spell_434.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (77769, -77769);
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(77769, 82946, 2, 'Trap Launcher - Add/Remove');
diff --git a/sql/old/4.3.4/2013_01_26_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2013_01_26_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..d0c4a61c422
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_26_00_world_spell_script_names_434.sql
@@ -0,0 +1,7 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_running_wild';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_two_forms';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_darkflight';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(87840,'spell_gen_running_wild'),
+(68996,'spell_gen_two_forms'),
+(68992,'spell_gen_darkflight');
diff --git a/sql/old/4.3.4/2013_01_29_00_world_creature_template_434.sql b/sql/old/4.3.4/2013_01_29_00_world_creature_template_434.sql
new file mode 100644
index 00000000000..52954b2b9f5
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_29_00_world_creature_template_434.sql
@@ -0,0 +1 @@
+ALTER TABLE `creature_template` DROP `trainer_spell`;
diff --git a/sql/old/4.3.4/2013_01_30_00_characters_characters_434.sql b/sql/old/4.3.4/2013_01_30_00_characters_characters_434.sql
new file mode 100644
index 00000000000..1ddb4c8900d
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_30_00_characters_characters_434.sql
@@ -0,0 +1,2 @@
+-- Add missing fields for new titles field
+UPDATE `characters` SET knownTitles = CONCAT(knownTitles, '0 0 ') WHERE (LENGTH(knownTitles) - LENGTH(REPLACE(knownTitles, ' ', ''))) = 6;
diff --git a/sql/old/4.3.4/2013_01_31_00_world_spell_script_names_434.sql b/sql/old/4.3.4/2013_01_31_00_world_spell_script_names_434.sql
new file mode 100644
index 00000000000..a615525b626
--- /dev/null
+++ b/sql/old/4.3.4/2013_01_31_00_world_spell_script_names_434.sql
@@ -0,0 +1,6 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warl_demon_soul', 'spell_warl_conflagrate', 'spell_warl_fel_flame');
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (17962, 77799, 77801);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(17962, 'spell_warl_conflagrate'),
+(77799, 'spell_warl_fel_flame'),
+(77801, 'spell_warl_demon_soul');
diff --git a/sql/old/4.3.4/2013_02_04_00_world_graveyard_orientation_434.sql b/sql/old/4.3.4/2013_02_04_00_world_graveyard_orientation_434.sql
new file mode 100644
index 00000000000..e140bbd3c4c
--- /dev/null
+++ b/sql/old/4.3.4/2013_02_04_00_world_graveyard_orientation_434.sql
@@ -0,0 +1,1025 @@
+DROP TABLE IF EXISTS `graveyard_orientation`;
+CREATE TABLE IF NOT EXISTS `graveyard_orientation` (
+ `Id` int(10) unsigned NOT NULL DEFAULT '0',
+ `Orientation` float NOT NULL DEFAULT '0',
+ PRIMARY KEY (`Id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Orientations used by graveyards';
+
+
+INSERT INTO `graveyard_orientation` (`Id`, `Orientation`) VALUES
+(1, 0),
+(2, 0.898845),
+(3, 3.84632),
+(4, 4.016),
+(5, 0),
+(6, 4.77915),
+(7, 2.52685),
+(8, 2.79253),
+(10, 1.22702),
+(31, 3.00197),
+(32, 0.212689),
+(33, 0),
+(34, 1.88888),
+(35, 4.86949),
+(36, 3.15402),
+(39, 4.74773),
+(49, 0),
+(70, 0.212059),
+(89, 1.86139),
+(90, 2.41417),
+(91, 2.71748),
+(92, 1.83612),
+(93, 1.11527),
+(94, 4.63856),
+(96, 0),
+(97, 3.14552),
+(98, 1.68075),
+(99, 2.25147),
+(100, 2.05774),
+(101, 2.54862),
+(102, 0),
+(103, 1.5708),
+(104, 1.01969),
+(105, 2.79406),
+(106, 4.4964),
+(107, 0),
+(108, 3.12588),
+(109, 1.31467),
+(129, 3.31613),
+(149, 0.212058),
+(169, 4.4855),
+(189, 3.00807),
+(209, 1.57738),
+(229, 1.3409),
+(249, 0.0921225),
+(269, 0),
+(289, 4.8891),
+(309, 6.0672),
+(310, 3.10232),
+(329, 0.0100359),
+(349, 2.58867),
+(369, 2.25408),
+(370, 5.99322),
+(389, 3.07483),
+(409, 0.180635),
+(429, 0.911064),
+(449, 0.746765),
+(450, 5.81195),
+(469, 5.80018),
+(489, 4.93017),
+(509, 4.98335),
+(510, 3.6137),
+(511, 0.0353394),
+(512, 0.0454096),
+(529, 0),
+(549, 0),
+(569, 3.38114),
+(609, 3.58927),
+(610, 0.898759),
+(611, 3.92699),
+(629, 0),
+(630, 0.153151),
+(631, 5.67057),
+(633, 3.8059),
+(634, 6.24615),
+(635, 0.195065),
+(636, 6.22035),
+(649, 4.91659),
+(669, 0),
+(670, 0),
+(671, 0),
+(689, 2.00713),
+(690, 4.71239),
+(709, 4.27606),
+(729, 1.53589),
+(749, 2.35619),
+(750, 0.261799),
+(751, 4.79878),
+(769, 3.14159),
+(770, 0),
+(771, 3.5541),
+(772, 5.88176),
+(789, 5.55591),
+(809, 1.5708),
+(810, 0.261799),
+(829, 4.7822),
+(830, 3.35103),
+(849, 0),
+(850, 0.915903),
+(851, 6.28305),
+(852, 0.78761),
+(853, 0),
+(854, 1.76699),
+(869, 2.43866),
+(889, 0.805031),
+(890, 3.8406),
+(891, 2.91208),
+(892, 3.11803),
+(893, 1.70431),
+(894, 1.68861),
+(895, 1.86139),
+(896, 2.53684),
+(897, 5.05011),
+(898, 2.74104),
+(899, 1.72003),
+(909, 6.05544),
+(910, 2.89725),
+(911, 0),
+(912, 5.49779),
+(913, 0),
+(914, 5.49779),
+(915, 0),
+(916, 4.71239),
+(917, 1.5708),
+(918, 5.49779),
+(919, 0.785398),
+(920, 2.44346),
+(921, 5.70723),
+(922, 3.14159),
+(923, 3.66519),
+(924, 4.71239),
+(925, 4.88692),
+(926, 2.35619),
+(927, 4.35582),
+(928, 0.174533),
+(929, 5.23599),
+(930, 4.45059),
+(931, 0),
+(932, 0),
+(933, 3.05433),
+(934, 2.96706),
+(935, 5.03124),
+(936, 2.0944),
+(937, 0.118475),
+(938, 4.7822),
+(939, 3.92699),
+(940, 0.785398),
+(941, 5.03124),
+(942, 5.03124),
+(943, 5.03124),
+(944, 5.03124),
+(945, 5.03124),
+(946, 5.03124),
+(947, 5.03124),
+(948, 5.03124),
+(949, 5.03124),
+(950, 5.03124),
+(951, 5.03124),
+(952, 5.03124),
+(953, 5.03124),
+(954, 5.03124),
+(955, 5.03124),
+(956, 5.03124),
+(957, 5.03124),
+(958, 5.03124),
+(959, 5.03124),
+(960, 5.03124),
+(961, 5.03124),
+(962, 5.03124),
+(963, 5.03124),
+(964, 5.03124),
+(965, 5.03124),
+(966, 5.03124),
+(967, 5.03124),
+(968, 5.03124),
+(969, 3.14159),
+(970, 0),
+(971, 0),
+(972, 0),
+(973, 1.5708),
+(974, 0),
+(975, 0),
+(976, 0),
+(977, 0),
+(978, 0),
+(979, 0),
+(980, 0),
+(981, 0),
+(982, 0),
+(983, 0),
+(984, 0),
+(985, 0),
+(986, 0),
+(987, 0),
+(988, 0),
+(989, 0),
+(990, 0),
+(991, 0),
+(992, 3.14159),
+(993, 3.31613),
+(994, 0.261799),
+(995, 0),
+(996, 5.03124),
+(997, 0.493387),
+(998, 0),
+(999, 0),
+(1000, 0),
+(1001, 0),
+(1002, 0),
+(1003, 0),
+(1004, 0),
+(1005, 0),
+(1006, 0),
+(1007, 0),
+(1008, 0),
+(1009, 0),
+(1010, 0),
+(1011, 0),
+(1012, 0),
+(1013, 0),
+(1014, 0),
+(1015, 0),
+(1016, 0),
+(1017, 0),
+(1018, 0),
+(1019, 0),
+(1020, 0),
+(1021, 0),
+(1022, 0),
+(1023, 0),
+(1024, 0),
+(1025, 0),
+(1026, 0),
+(1027, 0),
+(1028, 0),
+(1029, 0),
+(1030, 0),
+(1031, 0),
+(1032, 0),
+(1033, 0),
+(1034, 0),
+(1035, 0),
+(1036, 0),
+(1037, 0.523599),
+(1038, 2.35619),
+(1039, 0.785398),
+(1040, 2.0944),
+(1041, 4.71239),
+(1042, 1.48353),
+(1043, 0),
+(1044, 3.14159),
+(1045, 0.785398),
+(1046, 3.05433),
+(1047, 1.5708),
+(1048, 0.523599),
+(1049, 4.36332),
+(1050, 2.61799),
+(1051, 0),
+(1052, 0),
+(1053, 0),
+(1054, 0),
+(1055, 0),
+(1056, 0),
+(1057, 0),
+(1058, 0),
+(1059, 0),
+(1060, 0),
+(1061, 0),
+(1062, 0),
+(1063, 0),
+(1064, 0),
+(1065, 0),
+(1066, 0),
+(1067, 0),
+(1068, 0),
+(1069, 0),
+(1070, 0),
+(1071, 0),
+(1072, 0),
+(1073, 0),
+(1074, 0),
+(1075, 0),
+(1076, 0),
+(1077, 0),
+(1078, 0),
+(1079, 0),
+(1080, 0),
+(1081, 0),
+(1082, 0),
+(1083, 0),
+(1084, 0),
+(1085, 0),
+(1086, 0),
+(1087, 0),
+(1088, 0),
+(1089, 0),
+(1090, 0),
+(1091, 0),
+(1092, 0),
+(1093, 0),
+(1094, 0),
+(1095, 0),
+(1096, 0),
+(1097, 0),
+(1098, 0),
+(1099, 0),
+(1100, 0),
+(1101, 0),
+(1102, 0),
+(1103, 3.14159),
+(1104, 0),
+(1105, 5.93412),
+(1106, 1.13446),
+(1107, 4.71239),
+(1108, 3.92699),
+(1109, 3.14159),
+(1110, 3.14159),
+(1111, 3.14159),
+(1112, 3.14159),
+(1113, 3.14159),
+(1114, 3.14159),
+(1115, 3.14159),
+(1116, 3.14159),
+(1117, 3.14159),
+(1118, 3.14159),
+(1119, 3.14159),
+(1120, 3.14159),
+(1121, 3.14159),
+(1122, 3.14159),
+(1123, 3.14159),
+(1124, 3.14159),
+(1125, 3.14159),
+(1126, 3.14159),
+(1127, 3.14159),
+(1128, 3.14159),
+(1129, 3.14159),
+(1130, 3.14159),
+(1131, 3.14159),
+(1132, 3.14159),
+(1133, 3.14159),
+(1134, 0),
+(1135, 0),
+(1136, 0),
+(1137, 0),
+(1138, 0),
+(1139, 0),
+(1140, 0),
+(1141, 0),
+(1142, 0),
+(1143, 0),
+(1144, 0),
+(1145, 0),
+(1146, 0),
+(1147, 0),
+(1148, 0),
+(1149, 0),
+(1150, 0),
+(1151, 0),
+(1152, 0),
+(1153, 0),
+(1154, 0),
+(1155, 0),
+(1156, 0),
+(1157, 0),
+(1158, 0),
+(1159, 0),
+(1160, 0),
+(1161, 0),
+(1162, 0),
+(1163, 0),
+(1164, 0),
+(1165, 0),
+(1166, 0),
+(1167, 0),
+(1168, 0),
+(1169, 0),
+(1170, 0),
+(1171, 0),
+(1172, 0),
+(1173, 0),
+(1174, 0),
+(1175, 0),
+(1176, 0),
+(1177, 0),
+(1178, 0),
+(1179, 0),
+(1180, 0),
+(1181, 0),
+(1182, 0),
+(1183, 0),
+(1184, 0),
+(1185, 0),
+(1186, 0),
+(1187, 0),
+(1188, 0),
+(1189, 0),
+(1190, 0),
+(1191, 0),
+(1192, 0),
+(1193, 0),
+(1194, 0),
+(1195, 0),
+(1196, 0),
+(1197, 0),
+(1198, 0),
+(1199, 0),
+(1200, 0),
+(1201, 0),
+(1202, 0),
+(1203, 0),
+(1204, 0),
+(1205, 0),
+(1206, 0),
+(1207, 0),
+(1208, 0),
+(1209, 0),
+(1210, 0),
+(1211, 0),
+(1212, 0),
+(1213, 0),
+(1214, 0),
+(1215, 0),
+(1216, 0),
+(1217, 0),
+(1218, 0),
+(1219, 0),
+(1220, 0),
+(1221, 0),
+(1222, 0),
+(1223, 0),
+(1224, 0),
+(1225, 0),
+(1226, 0),
+(1227, 0),
+(1228, 0),
+(1229, 0),
+(1230, 0),
+(1231, 0),
+(1232, 0),
+(1233, 0),
+(1234, 0),
+(1235, 0),
+(1236, 0),
+(1237, 0),
+(1238, 0),
+(1239, 0),
+(1240, 3.28122),
+(1241, 2.35619),
+(1242, 0),
+(1243, 3.92699),
+(1244, 3.14159),
+(1245, 3.14159),
+(1246, 4.7822),
+(1247, 5.49779),
+(1248, 0.785398),
+(1249, 0.804483),
+(1250, 1.0472),
+(1251, 2.61799),
+(1252, 2.70526),
+(1253, 4.71239),
+(1254, 1.91986),
+(1255, 3.92699),
+(1256, 1.74533),
+(1257, 0),
+(1258, 4.88692),
+(1259, 1.74533),
+(1260, 0),
+(1261, 3.14159),
+(1262, 0),
+(1263, 0),
+(1264, 4.71239),
+(1265, 4.71239),
+(1266, 0),
+(1267, 0.785398),
+(1268, 3.14159),
+(1269, 0),
+(1270, 3.14159),
+(1271, 1.5708),
+(1272, 1.309),
+(1273, 0),
+(1274, 0),
+(1275, 3.92699),
+(1276, 5.23599),
+(1277, 3.14159),
+(1278, 0),
+(1279, 2.87979),
+(1280, 0.785398),
+(1281, 1.5708),
+(1282, 5.06145),
+(1283, 1.5708),
+(1284, 1.5708),
+(1285, 0.785398),
+(1286, 4.71239),
+(1287, 6.10865),
+(1288, 3.14159),
+(1289, 0.785398),
+(1290, 0),
+(1291, 5.13127),
+(1292, 2.7057),
+(1293, 2.7057),
+(1294, 2.7057),
+(1295, 0.785398),
+(1296, 0.785398),
+(1297, 0.785398),
+(1298, 0.785398),
+(1299, 0),
+(1300, 0.785398),
+(1301, 0.785398),
+(1302, 0.785398),
+(1303, 0.785398),
+(1304, 0.785398),
+(1305, 0.785398),
+(1306, 0.785398),
+(1307, 0.785398),
+(1308, 0.785398),
+(1309, 0.785398),
+(1310, 0.785398),
+(1311, 0.785398),
+(1312, 0.785398),
+(1313, 0.785398),
+(1314, 0.785398),
+(1315, 0.785398),
+(1316, 0.785398),
+(1317, 3.33358),
+(1318, 2.79253),
+(1319, 2.93215),
+(1320, 2.3911),
+(1321, 2.70526),
+(1322, 3.15905),
+(1323, 1.50098),
+(1324, 0.785398),
+(1325, 1.5708),
+(1326, 6.16101),
+(1327, 0.785398),
+(1328, 0.785398),
+(1329, 0.785398),
+(1330, 3.94444),
+(1331, 3.57792),
+(1332, 1.5708),
+(1333, 0.785398),
+(1334, 0.785398),
+(1336, 3.17063),
+(1337, 0),
+(1341, 0.95581),
+(1342, 0.515984),
+(1343, 1.76085),
+(1344, 4.79639),
+(1345, 4.61184),
+(1346, 0.785398),
+(1347, 0.785398),
+(1348, 0.785398),
+(1349, 0.785398),
+(1350, 0),
+(1351, 0.785398),
+(1352, 6.27788),
+(1353, 1.78305),
+(1354, 3.29495),
+(1355, 0.958894),
+(1356, 3.83293),
+(1357, 3.37739),
+(1358, 4.07248),
+(1359, 1.59829),
+(1360, 0.785398),
+(1361, 4.86949),
+(1362, 0.17455),
+(1363, 3.31614),
+(1364, 2.63545),
+(1365, 5.81195),
+(1366, 0.785398),
+(1367, 0.785398),
+(1368, 0.785398),
+(1369, 0.785398),
+(1370, 1.62316),
+(1371, 0),
+(1372, 0.785398),
+(1373, 4.7822),
+(1375, 4.7822),
+(1376, 0),
+(1377, 0.785398),
+(1378, 4.7822),
+(1379, 3.17063),
+(1380, 1.59829),
+(1381, 0.212059),
+(1383, 0.212059),
+(1384, 0.212059),
+(1385, 0.212059),
+(1387, 0.212059),
+(1388, 0.212059),
+(1391, 1.59829),
+(1392, 1.59829),
+(1393, 0.785398),
+(1394, 0.785398),
+(1395, 0.491507),
+(1396, 2.33719),
+(1397, 1.16937),
+(1398, 0.785398),
+(1399, 0.785398),
+(1400, 0.212059),
+(1401, 0.212059),
+(1402, 0.212059),
+(1403, 0.212059),
+(1404, 3.17063),
+(1405, 0.551332),
+(1407, 2.33719),
+(1408, 0.212059),
+(1409, 0.785398),
+(1410, 0.785398),
+(1411, 2.35619),
+(1416, 3.71755),
+(1417, 3.97935),
+(1418, 1.81514),
+(1419, 6.23212),
+(1420, 1.62577),
+(1421, 0.283921),
+(1422, 6.02139),
+(1423, 1.72788),
+(1424, 2.90967),
+(1425, 0.699179),
+(1426, 3.09276),
+(1427, 0.0733387),
+(1428, 0),
+(1429, 2.0944),
+(1430, 4.31096),
+(1431, 0.162371),
+(1432, 4.06662),
+(1433, 3.12414),
+(1434, 5.93412),
+(1435, 3.15905),
+(1436, 4.5204),
+(1437, 1.18682),
+(1438, 4.71239),
+(1439, 3.92699),
+(1440, 5.53269),
+(1441, 2.19911),
+(1442, 3.71755),
+(1443, 1.43117),
+(1444, 2.51327),
+(1445, 3.57792),
+(1446, 2.94961),
+(1447, 4.17134),
+(1448, 0.80333),
+(1449, 0.349066),
+(1450, 5.74213),
+(1451, 2.96706),
+(1452, 5.75959),
+(1453, 3.05433),
+(1454, 3.10669),
+(1455, 1.72788),
+(1456, 5.69962),
+(1457, 1.88496),
+(1458, 1.5708),
+(1459, 0.436332),
+(1460, 0.174533),
+(1461, 4.86947),
+(1462, 4.67748),
+(1463, 6.16101),
+(1464, 2.37365),
+(1465, 1.74533),
+(1466, 6.16101),
+(1467, 3.31613),
+(1468, 0.837758),
+(1469, 6.24828),
+(1470, 1.69297),
+(1471, 0.785398),
+(1472, 1.11701),
+(1473, 0.15708),
+(1474, 0),
+(1475, 5.80018),
+(1476, 2.87979),
+(1477, 0.785398),
+(1478, 0.212059),
+(1480, 4.71239),
+(1481, 1.5708),
+(1482, 4.57276),
+(1483, 5.23599),
+(1484, 1.88496),
+(1485, 0),
+(1486, 3.14159),
+(1488, 5.33195),
+(1489, 0.139626),
+(1491, 3.22886),
+(1492, 3.22624),
+(1493, 1.3409),
+(1494, 0.785398),
+(1495, 0.785398),
+(1496, 1.13446),
+(1497, 4.24115),
+(1681, 0.688792),
+(1682, 6.28163),
+(1683, 3.14159),
+(1689, 2.7646),
+(1690, 0.125664),
+(1691, 0.139626),
+(1692, 0),
+(1693, 2.61799),
+(1694, 0),
+(1695, 3.49066),
+(1696, 3.14159),
+(1697, 1.91986),
+(1698, 3.49066),
+(1699, 3.83972),
+(1700, 0),
+(1701, 0),
+(1702, 0.872665),
+(1703, 2.87979),
+(1704, 3.71755),
+(1705, 0.174533),
+(1706, 0),
+(1707, 0.872665),
+(1708, 3.26377),
+(1709, 3.83972),
+(1710, 4.45059),
+(1711, 5.75959),
+(1712, 1.51844),
+(1713, 0.453786),
+(1714, 5.41052),
+(1715, 1.0472),
+(1716, 0.715585),
+(1720, 0.698132),
+(1721, 4.66528),
+(1722, 1.23702),
+(1723, 5.57242),
+(1724, 1.0446),
+(1725, 6.21056),
+(1726, 2.61799),
+(1727, 0),
+(1728, 0),
+(1729, 3.14159),
+(1730, 5.15089),
+(1731, 2.6396),
+(1732, 4.07465),
+(1733, 5.67134),
+(1734, 0.16178),
+(1735, 1.5708),
+(1736, 4.53786),
+(1738, 0.523599),
+(1739, 3.14159),
+(1740, 5.93412),
+(1741, 3.93223),
+(1742, 3.66519),
+(1743, 0.698132),
+(1744, 3.50811),
+(1745, 3.07092),
+(1746, 5.52924),
+(1747, 0.718672),
+(1748, 2.21657),
+(1749, 4.18879),
+(1750, 1.0472),
+(1751, 6.26552),
+(1752, 5.48208),
+(1753, 0),
+(1754, 1.01316),
+(1755, 2.0944),
+(1756, 5.41052),
+(1757, 2.44346),
+(1758, 4.71239),
+(1759, 2.00713),
+(1761, 3.93052),
+(1762, 1.76952),
+(1763, 3.78736),
+(1764, 0.872665),
+(1765, 1.39626),
+(1766, 5.58505),
+(1767, 4.53786),
+(1768, 2.61799),
+(1769, 5.75959),
+(1770, 1.71042),
+(1771, 0),
+(1772, 1.0472),
+(1773, 0),
+(1774, 0.261799),
+(1775, 2.37365),
+(1777, 5.44675),
+(1778, 4.69494),
+(1779, 0),
+(1780, 0),
+(1781, 0),
+(1782, 0),
+(1783, 2.79253),
+(1784, 1.5708),
+(1785, 3.14159),
+(1786, 3.92699),
+(1787, 5.06145),
+(1788, 5.58505),
+(1789, 3.14159),
+(1790, 1.57864),
+(1791, 1.55116),
+(1792, 6.10008),
+(1793, 2.60113),
+(1794, 0.735801),
+(1795, 5.10263),
+(1796, 4.10519),
+(1797, 0.785398),
+(1798, 5.93412),
+(1799, 1.5708),
+(1800, 5.51597),
+(1801, 1.65965),
+(1802, 5.55915),
+(1803, 2.28795),
+(1804, 6.23062),
+(1805, 0.819221),
+(1806, 0),
+(1807, 0.959931),
+(1808, 0),
+(1809, 0.0872665),
+(1810, 5.58505),
+(1811, 3.90954),
+(1812, 4.71239),
+(1813, 3.40339),
+(1814, 2.44346),
+(1815, 3.40339),
+(1816, 0.715585),
+(1817, 6.10865),
+(1818, 0),
+(1819, 0),
+(1820, 0),
+(1821, 0),
+(1822, 1.02974),
+(1823, 1.55334),
+(1824, 3.12414),
+(1825, 0),
+(1826, 0),
+(1827, 5.23599),
+(1828, 5.41052),
+(1829, 4.18879),
+(1830, 4.18879),
+(1831, 2.79253),
+(1832, 2.0944),
+(1833, 2.44346),
+(1834, 2.26893),
+(1835, 5.49779),
+(1836, 0),
+(1837, 5.23599),
+(1838, 0),
+(1839, 2.61799),
+(1840, 1.91986),
+(1841, 0.523599),
+(1842, 3.14159),
+(1843, 3.14159),
+(1844, 1.69297),
+(1845, 4.36332),
+(1846, 2.40855),
+(1847, 4.18879),
+(1848, 2.44346),
+(1849, 4.06662),
+(1850, 4.71239),
+(1851, 2.18166),
+(1852, 1.0472),
+(1853, 2.23402),
+(1854, 3.80482),
+(1855, 0),
+(1856, 4.53786),
+(1857, 2.74017),
+(1858, 1.0472),
+(1859, 1.51844),
+(1860, 1.5708),
+(1861, 5.23599),
+(1862, 2.59225),
+(1863, 5.31016),
+(1866, 0),
+(1868, 1.39626),
+(1869, 3.4383),
+(1870, 1.3439),
+(1871, 3.26377),
+(1872, 6.10865),
+(1873, 3.87463),
+(1874, 2.00713),
+(1875, 0.0698132),
+(1876, 4.53786),
+(1877, 4.88692),
+(1878, 0.261799),
+(1880, 2.0944),
+(1881, 2.26893),
+(1886, 1.9166),
+(1889, 2.44346),
+(1961, 0.610865),
+(1962, 4.10152),
+(1966, 0),
+(1967, 0),
+(1969, 2.32129),
+(2807, 2.53073),
+(2808, 3.9619),
+(2809, 5.49779),
+(2815, 5.74213),
+(2816, 1.65806),
+(2841, 0),
+(2843, 3.14159),
+(2847, 1.13446),
+(2849, 4.71239),
+(2851, 5.93412),
+(2853, 3.92699),
+(2855, 3.14159),
+(2857, 3.14159),
+(2859, 3.14159),
+(2861, 3.14159),
+(2863, 3.14159),
+(2865, 3.14159),
+(2867, 3.14159),
+(2869, 3.14159),
+(2871, 3.14159),
+(2873, 3.14159),
+(2875, 3.14159),
+(2877, 3.14159),
+(2879, 3.14159),
+(2881, 3.14159),
+(2883, 3.14159),
+(2885, 3.14159),
+(2887, 3.14159),
+(2889, 3.14159),
+(2891, 3.14159),
+(2893, 3.14159),
+(2895, 3.14159),
+(2897, 3.14159),
+(2899, 3.14159),
+(2901, 3.14159),
+(2903, 3.14159),
+(2906, 0),
+(2908, 0),
+(2910, 0),
+(2912, 0),
+(2914, 0),
+(2916, 0),
+(2918, 0),
+(2920, 0),
+(2922, 0),
+(2924, 0),
+(2926, 0),
+(2928, 0),
+(2930, 0),
+(2932, 0),
+(2934, 0),
+(2936, 0),
+(2938, 0),
+(2940, 0),
+(2942, 0),
+(2944, 0),
+(2946, 0),
+(2948, 0),
+(2950, 0),
+(2952, 0),
+(2956, 0),
+(2958, 0),
+(2960, 0),
+(2962, 0),
+(2964, 0),
+(2966, 0),
+(2968, 0),
+(2970, 0),
+(2972, 0),
+(2974, 0),
+(2976, 0),
+(2978, 0),
+(3026, 0),
+(3028, 0),
+(3030, 0),
+(3032, 0),
+(3034, 0),
+(3036, 0),
+(3038, 0),
+(3040, 0),
+(3042, 0),
+(3044, 0),
+(3046, 0),
+(3048, 0),
+(3050, 0),
+(3052, 0),
+(3054, 0),
+(3056, 0),
+(3058, 0),
+(3060, 0),
+(3062, 0),
+(3064, 0),
+(3066, 0),
+(3068, 0),
+(3070, 0),
+(3072, 0),
+(3074, 0),
+(3076, 0),
+(3078, 0),
+(3080, 0),
+(3082, 0),
+(3084, 0),
+(3086, 0),
+(3088, 0),
+(3090, 0),
+(3092, 0),
+(3094, 0),
+(3096, 0),
+(3098, 0),
+(3100, 0),
+(3102, 0),
+(3104, 0),
+(3106, 0),
+(3108, 0),
+(3110, 0),
+(3112, 0),
+(3114, 0),
+(3116, 0),
+(3118, 0),
+(3120, 0),
+(3122, 0),
+(3124, 0),
+(3126, 0),
+(3128, 0),
+(3130, 0),
+(3132, 0),
+(3134, 0),
+(3136, 0),
+(3138, 0),
+(3212, 1.65806),
+(3236, 6.26367),
+(3238, 3.14159),
+(3240, 1.51844),
+(3244, 3.86386),
+(3403, 0),
+(3404, 0);
diff --git a/sql/old/4.3.4/2013_02_06_00_world_spell_proc_event_434.sql b/sql/old/4.3.4/2013_02_06_00_world_spell_proc_event_434.sql
new file mode 100644
index 00000000000..1363a2f7491
--- /dev/null
+++ b/sql/old/4.3.4/2013_02_06_00_world_spell_proc_event_434.sql
@@ -0,0 +1,6 @@
+-- Molten core
+DELETE FROM `spell_proc_event` WHERE `entry` IN (47245, 47246, 47247);
+INSERT INTO `spell_proc_event` (`entry`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`procFlags`,`procEx`,`ppmRate`,`CustomChance`,`Cooldown`) VALUES
+(47245, 0, 5, 4, 0, 0, 0, 1, 0, 0, 0),
+(47246, 0, 5, 4, 0, 0, 0, 1, 0, 0, 0),
+(47247, 0, 5, 4, 0, 0, 0, 1, 0, 0, 0);
diff --git a/sql/updates/world/2013_01_26_01_world_misc_434.sql b/sql/updates/world/2013_01_26_01_world_misc_434.sql
new file mode 100644
index 00000000000..2abe6090c3f
--- /dev/null
+++ b/sql/updates/world/2013_01_26_01_world_misc_434.sql
@@ -0,0 +1,7 @@
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (82676, 82691);
+INSERT INTO `spell_script_names`(`spell_id`, `ScriptName`) VALUES
+(82676, 'spell_mage_ring_of_frost'),
+(82691, 'spell_mage_ring_of_frost_freeze');
+
+-- Set flags UNIT_FLAG_DISABLE_MOVE| UNIT_FLAG_STUNNED|UNIT_FLAG_NOT_SELECTABLE on Ring of Frost
+UPDATE `creature_template` SET `unit_flags` = 0x4|0x40000|0x2000000 WHERE `entry` = 44199;
diff --git a/sql/updates/world/2013_02_27_00_world_creature_summon_groups_434.sql b/sql/updates/world/2013_02_27_00_world_creature_summon_groups_434.sql
new file mode 100644
index 00000000000..4cdd26a83e8
--- /dev/null
+++ b/sql/updates/world/2013_02_27_00_world_creature_summon_groups_434.sql
@@ -0,0 +1,10 @@
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=52151 AND `groupId`=0;
+INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`) VALUES
+(52151, 0, 0, 52156, -12330.3, -1878.41, 127.32, 3.89208, 8, 0),
+(52151, 0, 0, 52156, -12351.94, -1861.51, 127.4807, 4.677482, 8, 0),
+(52151, 0, 0, 52156, -12326.71, -1904.328, 127.4111, 2.75762, 8, 0),
+(52151, 0, 0, 52156, -12347.41, -1917.535, 127.3196, 1.553343, 8, 0),
+(52151, 0, 0, 52156, -12378.57, -1861.222, 127.5416, 5.340707, 8, 0),
+(52151, 0, 0, 52156, -12397.79, -1887.731, 127.5453, 0.03490658, 8, 0),
+(52151, 0, 0, 52156, -12372.36, -1918.844, 127.343, 1.151917, 8, 0),
+(52151, 0, 0, 52156, -12391.23, -1905.273, 127.3196, 0.6108652, 8, 0);
diff --git a/sql/updates/world/2013_03_15_01_world_keychain_db2_434.sql b/sql/updates/world/2013_03_15_01_world_keychain_db2_434.sql
new file mode 100644
index 00000000000..fb8364d47d0
--- /dev/null
+++ b/sql/updates/world/2013_03_15_01_world_keychain_db2_434.sql
@@ -0,0 +1,43 @@
+DROP TABLE IF EXISTS `keychain_db2`;
+CREATE TABLE `keychain_db2` (
+ `keyId` INT UNSIGNED NOT NULL DEFAULT '0',
+ `k1` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k2` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k3` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k4` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k5` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k6` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k7` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k8` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k9` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k10` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k11` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k12` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k13` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k14` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k15` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k16` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k17` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k18` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k19` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k20` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k21` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k22` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k23` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k24` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k25` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k26` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k27` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k28` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k29` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k30` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k31` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ `k32` TINYINT UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`keyId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO `keychain_db2` VALUES
+(33, 53, 6, 164, 135, 117, 210, 209, 135, 247, 162, 85, 200, 76, 220, 107, 56, 80, 214, 44, 121, 29, 66, 81, 25, 41, 38, 208, 8, 235, 154, 58, 139),
+(35, 16, 209, 60, 47, 154, 100, 204, 97, 125, 161, 79, 126, 191, 163, 7, 45, 64, 188, 199, 88, 141, 46, 153, 90, 143, 40, 6, 80, 29, 133, 217, 135),
+(36, 3, 169, 217, 5, 156, 76, 33, 82, 75, 181, 233, 203, 230, 52, 67, 197, 57, 99, 27, 108, 100, 197, 93, 156, 174, 2, 248, 216, 244, 115, 164, 210),
+(37, 119, 7, 189, 206, 199, 253, 234, 73, 232, 17, 162, 79, 0, 35, 222, 224, 7, 98, 132, 147, 229, 36, 19, 253, 79, 59, 198, 59, 48, 121, 97, 215);
diff --git a/sql/updates/world/2013_03_23_00_world_playercreateinfo_spell.sql b/sql/updates/world/2013_03_23_00_world_playercreateinfo_spell.sql
new file mode 100644
index 00000000000..667022eaba9
--- /dev/null
+++ b/sql/updates/world/2013_03_23_00_world_playercreateinfo_spell.sql
@@ -0,0 +1,777 @@
+TRUNCATE TABLE `playercreateinfo_spell`;
+TRUNCATE TABLE `playercreateinfo_spell_custom`;
+
+ALTER TABLE `playercreateinfo_spell`
+ CHANGE `race` `racemask` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+ CHANGE `class` `classmask` INT(10) UNSIGNED DEFAULT 0 NOT NULL;
+
+ALTER TABLE `playercreateinfo_spell_custom`
+ CHANGE `race` `racemask` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+ CHANGE `class` `classmask` INT(10) UNSIGNED DEFAULT 0 NOT NULL;
+
+INSERT INTO `playercreateinfo_spell` (`racemask`, `classmask`, `Spell`, `Note`) VALUES
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Death Knight
+(0x0, 0x27, 202, "Two-Handed Swords"),
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Rogue, Death Knight, Shaman
+(0x0, 0x6F, 196, "One-Handed Axes"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 2457, "Battle Stance"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 88161, "Strike"),
+-- Races: All
+-- Classes: Warrior, Hunter, Rogue
+(0x0, 0xD, 5011, "Crossbows"),
+-- Races: All
+-- Classes: Warrior, Rogue
+(0x0, 0x9, 3018, "Shoot"),
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Death Knight, Shaman
+(0x0, 0x67, 197, "Two-Handed Axes"),
+-- Races: All
+-- Classes: Warrior, Hunter, Rogue, Priest, Shaman, Mage, Warlock, Druid
+(0x0, 0x5DD, 1180, "Daggers"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 45927, "Summon Friend"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6478, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6603, "Auto Attack"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 22027, "Remove Insignia"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 22810, "Opening - No Text"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 21651, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 21652, "Closing"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 2382, "Generic"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 3365, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 3050, "Detect"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 9125, "Generic"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 8386, "Attacking"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 7266, "Duel"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 7267, "Grovel"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 7355, "Stuck"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6233, "Closing"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6246, "Closing"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6247, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 6477, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 61437, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 68398, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 96220, "Opening"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 203, "Unarmed"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 20864, "Mace Specialization"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 20599, "Diplomacy"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 20597, "Sword Specialization"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 20598, "The Human Spirit"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 59752, "Every Man for Himself"),
+-- Races: Human
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x1, 0x1BF, 79738, "Languages"),
+-- Races: All
+-- Classes: Warrior, Paladin, Death Knight
+(0x0, 0x23, 49410, "Forceful Deflection"),
+-- Races: All
+-- Classes: Warrior, Paladin, Death Knight, Shaman, Druid
+(0x0, 0x463, 199, "Two-Handed Maces"),
+-- Races: All
+-- Classes: Warrior, Hunter, Rogue, Shaman, Druid
+(0x0, 0x44D, 15590, "Fist Weapons"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 76268, "Armor Skills"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 76290, "Weapon Skills"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 88163, "Attack"),
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Death Knight, Druid
+(0x0, 0x427, 200, "Polearms"),
+-- Races: Human, Dwarf, Night elf, Gnome, Dranei, Worgen
+-- Classes: All
+(0x20044D, 0x0, 668, "Language Common"),
+-- Races: All
+-- Classes: Warrior, Hunter, Priest, Shaman, Mage, Warlock, Druid
+(0x0, 0x5D5, 227, "Staves"),
+-- Races: All
+-- Classes: Warrior, Paladin, Shaman
+(0x0, 0x43, 9116, "Shield"),
+-- Races: All
+-- Classes: Warrior, Paladin, Death Knight
+(0x0, 0x23, 8737, "Mail"),
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Rogue, Death Knight, Shaman, Druid
+(0x0, 0x46F, 9077, "Leather"),
+-- Races: All
+-- Classes: Warrior, Hunter, Rogue
+(0x0, 0xD, 264, "Bows"),
+-- Races: All
+-- Classes: Warrior, Hunter, Rogue
+(0x0, 0xD, 266, "Guns"),
+-- Races: All
+-- Classes: Warrior, Paladin, Shaman
+(0x0, 0x43, 107, "Block"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 81, "Dodge"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 32215, "Victorious State"),
+-- Races: All
+-- Classes: Warrior
+(0x0, 0x1, 5301, "Defensive State (DND)"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 204, "Defense"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 522, "SPELLDEFENSE (DND)"),
+-- Races: All
+-- Classes: Warrior, Rogue
+(0x0, 0x9, 2764, "Throw"),
+-- Races: All
+-- Classes: Warrior, Rogue
+(0x0, 0x9, 2567, "Thrown"),
+-- Races: All
+-- Classes: All
+(0x0, 0x0, 9078, "Cloth"),
+-- Races: All
+-- Classes: Warrior, Paladin, Rogue, Priest, Death Knight, Shaman, Druid
+(0x0, 0x47B, 198, "One-Handed Maces"),
+-- Races: All
+-- Classes: Warrior, Paladin, Hunter, Rogue, Death Knight, Mage, Warlock
+(0x0, 0x1AF, 201, "One-Handed Swords"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 27762, "Relic"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 76271, "Armor Skills"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 76294, "Weapon Skills"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 35395, "Crusader Strike"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 60091, "Judgement Anti-Parry/Dodge Passive"),
+-- Races: Human, Dwarf, Tauren, Blood elf, Dranei
+-- Classes: Paladin
+(0x625, 0x2, 20208, "Paladin pushback resistance"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 3044, "Arcane Shot"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 75, "Auto Shot"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 82928, "Aimed Shot!"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 34082, "Hunter Passive Auras (DND)"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 883, "Call Pet 1"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 982, "Revive Pet"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 13358, "Defensive State (DND)"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 24949, "Defensive State 2 (DND)"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 77442, "Focus"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 76249, "Weapon Skills"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 76250, "Armor Skills"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 87324, "Focused Aim"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Tauren, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Hunter
+(0x2007BF, 0x4, 87816, "General Hunter Passives"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Rogue
+(0x2003DF, 0x8, 1752, "Sinister Strike"),
+-- Races: All
+-- Classes: Rogue, Death Knight
+(0x0, 0x28, 674, "Dual Wield"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Rogue
+(0x2003DF, 0x8, 76273, "Armor Skills"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Rogue
+(0x2003DF, 0x8, 76297, "Weapon Skills"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Rogue
+(0x2003DF, 0x8, 16092, "Defensive State (DND)"),
+-- Races: All
+-- Classes: Priest, Mage, Warlock
+(0x0, 0x190, 5009, "Wands"),
+-- Races: All
+-- Classes: Priest, Mage, Warlock
+(0x0, 0x190, 5019, "Shoot"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 585, "Smite"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 84733, "Holy Focus"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 88685, "Holy Word: Sanctuary"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 88684, "Holy Word: Serenity"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 101062, "Flash Heal"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 76301, "Weapon Skills"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 76279, "Armor Skills"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 84734, "Dark Thoughts"),
+-- Races: Human, Dwarf, Night elf, Undead, Tauren, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Priest
+(0x2007FD, 0x10, 77486, "Shadow Orb Power"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 71761, "Deep Freeze Immunity State"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 79684, "Offensive State (DND)"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 133, "Fireball"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 92315, "Pyroblast!"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage, Warlock
+(0x2007DF, 0x180, 85801, "DPS Caster Crit Damage Bonus"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 76298, "Weapon Skills"),
+-- Races: Human, Orc, Dwarf, Night elf, Undead, Gnome, Troll, Goblin, Blood elf, Dranei, Worgen
+-- Classes: Mage
+(0x2007DF, 0x80, 76276, "Armor Skills"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 688, "Summon Imp"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 86213, "Soul Swap Exhale"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 89420, "Drain Life"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 76299, "Weapon Skills"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 76277, "Armor Skills"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 87330, "Suppression"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 75445, "Demonic Immolate"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 686, "Shadow Bolt"),
+-- Races: Human, Orc, Dwarf, Undead, Gnome, Troll, Goblin, Blood elf, Worgen
+-- Classes: Warlock
+(0x2003D7, 0x100, 58284, "Chaos Bolt Passive"),
+-- Races: Orc, Undead, Tauren, Troll, Goblin, Blood elf
+-- Classes: All
+(0x3B2, 0x0, 669, "Language Orcish"),
+-- Races: Orc
+-- Classes: Warrior, Rogue, Mage
+(0x2, 0x89, 21563, "Command"),
+-- Races: Orc
+-- Classes: Warrior, Hunter, Rogue, Death Knight
+(0x2, 0x2D, 20572, "Blood Fury"),
+-- Races: Orc
+-- Classes: Warrior, Hunter, Rogue, Death Knight, Shaman, Mage, Warlock
+(0x2, 0x1ED, 20573, "Hardiness"),
+-- Races: Orc
+-- Classes: Warrior, Hunter, Rogue, Death Knight, Shaman, Mage, Warlock
+(0x2, 0x1ED, 20574, "Axe Specialization"),
+-- Races: Orc
+-- Classes: Warrior, Hunter, Rogue, Death Knight, Shaman, Mage, Warlock
+(0x2, 0x1ED, 79743, "Languages"),
+-- Races: Orc
+-- Classes: Hunter
+(0x2, 0x4, 20576, "Command"),
+-- Races: Orc, Dwarf, Troll, Goblin, Dranei
+-- Classes: Shaman
+(0x586, 0x40, 27763, "Relic"),
+-- Races: Orc
+-- Classes: Shaman
+(0x2, 0x40, 65222, "Command"),
+-- Races: Orc
+-- Classes: Shaman
+(0x2, 0x40, 33697, "Blood Fury"),
+-- Races: Orc, Dwarf, Troll, Goblin, Dranei
+-- Classes: Shaman
+(0x586, 0x40, 76272, "Armor Skills"),
+-- Races: Orc, Dwarf, Troll, Goblin, Dranei
+-- Classes: Shaman
+(0x586, 0x40, 76296, "Weapon Skills"),
+-- Races: Orc, Dwarf, Troll, Goblin, Dranei
+-- Classes: Shaman
+(0x586, 0x40, 89920, "Ancestral Focus"),
+-- Races: Orc, Dwarf, Tauren, Troll, Goblin, Dranei
+-- Classes: Shaman
+(0x5A6, 0x40, 403, "Lightning Bolt"),
+-- Races: Orc
+-- Classes: Mage, Warlock
+(0x2, 0x180, 33702, "Blood Fury"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 20596, "Frost Resistance"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 20595, "Gun Specialization"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 20594, "Stoneform"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 59224, "Mace Specialization"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 92682, "Explorer"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 79739, "Languages"),
+-- Races: Dwarf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x4, 0x1FF, 672, "Language Dwarven"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 76252, "Languages"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 20583, "Nature Resistance"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 20582, "Quickness"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 20585, "Wisp Spirit"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 21009, "Elusiveness"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 58984, "Shadowmeld"),
+-- Races: Night elf
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Druid
+(0x8, 0x4BD, 671, "Language Darnassian"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 84736, "Nature's Focus"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 81170, "Ravage!"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 79577, "Eclipse Mastery Driver Passive"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 76300, "Weapon Skills"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 76275, "Armor Skills"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 5176, "Wrath"),
+-- Races: Night elf, Tauren, Troll, Worgen
+-- Classes: Druid
+(0x2000A8, 0x400, 84738, "Celestial Focus"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage
+(0x10, 0xBD, 17737, "Language Gutterspeak"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x10, 0x1BD, 5227, "Underwater Breathing"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x10, 0x1BD, 7744, "Will of the Forsaken"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x10, 0x1BD, 20577, "Cannibalize"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x10, 0x1BD, 20579, "Shadow Resistance"),
+-- Races: Undead
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x10, 0x1BD, 79747, "Languages"),
+-- Races: Undead
+-- Classes: Warlock
+(0x10, 0x100, 17747, "Language Gutterspeak"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 670, "Language Taurahe"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 20549, "War Stomp"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 20550, "Endurance"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 20551, "Nature Resistance"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 20552, "Cultivation"),
+-- Races: Tauren
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Druid
+(0x20, 0x437, 79746, "Languages"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 20591, "Expansive Mind"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 20593, "Engineering Specialization"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 20592, "Arcane Resistance"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 92680, "Shortblade Specialization"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 79740, "Languages"),
+-- Races: Gnome
+-- Classes: Warrior, Rogue, Priest, Death Knight, Mage, Warlock
+(0x40, 0x1B9, 7340, "Language Gnomish"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 7341, "Language Troll"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 26290, "Bow Specialization"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 26297, "Berserking"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 58943, "Da Voodoo Shuffle"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 20555, "Regeneration"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 20557, "Beast Slaying"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 20558, "Throwing Specialization"),
+-- Races: Troll
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock, Druid
+(0x80, 0x5FD, 79744, "Languages"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69269, "Language Goblin"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69070, "Rocket Jump"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69041, "Rocket Barrage"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69044, "Best Deals Anywhere"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69045, "Better Living Through Chemistry"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 69042, "Time is Money"),
+-- Races: Goblin
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Shaman, Mage, Warlock
+(0x100, 0x1FD, 79749, "Languages"),
+-- Races: Blood elf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x200, 0x1BF, 813, "Language Thalassian"),
+-- Races: Blood elf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x200, 0x1BF, 822, "Arcane Resistance"),
+-- Races: Blood elf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x200, 0x1BF, 28877, "Arcane Affinity"),
+-- Races: Blood elf
+-- Classes: Warrior
+(0x200, 0x1, 69179, "Arcane Torrent"),
+-- Races: Blood elf
+-- Classes: Warrior, Paladin, Hunter, Rogue, Priest, Death Knight, Mage, Warlock
+(0x200, 0x1BF, 79748, "Languages"),
+-- Races: Blood elf
+-- Classes: Paladin, Priest, Mage, Warlock
+(0x200, 0x192, 28730, "Arcane Torrent"),
+-- Races: Blood elf
+-- Classes: Hunter
+(0x200, 0x4, 80483, "Arcane Torrent"),
+-- Races: Blood elf
+-- Classes: Rogue
+(0x200, 0x8, 25046, "Arcane Torrent"),
+-- Races: Dranei
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Shaman, Mage
+(0x400, 0xF7, 29932, "Language Draenei"),
+-- Races: Dranei
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Shaman, Mage
+(0x400, 0xF7, 79741, "Languages"),
+-- Races: Dranei
+-- Classes: Warrior, Paladin, Hunter, Death Knight
+(0x400, 0x27, 6562, "Heroic Presence"),
+-- Races: Dranei
+-- Classes: Warrior
+(0x400, 0x1, 28880, "Gift of the Naaru"),
+-- Races: Dranei
+-- Classes: Warrior, Paladin, Hunter, Priest, Death Knight, Shaman, Mage
+(0x400, 0xF7, 28875, "Gemcutting"),
+-- Races: Dranei
+-- Classes: Warrior
+(0x400, 0x1, 59221, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Paladin
+(0x400, 0x2, 59535, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Paladin
+(0x400, 0x2, 59542, "Gift of the Naaru"),
+-- Races: Dranei
+-- Classes: Hunter
+(0x400, 0x4, 59543, "Gift of the Naaru"),
+-- Races: Dranei
+-- Classes: Hunter
+(0x400, 0x4, 59536, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Priest
+(0x400, 0x10, 59538, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Priest, Shaman, Mage
+(0x400, 0xD0, 28878, "Heroic Presence"),
+-- Races: Dranei
+-- Classes: Priest
+(0x400, 0x10, 59544, "Gift of the Naaru"),
+-- Races: Dranei
+-- Classes: Shaman
+(0x400, 0x40, 59540, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Shaman
+(0x400, 0x40, 59547, "Gift of the Naaru"),
+-- Races: Dranei
+-- Classes: Mage
+(0x400, 0x80, 59541, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Mage
+(0x400, 0x80, 59548, "Gift of the Naaru"),
+-- Races: Worgen
+-- Classes: Warrior, Hunter, Rogue, Priest, Death Knight, Mage, Warlock, Druid
+(0x200000, 0x5BD, 79742, "Languages"),
+-- Races: Worgen
+-- Classes: Warrior, Hunter, Rogue, Priest, Mage, Warlock, Druid
+(0x200000, 0x59D, 69001, ""),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 52665, "Relic"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 63645, "Activating Primary Spec"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 63644, "Activating Secondary Spec"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 45902, "Blood Strike"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 82246, "Parry"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 89832, "Death Strike Enabler"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 45477, "Icy Touch"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 48266, "Frost Presence"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 61455, "Runic Focus"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 59921, "Frost Fever"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 33391, "Journeyman Riding"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 89964, "Clear Glyph"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 76282, "Armor Skills"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 76292, "Weapon Skills"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 750, "Plate Mail"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 45462, "Plague Strike"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 47541, "Death Coil"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 49576, "Death Grip"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 59879, "Blood Plague"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 45903, "Offensive State (DND)"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 10846, "First Aid"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 3275, "Linen Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 18630, "Heavy Runecloth Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 3276, "Heavy Linen Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 3277, "Wool Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 3278, "Heavy Wool Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 7928, "Silk Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 7929, "Heavy Silk Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 10840, "Mageweave Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 10841, "Heavy Mageweave Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 18629, "Runecloth Bandage"),
+-- Races: All
+-- Classes: Death Knight
+(0x0, 0x20, 7934, "Anti-Venom"),
+-- Races: Orc
+-- Classes: Death Knight
+(0x2, 0x20, 54562, "Command"),
+-- Races: Gnome
+-- Classes: Death Knight
+(0x40, 0x20, 20589, "Escape Artist"),
+-- Races: Goblin
+-- Classes: Death Knight
+(0x100, 0x20, 69046, "Pack Hobgoblin"),
+-- Races: Blood elf
+-- Classes: Death Knight
+(0x200, 0x20, 50613, "Arcane Torrent"),
+-- Races: Dranei
+-- Classes: Death Knight
+(0x400, 0x20, 59539, "Shadow Resistance"),
+-- Races: Dranei
+-- Classes: Death Knight
+(0x400, 0x20, 59545, "Gift of the Naaru"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 68978, "Flayer"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 68992, "Darkflight"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 68976, "Aberration"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 68996, "Two Forms"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 68975, "Viciousness"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 94293, "Enable Worgen Altered Form"),
+-- Races: Worgen
+-- Classes: Death Knight
+(0x200000, 0x20, 87840, "Running Wild");
diff --git a/sql/updates/world/2013_04_03_00_world_playercreateinfo_button_434.sql b/sql/updates/world/2013_04_03_00_world_playercreateinfo_button_434.sql
new file mode 100644
index 00000000000..b7281422712
--- /dev/null
+++ b/sql/updates/world/2013_04_03_00_world_playercreateinfo_button_434.sql
@@ -0,0 +1,4 @@
+-- Fixes tauren druids not having wrath in their spell bar on character creation.
+DELETE FROM `playercreateinfo_action` WHERE `race`=6 AND `class`=11 AND `action`=5176;
+INSERT INTO `playercreateinfo_action` (`race`, `class`, `button`, `action`, `type`) VALUES
+(6, 11, 0, 5176, 0);
diff --git a/sql/updates/world/2013_05_09_00_world_spell_dbc_434.sql b/sql/updates/world/2013_05_09_00_world_spell_dbc_434.sql
new file mode 100644
index 00000000000..11fc9e7ed51
--- /dev/null
+++ b/sql/updates/world/2013_05_09_00_world_spell_dbc_434.sql
@@ -0,0 +1,138 @@
+DROP TABLE IF EXISTS `spell_dbc`;
+CREATE TABLE `spell_dbc` (
+ `Id` INT(10) UNSIGNED NOT NULL,
+ `Attributes` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx2` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx3` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx4` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx5` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx6` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx7` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx8` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx9` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `AttributesEx10` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `CastingTimeIndex` INT(10) UNSIGNED NOT NULL DEFAULT '1',
+ `DurationIndex` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `RangeIndex` INT(10) UNSIGNED NOT NULL DEFAULT '1',
+ `SchoolMask` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellAuraOptionsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellCastingRequirementsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellCategoriesId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellClassOptionsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellEquippedItemsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellLevelsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellTargetRestrictionsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `SpellInterruptsId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `Comment` TEXT NOT NULL,
+ PRIMARY KEY (`Id`)
+)
+COMMENT='Custom spell.dbc entries'
+COLLATE='utf8_general_ci'
+ENGINE=MyISAM;
+
+INSERT INTO `spell_dbc` (`Id`, `Attributes`, `AttributesEx`, `AttributesEx2`, `AttributesEx3`, `AttributesEx4`, `AttributesEx5`, `AttributesEx6`, `AttributesEx7`, `AttributesEx8`, `AttributesEx9`, `AttributesEx10`, `CastingTimeIndex`, `DurationIndex`, `RangeIndex`, `SchoolMask`, `SpellAuraOptionsId`, `SpellCastingRequirementsId`, `SpellCategoriesId`, `SpellClassOptionsId`, `SpellEquippedItemsId`, `SpellLevelsId`, `SpellTargetRestrictionsId`, `SpellInterruptsId`, `Comment`) VALUES
+(11202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Item 3776 spellid_1 serverside spell'),
+(25347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Item_template serverside spell'),
+(25359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Item 21293 spellid_2 serverside spell'),
+(27488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Grimoire of Blood Pack Rank 6: spell filler'),
+(32780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 10040 reward serverside spell'),
+(34145, 0, 0, 0, 67108864, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1035, 0, 0, 'Ritual of Souls Rank 1 - Trigger Create Soulwell (29886)'),
+(34448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Serverside spell orb of translocation (gobjid=180911)'),
+(34452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Serverside spell orb of translocation (gobjid=180912)'),
+(38406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 10721 RewSpellCast serverside spell'),
+(38665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Exorcising the Trees'),
+(38758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Nether Gas In a Fel Fire Engine'),
+(38788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Spirit Calling'),
+(39613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 10967 reward serverside spell'),
+(39616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 10966 reward serverside spell'),
+(40145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11000 RewSpellCast serverside spell'),
+(42876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 9275 reward serverside spell'),
+(43236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11288 reward serverside spell'),
+(43459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11332 reward serverside spell'),
+(43499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11250 reward serverside spell'),
+(43503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11261 reward serverside spell'),
+(44275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11432 reward serverside spell'),
+(44805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Aura used in creature_addon - serverside spell'),
+(44987, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11521 reward serverside spell'),
+(45140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Making Ready / Don\'t Stop Now....'),
+(45144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Disrupt the Greengill Coast'),
+(45148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Ata\'mal Armaments'),
+(45315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11566 reward serverside spell'),
+(45453, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11587 reward serverside spell'),
+(45459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Placeholder, Missing Aura'),
+(45460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Placeholder, Missing Aura'),
+(45767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 11670 RewSpellCast serverside spell'),
+(46251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, '[PH] Quest reward: Blood for Blood'),
+(48803, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 12214 reward serverside spell'),
+(50574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 12597 reward serverside spell'),
+(58888, 0, 0, 0, 67108864, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 91, 0, 0, 'Ritual of Souls Rank 2 - Trigger Create Soulwell (58889)'),
+(59046, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Tribunal of Ages - Criteria Marker'),
+(62388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Demonic Circle: Teleport(48020) - casterAuraSpell'),
+(62791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'XT-002 Heart Overload Trigger Spell'),
+(64689, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 13854 and 13862 reward serverside spell'),
+(65037, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Nerf the Scrapbots Achievement Criteria Marker'),
+(65074, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Freya Achievement spell - Criteria Marker'),
+(68496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Item_template serverside spell'),
+(70816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2146 spellid0 serverside spell'),
+(70878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Creature 40160 creature_addon serverside spell'),
+(71098, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Quest 24451 RewSpellCast serverside spell'),
+(71356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2108 spellid0 serverside spell'),
+(71803, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2108 spellid1 serverside spell'),
+(72111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2136 spellid0 serverside spell'),
+(72125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2136 spellid1 serverside spell'),
+(72233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2146 spellid1 serverside spell'),
+(72234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2146 spellid2 serverside spell'),
+(72235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Spelldifficulty_dbc id:2146 spellid3 serverside spell'),
+(100001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 1, 1, 38, 0, 0, 1205, 0, 0, 0, 0, 'Drain Soul increased damage - serverside spell'),
+(3617, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NPC 32958 suicide spell'),
+(18954, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Ranshalla Despawn'),
+(24308, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Summon Shade of Jin\'Do'),
+(24677, 256, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'GY Mid Trigger - 2.0.12 spell - AV Snowfall Graveyard'),
+(25900, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stun Self'),
+(28782, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stun Self + Immune'),
+(30023, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Gushing Wound Removal'),
+(30426, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 40, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Akida'),
+(30429, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 40, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Coo'),
+(30432, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 40, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Tikti'),
+(30454, 256, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 40, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Vark'),
+(31247, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Silithyst Cap Reward'),
+(40200, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Bombing Run: See Invisibility Aura Remover'),
+(70507, 256, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 702, 0, 0, 0, 0, 0, 0, 0, 'Halion - Combustion & Consumption Scale Aura'),
+(74810, 256, 268435456, 4, 0, 0, 0, 16785408, 0, 0, 0, 0, 1, 21, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Halion - Copy Damage'),
+(7056, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Pacified'),
+(25042, 384, 268435592, 4, 131072, 0, 0, 0, 0, 0, 0, 0, 1, 29, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Triggerspell - Mark of Nature'),
+(31934, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 3190, 0, 0, 0, 0, 0, 0, 0, 'Blessed Life'),
+(37794, 384, 0, 0, 1048576, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Transform Infernal'),
+(39707, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Creature 23487 creature_addon serverside spell'),
+(63975, 384, 0, 0, 262144, 128, 0, 0, 0, 0, 0, 0, 1, 0, 13, 1, 38, 0, 0, 0, 0, 0, 0, 0, 'Glyph of Blackstab - 3.2.2'),
+(24899, 400, 1024, 0, 0, 2097152, 0, 0, 0, 0, 0, 0, 1, 21, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Heart of the Wild Bear Effect'),
+(24900, 400, 1024, 0, 0, 2097152, 0, 0, 0, 0, 0, 0, 1, 21, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Heart of the Wild Cat Effect'),
+(72958, 448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Shaman T10 shoulder visual'),
+(12507, 464, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 38, 0, 0, 0, 0, 2, 0, 0, 'Atal\'ai Skeleton Totem'),
+(31982, 464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 0, 38, 0, 0, 0, 0, 1337, 0, 0, 'Tainted Earthgrab Totem'),
+(30437, 2304, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Akida TRIGGER'),
+(30442, 2304, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Coo TRIGGER'),
+(30443, 2304, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Tikti TRIGGER'),
+(30453, 2304, 268435456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Stillpine Ancestor Vark TRIGGER'),
+(13377, 2512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 1, 2, 0, 0, 22835, 0, 0, 141, 0, 0, 'Fire Shield'),
+(33134, 65920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 85, 1, 2, 38, 0, 0, 0, 0, 20, 0, 0, 'Tainted Nova Totem'),
+(31980, 328064, 1024, 4, 268894208, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 1, 0, 0, 0, 2826, 0, 37, 0, 0, 'Righteous Defense Trigger Spell'),
+(25893, 8388864, 268435456, 5, 269484032, 0, 0, 0, 0, 0, 0, 0, 1, 225, 13, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Viscidus Shrinks'),
+(65387, 8388864, 0, 5, 268697600, 128, 0, 16777216, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Steelforged Defender - Credit marker'),
+(58630, 8388992, 0, 5, 269484288, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Mal\'ganis credit marker'),
+(35009, 134545792, 1024, 268435460, 65536, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 6, 0, 0, 0, 50, 0, 0, 2, 0, 'Invisibility - Reducing threat'),
+(68308, 159383808, 1056, 16389, 268697600, 128, 8, 4096, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Vault of Archavon - Earth, Wind & Fire - Achievement Check'),
+(59450, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'The Four Horsemen credit marker'),
+(64899, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Hodir credit marker'),
+(64985, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Thorim credit marker'),
+(65195, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'The Iron Council credit marker'),
+(68572, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Grand Champions credit marker'),
+(68574, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent Champion credit marker'),
+(61698, 536871296, 269058048, 67108868, 268894272, 2048, 0, 1024, 0, 0, 0, 0, 1, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Flush - Knockback effect'),
+(5302, 536871312, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 28, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Defensive State - Follows a successful block,dodge or parry.'),
+(68184, 545259904, 0, 5, 268697856, 128, 0, 16777216, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Faction Champions - credit marker'),
+(68620, 545259904, 0, 5, 268697856, 128, 0, 16777216, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Resilience Will Fix It - achievement credit marker'),
+(60937, 562036736, 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Seaforium charges damaging wall achievement credit'),
+(58428, 671089024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 18, 1, 1, 1, 0, 0, 297, 0, 0, 0, 0, 'Overkill - aura remove spell'),
+(61988, 671089024, 268436480, 4, 269484032, 0, 0, 0, 0, 0, 0, 0, 1, 25, 13, 0, 38, 0, 0, 0, 0, 0, 0, 0, 'Divine Shield Exclude Aura - 61988');
diff --git a/sql/updates/world/2013_05_09_01_world_spelleffect_dbc_434.sql b/sql/updates/world/2013_05_09_01_world_spelleffect_dbc_434.sql
new file mode 100644
index 00000000000..a5446589859
--- /dev/null
+++ b/sql/updates/world/2013_05_09_01_world_spelleffect_dbc_434.sql
@@ -0,0 +1,105 @@
+DROP TABLE IF EXISTS `spelleffect_dbc`;
+CREATE TABLE `spelleffect_dbc` (
+ `Id` INT(10) UNSIGNED NOT NULL,
+ `Effect` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectValueMultiplier` FLOAT UNSIGNED NOT NULL DEFAULT '0',
+ `EffectApplyAuraName` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectAplitude` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectBasePoints` INT(10) NOT NULL DEFAULT '0',
+ `EffectBonusMultiplier` FLOAT UNSIGNED NOT NULL DEFAULT '0',
+ `EffectDamageMultiplier` FLOAT UNSIGNED NOT NULL DEFAULT '0',
+ `EffectChainTarget` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectDieSides` INT(10) NOT NULL DEFAULT '0',
+ `EffectMechanic` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectMiscValue` INT(10) NOT NULL DEFAULT '0',
+ `EffectMiscValueB` INT(10) NOT NULL DEFAULT '0',
+ `EffectRadiusIndex` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectRadiusIndexMax` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectRealPointsPerLevel` FLOAT UNSIGNED NOT NULL DEFAULT '0',
+ `EffectSpellClassMaskA` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectSpellClassMaskB` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectSpellClassMaskC` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectTriggerSpell` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectImplicitTargetA` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectImplicitTargetB` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ `EffectSpellId` INT(10) UNSIGNED NOT NULL,
+ `EffectIndex` INT(10) UNSIGNED NOT NULL,
+ PRIMARY KEY (`Id`)
+)
+COLLATE='utf8_general_ci'
+ENGINE=MyISAM;
+
+INSERT INTO `spelleffect_dbc` (`Id`, `Effect`, `EffectValueMultiplier`, `EffectApplyAuraName`, `EffectAplitude`, `EffectBasePoints`, `EffectBonusMultiplier`, `EffectDamageMultiplier`, `EffectChainTarget`, `EffectDieSides`, `EffectMechanic`, `EffectMiscValue`, `EffectMiscValueB`, `EffectRadiusIndex`, `EffectRadiusIndexMax`, `EffectRealPointsPerLevel`, `EffectSpellClassMaskA`, `EffectSpellClassMaskB`, `EffectSpellClassMaskC`, `EffectTriggerSpell`, `EffectImplicitTargetA`, `EffectImplicitTargetB`, `EffectSpellId`, `EffectIndex`) VALUES
+(153020, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 62388, 1),
+(153021, 64, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29886, 1, 0, 34145, 1),
+(153022, 64, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58889, 1, 0, 58888, 1),
+(153023, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 61988, 1),
+(153024, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 100001, 1),
+(153025, 6, 0, 23, 85000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72957, 1, 0, 72958, 1),
+(153026, 6, 0, 226, 20000, 9, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 58428, 1),
+(153027, 6, 0, 137, 0, -1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24899, 1),
+(153028, 6, 0, 166, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24900, 1),
+(153029, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 34448, 1),
+(153030, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 34452, 1),
+(153031, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70878, 1),
+(153032, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44805, 1),
+(153033, 6, 0, 18, 0, 49, 0, 1, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 39707, 1),
+(153034, 6, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7056, 1),
+(153035, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45459, 1),
+(153036, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45460, 1),
+(153037, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3617, 1),
+(153038, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 58630, 1),
+(153039, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 68572, 1),
+(153040, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 68574, 1),
+(153041, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 30, 59046, 1),
+(153042, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 68184, 1),
+(153043, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 59450, 1),
+(153044, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 65195, 1),
+(153045, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 64899, 1),
+(153046, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 64985, 1),
+(153047, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 30, 65074, 1),
+(153048, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10855, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38758, 1),
+(153049, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 60937, 1),
+(153050, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5302, 1),
+(153051, 6, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 25900, 1),
+(153052, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 22, 15, 25042, 1),
+(153053, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62791, 1),
+(153054, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 65037, 1),
+(153055, 28, 0, 0, 0, 0, 0, 1, 0, 1, 0, 14986, 64, 0, 0, 0, 0, 0, 0, 0, 18, 0, 24308, 1),
+(153056, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 68308, 1),
+(153057, 77, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 63975, 1),
+(153058, 77, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 24677, 1),
+(153059, 6, 0, 56, 0, 0, 0, 1, 0, 0, 0, 16963, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 37794, 1),
+(153060, 77, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 31247, 1),
+(153061, 6, 0, 23, 5000, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12504, 1, 0, 12507, 1),
+(153062, 6, 0, 23, 5000, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31983, 1, 0, 31982, 1),
+(153063, 6, 0, 23, 18000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29878, 1, 0, 33134, 1),
+(153064, 164, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35321, 18, 0, 30023, 1),
+(153065, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 22, 15, 31980, 1),
+(153066, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 61698, 1),
+(153067, 6, 0, 87, 0, -51, 0, 1, 0, 1, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 31934, 1),
+(153068, 6, 0, 23, 3000, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13376, 21, 0, 13377, 1),
+(153069, 6, 0, 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 28782, 1),
+(153070, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17379, 64, 15, 0, 0, 0, 0, 0, 0, 32, 0, 30426, 1),
+(153071, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30426, 21, 0, 30437, 1),
+(153072, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17391, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30429, 1),
+(153073, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30429, 21, 0, 30442, 1),
+(153074, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17410, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30454, 1),
+(153075, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30454, 21, 0, 30453, 1),
+(153076, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17392, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30432, 1),
+(153077, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30432, 21, 0, 30443, 1),
+(153078, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 65387, 1),
+(153079, 125, 0, 0, 0, -11, 0, 1, 0, 1, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 22, 16, 35009, 1),
+(153080, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 68620, 1),
+(153081, 164, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40195, 18, 0, 40200, 1),
+(153082, 6, 0, 61, 0, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 70507, 1),
+(153083, 6, 1, 300, 0, 100, 0, 0, 0, 0, 0, 127, 0, 22, 0, 0, 0, 0, 0, 0, 25, 0, 74810, 1),
+(153084, 6, 0, 61, 0, -5, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 25893, 1),
+(153085, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 18954, 1),
+(153088, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38363, 0, 0, 30023, 2),
+(153089, 6, 0, 40, 0, 0, 0, 1, 0, 1, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 28782, 2),
+(153090, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30426, 2),
+(153091, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30429, 2),
+(153092, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30454, 2),
+(153093, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30432, 2),
+(153095, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39215, 0, 0, 30023, 3); \ No newline at end of file
diff --git a/sql/updates/world/2013_05_11_00_world_spelleffect_dbc_434.sql b/sql/updates/world/2013_05_11_00_world_spelleffect_dbc_434.sql
new file mode 100644
index 00000000000..e5621cc396b
--- /dev/null
+++ b/sql/updates/world/2013_05_11_00_world_spelleffect_dbc_434.sql
@@ -0,0 +1,75 @@
+DELETE FROM `spelleffect_dbc`;
+INSERT INTO `spelleffect_dbc` (`Id`, `Effect`, `EffectValueMultiplier`, `EffectApplyAuraName`, `EffectAplitude`, `EffectBasePoints`, `EffectBonusMultiplier`, `EffectDamageMultiplier`, `EffectChainTarget`, `EffectDieSides`, `EffectMechanic`, `EffectMiscValue`, `EffectMiscValueB`, `EffectRadiusIndex`, `EffectRadiusIndexMax`, `EffectRealPointsPerLevel`, `EffectSpellClassMaskA`, `EffectSpellClassMaskB`, `EffectSpellClassMaskC`, `EffectTriggerSpell`, `EffectImplicitTargetA`, `EffectImplicitTargetB`, `EffectSpellId`, `EffectIndex`) VALUES
+(153020, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 62388, 0),
+(153021, 64, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29886, 1, 0, 34145, 0),
+(153022, 64, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58889, 1, 0, 58888, 0),
+(153023, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 61988, 0),
+(153024, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 100001, 0),
+(153025, 6, 0, 23, 85000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72957, 1, 0, 72958, 0),
+(153026, 6, 0, 226, 20000, 9, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 58428, 0),
+(153027, 6, 0, 137, 0, -1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24899, 0),
+(153028, 6, 0, 166, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24900, 0),
+(153029, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 34448, 0),
+(153030, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 34452, 0),
+(153031, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70878, 0),
+(153032, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44805, 0),
+(153033, 6, 0, 18, 0, 49, 0, 1, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 39707, 0),
+(153034, 6, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7056, 0),
+(153035, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45459, 0),
+(153036, 6, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45460, 0),
+(153037, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3617, 0),
+(153038, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 58630, 0),
+(153039, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 68572, 0),
+(153040, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 68574, 0),
+(153041, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 30, 59046, 0),
+(153042, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 68184, 0),
+(153043, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 59450, 0),
+(153044, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 65195, 0),
+(153045, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 64899, 0),
+(153046, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 18, 16, 64985, 0),
+(153047, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 30, 65074, 0),
+(153048, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10855, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38758, 0),
+(153049, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 60937, 0),
+(153050, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5302, 0),
+(153051, 6, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 25900, 0),
+(153052, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 22, 15, 25042, 0),
+(153053, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62791, 0),
+(153054, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 65037, 0),
+(153055, 28, 0, 0, 0, 0, 0, 1, 0, 1, 0, 14986, 64, 0, 0, 0, 0, 0, 0, 0, 18, 0, 24308, 0),
+(153056, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 68308, 0),
+(153057, 77, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 63975, 0),
+(153058, 77, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 24677, 0),
+(153059, 6, 0, 56, 0, 0, 0, 1, 0, 0, 0, 16963, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 37794, 0),
+(153060, 77, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 31247, 0),
+(153061, 6, 0, 23, 5000, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12504, 1, 0, 12507, 0),
+(153062, 6, 0, 23, 5000, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31983, 1, 0, 31982, 0),
+(153063, 6, 0, 23, 18000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29878, 1, 0, 33134, 0),
+(153064, 164, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35321, 18, 0, 30023, 0),
+(153065, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 22, 15, 31980, 0),
+(153066, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 61698, 0),
+(153067, 6, 0, 87, 0, -51, 0, 1, 0, 1, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 31934, 0),
+(153068, 6, 0, 23, 3000, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13376, 21, 0, 13377, 0),
+(153069, 6, 0, 12, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 28782, 0),
+(153070, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17379, 64, 15, 0, 0, 0, 0, 0, 0, 32, 0, 30426, 0),
+(153071, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30426, 21, 0, 30437, 0),
+(153072, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17391, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30429, 0),
+(153073, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30429, 21, 0, 30442, 0),
+(153074, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17410, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30454, 0),
+(153075, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30454, 21, 0, 30453, 0),
+(153076, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 17392, 64, 7, 0, 0, 0, 0, 0, 0, 32, 0, 30432, 0),
+(153077, 6, 0, 23, 1000, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30432, 21, 0, 30443, 0),
+(153078, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 65387, 0),
+(153079, 125, 0, 0, 0, -11, 0, 1, 0, 1, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 22, 16, 35009, 0),
+(153080, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 22, 7, 68620, 0),
+(153081, 164, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40195, 18, 0, 40200, 0),
+(153082, 6, 0, 61, 0, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 70507, 0),
+(153083, 6, 1, 300, 0, 100, 0, 0, 0, 0, 0, 127, 0, 22, 0, 0, 0, 0, 0, 0, 25, 0, 74810, 0),
+(153084, 6, 0, 61, 0, -5, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 25893, 0),
+(153085, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 18954, 0),
+(153088, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38363, 0, 0, 30023, 1),
+(153089, 6, 0, 40, 0, 0, 0, 1, 0, 1, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 28782, 1),
+(153090, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30426, 1),
+(153091, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30429, 1),
+(153092, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30454, 1),
+(153093, 6, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 30432, 1),
+(153095, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39215, 0, 0, 30023, 2);
diff --git a/sql/updates/world/2013_05_12_00_world_spell_learn_spell_434.sql b/sql/updates/world/2013_05_12_00_world_spell_learn_spell_434.sql
new file mode 100644
index 00000000000..04daf03b95e
--- /dev/null
+++ b/sql/updates/world/2013_05_12_00_world_spell_learn_spell_434.sql
@@ -0,0 +1,16 @@
+ALTER TABLE `spell_learn_spell`
+ CHANGE `entry` `entry` INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ CHANGE `SpellID` `SpellID` INT(10) UNSIGNED NOT NULL DEFAULT '0';
+
+DELETE FROM `spell_learn_spell` WHERE `entry` IN (86467,87491,87492,87493,87494,87495,87496,87497,87498,87500);
+INSERT INTO `spell_learn_spell` (`entry`,`SpellID`,`Active`) VALUES
+(86467,86473,1), -- Mage
+(87491,86470,1), -- Druid
+(87492,86471,1), -- Death Knight
+(87493,86472,1), -- Hunter
+(87494,86474,1), -- Paladin
+(87495,86475,1), -- Priest
+(87496,86476,1), -- Rogue
+(87497,86477,1), -- Shaman
+(87498,86478,1), -- Warlock
+(87500,86479,1); -- Warrior
diff --git a/sql/updates/world/2013_05_21_00_world_trinity_string_434.sql b/sql/updates/world/2013_05_21_00_world_trinity_string_434.sql
new file mode 100644
index 00000000000..ce82a4d0972
--- /dev/null
+++ b/sql/updates/world/2013_05_21_00_world_trinity_string_434.sql
@@ -0,0 +1,4 @@
+DELETE FROM `trinity_string` WHERE `entry` IN (183, 184);
+INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES
+(183, '|cff0099FFPhaseMgr: Report for player: %s, zoneId: %u, level: %u, team: %u, phaseupdateflag: %u|r'),
+(184, '|cff663399PhaseMgr: There are no definitions defined for zoneId %u.|r');
diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp
index 4b61e5da40b..b2d381b0ffd 100644
--- a/src/server/collision/Maps/TileAssembler.cpp
+++ b/src/server/collision/Maps/TileAssembler.cpp
@@ -347,10 +347,13 @@ namespace VMAP
uint32 name_length, displayId;
char buff[500];
- while (!feof(model_list))
+ while (true)
{
- if (fread(&displayId, sizeof(uint32), 1, model_list) != 1
- || fread(&name_length, sizeof(uint32), 1, model_list) != 1
+ if (fread(&displayId, sizeof(uint32), 1, model_list) != 1)
+ if (feof(model_list)) // EOF flag is only set after failed reading attempt
+ break;
+
+ if (fread(&name_length, sizeof(uint32), 1, model_list) != 1
|| name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
{
@@ -361,7 +364,7 @@ namespace VMAP
std::string model_name(buff, name_length);
WorldModel_Raw raw_model;
- if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) )
+ if (!raw_model.Read((iSrcDir + "/" + model_name).c_str()) )
continue;
spawnedModelFiles.insert(model_name);
diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp
index 8f035667a34..8b74db24a42 100644
--- a/src/server/game/AI/CreatureAIRegistry.cpp
+++ b/src/server/game/AI/CreatureAIRegistry.cpp
@@ -22,7 +22,6 @@
#include "GuardAI.h"
#include "PetAI.h"
#include "TotemAI.h"
-#include "CreatureEventAI.h"
#include "RandomMovementGenerator.h"
#include "MovementGeneratorImpl.h"
#include "CreatureAIRegistry.h"
@@ -46,7 +45,6 @@ namespace AIRegistry
(new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf();
(new CreatureAIFactory<ArcherAI>("ArcherAI"))->RegisterSelf();
(new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf();
- (new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
(new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf();
(new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf();
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp
deleted file mode 100644
index 52ad688b644..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAI.cpp
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "Common.h"
-#include "CreatureEventAI.h"
-#include "CreatureEventAIMgr.h"
-#include "ObjectMgr.h"
-#include "Spell.h"
-#include "World.h"
-#include "Cell.h"
-#include "CellImpl.h"
-#include "GameEventMgr.h"
-#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
-#include "InstanceScript.h"
-#include "SpellMgr.h"
-#include "CreatureAIImpl.h"
-#include "ConditionMgr.h"
-
-bool CreatureEventAIHolder::UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax)
-{
- if (repeatMin == repeatMax)
- Time = repeatMin;
- else if (repeatMax > repeatMin)
- Time = urand(repeatMin, repeatMax);
- else
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", creature->GetEntry(), Event.event_id, Event.event_type);
- Enabled = false;
- return false;
- }
-
- return true;
-}
-
-int CreatureEventAI::Permissible(const Creature* creature)
-{
- if (creature->GetAIName() == "EventAI")
- return PERMIT_BASE_SPECIAL;
- return PERMIT_BASE_NO;
-}
-
-CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c)
-{
- // Need make copy for filter unneeded steps and safe in case table reload
- CreatureEventAI_Event_Map::const_iterator CreatureEvents = sEventAIMgr->GetCreatureEventAIMap().find(me->GetEntry());
- if (CreatureEvents != sEventAIMgr->GetCreatureEventAIMap().end())
- {
- std::vector<CreatureEventAI_Event>::const_iterator i;
- for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i)
- {
- //Debug check
- #ifndef TRINITY_DEBUG
- if ((*i).event_flags & EFLAG_DEBUG_ONLY)
- continue;
- #endif
- if (me->GetMap()->IsDungeon())
- {
- if ((1 << (me->GetMap()->GetSpawnMode()+1)) & (*i).event_flags)
- {
- //event flagged for instance mode
- m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
- }
- continue;
- }
- m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
- }
- //EventMap had events but they were not added because they must be for instance
- if (m_CreatureEventAIList.empty())
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "CreatureEventAI: Creature %u has events but no events added to list because of instance flags.", me->GetEntry());
- }
- else
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", me->GetEntry());
-
- m_bEmptyList = m_CreatureEventAIList.empty();
- m_Phase = 0;
- m_CombatMovementEnabled = true;
- m_MeleeEnabled = true;
- m_AttackDistance = 0.0f;
- m_AttackAngle = 0.0f;
-
- m_InvincibilityHpLevel = 0;
-
- //Handle Spawned Events
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if (SpawnedEventConditionsCheck((*i).Event))
- ProcessEvent(*i);
- }
-}
-
-bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker /*=NULL*/)
-{
- if (!holder.Enabled || holder.Time)
- return false;
-
- //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask)
- if (holder.Event.event_inverse_phase_mask & (1 << m_Phase))
- return false;
-
- CreatureEventAI_Event const& event = holder.Event;
-
- //Check event conditions based on the event type, also reset events
- switch (event.event_type)
- {
- case EVENT_T_TIMER:
- if (!me->isInCombat())
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
- break;
- case EVENT_T_TIMER_OOC:
- if (me->isInCombat())
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
- break;
- case EVENT_T_HP:
- {
- if (!me->isInCombat() || !me->GetMaxHealth())
- return false;
-
- uint32 perc = uint32(me->GetHealthPct());
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_MANA:
- {
- if (!me->isInCombat() || !me->GetMaxPower(POWER_MANA))
- return false;
-
- uint32 perc = (me->GetPower(POWER_MANA)*100) / me->GetMaxPower(POWER_MANA);
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_AGGRO:
- break;
- case EVENT_T_KILL:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.kill.repeatMin, event.kill.repeatMax);
- break;
- case EVENT_T_DEATH:
- case EVENT_T_EVADE:
- break;
- case EVENT_T_SPELLHIT:
- //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.spell_hit.repeatMin, event.spell_hit.repeatMax);
- break;
- case EVENT_T_RANGE:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.range.repeatMin, event.range.repeatMax);
- break;
- case EVENT_T_OOC_LOS:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.ooc_los.repeatMin, event.ooc_los.repeatMax);
- break;
- case EVENT_T_RESET:
- case EVENT_T_SPAWNED:
- break;
- case EVENT_T_TARGET_HP:
- {
- if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxHealth())
- return false;
-
- uint32 perc = uint32(me->getVictim()->GetHealthPct());
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_TARGET_CASTING:
- if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->IsNonMeleeSpellCasted(false, false, true))
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.target_casting.repeatMin, event.target_casting.repeatMax);
- break;
- case EVENT_T_FRIENDLY_HP:
- {
- if (!me->isInCombat())
- return false;
-
- Unit* unit = DoSelectLowestHpFriendly((float)event.friendly_hp.radius, event.friendly_hp.hpDeficit);
- if (!unit)
- return false;
-
- actionInvoker = unit;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_hp.repeatMin, event.friendly_hp.repeatMax);
- break;
- }
- case EVENT_T_FRIENDLY_IS_CC:
- {
- if (!me->isInCombat())
- return false;
-
- std::list<Creature*> pList;
- DoFindFriendlyCC(pList, (float)event.friendly_is_cc.radius);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- actionInvoker = *(pList.begin());
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_is_cc.repeatMin, event.friendly_is_cc.repeatMax);
- break;
- }
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- std::list<Creature*> pList;
- DoFindFriendlyMissingBuff(pList, (float)event.friendly_buff.radius, event.friendly_buff.spellId);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- actionInvoker = *(pList.begin());
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_buff.repeatMin, event.friendly_buff.repeatMax);
- break;
- }
- case EVENT_T_SUMMONED_UNIT:
- {
- //Prevent event from occuring on no unit or non creatures
- if (!actionInvoker || actionInvoker->GetTypeId() != TYPEID_UNIT)
- return false;
-
- //Creature id doesn't match up
- if (actionInvoker->ToCreature()->GetEntry() != event.summon_unit.creatureId)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.summon_unit.repeatMin, event.summon_unit.repeatMax);
- break;
- }
- case EVENT_T_TARGET_MANA:
- {
- if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxPower(POWER_MANA))
- return false;
-
- uint32 perc = (me->getVictim()->GetPower(POWER_MANA)*100) / me->getVictim()->GetMaxPower(POWER_MANA);
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_REACHED_HOME:
- case EVENT_T_RECEIVE_EMOTE:
- break;
- case EVENT_T_BUFFED:
- {
- //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
- // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
- Aura const* aura = me->GetAura(event.buffed.spellId);
- if (!aura || aura->GetStackAmount() < event.buffed.amount)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
- break;
- }
- case EVENT_T_TARGET_BUFFED:
- {
- //Prevent event from occuring on no unit
- if (!actionInvoker)
- return false;
-
- //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
- // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
- Aura const* aura = actionInvoker->GetAura(event.buffed.spellId);
- if (!aura || aura->GetStackAmount() < event.buffed.amount)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
- break;
- }
- default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", me->GetEntry(), holder.Event.event_id, holder.Event.event_type);
- break;
- }
-
- //Disable non-repeatable events
- if (!(holder.Event.event_flags & EFLAG_REPEATABLE))
- holder.Enabled = false;
-
- //Store random here so that all random actions match up
- uint32 rnd = rand();
-
- //Return if chance for event is not met
- if (holder.Event.event_chance <= rnd % 100)
- return false;
-
- //Process actions
- for (uint8 j = 0; j < MAX_ACTIONS; ++j)
- ProcessAction(holder.Event.action[j], rnd, holder.Event.event_id, actionInvoker);
-
- return true;
-}
-
-void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker)
-{
- switch (action.type)
- {
- case ACTION_T_TEXT:
- {
- if (!action.text.TextId1)
- return;
-
- int32 temp = action.text.TextId1;
-
- if (action.text.TextId2 && action.text.TextId3)
- temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3);
- else if (action.text.TextId2 && urand(0, 1))
- temp = action.text.TextId2;
-
- if (temp)
- {
- Unit* target = NULL;
-
- if (actionInvoker)
- {
- if (actionInvoker->GetTypeId() == TYPEID_PLAYER)
- target = actionInvoker;
- else if (Unit* owner = actionInvoker->GetOwner())
- {
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
- }
- else
- {
- target = me->getVictim();
- if (target && target->GetTypeId() != TYPEID_PLAYER)
- if (Unit* owner = target->GetOwner())
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
-
- DoScriptText(temp, me, target);
- }
- break;
- }
- case ACTION_T_SET_FACTION:
- {
- if (action.set_faction.factionId)
- me->setFaction(action.set_faction.factionId);
- else
- {
- if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(me->GetEntry()))
- {
- //if no id provided, assume reset and then use default
- if (me->getFaction() != ci->faction_A)
- me->setFaction(ci->faction_A);
- }
- }
- break;
- }
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- {
- if (action.morph.creatureId || action.morph.modelId)
- {
- //set model based on entry from creature_template
- if (action.morph.creatureId)
- {
- if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
- me->SetDisplayId(ObjectMgr::ChooseDisplayId(ci));
- }
- //if no param1, then use value from param2 (modelId)
- else
- me->SetDisplayId(action.morph.modelId);
- }
- else
- me->DeMorph();
- break;
- }
- case ACTION_T_SOUND:
- me->PlayDirectSound(action.sound.soundId);
- break;
- case ACTION_T_EMOTE:
- me->HandleEmoteCommand(action.emote.emoteId);
- break;
- case ACTION_T_RANDOM_SOUND:
- {
- int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3);
- if (temp >= 0)
- me->PlayDirectSound(temp);
- break;
- }
- case ACTION_T_RANDOM_EMOTE:
- {
- int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3);
- if (temp >= 0)
- me->HandleEmoteCommand(temp);
- break;
- }
- case ACTION_T_CAST:
- {
- Unit* target = GetTargetByType(action.cast.target, actionInvoker);
- Unit* caster = me;
-
- if (!target)
- return;
-
- if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
- caster = target;
-
- //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
- bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS));
-
- // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
- if (action.cast.castFlags & CAST_AURA_NOT_PRESENT)
- {
- if (target->HasAura(action.cast.spellId))
- return;
- }
-
- if (canCast)
- {
- const SpellInfo* tSpell = sSpellMgr->GetSpellInfo(action.cast.spellId);
-
- //Verify that spell exists
- if (tSpell)
- {
- //Check if cannot cast spell
- if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
- !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED)))
- {
- //Melee current victim if flag not set
- if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM))
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
- {
- m_AttackDistance = 0.0f;
- m_AttackAngle = 0.0f;
-
- me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
- }
- }
- }
- else
- {
- //Interrupt any previous spell
- if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS)
- caster->InterruptNonMeleeSpells(false);
-
- caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED));
- }
- }
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", eventId, me->GetEntry(), action.cast.spellId);
- }
- break;
- }
- case ACTION_T_THREAT_SINGLE_PCT:
- if (Unit* target = GetTargetByType(action.threat_single_pct.target, actionInvoker))
- me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
- break;
- case ACTION_T_THREAT_ALL_PCT:
- {
- ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
- for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
- if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()))
- me->getThreatManager().modifyThreatPercent(unit, action.threat_all_pct.percent);
- break;
- }
- case ACTION_T_QUEST_EVENT:
- if (Unit* target = GetTargetByType(action.quest_event.target, actionInvoker))
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId);
- break;
- case ACTION_T_CAST_EVENT:
- if (Unit* target = GetTargetByType(action.cast_event.target, actionInvoker))
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->CastedCreatureOrGO(action.cast_event.creatureId, me->GetGUID(), action.cast_event.spellId);
- break;
- case ACTION_T_SET_UNIT_FIELD:
- {
- Unit* target = GetTargetByType(action.set_unit_field.target, actionInvoker);
-
- // not allow modify important for integrity object fields
- if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
- return;
-
- if (target)
- target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value);
-
- break;
- }
- case ACTION_T_SET_UNIT_FLAG:
- if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
- target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
- break;
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
- target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
- break;
- case ACTION_T_AUTO_ATTACK:
- m_MeleeEnabled = action.auto_attack.state != 0;
- break;
- case ACTION_T_COMBAT_MOVEMENT:
- // ignore no affect case
- if (m_CombatMovementEnabled == (action.combat_movement.state != 0))
- return;
-
- m_CombatMovementEnabled = action.combat_movement.state != 0;
-
- //Allow movement (create new targeted movement gen only if idle)
- if (m_CombatMovementEnabled)
- {
- Unit* victim = me->getVictim();
- if (me->isInCombat() && victim)
- {
- if (action.combat_movement.melee)
- {
- me->AddUnitState(UNIT_STATE_MELEE_ATTACKING);
- me->SendMeleeAttackStart(victim);
- }
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
- me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly
- }
- }
- else
- {
- if (me->isInCombat())
- {
- Unit* victim = me->getVictim();
- if (action.combat_movement.melee && victim)
- {
- me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
- me->SendMeleeAttackStop(victim);
- }
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
- me->GetMotionMaster()->MoveIdle();
- }
- }
- break;
- case ACTION_T_SET_PHASE:
- m_Phase = action.set_phase.phase;
- break;
- case ACTION_T_INC_PHASE:
- {
- int32 new_phase = int32(m_Phase)+action.set_inc_phase.step;
- if (new_phase < 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", eventId, me->GetEntry());
- m_Phase = 0;
- }
- else if (new_phase >= MAX_PHASE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", eventId, MAX_PHASE-1, MAX_PHASE-1, me->GetEntry());
- m_Phase = MAX_PHASE-1;
- }
- else
- m_Phase = new_phase;
-
- break;
- }
- case ACTION_T_EVADE:
- EnterEvadeMode();
- break;
- case ACTION_T_FLEE_FOR_ASSIST:
- me->DoFleeToGetAssistance();
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- if (actionInvoker && actionInvoker->GetTypeId() == TYPEID_PLAYER)
- {
- if (Unit* Temp = Unit::GetUnit(*me, actionInvoker->GetGUID()))
- if (Temp->GetTypeId() == TYPEID_PLAYER)
- Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me);
- }
- break;
- case ACTION_T_CAST_EVENT_ALL:
- {
- ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
- for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
- if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()))
- if (unit->GetTypeId() == TYPEID_PLAYER)
- unit->ToPlayer()->CastedCreatureOrGO(action.cast_event_all.creatureId, me->GetGUID(), action.cast_event_all.spellId);
- break;
- }
- case ACTION_T_REMOVEAURASFROMSPELL:
- if (Unit* target = GetTargetByType(action.remove_aura.target, actionInvoker))
- target->RemoveAurasDueToSpell(action.remove_aura.spellId);
- break;
- case ACTION_T_RANGED_MOVEMENT:
- m_AttackDistance = (float)action.ranged_movement.distance;
- m_AttackAngle = action.ranged_movement.angle/180.0f*M_PI;
-
- if (m_CombatMovementEnabled)
- {
- me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
- }
- break;
- case ACTION_T_RANDOM_PHASE:
- m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3);
- break;
- case ACTION_T_RANDOM_PHASE_RANGE:
- if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax)
- m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", eventId, me->GetEntry());
- break;
- case ACTION_T_KILLED_MONSTER:
- //first attempt player who tapped creature
- if (Player* player = me->GetLootRecipient())
- player->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player); // player as param is a hacky solution not to use GUID
- else
- {
- //if not available, use actionInvoker
- if (Unit* target = GetTargetByType(action.killed_monster.target, actionInvoker))
- if (Player* player2 = target->GetCharmerOrOwnerPlayerOrPlayerItself())
- player2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player2);
- }
- break;
- case ACTION_T_SET_INST_DATA:
- {
- InstanceScript* instance = me->GetInstanceScript();
- if (!instance)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- instance->SetData(action.set_inst_data.field, action.set_inst_data.value);
- break;
- }
- case ACTION_T_SET_INST_DATA64:
- {
- Unit* target = GetTargetByType(action.set_inst_data64.target, actionInvoker);
- if (!target)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- InstanceScript* instance = me->GetInstanceScript();
- if (!instance)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- instance->SetData64(action.set_inst_data64.field, target->GetGUID());
- break;
- }
- case ACTION_T_UPDATE_TEMPLATE:
- if (me->GetEntry() == action.update_template.creatureId)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
- break;
- case ACTION_T_DIE:
- if (me->isDead())
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", eventId, me->GetEntry());
- return;
- }
- me->Kill(me);
- break;
- case ACTION_T_ZONE_COMBAT_PULSE:
- {
- me->SetInCombatWithZone();
- break;
- }
- case ACTION_T_CALL_FOR_HELP:
- {
- me->CallForHelp((float)action.call_for_help.radius);
- break;
- }
- break;
-
- // TRINITY ONLY
- case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat
- {
- float x, y, z;
- me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)action.raw.param1);
- me->GetMotionMaster()->MovePoint(0, x, y, z);
- break;
- }
- case ACTION_T_SET_STAND_STATE:
- me->SetStandState(UnitStandStateType(action.raw.param1));
- break;
- case ACTION_T_SET_PHASE_MASK:
- me->SetPhaseMask(action.raw.param1, true);
- break;
- case ACTION_T_SET_VISIBILITY:
- me->SetVisible(bool(action.raw.param1));
- break;
- case ACTION_T_SET_ACTIVE:
- me->setActive(action.raw.param1 ? true : false);
- break;
- case ACTION_T_SET_AGGRESSIVE:
- me->SetReactState(ReactStates(action.raw.param1));
- break;
- case ACTION_T_ATTACK_START_PULSE:
- AttackStart(me->SelectNearestTarget((float)action.raw.param1));
- break;
- case ACTION_T_SUMMON_GO:
- {
- float x, y, z;
- me->GetPosition(x, y, z);
- GameObject* object = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2);
- if (!object)
- TC_LOG_ERROR(LOG_FILTER_TSCR, "EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, eventId, me->GetEntry());
-
- break;
- }
- case ACTION_T_SET_SHEATH:
- {
- me->SetSheath(SheathState(action.set_sheath.sheath));
- break;
- }
- case ACTION_T_FORCE_DESPAWN:
- {
- me->DespawnOrUnsummon(action.forced_despawn.msDelay);
- break;
- }
- case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
- {
- if (action.invincibility_hp_level.is_percent)
- m_InvincibilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level);
- else
- m_InvincibilityHpLevel = action.invincibility_hp_level.hp_level;
- break;
- }
- case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
- {
- if (action.mount.creatureId || action.mount.modelId)
- {
- // set model based on entry from creature_template
- if (action.mount.creatureId)
- {
- if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
- me->Mount(ObjectMgr::ChooseDisplayId(cInfo));
- }
- //if no param1, then use value from param2 (modelId)
- else
- me->Mount(action.mount.modelId);
- }
- else
- me->Dismount();
-
- break;
- }
- default:
- break;
- }
-}
-
-void CreatureEventAI::JustRespawned()
-{
- Reset();
-
- if (m_bEmptyList)
- return;
-
- //Handle Spawned Events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if (SpawnedEventConditionsCheck((*i).Event))
- ProcessEvent(*i);
-}
-
-void CreatureEventAI::Reset()
-{
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- m_EventDiff = 0;
-
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_RESET)
- ProcessEvent(*i);
- }
-
- //Reset all events to enabled
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- CreatureEventAI_Event const& event = (*i).Event;
- switch (event.event_type)
- {
- //Reset all out of combat timers
- case EVENT_T_TIMER_OOC:
- {
- if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax))
- (*i).Enabled = true;
- break;
- }
- default:
- /// @todo enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void EnterCombat()
- //(*i).Enabled = true;
- //(*i).Time = 0;
- break;
- }
- }
-}
-
-void CreatureEventAI::JustReachedHome()
-{
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_REACHED_HOME)
- ProcessEvent(*i);
- }
- }
-
- Reset();
-}
-
-void CreatureEventAI::EnterEvadeMode()
-{
- CreatureAI::EnterEvadeMode();
-
- if (m_bEmptyList)
- return;
-
- //Handle Evade events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_EVADE)
- ProcessEvent(*i);
- }
-}
-
-void CreatureEventAI::JustDied(Unit* killer)
-{
- Reset();
-
- if (m_bEmptyList)
- return;
-
- //Handle Evade events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_DEATH)
- ProcessEvent(*i, killer);
- }
-
- // reset phase after any death state events
- m_Phase = 0;
-}
-
-void CreatureEventAI::KilledUnit(Unit* victim)
-{
- if (m_bEmptyList || victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_KILL)
- ProcessEvent(*i, victim);
- }
-}
-
-void CreatureEventAI::JustSummoned(Creature* unit)
-{
- if (m_bEmptyList || !unit)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT)
- ProcessEvent(*i, unit);
- }
-}
-
-void CreatureEventAI::EnterCombat(Unit* enemy)
-{
- //Check for on combat start events
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- CreatureEventAI_Event const& event = (*i).Event;
- switch (event.event_type)
- {
- case EVENT_T_AGGRO:
- (*i).Enabled = true;
- ProcessEvent(*i, enemy);
- break;
- //Reset all in combat timers
- case EVENT_T_TIMER:
- if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax))
- (*i).Enabled = true;
- break;
- //All normal events need to be re-enabled and their time set to 0
- default:
- (*i).Enabled = true;
- (*i).Time = 0;
- break;
- }
- }
- }
-
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- m_EventDiff = 0;
-}
-
-void CreatureEventAI::AttackStart(Unit* who)
-{
- if (!who)
- return;
-
- if (me->Attack(who, m_MeleeEnabled))
- {
- if (m_CombatMovementEnabled)
- {
- me->GetMotionMaster()->MoveChase(who, m_AttackDistance, m_AttackAngle);
- }
- else
- {
- me->GetMotionMaster()->MoveIdle();
- }
- }
-}
-
-void CreatureEventAI::MoveInLineOfSight(Unit* who)
-{
- if (me->getVictim())
- return;
-
- //Check for OOC LOS Event
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
- {
- //can trigger if closer than fMaxAllowedRange
- float fMaxAllowedRange = (float)((*itr).Event.ooc_los.maxRange);
-
- //if range is ok and we are actually in LOS
- if (me->IsWithinDistInMap(who, fMaxAllowedRange) && me->IsWithinLOSInMap(who))
- {
- //if friendly event&&who is not hostile OR hostile event&&who is hostile
- if (((*itr).Event.ooc_los.noHostile && !me->IsHostileTo(who)) ||
- ((!(*itr).Event.ooc_los.noHostile) && me->IsHostileTo(who)))
- ProcessEvent(*itr, who);
- }
- }
- }
- }
-
- CreatureAI::MoveInLineOfSight(who);
-}
-
-void CreatureEventAI::SpellHit(Unit* unit, const SpellInfo* spell)
-{
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if ((*i).Event.event_type == EVENT_T_SPELLHIT)
- //If spell id matches (or no spell id) & if spell school matches (or no spell school)
- if (!(*i).Event.spell_hit.spellId || spell->Id == (*i).Event.spell_hit.spellId)
- if (spell->SchoolMask & (*i).Event.spell_hit.schoolMask)
- ProcessEvent(*i, unit);
-}
-
-void CreatureEventAI::UpdateAI(uint32 diff)
-{
- //Check if we are in combat (also updates calls threat update code)
- bool Combat = UpdateVictim();
-
- if (!m_bEmptyList)
- {
- //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events
- if (m_EventUpdateTime <= diff)
- {
- m_EventDiff += diff;
-
- //Check for time based events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- //Decrement Timers
- if ((*i).Time)
- {
- if (m_EventDiff <= (*i).Time)
- {
- //Do not decrement timers if event cannot trigger in this phase
- if (!((*i).Event.event_inverse_phase_mask & (1 << m_Phase)))
- (*i).Time -= m_EventDiff;
-
- //Skip processing of events that have time remaining
- continue;
- }
- else (*i).Time = 0;
- }
-
- //Events that are updated every EVENT_UPDATE_TIME
- switch ((*i).Event.event_type)
- {
- case EVENT_T_TIMER_OOC:
- ProcessEvent(*i);
- break;
- case EVENT_T_TIMER:
- case EVENT_T_MANA:
- case EVENT_T_HP:
- case EVENT_T_TARGET_HP:
- case EVENT_T_TARGET_CASTING:
- case EVENT_T_FRIENDLY_HP:
- if (me->getVictim())
- ProcessEvent(*i);
- break;
- case EVENT_T_RANGE:
- if (me->getVictim())
- if (me->IsInMap(me->getVictim()) && me->InSamePhase(me->getVictim()))
- if (me->IsInRange(me->getVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist))
- ProcessEvent(*i);
- break;
- default:
- break;
- }
- }
-
- m_EventDiff = 0;
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- }
- else
- {
- m_EventDiff += diff;
- m_EventUpdateTime -= diff;
- }
- }
-
- //Melee Auto-Attack
- if (Combat && m_MeleeEnabled)
- DoMeleeAttackIfReady();
-}
-
-inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3)
-{
- switch (rnd % 3)
- {
- case 0: return param1;
- case 1: return param2;
- case 2: return param3;
- }
- return 0;
-}
-
-inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3)
-{
- switch (rnd % 3)
- {
- case 0: return param1;
- case 1: return param2;
- case 2: return param3;
- }
- return 0;
-}
-
-inline Unit* CreatureEventAI::GetTargetByType(uint32 target, Unit* actionInvoker)
-{
- switch (target)
- {
- case TARGET_T_SELF:
- return me;
- case TARGET_T_HOSTILE:
- return me->getVictim();
- case TARGET_T_HOSTILE_SECOND_AGGRO:
- return SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
- case TARGET_T_HOSTILE_LAST_AGGRO:
- return SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0);
- case TARGET_T_HOSTILE_RANDOM:
- return SelectTarget(SELECT_TARGET_RANDOM, 0);
- case TARGET_T_HOSTILE_RANDOM_NOT_TOP:
- return SelectTarget(SELECT_TARGET_RANDOM, 1);
- case TARGET_T_ACTION_INVOKER:
- return actionInvoker;
- default:
- return NULL;
- };
-}
-
-Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Unit* unit = NULL;
-
- Trinity::MostHPMissingInRange u_check(me, range, minHPDiff);
- Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check);
-
- /*
- typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes;
- This means that if we only search grid then we cannot possibly return pets or players so this is safe
- */
- TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
-
- cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range);
- return unit;
-}
-
-void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Trinity::FriendlyCCedInRange u_check(me, range);
- Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, _list, u_check);
-
- TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
-
- cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
-}
-
-void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Trinity::FriendlyMissingBuffInRange u_check(me, range, spellid);
- Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, _list, u_check);
-
- TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
-
- cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
-}
-
-// *********************************
-// *** Functions used globally ***
-
-void CreatureEventAI::DoScriptText(int32 textEntry, WorldObject* source, Unit* target)
-{
- if (!source)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i, invalid Source pointer.", textEntry);
- return;
- }
-
- if (textEntry >= 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry);
- return;
- }
-
- CreatureEventAI_TextMap::const_iterator i = sEventAIMgr->GetCreatureEventAITextMap().find(textEntry);
-
- if (i == sEventAIMgr->GetCreatureEventAITextMap().end())
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry);
- return;
- }
-
- TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "CreatureEventAI: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", textEntry, (*i).second.SoundId, (*i).second.Type, (*i).second.Language, (*i).second.Emote);
-
- if ((*i).second.SoundId)
- {
- if (sSoundEntriesStore.LookupEntry((*i).second.SoundId))
- source->PlayDirectSound((*i).second.SoundId);
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i tried to process invalid sound id %u.", textEntry, (*i).second.SoundId);
- }
-
- if ((*i).second.Emote)
- {
- if (source->GetTypeId() == TYPEID_UNIT || source->GetTypeId() == TYPEID_PLAYER)
- {
- ((Unit*)source)->HandleEmoteCommand((*i).second.Emote);
- }
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", textEntry, source->GetTypeId());
- }
-
- switch ((*i).second.Type)
- {
- case CHAT_TYPE_SAY:
- source->MonsterSay(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_YELL:
- source->MonsterYell(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_TEXT_EMOTE:
- source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_BOSS_EMOTE:
- source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0, true);
- break;
- case CHAT_TYPE_WHISPER:
- {
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- source->MonsterWhisper(textEntry, target->GetGUID());
- else TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
- }break;
- case CHAT_TYPE_BOSS_WHISPER:
- {
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- source->MonsterWhisper(textEntry, target->GetGUID(), true);
- else TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
- }break;
- case CHAT_TYPE_ZONE_YELL:
- source->MonsterYellToZone(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- }
-}
-
-bool CreatureEventAI::CanCast(Unit* target, SpellInfo const* spell, bool triggered)
-{
- //No target so we can't cast
- if (!target || !spell)
- return false;
-
- //Silenced so we can't cast
- if (!triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
- return false;
-
- //Check for power
- if (!triggered && me->GetPower((Powers)spell->PowerType) < uint32(spell->CalcPowerCost(me, spell->GetSchoolMask())))
- return false;
-
- //Unit is out of range of this spell
- if (!me->IsInRange(target, spell->GetMinRange(false), spell->GetMaxRange(false)))
- return false;
-
- //Spell is on cooldown
- if (me->HasSpellCooldown(spell->Id))
- return false;
-
- return true;
-}
-
-void CreatureEventAI::ReceiveEmote(Player* player, uint32 textEmote)
-{
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
- {
- if ((*itr).Event.receive_emote.emoteId != textEmote)
- return;
-
- Condition cond;
- cond.ConditionType = ConditionTypes((*itr).Event.receive_emote.condition);
- cond.ConditionValue1 = (*itr).Event.receive_emote.conditionValue1;
- cond.ConditionValue2 = (*itr).Event.receive_emote.conditionValue2;
-
- ConditionSourceInfo srcInfo = ConditionSourceInfo(player);
- if (cond.Meets(srcInfo))
- {
- TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
- ProcessEvent(*itr, player);
- }
- }
- }
-}
-
-void CreatureEventAI::DamageTaken(Unit* /*done_by*/, uint32& damage)
-{
- if (m_InvincibilityHpLevel > 0 && me->GetHealth() < m_InvincibilityHpLevel+damage)
- {
- if (me->GetHealth() <= m_InvincibilityHpLevel)
- damage = 0;
- else
- damage = me->GetHealth() - m_InvincibilityHpLevel;
- }
-}
-
-bool CreatureEventAI::SpawnedEventConditionsCheck(CreatureEventAI_Event const& event)
-{
- if (event.event_type != EVENT_T_SPAWNED)
- return false;
-
- switch (event.spawned.condition)
- {
- case SPAWNED_EVENT_ALWAY:
- // always
- return true;
- case SPAWNED_EVENT_MAP:
- // map ID check
- return me->GetMapId() == event.spawned.conditionValue1;
- case SPAWNED_EVENT_ZONE:
- {
- // zone ID check
- uint32 zone, area;
- me->GetZoneAndAreaId(zone, area);
- return zone == event.spawned.conditionValue1 || area == event.spawned.conditionValue1;
- }
- default:
- break;
- }
-
- return false;
-}
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.h b/src/server/game/AI/EventAI/CreatureEventAI.h
deleted file mode 100644
index d67fef64b95..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAI.h
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_CREATURE_EAI_H
-#define TRINITY_CREATURE_EAI_H
-
-#include "Common.h"
-#include "Creature.h"
-#include "CreatureAI.h"
-#include "Unit.h"
-
-class Player;
-class WorldObject;
-
-#define EVENT_UPDATE_TIME 500
-#define MAX_ACTIONS 3
-#define MAX_PHASE 32
-
-enum EventAI_Type
-{
- EVENT_T_TIMER = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_TIMER_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_HP = 2, // HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_MANA = 3, // ManaMax%, ManaMin% RepeatMin, RepeatMax
- EVENT_T_AGGRO = 4, // NONE
- EVENT_T_KILL = 5, // RepeatMin, RepeatMax
- EVENT_T_DEATH = 6, // NONE
- EVENT_T_EVADE = 7, // NONE
- EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax
- EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax
- EVENT_T_OOC_LOS = 10, // NoHostile, MaxRnage, RepeatMin, RepeatMax
- EVENT_T_SPAWNED = 11, // Condition, CondValue1
- EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_HP = 14, // HPDeficit, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_IS_CC = 15, // DispelType, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax
- EVENT_T_SUMMONED_UNIT = 17, // CreatureId, RepeatMin, RepeatMax
- EVENT_T_TARGET_MANA = 18, // ManaMax%, ManaMin%, RepeatMin, RepeatMax
- EVENT_T_QUEST_ACCEPT = 19, // QuestID
- EVENT_T_QUEST_COMPLETE = 20, //
- EVENT_T_REACHED_HOME = 21, // NONE
- EVENT_T_RECEIVE_EMOTE = 22, // EmoteId, Condition, CondValue1, CondValue2
- EVENT_T_BUFFED = 23, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max
- EVENT_T_TARGET_BUFFED = 24, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max
- EVENT_T_RESET = 35, // Is it called after combat, when the creature respawn and spawn. -- TRINITY ONLY
-
- EVENT_T_END
-};
-
-enum EventAI_ActionType
-{
- ACTION_T_NONE = 0, // No action
- ACTION_T_TEXT = 1, // TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
- ACTION_T_SET_FACTION = 2, // FactionId (or 0 for default)
- ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
- ACTION_T_SOUND = 4, // SoundId
- ACTION_T_EMOTE = 5, // EmoteId
- ACTION_T_RANDOM_SAY = 6, // UNUSED
- ACTION_T_RANDOM_YELL = 7, // UNUSED
- ACTION_T_RANDOM_TEXTEMOTE = 8, // UNUSED
- ACTION_T_RANDOM_SOUND = 9, // SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
- ACTION_T_RANDOM_EMOTE = 10, // EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
- ACTION_T_CAST = 11, // SpellId, Target, CastFlags
- ACTION_T_SUMMON = 12, // CreatureID, Target, Duration in ms
- ACTION_T_THREAT_SINGLE_PCT = 13, // Threat%, Target
- ACTION_T_THREAT_ALL_PCT = 14, // Threat%
- ACTION_T_QUEST_EVENT = 15, // QuestID, Target
- ACTION_T_CAST_EVENT = 16, // CreatureId, SpellId, Target - must be removed as hack?
- ACTION_T_SET_UNIT_FIELD = 17, // Field_Number, Value, Target
- ACTION_T_SET_UNIT_FLAG = 18, // Flags (may be more than one field OR'd together), Target
- ACTION_T_REMOVE_UNIT_FLAG = 19, // Flags (may be more than one field OR'd together), Target
- ACTION_T_AUTO_ATTACK = 20, // AllowAttackState (0 = stop attack, anything else means continue attacking)
- ACTION_T_COMBAT_MOVEMENT = 21, // AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- ACTION_T_SET_PHASE = 22, // Phase
- ACTION_T_INC_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
- ACTION_T_EVADE = 24, // No Params
- ACTION_T_FLEE_FOR_ASSIST = 25, // No Params
- ACTION_T_QUEST_EVENT_ALL = 26, // QuestID
- ACTION_T_CAST_EVENT_ALL = 27, // CreatureId, SpellId
- ACTION_T_REMOVEAURASFROMSPELL = 28, // Target, Spellid
- ACTION_T_RANGED_MOVEMENT = 29, // Distance, Angle
- ACTION_T_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3
- ACTION_T_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax
- ACTION_T_SUMMON_ID = 32, // CreatureId, Target, SpawnId
- ACTION_T_KILLED_MONSTER = 33, // CreatureId, Target
- ACTION_T_SET_INST_DATA = 34, // Field, Data
- ACTION_T_SET_INST_DATA64 = 35, // Field, Target
- ACTION_T_UPDATE_TEMPLATE = 36, // Entry, Team
- ACTION_T_DIE = 37, // No Params
- ACTION_T_ZONE_COMBAT_PULSE = 38, // No Params
- ACTION_T_CALL_FOR_HELP = 39, // Radius
- ACTION_T_SET_SHEATH = 40, // Sheath (0-passive, 1-melee, 2-ranged)
- ACTION_T_FORCE_DESPAWN = 41, // No Params
- ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat, 1-percent from max health)
- ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
-
- ACTION_T_SET_PHASE_MASK = 97,
- ACTION_T_SET_STAND_STATE = 98,
- ACTION_T_MOVE_RANDOM_POINT = 99,
- ACTION_T_SET_VISIBILITY = 100,
- ACTION_T_SET_ACTIVE = 101, //Apply
- ACTION_T_SET_AGGRESSIVE = 102, //Apply
- ACTION_T_ATTACK_START_PULSE = 103, //Distance
- ACTION_T_SUMMON_GO = 104, //GameObjectID, DespawnTime in ms
-
- ACTION_T_END = 105
-};
-
-enum Target
-{
- //Self (me)
- TARGET_T_SELF = 0, //Self cast
-
- //Hostile targets (if pet then returns pet owner)
- TARGET_T_HOSTILE, //Our current target (ie: highest aggro)
- TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat
-
- //Invoker targets (if pet then returns pet owner)
- TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
-
- //Hostile targets (including pets)
- TARGET_T_HOSTILE_WPET, //Current target (can be a pet)
- TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat
-
- TARGET_T_ACTION_INVOKER_WPET,
-
- TARGET_T_END
-};
-
-enum CastFlags
-{
- CAST_INTERRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
- CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
- CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
- CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
- CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
- CAST_AURA_NOT_PRESENT = 0x20 //Only casts the spell if the target does not have an aura from the spell
-};
-
-enum EventFlags
-{
- EFLAG_REPEATABLE = 0x01, //Event repeats
- EFLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0
- EFLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1
- EFLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2
- EFLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3
- EFLAG_RESERVED_5 = 0x20,
- EFLAG_RESERVED_6 = 0x40,
- EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build
-
- EFLAG_DIFFICULTY_ALL = (EFLAG_DIFFICULTY_0|EFLAG_DIFFICULTY_1|EFLAG_DIFFICULTY_2|EFLAG_DIFFICULTY_3)
-};
-
-enum SpawnedEventMode
-{
- SPAWNED_EVENT_ALWAY = 0,
- SPAWNED_EVENT_MAP = 1,
- SPAWNED_EVENT_ZONE = 2
-};
-
-// String text additional data, used in (CreatureEventAI)
-struct StringTextData
-{
- uint32 SoundId;
- uint8 Type;
- uint32 Language;
- uint32 Emote;
-};
-// Text Maps
-typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap;
-
-struct CreatureEventAI_Action
-{
- EventAI_ActionType type: 16;
- union
- {
- // ACTION_T_TEXT = 1
- struct
- {
- int32 TextId1;
- int32 TextId2;
- int32 TextId3;
- } text;
- // ACTION_T_SET_FACTION = 2
- struct
- {
- uint32 factionId; // faction or 0 for default)
- } set_faction;
- // ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3
- struct
- {
- uint32 creatureId; // set one from fields (or 0 for both to demorph)
- uint32 modelId;
- } morph;
- // ACTION_T_SOUND = 4
- struct
- {
- uint32 soundId;
- } sound;
- // ACTION_T_EMOTE = 5
- struct
- {
- uint32 emoteId;
- } emote;
- // ACTION_T_RANDOM_SOUND = 9
- struct
- {
- int32 soundId1; // (-1 in any field means no output if randomed that field)
- int32 soundId2;
- int32 soundId3;
- } random_sound;
- // ACTION_T_RANDOM_EMOTE = 10
- struct
- {
- int32 emoteId1; // (-1 in any field means no output if randomed that field)
- int32 emoteId2;
- int32 emoteId3;
- } random_emote;
- // ACTION_T_CAST = 11
- struct
- {
- uint32 spellId;
- uint32 target;
- uint32 castFlags;
- } cast;
- // ACTION_T_SUMMON = 12
- struct
- {
- uint32 creatureId;
- uint32 target;
- uint32 duration;
- } summon;
- // ACTION_T_THREAT_SINGLE_PCT = 13
- struct
- {
- int32 percent;
- uint32 target;
- } threat_single_pct;
- // ACTION_T_THREAT_ALL_PCT = 14
- struct
- {
- int32 percent;
- } threat_all_pct;
- // ACTION_T_QUEST_EVENT = 15
- struct
- {
- uint32 questId;
- uint32 target;
- } quest_event;
- // ACTION_T_CAST_EVENT = 16
- struct
- {
- uint32 creatureId;
- uint32 spellId;
- uint32 target;
- } cast_event;
- // ACTION_T_SET_UNIT_FIELD = 17
- struct
- {
- uint32 field;
- uint32 value;
- uint32 target;
- } set_unit_field;
- // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set
- // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear
- struct
- {
- uint32 value;
- uint32 target;
- } unit_flag;
- // ACTION_T_AUTO_ATTACK = 20
- struct
- {
- uint32 state; // 0 = stop attack, anything else means continue attacking
- } auto_attack;
- // ACTION_T_COMBAT_MOVEMENT = 21
- struct
- {
- uint32 state; // 0 = stop combat based movement, anything else continue attacking
- uint32 melee; // if set: at stop send melee combat stop if in combat, use for terminate melee fighting state for switch to ranged
- } combat_movement;
- // ACTION_T_SET_PHASE = 22
- struct
- {
- uint32 phase;
- } set_phase;
- // ACTION_T_INC_PHASE = 23
- struct
- {
- int32 step;
- } set_inc_phase;
- // ACTION_T_QUEST_EVENT_ALL = 26
- struct
- {
- uint32 questId;
- } quest_event_all;
- // ACTION_T_CAST_EVENT_ALL = 27
- struct
- {
- uint32 creatureId;
- uint32 spellId;
- } cast_event_all;
- // ACTION_T_REMOVEAURASFROMSPELL = 28
- struct
- {
- uint32 target;
- uint32 spellId;
- } remove_aura;
- // ACTION_T_RANGED_MOVEMENT = 29
- struct
- {
- uint32 distance;
- int32 angle;
- } ranged_movement;
- // ACTION_T_RANDOM_PHASE = 30
- struct
- {
- uint32 phase1;
- uint32 phase2;
- uint32 phase3;
- } random_phase;
- // ACTION_T_RANDOM_PHASE_RANGE = 31
- struct
- {
- uint32 phaseMin;
- uint32 phaseMax;
- } random_phase_range;
- // ACTION_T_SUMMON_ID = 32
- struct
- {
- uint32 creatureId;
- uint32 target;
- uint32 spawnId;
- } summon_id;
- // ACTION_T_KILLED_MONSTER = 33
- struct
- {
- uint32 creatureId;
- uint32 target;
- } killed_monster;
- // ACTION_T_SET_INST_DATA = 34
- struct
- {
- uint32 field;
- uint32 value;
- } set_inst_data;
- // ACTION_T_SET_INST_DATA64 = 35
- struct
- {
- uint32 field;
- uint32 target;
- } set_inst_data64;
- // ACTION_T_UPDATE_TEMPLATE = 36
- struct
- {
- uint32 creatureId;
- uint32 team;
- } update_template;
- // ACTION_T_CALL_FOR_HELP = 39
- struct
- {
- uint32 radius;
- } call_for_help;
- // ACTION_T_SET_SHEATH = 40
- struct
- {
- uint32 sheath;
- } set_sheath;
- // ACTION_T_FORCE_DESPAWN = 41
- struct
- {
- uint32 msDelay;
- } forced_despawn;
- // ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42
- struct
- {
- uint32 hp_level;
- uint32 is_percent;
- } invincibility_hp_level;
- // ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43
- struct
- {
- uint32 creatureId; // set one from fields (or 0 for both to dismount)
- uint32 modelId;
- } mount;
- // RAW
- struct
- {
- uint32 param1;
- uint32 param2;
- uint32 param3;
- } raw;
- };
-};
-
-struct CreatureEventAI_Event
-{
- uint32 event_id;
-
- uint32 creature_id;
-
- uint32 event_inverse_phase_mask;
-
- EventAI_Type event_type : 16;
- uint8 event_chance : 8;
- uint8 event_flags : 8;
-
- union
- {
- // EVENT_T_TIMER = 0
- // EVENT_T_TIMER_OOC = 1
- struct
- {
- uint32 initialMin;
- uint32 initialMax;
- uint32 repeatMin;
- uint32 repeatMax;
- } timer;
- // EVENT_T_HP = 2
- // EVENT_T_MANA = 3
- // EVENT_T_TARGET_HP = 12
- // EVENT_T_TARGET_MANA = 18
- struct
- {
- uint32 percentMax;
- uint32 percentMin;
- uint32 repeatMin;
- uint32 repeatMax;
- } percent_range;
- // EVENT_T_KILL = 5
- struct
- {
- uint32 repeatMin;
- uint32 repeatMax;
- } kill;
- // EVENT_T_SPELLHIT = 8
- struct
- {
- uint32 spellId;
- uint32 schoolMask; // -1 ( == 0xffffffff) is ok value for full mask, or must be more limited mask like (0 < 1) = 1 for normal/physical school
- uint32 repeatMin;
- uint32 repeatMax;
- } spell_hit;
- // EVENT_T_RANGE = 9
- struct
- {
- uint32 minDist;
- uint32 maxDist;
- uint32 repeatMin;
- uint32 repeatMax;
- } range;
- // EVENT_T_OOC_LOS = 10
- struct
- {
- uint32 noHostile;
- uint32 maxRange;
- uint32 repeatMin;
- uint32 repeatMax;
- } ooc_los;
- // EVENT_T_SPAWNED = 11
- struct
- {
- uint32 condition;
- uint32 conditionValue1;
- } spawned;
- // EVENT_T_TARGET_CASTING = 13
- struct
- {
- uint32 repeatMin;
- uint32 repeatMax;
- } target_casting;
- // EVENT_T_FRIENDLY_HP = 14
- struct
- {
- uint32 hpDeficit;
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_hp;
- // EVENT_T_FRIENDLY_IS_CC = 15
- struct
- {
- uint32 dispelType; // unused ?
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_is_cc;
- // EVENT_T_FRIENDLY_MISSING_BUFF = 16
- struct
- {
- uint32 spellId;
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_buff;
- // EVENT_T_SUMMONED_UNIT = 17
- struct
- {
- uint32 creatureId;
- uint32 repeatMin;
- uint32 repeatMax;
- } summon_unit;
- // EVENT_T_QUEST_ACCEPT = 19
- // EVENT_T_QUEST_COMPLETE = 20
- struct
- {
- uint32 questId;
- } quest;
- // EVENT_T_RECEIVE_EMOTE = 22
- struct
- {
- uint32 emoteId;
- uint32 condition;
- uint32 conditionValue1;
- uint32 conditionValue2;
- } receive_emote;
- // EVENT_T_BUFFED = 23
- // EVENT_T_TARGET_BUFFED = 24
- struct
- {
- uint32 spellId;
- uint32 amount;
- uint32 repeatMin;
- uint32 repeatMax;
- } buffed;
-
- // RAW
- struct
- {
- uint32 param1;
- uint32 param2;
- uint32 param3;
- uint32 param4;
- } raw;
- };
-
- CreatureEventAI_Action action[MAX_ACTIONS];
-};
-//Event_Map
-typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map;
-
-struct CreatureEventAI_Summon
-{
- //uint32 id;
-
- float position_x;
- float position_y;
- float position_z;
- float orientation;
- uint32 SpawnTimeSecs;
-};
-
-//EventSummon_Map
-typedef UNORDERED_MAP<uint32, CreatureEventAI_Summon> CreatureEventAI_Summon_Map;
-
-struct CreatureEventAIHolder
-{
- CreatureEventAIHolder(CreatureEventAI_Event const& p) : Event(p), Time(0), Enabled(true){}
-
- CreatureEventAI_Event Event;
- uint32 Time;
- bool Enabled;
-
- // helper
- bool UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax);
-};
-
-class CreatureEventAI : public CreatureAI
-{
- public:
- explicit CreatureEventAI(Creature* c);
- ~CreatureEventAI() { }
-
- void JustRespawned();
- void Reset();
- void JustReachedHome();
- void EnterCombat(Unit* enemy);
- void EnterEvadeMode();
- void JustDied(Unit* /*killer*/);
- void KilledUnit(Unit* victim);
- void JustSummoned(Creature* unit);
- void AttackStart(Unit* who);
- void MoveInLineOfSight(Unit* who);
- void SpellHit(Unit* unit, const SpellInfo* spell);
- void DamageTaken(Unit* done_by, uint32& damage);
- void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) {}
- void UpdateAI(uint32 diff);
- void ReceiveEmote(Player* player, uint32 textEmote);
- static int Permissible(const Creature*);
-
- bool ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker = NULL);
- void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker);
- inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3);
- inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3);
- inline Unit* GetTargetByType(uint32 target, Unit* actionInvoker);
-
- void DoScriptText(int32 textEntry, WorldObject* source, Unit* target);
- bool CanCast(Unit* target, SpellInfo const* spell, bool triggered);
-
- bool SpawnedEventConditionsCheck(CreatureEventAI_Event const& event);
-
- Unit* DoSelectLowestHpFriendly(float range, uint32 minHPDiff);
- void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);
- void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
-
- protected:
- uint32 m_EventUpdateTime; // Time between event updates
- uint32 m_EventDiff; // Time between the last event call
- bool m_bEmptyList;
-
- typedef std::vector<CreatureEventAIHolder> CreatureEventAIList;
- CreatureEventAIList m_CreatureEventAIList; // Holder for events (stores enabled, time, and eventid)
- // Variables used by Events themselves
- uint8 m_Phase; // Current phase, max 32 phases
- bool m_CombatMovementEnabled; // If we allow targeted movment gen (movement twoards top threat)
- bool m_MeleeEnabled; // If we allow melee auto attack
- float m_AttackDistance; // Distance to attack from
- float m_AttackAngle; // Angle of attack
- uint32 m_InvincibilityHpLevel; // Minimal health level allowed at damage apply
-};
-#endif
diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp
deleted file mode 100644
index 4d2aa9b469f..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "Common.h"
-#include "DatabaseEnv.h"
-#include "CreatureEventAI.h"
-#include "CreatureEventAIMgr.h"
-#include "ObjectMgr.h"
-#include "ObjectDefines.h"
-#include "GridDefines.h"
-#include "ConditionMgr.h"
-#include "SpellMgr.h"
-#include "SpellInfo.h"
-#include "Player.h"
-
-// -------------------
-void CreatureEventAIMgr::LoadCreatureEventAI_Texts()
-{
- uint32 oldMSTime = getMSTime();
-
- // Drop Existing Text Map, only done once and we are ready to add data from multiple sources.
- m_CreatureEventAI_TextMap.clear();
-
- // Load EventAI Text
- sObjectMgr->LoadTrinityStrings("creature_ai_texts", MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID);
-
- // Gather Additional data from EventAI Texts 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
-
- if (!result)
- {
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty.");
- return;
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
- StringTextData temp;
-
- int32 i = fields[0].GetInt32();
- temp.SoundId = fields[1].GetUInt32();
- temp.Type = fields[2].GetUInt8();
- temp.Language = fields[3].GetUInt8();
- temp.Emote = fields[4].GetUInt16();
-
- // range negative
- if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` is not in valid range(%d-%d)", i, MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID);
- continue;
- }
-
- // range negative (must not happen, loaded from same table)
- if (!sObjectMgr->GetTrinityStringLocale(i))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` not found", i);
- continue;
- }
-
- if (temp.SoundId)
- {
- if (!sSoundEntriesStore.LookupEntry(temp.SoundId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.", i, temp.SoundId);
- }
-
- if (!GetLanguageDescByID(temp.Language))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.", i, temp.Language);
-
- if (temp.Type > CHAT_TYPE_ZONE_YELL)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.", i, temp.Type);
-
- if (temp.Emote)
- {
- if (!sEmotesStore.LookupEntry(temp.Emote))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Emote %u but emote does not exist.", i, temp.Emote);
- }
-
- m_CreatureEventAI_TextMap[i] = temp;
- ++count;
- }
- while (result->NextRow());
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u additional CreatureEventAI Texts data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
-
-void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
-{
- uint32 oldMSTime = getMSTime();
-
- //Drop Existing EventAI List
- m_CreatureEventAI_Event_Map.clear();
-
- // Gather event data
- QueryResult result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
- "event_param1, event_param2, event_param3, event_param4, "
- "action1_type, action1_param1, action1_param2, action1_param3, "
- "action2_type, action2_param1, action2_param2, action2_param3, "
- "action3_type, action3_param1, action3_param2, action3_param3 "
- "FROM creature_ai_scripts");
-
- if (!result)
- {
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty.");
- return;
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
-
- CreatureEventAI_Event temp;
- temp.event_id = EventAI_Type(fields[0].GetUInt32());
- uint32 i = temp.event_id;
-
- temp.creature_id = fields[1].GetUInt32();
- uint32 creature_id = temp.creature_id;
-
- uint32 e_type = fields[2].GetUInt8();
- //Report any errors in event
- if (e_type >= EVENT_T_END)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u have wrong type (%u), skipping.", i, e_type);
- continue;
- }
- temp.event_type = EventAI_Type(e_type);
-
- temp.event_inverse_phase_mask = fields[3].GetInt32();
- temp.event_chance = fields[4].GetUInt32();
- temp.event_flags = fields[5].GetUInt32();
- temp.raw.param1 = fields[6].GetInt32();
- temp.raw.param2 = fields[7].GetInt32();
- temp.raw.param3 = fields[8].GetInt32();
- temp.raw.param4 = fields[9].GetInt32();
-
- CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id);
- //Creature does not exist in database
- if (!cInfo)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id);
- continue;
- }
-
- // Only on the first script
- if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty())
- TC_LOG_ERROR(LOG_FILTER_SQL, "Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id);
-
- //No chance of this event occuring
- if (temp.event_chance == 0)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i);
- //Chance above 100, force it to be 100
- else if (temp.event_chance > 100)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i);
- temp.event_chance = 100;
- }
-
- //Individual event checks
- switch (temp.event_type)
- {
- case EVENT_T_TIMER:
- case EVENT_T_TIMER_OOC:
- if (temp.timer.initialMax < temp.timer.initialMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i);
- if (temp.timer.repeatMax < temp.timer.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_HP:
- case EVENT_T_MANA:
- case EVENT_T_TARGET_HP:
- case EVENT_T_TARGET_MANA:
- if (temp.percent_range.percentMax > 100)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
-
- if (temp.percent_range.percentMax <= temp.percent_range.percentMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i);
-
- if (temp.event_flags & EFLAG_REPEATABLE && !temp.percent_range.repeatMin && !temp.percent_range.repeatMax)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
- break;
- case EVENT_T_SPELLHIT:
- if (temp.spell_hit.spellId)
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId);
- if (!spell)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
-
- if ((temp.spell_hit.schoolMask & spell->SchoolMask) != spell->SchoolMask)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.",
- temp.creature_id, temp.spell_hit.schoolMask, i);
- }
- }
-
- if (!temp.spell_hit.schoolMask)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i);
-
- if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_RANGE:
- if (temp.range.maxDist < temp.range.minDist)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i);
- if (temp.range.repeatMax < temp.range.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_OOC_LOS:
- if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_SPAWNED:
- switch (temp.spawned.condition)
- {
- case SPAWNED_EVENT_ALWAY:
- break;
- case SPAWNED_EVENT_MAP:
- if (!sMapStore.LookupEntry(temp.spawned.conditionValue1))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'map specific' but with not existed map (%u) in param2. Event will never repeat.",
- temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
- }
- break;
- case SPAWNED_EVENT_ZONE:
- if (!GetAreaEntryByAreaID(temp.spawned.conditionValue1))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'area specific' but with not existed area (%u) in param2. Event will never repeat.",
- temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
- }
- break;
- default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using invalid spawned event %u mode (%u) in param1", temp.creature_id, i, temp.spawned.condition);
- break;
- }
- break;
- case EVENT_T_FRIENDLY_HP:
- if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_FRIENDLY_IS_CC:
- if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId);
- if (!spell)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
- if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- }
- case EVENT_T_KILL:
- if (temp.kill.repeatMax < temp.kill.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_TARGET_CASTING:
- if (temp.target_casting.repeatMax < temp.target_casting.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_SUMMONED_UNIT:
- if (!sObjectMgr->GetCreatureTemplate(temp.summon_unit.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.summon_unit.creatureId);
- if (temp.summon_unit.repeatMax < temp.summon_unit.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_QUEST_ACCEPT:
- case EVENT_T_QUEST_COMPLETE:
- if (!sObjectMgr->GetQuestTemplate(temp.quest.questId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId);
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i);
- continue;
-
- case EVENT_T_AGGRO:
- case EVENT_T_DEATH:
- case EVENT_T_EVADE:
- case EVENT_T_REACHED_HOME:
- {
- if (temp.event_flags & EFLAG_REPEATABLE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
-
- break;
- }
-
- case EVENT_T_RECEIVE_EMOTE:
- {
- if (!sEmotesTextStore.LookupEntry(temp.receive_emote.emoteId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.", temp.creature_id, i, temp.receive_emote.emoteId);
- continue;
- }
- if (temp.receive_emote.condition)
- {
- Condition cond;
- cond.ConditionType = ConditionTypes(temp.receive_emote.condition);
- cond.ConditionValue1 = temp.receive_emote.conditionValue1;
- cond.ConditionValue2 = temp.receive_emote.conditionValue2;
- if (!sConditionMgr->isConditionTypeValid(&cond))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.", temp.creature_id, i, temp.receive_emote.condition);
- continue;
- }
- }
-
- if (!(temp.event_flags & EFLAG_REPEATABLE))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: EFLAG_REPEATABLE not set. Event must always be repeatable. Flag applied.", temp.creature_id, i);
- temp.event_flags |= EFLAG_REPEATABLE;
- }
-
- break;
- }
-
- case EVENT_T_BUFFED:
- case EVENT_T_TARGET_BUFFED:
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.buffed.spellId);
- if (!spell)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
- if (temp.buffed.repeatMax < temp.buffed.repeatMin)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- }
-
- default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i);
- break;
- }
-
- for (uint32 j = 0; j < MAX_ACTIONS; j++)
- {
- uint16 action_type = fields[10+(j*4)].GetUInt8();
- if (action_type >= ACTION_T_END)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has incorrect action type (%u), replace by ACTION_T_NONE.", i, j+1, action_type);
- temp.action[j].type = ACTION_T_NONE;
- continue;
- }
-
- CreatureEventAI_Action& action = temp.action[j];
-
- action.type = EventAI_ActionType(action_type);
- action.raw.param1 = fields[11+(j*4)].GetInt32();
- action.raw.param2 = fields[12+(j*4)].GetInt32();
- action.raw.param3 = fields[13+(j*4)].GetInt32();
-
- //Report any errors in actions
- switch (action.type)
- {
- case ACTION_T_NONE:
- break;
- case ACTION_T_TEXT:
- {
- if (action.text.TextId1 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
- }
- if (action.text.TextId2 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
-
- if (!action.text.TextId1)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
- }
- if (action.text.TextId3 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
-
- if (!action.text.TextId1 || !action.text.TextId2)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
- }
- break;
- }
- case ACTION_T_SET_FACTION:
- if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId);
- action.set_faction.factionId = 0;
- }
- break;
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- if (action.morph.creatureId !=0 || action.morph.modelId !=0)
- {
- if (action.morph.creatureId && !sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatureId);
- action.morph.creatureId = 0;
- }
-
- if (action.morph.modelId)
- {
- if (action.morph.creatureId)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId, action.morph.creatureId);
- action.morph.modelId = 0;
- }
- else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId);
- action.morph.modelId = 0;
- }
- }
- }
- break;
- case ACTION_T_SOUND:
- if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
- break;
- case ACTION_T_EMOTE:
- if (!sEmotesStore.LookupEntry(action.emote.emoteId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId);
- break;
- case ACTION_T_RANDOM_SOUND:
- if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1);
- if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2);
- if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3);
- break;
- case ACTION_T_RANDOM_EMOTE:
- if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1);
- if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2);
- if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3);
- break;
- case ACTION_T_CAST:
- {
- const SpellInfo* spell = sSpellMgr->GetSpellInfo(action.cast.spellId);
- if (!spell)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId);
- /* FIXME: temp.raw.param3 not have event tipes with recovery time in it....
- else
- {
- if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
- {
- //output as debug for now, also because there's no general rule all spells have RecoveryTime
- if (temp.event_param3 < spell->RecoveryTime)
- TC_LOG_DEBUG("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1, action.cast.spellId, spell->RecoveryTime, temp.event_param3);
- }
- }
- */
-
- //Cast is always triggered if target is forced to cast on self
- if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
- action.cast.castFlags |= CAST_TRIGGERED;
-
- if (action.cast.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- }
- case ACTION_T_SUMMON:
- if (!sObjectMgr->GetCreatureTemplate(action.summon.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatureId);
-
- if (action.summon.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_THREAT_SINGLE_PCT:
- if (std::abs(action.threat_single_pct.percent) > 100)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent);
- if (action.threat_single_pct.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_THREAT_ALL_PCT:
- if (std::abs(action.threat_all_pct.percent) > 100)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent);
- break;
- case ACTION_T_QUEST_EVENT:
- if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event.questId))
- {
- if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId);
- }
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId);
-
- if (action.quest_event.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
-
- break;
- case ACTION_T_CAST_EVENT:
- if (!sObjectMgr->GetCreatureTemplate(action.cast_event.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event.creatureId);
- if (!sSpellMgr->GetSpellInfo(action.cast_event.spellId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event.spellId);
- if (action.cast_event.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_UNIT_FIELD:
- if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
- if (action.set_unit_field.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_UNIT_FLAG:
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (action.unit_flag.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_PHASE:
- if (action.set_phase.phase >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- break;
- case ACTION_T_INC_PHASE:
- if (action.set_inc_phase.step == 0)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
- else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step);
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event_all.questId))
- {
- if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId);
- }
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId);
- break;
- case ACTION_T_CAST_EVENT_ALL:
- if (!sObjectMgr->GetCreatureTemplate(action.cast_event_all.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event_all.creatureId);
- if (!sSpellMgr->GetSpellInfo(action.cast_event_all.spellId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event_all.spellId);
- break;
- case ACTION_T_REMOVEAURASFROMSPELL:
- if (!sSpellMgr->GetSpellInfo(action.remove_aura.spellId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId);
- if (action.remove_aura.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3
- if (action.random_phase.phase1 >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase.phase2 >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase.phase3 >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- break;
- case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax
- if (action.random_phase_range.phaseMin >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase_range.phaseMin >= MAX_PHASE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1);
- std::swap(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
- // equal case processed at call
- }
- break;
- case ACTION_T_KILLED_MONSTER:
- if (!sObjectMgr->GetCreatureTemplate(action.killed_monster.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId);
- if (action.killed_monster.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_INST_DATA:
- if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
- if (action.set_inst_data.value > 4/*SPECIAL*/)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
- break;
- case ACTION_T_SET_INST_DATA64:
- if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
- if (action.set_inst_data64.target >= TARGET_T_END)
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_UPDATE_TEMPLATE:
- if (!sObjectMgr->GetCreatureTemplate(action.update_template.creatureId))
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId);
- break;
- case ACTION_T_SET_SHEATH:
- if (action.set_sheath.sheath >= MAX_SHEATH_STATE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses wrong sheath state %u.", i, j+1, action.set_sheath.sheath);
- action.set_sheath.sheath = SHEATH_STATE_UNARMED;
- }
- break;
- case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
- if (action.invincibility_hp_level.is_percent)
- {
- if (action.invincibility_hp_level.hp_level > 100)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses wrong percent value %u.", i, j+1, action.invincibility_hp_level.hp_level);
- action.invincibility_hp_level.hp_level = 100;
- }
- }
- break;
- case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
- if (action.mount.creatureId != 0 || action.mount.modelId != 0)
- {
- if (action.mount.creatureId && !sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses nonexistent Creature entry %u.", i, j+1, action.mount.creatureId);
- action.morph.creatureId = 0;
- }
-
- if (action.mount.modelId)
- {
- if (action.mount.creatureId)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.mount.modelId, action.mount.creatureId);
- action.mount.modelId = 0;
- }
- else if (!sCreatureDisplayInfoStore.LookupEntry(action.mount.modelId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses nonexistent ModelId %u.", i, j+1, action.mount.modelId);
- action.mount.modelId = 0;
- }
- }
- }
- break;
- case ACTION_T_EVADE: //No Params
- case ACTION_T_FLEE_FOR_ASSIST: //No Params
- case ACTION_T_DIE: //No Params
- case ACTION_T_ZONE_COMBAT_PULSE: //No Params
- case ACTION_T_FORCE_DESPAWN: //No Params
- case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking)
- case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- case ACTION_T_RANGED_MOVEMENT: //Distance, Angle
- case ACTION_T_CALL_FOR_HELP: //Distance
- break;
-
- case ACTION_T_RANDOM_SAY:
- case ACTION_T_RANDOM_YELL:
- case ACTION_T_RANDOM_TEXTEMOTE:
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
- break;
-
- case ACTION_T_MOVE_RANDOM_POINT:
- case ACTION_T_SET_STAND_STATE:
- case ACTION_T_SET_PHASE_MASK:
- case ACTION_T_SET_VISIBILITY:
- case ACTION_T_SET_ACTIVE:
- case ACTION_T_SET_AGGRESSIVE:
- case ACTION_T_ATTACK_START_PULSE:
- case ACTION_T_SUMMON_GO:
- break;
-
- default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j+1, action.type);
- break;
- }
- }
-
- //Add to list
- m_CreatureEventAI_Event_Map[creature_id].push_back(temp);
- ++count;
-
- }
- while (result->NextRow());
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.h b/src/server/game/AI/EventAI/CreatureEventAIMgr.h
deleted file mode 100644
index 8e862a9279b..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAIMgr.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_CREATURE_EAI_MGR_H
-#define TRINITY_CREATURE_EAI_MGR_H
-
-#include "Common.h"
-#include "CreatureEventAI.h"
-
-class CreatureEventAIMgr
-{
- friend class ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>;
-
- private:
- CreatureEventAIMgr(){}
- ~CreatureEventAIMgr(){}
-
- public:
- void LoadCreatureEventAI_Texts();
- void LoadCreatureEventAI_Scripts();
-
- CreatureEventAI_Event_Map const& GetCreatureEventAIMap() const { return m_CreatureEventAI_Event_Map; }
- CreatureEventAI_TextMap const& GetCreatureEventAITextMap() const { return m_CreatureEventAI_TextMap; }
-
- private:
- CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map;
- CreatureEventAI_TextMap m_CreatureEventAI_TextMap;
-};
-
-#define sEventAIMgr ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>::instance()
-#endif
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 7d7ae278b43..687f43f616d 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -223,7 +223,7 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
continue;
//Continue if we don't have the mana to actually cast this spell
- if (tempSpell->ManaCost > me->GetPower(Powers(tempSpell->PowerType)))
+ if (tempSpell->ManaCost > (uint32)me->GetPower(Powers(tempSpell->PowerType)))
continue;
//Check if the spell meets our range requirements
@@ -580,6 +580,20 @@ void BossAI::UpdateAI(uint32 diff)
DoMeleeAttackIfReady();
}
+void BossAI::_DespawnAtEvade()
+{
+ uint32 corpseDelay = me->GetCorpseDelay();
+ uint32 respawnDelay = me->GetRespawnDelay();
+
+ me->SetCorpseDelay(1);
+ me->SetRespawnDelay(29);
+
+ me->DespawnOrUnsummon();
+
+ me->SetCorpseDelay(corpseDelay);
+ me->SetRespawnDelay(respawnDelay);
+}
+
// WorldBossAI - for non-instanced bosses
WorldBossAI::WorldBossAI(Creature* creature) :
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index 4523080adbd..8634355b974 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -360,6 +360,7 @@ class BossAI : public ScriptedAI
void _EnterCombat();
void _JustDied();
void _JustReachedHome() { me->setActive(false); }
+ void _DespawnAtEvade();
bool CheckInRoom()
{
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index a2612df2f89..f8c99816cdf 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -735,7 +735,7 @@ void SmartAI::SetRun(bool run)
void SmartAI::SetFly(bool fly)
{
me->SetDisableGravity(fly);
- me->SendMovementFlagUpdate();
+ me->SendMovementDisableGravity();
}
void SmartAI::SetSwim(bool swim)
@@ -744,7 +744,7 @@ void SmartAI::SetSwim(bool swim)
me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
else
me->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
- me->SendMovementFlagUpdate();
+ me->SendMovementSwimming();
}
void SmartAI::sGossipHello(Player* player)
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index ec7f307c5ef..8fe67f7b384 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -674,7 +674,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
{
- if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u SpecialFlags for Quest entry %u does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
return false;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 2fcee55ed14..d80b4816d4b 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -23,6 +23,7 @@
#include "CreatureAI.h"
#include "Unit.h"
#include "Spell.h"
+#include "DB2Stores.h"
//#include "SmartScript.h"
//#include "SmartAI.h"
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 00bffb8f21c..845e96794bd 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -28,6 +28,7 @@
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GridNotifiersImpl.h"
+#include "Group.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "InstanceScript.h"
@@ -80,7 +81,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false;
}
- switch (criteria->requiredType)
+ switch (criteria->type)
{
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
@@ -108,7 +109,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
default:
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` has data for non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->requiredType);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` has data for non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->type);
return false;
}
break;
@@ -124,21 +125,27 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!creature.id || !sObjectMgr->GetCreatureTemplate(creature.id))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) has non-existing creature id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, creature.id);
+ criteria->ID, criteria->type, dataType, creature.id);
return false;
}
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if (!classRace.class_id && !classRace.race_id)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
+ criteria->ID, criteria->type, dataType);
+ return false;
+ }
if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.class_id);
+ criteria->ID, criteria->type, dataType, classRace.class_id);
return false;
}
if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.race_id);
+ criteria->ID, criteria->type, dataType, classRace.race_id);
return false;
}
return true;
@@ -146,15 +153,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (health.percent < 1 || health.percent > 100)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) has wrong percent value in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, health.percent);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
- if (player_dead.own_team_flag > 1)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD (%u) has wrong boolean value1 (%u).",
- criteria->ID, criteria->requiredType, dataType, player_dead.own_team_flag);
+ criteria->ID, criteria->type, dataType, health.percent);
return false;
}
return true;
@@ -165,36 +164,28 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!spellEntry)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id);
return false;
}
if (aura.effect_idx >= 3)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell effect index in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx);
return false;
}
if (!spellEntry->Effects[aura.effect_idx].ApplyAuraName)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has non-aura spell effect (ID: %u Effect: %u), ignores.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx);
return false;
}
return true;
}
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
- if (!GetAreaEntryByAreaID(area.id))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) has wrong area id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, area.id);
- return false;
- }
- return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL:
if (level.minlevel > STRONG_MAX_LEVEL)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL (%u) has wrong minlevel in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, level.minlevel);
+ criteria->ID, criteria->type, dataType, level.minlevel);
return false;
}
return true;
@@ -202,7 +193,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (gender.gender > GENDER_NONE)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER (%u) has wrong gender in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, gender.gender);
+ criteria->ID, criteria->type, dataType, gender.gender);
return false;
}
return true;
@@ -210,15 +201,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!ScriptId)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT (%u) does not have ScriptName set, ignored.",
- criteria->ID, criteria->requiredType, dataType);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- if (difficulty.difficulty >= MAX_DIFFICULTY)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY (%u) has wrong difficulty in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, difficulty.difficulty);
+ criteria->ID, criteria->type, dataType);
return false;
}
return true;
@@ -226,7 +209,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (map_players.maxcount <= 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT (%u) has wrong max players count in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, map_players.maxcount);
+ criteria->ID, criteria->type, dataType, map_players.maxcount);
return false;
}
return true;
@@ -234,7 +217,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (team.team != ALLIANCE && team.team != HORDE)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM (%u) has unknown team in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, team.team);
+ criteria->ID, criteria->type, dataType, team.team);
return false;
}
return true;
@@ -242,7 +225,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (drunk.state >= MAX_DRUNKEN)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK (%u) has unknown drunken state in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, drunk.state);
+ criteria->ID, criteria->type, dataType, drunk.state);
return false;
}
return true;
@@ -250,7 +233,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!sHolidaysStore.LookupEntry(holiday.id))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY (%u) has unknown holiday in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, holiday.id);
+ criteria->ID, criteria->type, dataType, holiday.id);
return false;
}
return true;
@@ -260,15 +243,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (equipped_item.item_quality >= MAX_ITEM_QUALITY)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_S_EQUIPED_ITEM (%u) has unknown quality state in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, equipped_item.item_quality);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
- if (!sMapStore.LookupEntry(map_id.mapId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID (%u) has unknown map id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, map_id.mapId);
+ criteria->ID, criteria->type, dataType, equipped_item.item_quality);
return false;
}
return true;
@@ -276,29 +251,29 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!classRace.class_id && !classRace.race_id)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
- criteria->ID, criteria->requiredType, dataType);
+ criteria->ID, criteria->type, dataType);
return false;
}
if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.class_id);
+ criteria->ID, criteria->type, dataType, classRace.class_id);
return false;
}
if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.race_id);
+ criteria->ID, criteria->type, dataType, classRace.race_id);
return false;
}
return true;
default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->requiredType, dataType);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->type, dataType);
return false;
}
}
-bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscvalue1 /*= 0*/) const
+bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 /*= 0*/) const
{
switch (dataType)
{
@@ -328,25 +303,12 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
if (!target || target->GetTypeId() != TYPEID_PLAYER)
return false;
return !target->HealthAbovePct(health.percent);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
- if (target && !target->isAlive())
- if (const Player* player = target->ToPlayer())
- if (player->GetDeathTimer() != 0)
- // flag set == must be same team, not set == different team
- return (player->GetTeam() == source->GetTeam()) == (player_dead.own_team_flag != 0);
- return false;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
return source->HasAuraEffect(aura.spell_id, aura.effect_idx);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
- {
- uint32 zone_id, area_id;
- source->GetZoneAndAreaId(zone_id, area_id);
- return area.id == zone_id || area.id == area_id;
- }
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
return target && target->HasAuraEffect(aura.spell_id, aura.effect_idx);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE:
- return miscvalue1 >= value.minvalue;
+ return miscValue1 >= value.minvalue;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL:
if (!target)
return false;
@@ -357,11 +319,6 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return target->getGender() == gender.gender;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT:
return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target));
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- if (source->GetMap()->IsRaid())
- if (source->GetMap()->Is25ManRaid() != ((difficulty.difficulty & RAID_DIFFICULTY_MASK_25MAN) != 0))
- return false;
- return source->GetMap()->GetSpawnMode() >= difficulty.difficulty;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM:
@@ -399,71 +356,116 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT, criteria_id, map->GetId());
return false;
}
- return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1);
+ return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscValue1);
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
{
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1);
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
if (!pProto)
return false;
return pProto->ItemLevel >= equipped_item.item_level && pProto->Quality >= equipped_item.item_quality;
}
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
- return source->GetMapId() == map_id.mapId;
default:
break;
}
return false;
}
-bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscvalue /*= 0*/) const
+bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscValue /*= 0*/) const
{
for (Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr)
- if (!itr->Meets(criteria_id, source, target, miscvalue))
+ if (!itr->Meets(criteria_id, source, target, miscValue))
return false;
return true;
}
-AchievementMgr::AchievementMgr(Player* player)
+template<class T>
+AchievementMgr<T>::AchievementMgr(T* owner): _owner(owner), _achievementPoints(0) {}
+
+template<class T>
+AchievementMgr<T>::~AchievementMgr()
{
- m_player = player;
}
-AchievementMgr::~AchievementMgr()
+template<class T>
+void AchievementMgr<T>::SendPacket(WorldPacket* data) const
{
}
-void AchievementMgr::Reset()
+template<>
+void AchievementMgr<Guild>::SendPacket(WorldPacket* data) const
{
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
- {
- WorldPacket data(SMSG_ACHIEVEMENT_DELETED, 4);
- data << uint32(iter->first);
- m_player->SendDirectMessage(&data);
- }
+ GetOwner()->BroadcastPacket(data);
+}
- for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
- {
- WorldPacket data(SMSG_CRITERIA_DELETED, 4);
- data << uint32(iter->first);
- m_player->SendDirectMessage(&data);
- }
+template<>
+void AchievementMgr<Player>::SendPacket(WorldPacket* data) const
+{
+ GetOwner()->GetSession()->SendPacket(data);
+}
- m_completedAchievements.clear();
- m_criteriaProgress.clear();
- DeleteFromDB(m_player->GetGUIDLow());
+template<class T>
+void AchievementMgr<T>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
+{
+ if (!entry)
+ return;
- // re-fill data
- CheckAllAchievementCriteria();
+ CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
+ if (criteriaProgress == m_criteriaProgress.end())
+ return;
+
+ WorldPacket data(SMSG_CRITERIA_DELETED, 4);
+ data << uint32(entry->ID);
+ SendPacket(&data);
+
+ m_criteriaProgress.erase(criteriaProgress);
}
-void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, bool evenIfCriteriaComplete)
+template<>
+void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
{
- TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::ResetAchievementCriteria(%u, %u, %u)", type, miscvalue1, miscvalue2);
+ if (!entry)
+ return;
+
+ CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
+ if (criteriaProgress == m_criteriaProgress.end())
+ return;
+
+ ObjectGuid guid = GetOwner()->GetGUID();
+
+ WorldPacket data(SMSG_GUILD_CRITERIA_DELETED, 4 + 8);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[7]);
+ data << uint32(entry->ID);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ SendPacket(&data);
+
+ m_criteriaProgress.erase(criteriaProgress);
+}
+
+template<class T>
+void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
+{
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "ResetAchievementCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
// disable for gamemasters with GM-mode enabled
- if (m_player->isGameMaster())
+ if (GetOwner()->isGameMaster())
return;
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
@@ -471,7 +473,7 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->achievement);
if (!achievement)
continue;
@@ -480,9 +482,9 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
continue;
for (uint8 j = 0; j < MAX_CRITERIA_REQUIREMENTS; ++j)
- if (achievementCriteria->additionalRequirements[j].additionalRequirement_type == miscvalue1 &&
+ if (achievementCriteria->additionalRequirements[j].additionalRequirement_type == miscValue1 &&
(!achievementCriteria->additionalRequirements[j].additionalRequirement_value ||
- achievementCriteria->additionalRequirements[j].additionalRequirement_value == miscvalue2))
+ achievementCriteria->additionalRequirements[j].additionalRequirement_value == miscValue2))
{
RemoveCriteriaProgress(achievementCriteria);
break;
@@ -490,7 +492,19 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
}
}
-void AchievementMgr::DeleteFromDB(uint32 lowguid)
+template<>
+void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint64 /*miscValue1*/, uint64 /*miscValue2*/, bool /*evenIfCriteriaComplete*/)
+{
+ // Not needed
+}
+
+template<class T>
+void AchievementMgr<T>::DeleteFromDB(uint32 /*lowguid*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::DeleteFromDB(uint32 lowguid)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -505,7 +519,29 @@ void AchievementMgr::DeleteFromDB(uint32 lowguid)
CharacterDatabase.CommitTransaction(trans);
}
-void AchievementMgr::SaveToDB(SQLTransaction& trans)
+template<>
+void AchievementMgr<Guild>::DeleteFromDB(uint32 lowguid)
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS);
+ stmt->setUInt32(0, lowguid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, lowguid);
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+template<class T>
+void AchievementMgr<T>::SaveToDB(SQLTransaction& /*trans*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::SaveToDB(SQLTransaction& trans)
{
if (!m_completedAchievements.empty())
{
@@ -520,7 +556,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
/// first new/changed record prefix
if (!need_execute)
{
- ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN (";
+ ssdel << "DELETE FROM character_achievement WHERE guid = " << GetOwner()->GetGUIDLow() << " AND achievement IN (";
ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
need_execute = true;
}
@@ -533,7 +569,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
// new/changed record data
ssdel << iter->first;
- ssins << '(' << GetPlayer()->GetGUIDLow() << ',' << iter->first << ',' << uint64(iter->second.date) << ')';
+ ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << uint64(iter->second.date) << ')';
/// mark as saved in db
iter->second.changed = false;
@@ -564,7 +600,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
/// first new/changed record prefix (for any counter value)
if (!need_execute_del)
{
- ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN (";
+ ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetOwner()->GetGUIDLow() << " AND criteria IN (";
need_execute_del = true;
}
/// next new/changed record prefix
@@ -589,7 +625,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
ssins << ',';
// new/changed record data
- ssins << '(' << GetPlayer()->GetGUIDLow() << ',' << iter->first << ',' << iter->second.counter << ',' << iter->second.date << ')';
+ ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << iter->second.counter << ',' << iter->second.date << ')';
}
/// mark as updated in db
@@ -609,7 +645,61 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
}
}
-void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+template<>
+void AchievementMgr<Guild>::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt;
+ std::ostringstream guidstr;
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!itr->second.changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt32(2, itr->second.date);
+ for (std::set<uint64>::const_iterator gItr = itr->second.guids.begin(); gItr != itr->second.guids.end(); ++gItr)
+ guidstr << GUID_LOPART(*gItr) << ',';
+
+ stmt->setString(3, guidstr.str());
+ trans->Append(stmt);
+
+ guidstr.str("");
+ }
+
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ {
+ if (!itr->second.changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt32(2, itr->second.counter);
+ stmt->setUInt32(3, itr->second.date);
+ stmt->setUInt32(4, GUID_LOPART(itr->second.CompletedGUID));
+ trans->Append(stmt);
+ }
+}
+
+template<class T>
+void AchievementMgr<T>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+{
+}
+
+template<>
+void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
{
if (achievementResult)
{
@@ -627,22 +717,26 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
ca.date = time_t(fields[1].GetUInt32());
ca.changed = false;
+ _achievementPoints += achievement->points;
+
// title achievement rewards are retroactive
if (AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement))
- if (uint32 titleId = reward->titleId[Player::TeamForRace(GetPlayer()->getRace()) == ALLIANCE ? 0 : 1])
+ if (uint32 titleId = reward->titleId[Player::TeamForRace(GetOwner()->getRace()) == ALLIANCE ? 0 : 1])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetPlayer()->SetTitle(titleEntry);
+ GetOwner()->SetTitle(titleEntry);
- } while (achievementResult->NextRow());
+ }
+ while (achievementResult->NextRow());
}
if (criteriaResult)
{
+ time_t now = time(NULL);
do
{
Field* fields = criteriaResult->Fetch();
uint32 id = fields[0].GetUInt16();
- uint32 counter = fields[1].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
time_t date = time_t(fields[2].GetUInt32());
AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(id);
@@ -652,87 +746,249 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
TC_LOG_ERROR(LOG_FILTER_ACHIEVEMENTSYS, "Non-existing achievement criteria %u data removed from table `character_achievement_progress`.", id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA);
-
stmt->setUInt16(0, uint16(id));
-
CharacterDatabase.Execute(stmt);
continue;
}
- if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))
+ if (criteria->timeLimit && time_t(date + criteria->timeLimit) < now)
+ continue;
+
+ CriteriaProgress& progress = m_criteriaProgress[id];
+ progress.counter = counter;
+ progress.date = date;
+ progress.changed = false;
+ }
+ while (criteriaResult->NextRow());
+ }
+}
+
+template<>
+void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+{
+ if (achievementResult)
+ {
+ do
+ {
+ Field* fields = achievementResult->Fetch();
+ uint32 achievementid = fields[0].GetUInt16();
+
+ // must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementid);
+ if (!achievement)
+ continue;
+
+ CompletedAchievementData& ca = m_completedAchievements[achievementid];
+ ca.date = time_t(fields[1].GetUInt32());
+ Tokenizer guids(fields[2].GetString(), ' ');
+ for (uint32 i = 0; i < guids.size(); ++i)
+ ca.guids.insert(MAKE_NEW_GUID(atol(guids[i]), 0, HIGHGUID_PLAYER));
+
+ ca.changed = false;
+
+ _achievementPoints += achievement->points;
+ }
+ while (achievementResult->NextRow());
+ }
+
+ if (criteriaResult)
+ {
+ time_t now = time(NULL);
+ do
+ {
+ Field* fields = criteriaResult->Fetch();
+ uint32 id = fields[0].GetUInt16();
+ uint32 counter = fields[1].GetUInt32();
+ time_t date = time_t(fields[2].GetUInt32());
+ uint64 guid = fields[3].GetUInt32();
+
+ AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(id);
+ if (!criteria)
+ {
+ // we will remove not existed criteria for all guilds
+ TC_LOG_ERROR(LOG_FILTER_ACHIEVEMENTSYS, "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`.", id);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD);
+ stmt->setUInt16(0, uint16(id));
+ CharacterDatabase.Execute(stmt);
+ continue;
+ }
+
+ if (criteria->timeLimit && time_t(date + criteria->timeLimit) < now)
continue;
CriteriaProgress& progress = m_criteriaProgress[id];
progress.counter = counter;
progress.date = date;
+ progress.CompletedGUID = MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER);
progress.changed = false;
} while (criteriaResult->NextRow());
}
}
-void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) const
+template<class T>
+void AchievementMgr<T>::Reset()
{
- if (GetPlayer()->GetSession()->PlayerLoading())
- return;
+}
+
+template<>
+void AchievementMgr<Player>::Reset()
+{
+ for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ {
+ WorldPacket data(SMSG_ACHIEVEMENT_DELETED, 4);
+ data << uint32(iter->first);
+ SendPacket(&data);
+ }
+
+ for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
+ {
+ WorldPacket data(SMSG_CRITERIA_DELETED, 4);
+ data << uint32(iter->first);
+ SendPacket(&data);
+ }
+
+ m_completedAchievements.clear();
+ _achievementPoints = 0;
+ m_criteriaProgress.clear();
+ DeleteFromDB(GetOwner()->GetGUIDLow());
+
+ // re-fill data
+ CheckAllAchievementCriteria(GetOwner());
+}
+
+template<>
+void AchievementMgr<Guild>::Reset()
+{
+ ObjectGuid guid = GetOwner()->GetGUID();
+ for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ {
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DELETED, 4);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[6]);
+ data << uint32(iter->first);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[7]);
+ data.AppendPackedTime(iter->second.date);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[2]);
+ SendPacket(&data);
+ }
+
+ while (!m_criteriaProgress.empty())
+ if (AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(m_criteriaProgress.begin()->first))
+ RemoveCriteriaProgress(criteria);
- // Don't send for achievements with ACHIEVEMENT_FLAG_TRACKING
+ _achievementPoints = 0;
+ m_completedAchievements.clear();
+ DeleteFromDB(GetOwner()->GetId());
+}
+
+template<class T>
+void AchievementMgr<T>::SendAchievementEarned(AchievementEntry const* achievement) const
+{
+ // Don't send for achievements with ACHIEVEMENT_FLAG_HIDDEN
if (achievement->flags & ACHIEVEMENT_FLAG_HIDDEN)
return;
- #ifdef TRINITY_DEBUG
- TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
- #endif
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
- if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId()))
+ if (Guild* guild = sGuildMgr->GetGuildById(GetOwner()->GetGuildId()))
{
- Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_GUILD_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID);
+ Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_GUILD_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID);
Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder);
- guild->BroadcastWorker(say_do, GetPlayer());
+ guild->BroadcastWorker(say_do);
}
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
{
// broadcast realm first reached
- WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetPlayer()->GetName().size() + 1 + 8 + 4 + 4);
- data << GetPlayer()->GetName();
- data << uint64(GetPlayer()->GetGUID());
+ WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetOwner()->GetName().size() + 1 + 8 + 4 + 4);
+ data << GetOwner()->GetName();
+ data << uint64(GetOwner()->GetGUID());
data << uint32(achievement->ID);
data << uint32(0); // 1=link supplied string as player name, 0=display plain string
sWorld->SendGlobalMessage(&data);
}
// if player is in world he can tell his friends about new achievement
- else if (GetPlayer()->IsInWorld())
+ else if (GetOwner()->IsInWorld())
{
- CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
+ Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID);
+
+ CellCoord p = Trinity::ComputeCellCoord(GetOwner()->GetPositionX(), GetOwner()->GetPositionY());
Cell cell(p);
cell.SetNoCreate();
- Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID);
Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder);
- Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do);
+ Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do);
TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker);
- cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY));
+ cell.Visit(p, message, *GetOwner()->GetMap(), *GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY));
}
WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);
- data.append(GetPlayer()->GetPackGUID());
+ data.append(GetOwner()->GetPackGUID());
data << uint32(achievement->ID);
data.AppendPackedTime(time(NULL));
- data << uint32(0);
- GetPlayer()->SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
+ data << uint32(0); // does not notify player ingame
+ GetOwner()->SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
}
-void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
+template<>
+void AchievementMgr<Guild>::SendAchievementEarned(AchievementEntry const* achievement) const
{
- WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
+ ObjectGuid guid = GetOwner()->GetGUID();
+
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_EARNED, 8+4+8);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[5]);
+
+ data.WriteByteSeq(guid[2]);
+ data.AppendPackedTime(time(NULL));
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ data << uint32(achievement->ID);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[6]);
+
+ SendPacket(&data);
+}
+
+template<class T>
+void AchievementMgr<T>::SendCriteriaUpdate(AchievementCriteriaEntry const* /*entry*/, CriteriaProgress const* /*progress*/, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
+{
+}
+
+template<>
+void AchievementMgr<Player>::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
+{
+ WorldPacket data(SMSG_CRITERIA_UPDATE, 8 + 4 + 8);
data << uint32(entry->ID);
// the counter is packed like a packed Guid
data.appendPackGUID(progress->counter);
- data.append(GetPlayer()->GetPackGUID());
+ data.appendPackGUID(GetOwner()->GetGUID());
if (!entry->timeLimit)
data << uint32(0);
else
@@ -740,20 +996,75 @@ void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, C
data.AppendPackedTime(progress->date);
data << uint32(timeElapsed); // time elapsed in seconds
data << uint32(0); // unk
- GetPlayer()->SendDirectMessage(&data);
+ SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Guild>::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
+{
+ //will send response to criteria progress request
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, 3 + 1 + 1 + 8 + 8 + 4 + 4 + 4 + 4 + 4);
+
+ ObjectGuid counter = progress->counter; // for accessing every byte individually
+ ObjectGuid guid = progress->CompletedGUID;
+
+ data.WriteBits(1, 21);
+ data.WriteBit(counter[4]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(counter[5]);
+ data.WriteBit(counter[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[7]);
+ data.WriteBit(guid[4]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[5]);
+ data << uint32(progress->date); // unknown date
+ data.WriteByteSeq(counter[3]);
+ data.WriteByteSeq(counter[7]);
+ data << uint32(progress->date); // unknown date
+ data.WriteByteSeq(counter[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(counter[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(counter[0]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(counter[1]);
+ data.WriteByteSeq(guid[6]);
+ data << uint32(progress->date); // last update time (not packed!)
+ data << uint32(entry->ID);
+ data.WriteByteSeq(counter[5]);
+ data << uint32(0);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(counter[2]);
+ data.WriteByteSeq(guid[0]);
+
+ SendPacket(&data);
}
/**
* called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
*/
-void AchievementMgr::CheckAllAchievementCriteria()
+template<class T>
+void AchievementMgr<T>::CheckAllAchievementCriteria(Player* referencePlayer)
{
// suppress sending packets
for (uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; ++i)
- UpdateAchievementCriteria(AchievementCriteriaTypes(i));
+ UpdateAchievementCriteria(AchievementCriteriaTypes(i), 0, 0, 0, NULL, referencePlayer);
}
-static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 };
+static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = {1057, 1107, 1108};
static const uint32 achievIdForDungeon[][4] =
{
// ach_cr_id, is_dungeon, is_raid, is_heroic_dungeon
@@ -765,28 +1076,62 @@ static const uint32 achievIdForDungeon[][4] =
{ 0, false, false, false }
};
+// Helper function to avoid having to specialize template for a 800 line long function
+template <typename T> static bool IsGuild() { return false; }
+template<> bool IsGuild<Guild>() { return true; }
+
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
-void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
+template<class T>
+void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit const* unit /*= NULL*/, Player* referencePlayer /*= NULL*/)
{
- TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::UpdateAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2);
+ if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: Wrong criteria type %u", type);
+ return;
+ }
+
+ if (!referencePlayer)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: Player is NULL! Cant update criteria");
+ return;
+ }
// disable for gamemasters with GM-mode enabled
- if (m_player->isGameMaster())
+ if (referencePlayer->isGameMaster())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: [Player %s GM mode on] %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
+ , referencePlayer->GetName().c_str(), GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
return;
+ }
- AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
+ , GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
+
+ // Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab
+ if (IsGuild<T>() && !sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, IsGuild<T>());
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->achievement);
if (!achievement)
+ {
+ TC_LOG_ERROR(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: Achievement %u not found!", achievementCriteria->achievement);
continue;
+ }
- if (!CanUpdateCriteria(achievementCriteria, achievement))
+ if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
continue;
+ // requirements not found in the dbc
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(referencePlayer, unit, miscValue1))
+ continue;
+
switch (type)
{
// std. case: increment at 1
@@ -799,13 +1144,38 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
break;
- // std case: increment at miscvalue1
+ // std case: increment at miscValue1
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
@@ -816,102 +1186,43 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
break;
- // std case: high value at miscvalue1
+ // std case: high value at miscValue1
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
- break;
-
- // specialized cases
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId())
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (achievementCriteria->kill_creature.creatureID != miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
- SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->getLevel(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
- continue;
- if (uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
- SetCriteriaProgress(achievementCriteria, skillvalue);
+ if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
+ SetCriteriaProgress(achievementCriteria, skillvalue, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
- continue;
- if (uint32 maxSkillvalue = GetPlayer()->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID))
- SetCriteriaProgress(achievementCriteria, maxSkillvalue);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- if (m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end())
- SetCriteriaProgress(achievementCriteria, 1);
+ if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID))
+ SetCriteriaProgress(achievementCriteria, maxSkillvalue, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- {
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetRewardedQuestCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
{
time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
@@ -921,7 +1232,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
// reset if player missed one day.
if (progress && progress->date < (nextDailyResetTime - 2 * DAY))
- SetCriteriaProgress(achievementCriteria, 0, PROGRESS_SET);
+ SetCriteriaProgress(achievementCriteria, 0, referencePlayer, PROGRESS_SET);
continue;
}
@@ -930,7 +1241,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// 1st time. Start count.
progressType = PROGRESS_SET;
else if (progress->date < (nextDailyResetTime - 2 * DAY))
- // last progress is older than 2 days. Player missed 1 day => Retart count.
+ // last progress is older than 2 days. Player missed 1 day => Restart count.
progressType = PROGRESS_SET;
else if (progress->date < (nextDailyResetTime - DAY))
// last progress is between 1 and 2 days. => 1st time of the day.
@@ -939,463 +1250,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// last progress is within the day before the reset => Already counted today.
continue;
- SetCriteriaProgress(achievementCriteria, 1, progressType);
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer, progressType);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
{
- // speedup for non-login case
- if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
- continue;
-
uint32 counter = 0;
- const RewardedQuestSet &rewQuests = GetPlayer()->getRewardedQuests();
+ const RewardedQuestSet &rewQuests = referencePlayer->getRewardedQuests();
for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
{
Quest const* quest = sObjectMgr->GetQuestTemplate(*itr);
if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID)
++counter;
}
- SetCriteriaProgress(achievementCriteria, counter);
+ SetCriteriaProgress(achievementCriteria, counter, referencePlayer);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
- bool notfit = false;
- for (int j = 0; j < MAX_ARENA_SLOT; ++j)
- {
- if (achievIdByArenaSlot[j] == achievement->ID)
- {
- Battleground* bg = GetPlayer()->GetBattleground();
- if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
- notfit = true;
-
- break;
- }
- }
- if (notfit)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : sMapMgr->FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId());
- if (!map || !map->IsDungeon())
- continue;
-
- // search case
- bool found = false;
- for (int j = 0; achievIdForDungeon[j][0]; ++j)
- {
- if (achievIdForDungeon[j][0] == achievement->ID)
- {
- if (map->IsRaid())
- {
- // if raid accepted (ignore difficulty)
- if (!achievIdForDungeon[j][2])
- break; // for
- }
- else if (GetPlayer()->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL)
- {
- // dungeon in normal mode accepted
- if (!achievIdForDungeon[j][1])
- break; // for
- }
- else
- {
- // dungeon in heroic mode accepted
- if (!achievIdForDungeon[j][3])
- break; // for
- }
-
- found = true;
- break; // for
- }
- }
- if (!found)
- continue;
-
- //FIXME: work only for instances where max == min for players
- if (((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
-
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->killed_by_creature.creatureEntry)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // if team check required: must kill by opposition faction
- if (achievement->ID == 318 && miscValue2 == GetPlayer()->GetTeam())
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- // miscvalue1 is the ingame fallheight*100 as stored in dbc
- SetCriteriaProgress(achievementCriteria, miscValue1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->death_from.type)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ // miscValue1 is the ingame fallheight*100 as stored in dbc
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- // if miscvalues != 0, it contains the questID.
- if (miscValue1)
- {
- if (miscValue1 != achievementCriteria->complete_quest.questID)
- continue;
- }
- else
- {
- // login case.
- if (!GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
- continue;
- }
-
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
- continue;
-
- if (GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- {
- // miscvalue1=loot_type (note: 0 = LOOT_CORPSE and then it ignored)
- // miscvalue2=count of item loot
- if (!miscValue1 || !miscValue2)
- continue;
- if (miscValue1 != achievementCriteria->loot_type.lootType)
- continue;
-
- // zone specific
- if (achievementCriteria->loot_type.lootTypeCount == 1)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- // speedup for non-login case
- if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- if (!miscValue1) // no update at login
- continue;
-
- // additional requirements
- if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit, miscValue1))
- {
- // reset the progress as we have a win without the requirement.
- SetCriteriaProgress(achievementCriteria, 0);
- continue;
- }
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->use_item.itemID != miscValue1)
- continue;
-
- // Children's Week achievements have extra requirements
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- // You _have_ to loot that item, just owning it when logging in does _not_ count!
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->own_item.itemID)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- {
- WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
- if (!worldOverlayEntry)
- break;
-
- bool matchFound = false;
- for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
- {
- uint32 area_id = worldOverlayEntry->areatableID[j];
- if (!area_id) // array have 0 only in empty tail
- break;
-
- int32 exploreFlag = GetAreaFlagByAreaID(area_id);
- if (exploreFlag < 0)
- continue;
-
- uint32 playerIndexOffset = uint32(exploreFlag) / 32;
- uint32 mask = 1<< (uint32(exploreFlag) % 32);
-
- if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
- {
- matchFound = true;
- break;
- }
- }
-
- if (matchFound)
- SetCriteriaProgress(achievementCriteria, 1);
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetBankBagSlotCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
{
- // skip faction check only at loading
- if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
- continue;
-
- int32 reputation = GetPlayer()->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID);
+ int32 reputation = referencePlayer->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID);
if (reputation > 0)
- SetCriteriaProgress(achievementCriteria, reputation);
+ SetCriteriaProgress(achievementCriteria, reputation, referencePlayer);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- {
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetExaltedFactionCount());
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- {
- // skip for login case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- {
- // miscvalue1 = itemid
- // miscvalue2 = itemSlot
- if (!miscValue1)
- continue;
-
- if (miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
- continue;
-
- // check item level and quality via achievement_criteria_data
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), 0, miscValue1))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
-
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- {
- // miscvalue1 = itemid
- // miscvalue2 = diced value
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
- continue;
-
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!pProto)
- continue;
-
- // check item level via achievement_criteria_data
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), 0, pProto->ItemLevel))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- {
- // miscvalue1 = emote
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->do_emote.emoteID)
- continue;
- if (achievementCriteria->do_emote.count)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- {
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
- {
- if (GetPlayer()->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
- continue;
-
- // map specific case (BG in fact) expected player targeted damage/heal
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- // miscvalue1 = item_id
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->equip_item.itemID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- // miscvalue1 = go entry
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->use_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
- continue;
-
uint32 spellCount = 0;
- for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
- spellIter != GetPlayer()->GetSpellMap().end();
+ for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
+ spellIter != referencePlayer->GetSpellMap().end();
++spellIter)
{
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
@@ -1405,56 +1307,23 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
spellCount++;
}
}
- SetCriteriaProgress(achievementCriteria, spellCount);
+ SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->win_duel.duelCount)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetHonoredFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
- continue;
-
uint32 spellCount = 0;
- for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
- spellIter != GetPlayer()->GetSpellMap().end();
+ for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
+ spellIter != referencePlayer->GetSpellMap().end();
++spellIter)
{
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
@@ -1462,78 +1331,21 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (skillIter->second->skillId == achievementCriteria->learn_skill_line.skillLine)
spellCount++;
}
- SetCriteriaProgress(achievementCriteria, spellCount);
+ SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetMoney(), PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
break;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- {
if (!miscValue1)
- {
- uint32 points = 0;
- for (CompletedAchievementMap::iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
- if (AchievementEntry const* pAchievement = sAchievementMgr->GetAchievement(itr->first))
- points += pAchievement->points;
- SetCriteriaProgress(achievementCriteria, points, PROGRESS_SET);
- }
+ SetCriteriaProgress(achievementCriteria, _achievementPoints, referencePlayer, PROGRESS_SET);
else
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- {
- // skip login update
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
{
uint32 reqTeamType = achievementCriteria->highest_team_rating.teamtype;
@@ -1543,13 +1355,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (miscValue2 != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
- uint32 teamId = GetPlayer()->GetArenaTeamId(arena_slot);
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
if (!teamId)
continue;
@@ -1557,7 +1369,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!team || team->GetType() != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, team->GetStats().Rating, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, team->GetStats().Rating, referencePlayer, PROGRESS_HIGHEST);
break;
}
}
@@ -1573,13 +1385,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (miscValue2 != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
- uint32 teamId = GetPlayer()->GetArenaTeamId(arena_slot);
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
if (!teamId)
continue;
@@ -1587,9 +1399,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!team || team->GetType() != reqTeamType)
continue;
- if (ArenaTeamMember const* member = team->GetMember(GetPlayer()->GetGUID()))
+ if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
{
- SetCriteriaProgress(achievementCriteria, member->PersonalRating, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
break;
}
}
@@ -1597,20 +1409,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
- {
- // Check map id requirement
- if (miscValue1 == achievementCriteria->win_arena.mapID)
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- // std case: not exist in DBC, not triggered in code as result
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
break;
// FIXME: not triggered in code as result, need to implement
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
@@ -1618,26 +1418,41 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
break; // Not implemented yet :(
}
if (IsCompletedCriteria(achievementCriteria, achievement))
- CompletedCriteriaFor(achievement);
+ CompletedCriteriaFor(achievement, referencePlayer);
// check again the completeness for SUMM and REQ COUNT achievements,
// as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
if (IsCompletedAchievement(achievement))
- CompletedAchievement(achievement);
+ CompletedAchievement(achievement, referencePlayer);
if (AchievementEntryList const* achRefList = sAchievementMgr->GetAchievementByReferencedId(achievement->ID))
for (AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr)
if (IsCompletedAchievement(*itr))
- CompletedAchievement(*itr);
+ CompletedAchievement(*itr, referencePlayer);
}
}
-bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement)
+template<class T>
+bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement)
{
if (!achievement)
return false;
@@ -1657,13 +1472,14 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
if (!progress)
return false;
- switch (achievementCriteria->requiredType)
+ switch (AchievementCriteriaTypes(achievementCriteria->type))
{
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
return progress->counter >= achievementCriteria->win_bg.winCount;
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
return progress->counter >= achievementCriteria->reach_level.level;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
@@ -1758,6 +1574,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->use_lfg.dungeonsComplete;
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
return progress->counter >= achievementCriteria->get_killing_blow.killCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ return progress->counter >= achievementCriteria->currencyGain.count;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count;
// handle all statistic-only criteria here
@@ -1788,19 +1606,18 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
default:
break;
}
+
return false;
}
-void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement)
+template<class T>
+void AchievementMgr<T>::CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer)
{
// counter can never complete
if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
@@ -1811,26 +1628,27 @@ void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement)
return;
if (IsCompletedAchievement(achievement))
- CompletedAchievement(achievement);
+ CompletedAchievement(achievement, referencePlayer);
}
-bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
+template<class T>
+bool AchievementMgr<T>::IsCompletedAchievement(AchievementEntry const* entry)
{
// counter can never complete
if (entry->flags & ACHIEVEMENT_FLAG_COUNTER)
return false;
// for achievement with referenced achievement criterias get from referenced and counter from self
- uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
- uint32 achievmentForTestCount = entry->count;
+ uint32 achievementForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
+ uint32 achievementForTestCount = entry->count;
- AchievementCriteriaEntryList const* cList = sAchievementMgr->GetAchievementCriteriaByAchievement(achievmentForTestId);
+ AchievementCriteriaEntryList const* cList = sAchievementMgr->GetAchievementCriteriaByAchievement(achievementForTestId);
if (!cList)
return false;
- uint32 count = 0;
+ uint64 count = 0;
// For SUMM achievements, we have to count the progress of each criteria of the achievement.
- // Oddly, the target count is NOT countained in the achievement, but in each individual criteria
+ // Oddly, the target count is NOT contained in the achievement, but in each individual criteria
if (entry->flags & ACHIEVEMENT_FLAG_SUMM)
{
for (AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
@@ -1865,18 +1683,19 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
completed_all = false;
// completed as have req. count of completed criterias
- if (achievmentForTestCount > 0 && achievmentForTestCount <= count)
+ if (achievementForTestCount > 0 && achievementForTestCount <= count)
return true;
}
// all criterias completed requirement
- if (completed_all && achievmentForTestCount == 0)
+ if (completed_all && achievementForTestCount == 0)
return true;
return false;
}
-CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry const* entry)
+template<class T>
+CriteriaProgress* AchievementMgr<T>::GetCriteriaProgress(AchievementCriteriaEntry const* entry)
{
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
@@ -1886,14 +1705,16 @@ CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry c
return &(iter->second);
}
-void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype)
+template<class T>
+void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype)
{
// Don't allow to cheat - doing timed achievements without timer active
TimedAchievementMap::iterator timedIter = m_timedAchievements.find(entry->ID);
if (entry->timeLimit && timedIter == m_timedAchievements.end())
return;
- TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue, m_player->GetGUIDLow());
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "SetCriteriaProgress(%u, " UI64FMTD ") for (%s GUID: %u)",
+ entry->ID, changeValue, GetLogNameForGuid(GetOwner()->GetGUID()), GUID_LOPART(GetOwner()->GetGUID()));
CriteriaProgress* progress = GetCriteriaProgress(entry);
if (!progress)
@@ -1908,7 +1729,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
}
else
{
- uint32 newValue = 0;
+ uint64 newValue = 0;
switch (ptype)
{
case PROGRESS_SET:
@@ -1917,7 +1738,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
case PROGRESS_ACCUMULATE:
{
// avoid overflow
- uint32 max_value = std::numeric_limits<uint32>::max();
+ uint64 max_value = std::numeric_limits<uint64>::max();
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break;
}
@@ -1936,41 +1757,28 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
progress->changed = true;
progress->date = time(NULL); // set the date to the latest update.
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(entry->achievement);
uint32 timeElapsed = 0;
- bool timedCompleted = false;
+ bool criteriaComplete = IsCompletedCriteria(entry, achievement);
if (entry->timeLimit)
{
- // has to exist else we wouldn't be here
- timedCompleted = IsCompletedCriteria(entry, sAchievementMgr->GetAchievement(entry->referredAchievement));
// Client expects this in packet
timeElapsed = entry->timeLimit - (timedIter->second/IN_MILLISECONDS);
// Remove the timer, we wont need it anymore
- if (timedCompleted)
+ if (criteriaComplete)
m_timedAchievements.erase(timedIter);
}
- SendCriteriaUpdate(entry, progress, timeElapsed, timedCompleted);
-}
+ if (criteriaComplete && achievement->flags & ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS && !progress->CompletedGUID)
+ progress->CompletedGUID = referencePlayer->GetGUID();
-void AchievementMgr::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
-{
- if (!entry)
- return;
-
- CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
- if (criteriaProgress == m_criteriaProgress.end())
- return;
-
- WorldPacket data(SMSG_CRITERIA_DELETED, 4);
- data << uint32(entry->ID);
- m_player->SendDirectMessage(&data);
-
- m_criteriaProgress.erase(criteriaProgress);
+ SendCriteriaUpdate(entry, progress, timeElapsed, criteriaComplete);
}
-void AchievementMgr::UpdateTimedAchievements(uint32 timeDiff)
+template<class T>
+void AchievementMgr<T>::UpdateTimedAchievements(uint32 timeDiff)
{
if (!m_timedAchievements.empty())
{
@@ -1992,15 +1800,21 @@ void AchievementMgr::UpdateTimedAchievements(uint32 timeDiff)
}
}
-void AchievementMgr::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /*= 0*/)
+template<class T>
+void AchievementMgr<T>::StartTimedAchievement(AchievementCriteriaTimedTypes /*type*/, uint32 /*entry*/, uint32 /*timeLost = 0*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /* = 0 */)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
- if ((*i)->timerStartEvent != entry)
+ if ((*i)->timedCriteriaMiscId != entry)
continue;
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement((*i)->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement((*i)->achievement);
if (m_timedAchievements.find((*i)->ID) == m_timedAchievements.end() && !IsCompletedCriteria(*i, achievement))
{
// Start the timer
@@ -2009,18 +1823,19 @@ void AchievementMgr::StartTimedAchievement(AchievementCriteriaTimedTypes type, u
m_timedAchievements[(*i)->ID] = (*i)->timeLimit * IN_MILLISECONDS - timeLost;
// and at client too
- SetCriteriaProgress(*i, 0, PROGRESS_SET);
+ SetCriteriaProgress(*i, 0, GetOwner(), PROGRESS_SET);
}
}
}
}
-void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+template<class T>
+void AchievementMgr<T>::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
- for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
+ for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
- if ((*i)->timerStartEvent != entry)
+ if ((*i)->timedCriteriaMiscId != entry)
continue;
TimedAchievementMap::iterator timedIter = m_timedAchievements.find((*i)->ID);
@@ -2036,19 +1851,26 @@ void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type,
}
}
-void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
+template<>
+void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
// disable for gamemasters with GM-mode enabled
- if (m_player->isGameMaster())
+ if (GetOwner()->isGameMaster())
return;
if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
return;
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
+ if (Guild* guild = referencePlayer->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_PLAYER_ACHIEVEMENT, referencePlayer->GetGUID(), achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
+
+ if (!GetOwner()->GetSession()->PlayerLoading())
+ SendAchievementEarned(achievement);
+
TC_LOG_INFO(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::CompletedAchievement(%u). Player: %s (%u)",
- achievement->ID, m_player->GetName().c_str(), m_player->GetGUIDLow());
+ achievement->ID, GetOwner()->GetName().c_str(), GetOwner()->GetGUIDLow());
- SendAchievementEarned(achievement);
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
ca.date = time(NULL);
ca.changed = true;
@@ -2058,8 +1880,10 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
if (!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
sAchievementMgr->SetRealmCompleted(achievement);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points);
+ _achievementPoints += achievement->points;
+
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer);
// reward items and titles if any
AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement);
@@ -2073,16 +1897,16 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
- if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->getGender() : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
+ if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetOwner()->getGender() : (GetOwner()->GetTeam() == ALLIANCE ? 0 : 1)])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetPlayer()->SetTitle(titleEntry);
+ GetOwner()->SetTitle(titleEntry);
// mail
if (reward->sender)
{
- Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
+ Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetOwner()) : NULL;
- int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
+ int loc_idx = GetOwner()->GetSession()->GetSessionDbLocaleIndex();
// subject and text
std::string subject = reward->subject;
@@ -2108,74 +1932,391 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
draft.AddItem(item);
}
- draft.SendMailTo(trans, GetPlayer(), MailSender(MAIL_CREATURE, reward->sender));
+ draft.SendMailTo(trans, GetOwner(), MailSender(MAIL_CREATURE, reward->sender));
CharacterDatabase.CommitTransaction(trans);
}
}
-void AchievementMgr::SendAllAchievementData() const
+template<>
+void AchievementMgr<Guild>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
- WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, m_completedAchievements.size()*8+4+m_criteriaProgress.size()*38+4);
- BuildAllDataPacket(&data);
- GetPlayer()->GetSession()->SendPacket(&data);
+ TC_LOG_DEBUG(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr<Guild>::CompletedAchievement(%u)", achievement->ID);
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
+ return;
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
+ if (Guild* guild = referencePlayer->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_GUILD_ACHIEVEMENT, 0, achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
+
+ SendAchievementEarned(achievement);
+ CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
+ ca.date = time(NULL);
+ ca.changed = true;
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS)
+ {
+ if (referencePlayer->GetGuildId() == GetOwner()->GetId())
+ ca.guids.insert(referencePlayer->GetGUID());
+
+ if (Group const* group = referencePlayer->GetGroup())
+ for (GroupReference const* ref = group->GetFirstMember(); ref != NULL; ref = ref->next())
+ if (Player const* groupMember = ref->getSource())
+ if (groupMember->GetGuildId() == GetOwner()->GetId())
+ ca.guids.insert(groupMember->GetGUID());
+ }
+
+ sAchievementMgr->SetRealmCompleted(achievement);
+
+ _achievementPoints += achievement->points;
+
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer);
}
-void AchievementMgr::SendRespondInspectAchievements(Player* player) const
+struct VisibleAchievementPred
{
- WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 9+m_completedAchievements.size()*8+4+m_criteriaProgress.size()*38+4);
- data.append(GetPlayer()->GetPackGUID());
- BuildAllDataPacket(&data);
- player->GetSession()->SendPacket(&data);
+ bool operator()(CompletedAchievementMap::value_type const& val)
+ {
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(val.first);
+ return achievement && !(achievement->flags & ACHIEVEMENT_FLAG_HIDDEN);
+ }
+};
+
+template<class T>
+void AchievementMgr<T>::SendAllAchievementData(Player* /*receiver*/) const
+{
+ VisibleAchievementPred isVisible;
+ size_t numCriteria = m_criteriaProgress.size();
+ size_t numAchievements = std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible);
+ ByteBuffer criteriaData(numCriteria * (4 + 4 + 4 + 4 + 8 + 8));
+ ObjectGuid guid = GetOwner()->GetGUID();
+ ObjectGuid counter;
+
+ WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4 + numAchievements * (4 + 4) + 4 + numCriteria * (4 + 4 + 4 + 4 + 8 + 8));
+ data.WriteBits(numCriteria, 21);
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ {
+ counter = uint64(itr->second.counter);
+
+ data.WriteBit(guid[4]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(counter[0]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[4]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[7]);
+ data.WriteBit(guid[7]);
+ data.WriteBits(0u, 2);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(counter[5]);
+ data.WriteBit(guid[1]);
+
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData.WriteByteSeq(counter[2]);
+ criteriaData << uint32(0); // timer 2
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData << uint32(itr->first); // criteria id
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData.WriteByteSeq(guid[0]);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData << uint32(0); // timer 1
+ criteriaData.AppendPackedTime(itr->second.date); // criteria date
+ criteriaData.WriteByteSeq(guid[1]);
+ }
+
+ data.WriteBits(numAchievements, 23);
+ data.FlushBits();
+ data.append(criteriaData);
+
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!isVisible(*itr))
+ continue;
+
+ data << uint32(itr->first);
+ data.AppendPackedTime(itr->second.date);
+ }
+
+ SendPacket(&data);
}
-/**
- * used by SMSG_RESPOND_INSPECT_ACHIEVEMENT and SMSG_ALL_ACHIEVEMENT_DATA
- */
-void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
+template<>
+void AchievementMgr<Guild>::SendAllAchievementData(Player* receiver) const
{
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ VisibleAchievementPred isVisible;
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DATA, m_completedAchievements.size() * (4 + 4) + 3);
+ data.WriteBits(std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible), 23);
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
{
- // Skip hidden achievements
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(iter->first);
- if (!achievement || achievement->flags & ACHIEVEMENT_FLAG_HIDDEN)
+ if (!isVisible(*itr))
continue;
- *data << uint32(iter->first);
- data->AppendPackedTime(iter->second.date);
+ data.AppendPackedTime(itr->second.date);
+ data << uint32(itr->first);
}
- *data << int32(-1);
- for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
+ receiver->GetSession()->SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Player>::SendAchievementInfo(Player* receiver, uint32 /*achievementId = 0 */) const
+{
+ ObjectGuid guid = GetOwner()->GetGUID();
+ ObjectGuid counter;
+
+ VisibleAchievementPred isVisible;
+ size_t numCriteria = m_criteriaProgress.size();
+ size_t numAchievements = std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible);
+ ByteBuffer criteriaData(numCriteria * (0));
+
+ WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 1 + 8 + 3 + 3 + numAchievements * (4 + 4) + numCriteria * (0));
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBits(numAchievements, 23);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBits(numCriteria, 21);
+ data.WriteBit(guid[2]);
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
{
- *data << uint32(iter->first);
- data->appendPackGUID(iter->second.counter);
- data->append(GetPlayer()->GetPackGUID());
- *data << uint32(0);
- data->AppendPackedTime(iter->second.date);
- *data << uint32(0);
- *data << uint32(0);
+ counter = itr->second.counter;
+
+ data.WriteBit(counter[5]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[4]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBits(0, 2); // criteria progress flags
+ data.WriteBit(counter[0]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[7]);
+
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData << uint32(0); // timer 1
+ criteriaData.WriteByteSeq(guid[1]);
+ criteriaData.AppendPackedTime(itr->second.date);
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData << uint32(itr->first);
+ criteriaData << uint32(0); // timer 2
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData.WriteByteSeq(guid[0]);
+ criteriaData.WriteByteSeq(counter[2]);
+ }
+
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.FlushBits();
+ data.append(criteriaData);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[2]);
+
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!isVisible(*itr))
+ continue;
+
+ data << uint32(itr->first);
+ data.AppendPackedTime(itr->second.date);
+ }
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+
+ receiver->GetSession()->SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Guild>::SendAchievementInfo(Player* receiver, uint32 achievementId /*= 0*/) const
+{
+ //will send response to criteria progress request
+ AchievementCriteriaEntryList const* criteria = sAchievementMgr->GetAchievementCriteriaByAchievement(achievementId);
+ if (!criteria)
+ {
+ // send empty packet
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, 3);
+ data.WriteBits(0, 21);
+ receiver->GetSession()->SendPacket(&data);
+ return;
+ }
+
+ ObjectGuid counter;
+ ObjectGuid guid;
+ uint32 numCriteria = 0;
+ ByteBuffer criteriaData(criteria->size() * (8 + 8 + 4 + 4 + 4));
+ ByteBuffer criteriaBits(criteria->size() * (8 + 8) / 8);
+ for (AchievementCriteriaEntryList::const_iterator itr = criteria->begin(); itr != criteria->end(); ++itr)
+ {
+ uint32 criteriaId = (*itr)->ID;
+ CriteriaProgressMap::const_iterator progress = m_criteriaProgress.find(criteriaId);
+ if (progress == m_criteriaProgress.end())
+ continue;
+
+ ++numCriteria;
+ }
+
+ criteriaBits.WriteBits(numCriteria, 21);
+
+ for (AchievementCriteriaEntryList::const_iterator itr = criteria->begin(); itr != criteria->end(); ++itr)
+ {
+ uint32 criteriaId = (*itr)->ID;
+ CriteriaProgressMap::const_iterator progress = m_criteriaProgress.find(criteriaId);
+ if (progress == m_criteriaProgress.end())
+ continue;
+
+ counter = progress->second.counter;
+ guid = progress->second.CompletedGUID;
+
+ criteriaBits.WriteBit(counter[4]);
+ criteriaBits.WriteBit(counter[1]);
+ criteriaBits.WriteBit(guid[2]);
+ criteriaBits.WriteBit(counter[3]);
+ criteriaBits.WriteBit(guid[1]);
+ criteriaBits.WriteBit(counter[5]);
+ criteriaBits.WriteBit(counter[0]);
+ criteriaBits.WriteBit(guid[3]);
+ criteriaBits.WriteBit(counter[2]);
+ criteriaBits.WriteBit(guid[7]);
+ criteriaBits.WriteBit(guid[5]);
+ criteriaBits.WriteBit(guid[0]);
+ criteriaBits.WriteBit(counter[6]);
+ criteriaBits.WriteBit(guid[6]);
+ criteriaBits.WriteBit(counter[7]);
+ criteriaBits.WriteBit(guid[4]);
+
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData << uint32(progress->second.date); // unknown date
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData << uint32(progress->second.date); // unknown date
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[1]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData << uint32(progress->second.date); // last update time (not packed!)
+ criteriaData << uint32(criteriaId);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData << uint32(0);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[2]);
+ criteriaData.WriteByteSeq(guid[0]);
}
- *data << int32(-1);
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, criteriaBits.size() + criteriaData.size());
+ data.append(criteriaBits);
+ if (numCriteria)
+ data.append(criteriaData);
+
+ receiver->GetSession()->SendPacket(&data);
}
-bool AchievementMgr::HasAchieved(uint32 achievementId) const
+template<class T>
+bool AchievementMgr<T>::HasAchieved(uint32 achievementId) const
{
return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
}
-bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
+template<class T>
+bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer)
{
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Disabled",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
- if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID))
+ if (achievement->mapID != -1 && referencePlayer->GetMapId() != uint32(achievement->mapID))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Wrong map",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
- if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && GetPlayer()->GetTeam() != HORDE) ||
- (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE))
+ if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
+ (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Wrong faction",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
+ if (IsCompletedCriteria(criteria, achievement))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Is Completed",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Requirements not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if (!AdditionalRequirementsSatisfied(criteria, miscValue1, miscValue2, unit, referencePlayer))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Additional requirements not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if (!ConditionsSatisfied(criteria, referencePlayer))
+ {
+ TC_LOG_TRACE(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Conditions not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ return true;
+}
+
+template<class T>
+bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const
+{
for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i)
{
if (!criteria->additionalRequirements[i].additionalRequirement_type)
@@ -2184,11 +2325,11 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
switch (criteria->additionalRequirements[i].additionalRequirement_type)
{
case ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP:
- if (GetPlayer()->GetMapId() != criteria->additionalRequirements[i].additionalRequirement_value)
+ if (referencePlayer->GetMapId() != criteria->additionalRequirements[i].additionalRequirement_value)
return false;
break;
case ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP:
- if (GetPlayer()->GetGroup())
+ if (referencePlayer->GetGroup())
return false;
break;
default:
@@ -2196,13 +2337,746 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
}
}
- // don't update already completed criteria
- if (IsCompletedCriteria(criteria, achievement))
- return false;
+ return true;
+}
+
+template<class T>
+bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* achievementCriteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const
+{
+ switch (AchievementCriteriaTypes(achievementCriteria->type))
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ if (!miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ if (m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) == m_completedAchievements.end())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ if (!miscValue1 || achievementCriteria->win_bg.bgMapID != referencePlayer->GetMapId())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ if (!miscValue1 || achievementCriteria->kill_creature.creatureID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ // update at loading or specific skill update
+ if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ // update at loading or specific skill update
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ if (!miscValue1 || referencePlayer->GetMapId() != achievementCriteria->complete_battleground.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ if (!miscValue1 || referencePlayer->GetMapId() != achievementCriteria->death_at_map.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ {
+ if (!miscValue1)
+ return false;
+ // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
+ bool notfit = false;
+ for (int j = 0; j < MAX_ARENA_SLOT; ++j)
+ {
+ if (achievIdByArenaSlot[j] == achievementCriteria->achievement)
+ {
+ Battleground* bg = referencePlayer->GetBattleground();
+ if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
+ notfit = true;
+ break;
+ }
+ }
+ if (notfit)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ {
+ if (!miscValue1)
+ return false;
+
+ Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
+ if (!map || !map->IsDungeon())
+ return false;
+
+ // search case
+ bool found = false;
+ for (int j = 0; achievIdForDungeon[j][0]; ++j)
+ {
+ if (achievIdForDungeon[j][0] == achievementCriteria->achievement)
+ {
+ if (map->IsRaid())
+ {
+ // if raid accepted (ignore difficulty)
+ if (!achievIdForDungeon[j][2])
+ break; // for
+ }
+ else if (referencePlayer->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL)
+ {
+ // dungeon in normal mode accepted
+ if (!achievIdForDungeon[j][1])
+ break; // for
+ }
+ else
+ {
+ // dungeon in heroic mode accepted
+ if (!achievIdForDungeon[j][3])
+ break; // for
+ }
+
+ found = true;
+ break; // for
+ }
+ }
+ if (!found)
+ return false;
+
+ //FIXME: work only for instances where max == min for players
+ if (((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->killed_by_creature.creatureEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ if (!miscValue1 || !unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ if (!miscValue1 || miscValue2 != achievementCriteria->death_from.type)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ {
+ // if miscValues != 0, it contains the questID.
+ if (miscValue1)
+ {
+ if (miscValue1 != achievementCriteria->complete_quest.questID)
+ return false;
+ }
+ else
+ {
+ // login case.
+ if (!referencePlayer->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
+ return false;
+ }
+
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(referencePlayer, unit))
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
+ return false;
+
+ if (!referencePlayer->HasSpell(achievementCriteria->learn_spell.spellID))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ // miscValue1 = itemId - miscValue2 = count of item loot
+ // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
+ if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != achievementCriteria->loot_type.lootType)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ if (!miscValue1 || achievementCriteria->use_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ if (!miscValue1 || miscValue1 != achievementCriteria->own_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
+ if (!worldOverlayEntry)
+ break;
+
+ bool matchFound = false;
+ for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
+ {
+ uint32 area_id = worldOverlayEntry->areatableID[j];
+ if (!area_id) // array have 0 only in empty tail
+ break;
+
+ int32 exploreFlag = GetAreaFlagByAreaID(area_id);
+ if (exploreFlag < 0)
+ continue;
+
+ uint32 playerIndexOffset = uint32(exploreFlag) / 32;
+ uint32 mask = 1 << (uint32(exploreFlag) % 32);
+
+ if (referencePlayer->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
+ {
+ matchFound = true;
+ break;
+ }
+ }
+
+ if (!matchFound)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ // miscValue1 = itemid miscValue2 = itemSlot
+ if (!miscValue1 || miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ {
+ // miscValue1 = itemid miscValue2 = diced value
+ if (!miscValue1 || miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
+ return false;
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->do_emote.emoteID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ if (!miscValue1)
+ return false;
+
+ if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
+ {
+ if (referencePlayer->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
+ return false;
+
+ // map specific case (BG in fact) expected player targeted damage/heal
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ }
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ // miscValue1 = item_id
+ if (!miscValue1 || miscValue1 != achievementCriteria->equip_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ if (!miscValue1 || miscValue1 != achievementCriteria->use_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ if (!miscValue1 || miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ {
+ if (!miscValue1)
+ return false;
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
+ || miscValue1 != achievementCriteria->currencyGain.currency)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ if (miscValue1 != achievementCriteria->win_arena.mapID)
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+template<class T>
+bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 /*miscValue2*/, Unit const* unit, Player* referencePlayer) const
+{
+ for (uint8 i = 0; i < MAX_ADDITIONAL_CRITERIA_CONDITIONS; ++i)
+ {
+ uint32 reqType = criteria->additionalConditionType[i];
+
+ ///@TODO Extract additionalConditionValue[2] column from an older dbc and store it in database
+ /// This column is not present in 4.3.4 Achievement_Criteria.dbc
+ /// so for now, just return as failed condition to prevent invalid memory access
+ if (i == 2 && reqType)
+ return false;
+
+ uint32 reqValue = criteria->additionalConditionValue[i];
+
+ switch (AchievementCriteriaAdditionalCondition(reqType))
+ {
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: // 4
+ if (!unit || unit->GetEntry() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: // 5
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: // 6
+ if (!unit || unit->isAlive())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7
+ if (!unit || !referencePlayer->IsHostileTo(unit))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8
+ if (!referencePlayer->HasAura(reqValue))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10
+ if (!unit || !unit->HasAura(reqValue))
+ return false;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11
+ if (!unit || !unit->HasAuraType(AuraType(reqValue)))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->Quality < reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: // 15
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->Quality != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17
+ {
+ uint32 zoneId, areaId;
+ referencePlayer->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18
+ {
+ if (!unit)
+ return false;
+ uint32 zoneId, areaId;
+ unit->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20
+ if (uint32(referencePlayer->GetMap()->GetDifficulty()) != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25
+ if (referencePlayer->getRace() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: // 26
+ if (referencePlayer->getClass() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: // 27
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getRace() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: // 28
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getClass() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: // 29
+ if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: // 30
+ {
+ if (!unit)
+ return false;
+ Creature const* const creature = unit->ToCreature();
+ if (!creature || creature->GetCreatureType() != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32
+ if (referencePlayer->GetMapId() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38
+ // miscValue1 is title's bit index
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: // 39
+ if (referencePlayer->getLevel() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: // 40
+ if (!unit || unit->getLevel() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 41
+ if (!unit || unit->GetZoneId() != reqValue)
+ return false;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: // 46
+ if (!unit || unit->GetHealthPct() >= reqValue)
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
return true;
}
+char const* AchievementGlobalMgr::GetCriteriaTypeString(uint32 type)
+{
+ return GetCriteriaTypeString(AchievementCriteriaTypes(type));
+}
+
+char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes type)
+{
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ return "KILL_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ return "TYPE_WIN_BG";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ return "COMPLETE_RESEARCH";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ return "REACH_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ return "REACH_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ return "COMPLETE_ACHIEVEMENT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ return "COMPLETE_QUEST_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ return "COMPLETE_DAILY_QUEST_DAILY";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ return "COMPLETE_QUESTS_IN_ZONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ return "CURRENCY";
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ return "DAMAGE_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ return "COMPLETE_DAILY_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ return "COMPLETE_BATTLEGROUND";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ return "DEATH_AT_MAP";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ return "DEATH";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ return "DEATH_IN_DUNGEON";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
+ return "COMPLETE_RAID";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ return "KILLED_BY_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ return "KILLED_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ return "FALL_WITHOUT_DYING";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ return "DEATHS_FROM";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ return "COMPLETE_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ return "BE_SPELL_TARGET";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ return "CAST_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ return "BG_OBJECTIVE_CAPTURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ return "HONORABLE_KILL_AT_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ return "WIN_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
+ return "PLAY_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ return "LEARN_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ return "HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ return "OWN_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ return "WIN_RATED_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ return "HIGHEST_TEAM_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ return "HIGHEST_PERSONAL_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ return "LEARN_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ return "USE_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ return "LOOT_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ return "EXPLORE_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
+ return "OWN_RANK";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ return "BUY_BANK_SLOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ return "GAIN_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ return "GAIN_EXALTED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ return "VISIT_BARBER_SHOP";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ return "EQUIP_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ return "ROLL_NEED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ return "GREED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ return "HK_CLASS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ return "HK_RACE";
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ return "DO_EMOTE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ return "HEALING_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ return "GET_KILLING_BLOWS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ return "EQUIP_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ return "MONEY_FROM_VENDORS";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ return "GOLD_SPENT_FOR_TALENTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ return "NUMBER_OF_TALENT_RESETS";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ return "MONEY_FROM_QUEST_REWARD";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ return "GOLD_SPENT_FOR_TRAVELLING";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ return "GOLD_SPENT_AT_BARBER";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ return "GOLD_SPENT_FOR_MAIL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ return "LOOT_MONEY";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ return "USE_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ return "BE_SPELL_TARGET2";
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ return "SPECIAL_PVP_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ return "FISH_IN_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
+ return "EARNED_PVP_TITLE";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ return "LEARN_SKILLLINE_SPELLS";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ return "WIN_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ return "LOSE_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ return "KILL_CREATURE_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ return "GOLD_EARNED_BY_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ return "CREATE_AUCTION";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ return "HIGHEST_AUCTION_BID";
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ return "WON_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ return "HIGHEST_AUCTION_SOLD";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ return "HIGHEST_GOLD_VALUE_OWNED";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ return "GAIN_REVERED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ return "GAIN_HONORED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ return "KNOWN_FACTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ return "LOOT_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ return "RECEIVE_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ return "ROLL_NEED";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ return "ROLL_GREED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ return "HIT_DEALT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ return "HIT_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ return "TOTAL_DAMAGE_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED:
+ return "HIGHEST_HEAL_CASTED";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ return "TOTAL_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ return "HIGHEST_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ return "QUEST_ABANDONED";
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ return "FLIGHT_PATHS_TAKEN";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ return "LOOT_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ return "CAST_SPELL2";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ return "LEARN_SKILL_LINE";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ return "EARN_HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ return "ACCEPTED_SUMMONINGS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ return "EARN_ACHIEVEMENT_POINTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ return "USE_LFD_TO_GROUP_WITH_PLAYERS";
+ case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ return "SPENT_GOLD_GUILD_REPAIRS";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ return "REACH_GUILD_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ return "CRAFT_ITEMS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
+ return "CATCH_FROM_POOL";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ return "BUY_GUILD_BANK_SLOTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ return "EARN_GUILD_ACHIEVEMENT_POINTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ return "WIN_RATED_BATTLEGROUND";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
+ return "REACH_BG_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
+ return "BUY_GUILD_TABARD";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ return "COMPLETE_QUESTS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ return "HONORABLE_KILLS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ return "KILL_CREATURE_TYPE_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ return "GUILD_CHALLENGE_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ return "GUILD_CHALLENGE";
+ }
+ return "MISSING_TYPE";
+}
+
+template class AchievementMgr<Guild>;
+template class AchievementMgr<Player>;
+
//==========================================================
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
@@ -2214,23 +3088,28 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
return;
}
- uint32 loaded = 0;
+ uint32 criterias = 0;
+ uint32 guildCriterias = 0;
for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId)
{
AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(entryId);
if (!criteria)
continue;
- m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
- m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->achievement);
- if (criteria->timeLimit)
- m_AchievementCriteriasByTimedType[criteria->timedType].push_back(criteria);
+ m_AchievementCriteriaListByAchievement[criteria->achievement].push_back(criteria);
+
+ if (achievement && achievement->flags & ACHIEVEMENT_FLAG_GUILD)
+ ++guildCriterias, m_GuildAchievementCriteriasByType[criteria->type].push_back(criteria);
+ else
+ ++criterias, m_AchievementCriteriasByType[criteria->type].push_back(criteria);
- ++loaded;
+ if (criteria->timeLimit)
+ m_AchievementCriteriasByTimedType[criteria->timedCriteriaStartType].push_back(criteria);
}
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u achievement criteria in %u ms", loaded, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms", criterias, guildCriterias, GetMSTimeDiffToNow(oldMSTime));
}
void AchievementGlobalMgr::LoadAchievementReferenceList()
@@ -2320,89 +3199,6 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
}
while (result->NextRow());
- // post loading checks
- for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId)
- {
- AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(entryId);
- if (!criteria)
- continue;
-
- switch (criteria->requiredType)
- {
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement);
- if (!achievement)
- continue;
-
- // exist many achievements with this criteria, use at this moment hardcoded check to skil simple case
- if (achievement->ID == 1282)
- break;
-
- continue;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: // need skip generic cases
- if (criteria->additionalRequirements[0].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases
- if (criteria->do_emote.count == 0)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics
- if (criteria->win_duel.duelCount == 0)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases
- if (criteria->loot_type.lootTypeCount != 1)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- break; // any cases
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: // any cases
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
- {
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement);
- if (!achievement)
- continue;
- if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK)
- continue;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- break;
- default: // type not use DB data, ignore
- continue;
- }
-
- if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, NULL))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` does not have expected data for criteria (Entry: %u Type: %u) for achievement %u.", criteria->ID, criteria->requiredType, criteria->referredAchievement);
- }
-
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u additional achievement criteria data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index ce6ab9cd29b..ad97af3ec6e 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -42,6 +42,7 @@ struct CriteriaProgress
{
uint32 counter;
time_t date; // latest update time.
+ uint64 CompletedGUID; // GUID of the player that completed this criteria (guild achievements)
bool changed;
};
@@ -51,15 +52,13 @@ enum AchievementCriteriaDataType
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // own_team 0 not corpse (not released body), own_team == false if enemy team expected
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8, // minvalue value provided with achievement update must be not less that limit
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9, // minlevel minlevel of target
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10, // gender 0=male; 1=female
ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11, // scripted requirement
- ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12, // difficulty normal/heroic difficulty for current event map
+ // REUSE
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13, // count "with less than %u people in the zone"
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14, // team HORDE(67), ALLIANCE(469)
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15, // drunken_state 0 (enum DrunkenState) of player
@@ -67,7 +66,6 @@ enum AchievementCriteriaDataType
ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range
ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
- ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21 // class_id race_id
};
@@ -96,11 +94,6 @@ struct AchievementCriteriaData
{
uint32 percent;
} health;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4
- struct
- {
- uint32 own_team_flag;
- } player_dead;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7
struct
@@ -108,11 +101,6 @@ struct AchievementCriteriaData
uint32 spell_id;
uint32 effect_idx;
} aura;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6
- struct
- {
- uint32 id;
- } area;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8
struct
{
@@ -129,11 +117,6 @@ struct AchievementCriteriaData
uint32 gender;
} gender;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11 (no data)
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12
- struct
- {
- uint32 difficulty;
- } difficulty;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
struct
{
@@ -167,12 +150,7 @@ struct AchievementCriteriaData
uint32 item_level;
uint32 item_quality;
} equipped_item;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20
- struct
- {
- uint32 mapId;
- } map_id;
- // ...
+ // raw
struct
{
uint32 value1;
@@ -235,6 +213,7 @@ typedef UNORDERED_MAP<uint32, AchievementRewardLocale> AchievementRewardLocales;
struct CompletedAchievementData
{
time_t date;
+ std::set<uint64> guids;
bool changed;
};
@@ -248,45 +227,53 @@ enum ProgressType
PROGRESS_HIGHEST
};
+template<class T>
class AchievementMgr
{
public:
- AchievementMgr(Player* player);
+ AchievementMgr(T* owner);
~AchievementMgr();
void Reset();
static void DeleteFromDB(uint32 lowguid);
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(SQLTransaction& trans);
- void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, bool evenIfCriteriaComplete = false);
- void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
- void CompletedAchievement(AchievementEntry const* entry);
- void CheckAllAchievementCriteria();
- void SendAllAchievementData() const;
- void SendRespondInspectAchievements(Player* player) const;
+ void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit const* unit = NULL, Player* referencePlayer = NULL);
+ void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
+ void CheckAllAchievementCriteria(Player* referencePlayer);
+ void SendAllAchievementData(Player* receiver) const;
+ void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
bool HasAchieved(uint32 achievementId) const;
- Player* GetPlayer() const { return m_player; }
+ T* GetOwner() const { return _owner; }
+
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
+ uint32 GetAchievementPoints() const { return _achievementPoints; }
private:
void SendAchievementEarned(AchievementEntry const* achievement) const;
void SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const;
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
- void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype = PROGRESS_SET);
+ void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype = PROGRESS_SET);
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
- void CompletedCriteriaFor(AchievementEntry const* achievement);
+ void CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer);
bool IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement);
bool IsCompletedAchievement(AchievementEntry const* entry);
- bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement);
- void BuildAllDataPacket(WorldPacket* data) const;
+ bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer);
+ void SendPacket(WorldPacket* data) const;
- Player* m_player;
+ bool ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const;
+ bool RequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const;
+ bool AdditionalRequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const;
+
+ T* _owner;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
typedef std::map<uint32, uint32> TimedAchievementMap;
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
+ uint32 _achievementPoints;
};
class AchievementGlobalMgr
@@ -296,9 +283,12 @@ class AchievementGlobalMgr
~AchievementGlobalMgr() {}
public:
- AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type) const
+ static char const* GetCriteriaTypeString(AchievementCriteriaTypes type);
+ static char const* GetCriteriaTypeString(uint32 type);
+
+ AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, bool guild = false) const
{
- return m_AchievementCriteriasByType[type];
+ return guild ? m_GuildAchievementCriteriasByType[type] : m_AchievementCriteriasByType[type];
}
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
@@ -346,6 +336,24 @@ class AchievementGlobalMgr
m_allCompletedAchievements.insert(achievement->ID);
}
+ bool IsGroupCriteriaType(AchievementCriteriaTypes type) const
+ {
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // NYI
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: // NYI
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND: // NYI
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
void LoadAchievementCriteriaList();
void LoadAchievementCriteriaData();
void LoadAchievementReferenceList();
@@ -359,6 +367,7 @@ class AchievementGlobalMgr
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
+ AchievementCriteriaEntryList m_GuildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 8b994545536..6186e616928 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -233,7 +233,7 @@ void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 new
}
//this function sends mail, when auction is cancelled to old bidder
-void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans)
+void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans, Item* item)
{
uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
Player* bidder = ObjectAccessor::FindPlayer(bidder_guid);
@@ -242,6 +242,9 @@ void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQ
if (!bidder)
bidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(bidder_guid);
+ if (bidder)
+ bidder->GetSession()->SendAuctionRemovedNotification(auction->Id, auction->itemEntry, item->GetItemRandomPropertyId());
+
// bidder exist
if (bidder || bidder_accId)
MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELLED_TO_BIDDER), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, auction->deposit, 0))
@@ -576,7 +579,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
if (itemRandProp)
{
- char* const* temp = itemRandProp->nameSuffix;
+ char* temp = itemRandProp->nameSuffix;
// dbc local name
if (temp)
@@ -616,7 +619,7 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const
data << uint32(Id);
data << uint32(item->GetEntry());
- for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i)
+ for (uint8 i = 0; i < PROP_ENCHANTMENT_SLOT_0; ++i) // PROP_ENCHANTMENT_SLOT_0 = 10
{
data << uint32(item->GetEnchantmentId(EnchantmentSlot(i)));
data << uint32(item->GetEnchantmentDuration(EnchantmentSlot(i)));
@@ -629,13 +632,13 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const
data << uint32(item->GetSpellCharges()); // item->charge FFFFFFF
data << uint32(0); // Unknown
data << uint64(owner); // Auction->owner
- data << uint32(startbid); // Auction->startbid (not sure if useful)
- data << uint32(bid ? GetAuctionOutBid() : 0);
+ data << uint64(startbid); // Auction->startbid (not sure if useful)
+ data << uint64(bid ? GetAuctionOutBid() : 0);
// Minimal outbid
- data << uint32(buyout); // Auction->buyout
+ data << uint64(buyout); // Auction->buyout
data << uint32((expire_time - time(NULL)) * IN_MILLISECONDS); // time left
data << uint64(bidder); // auction->bidder current
- data << uint32(bid); // current bid
+ data << uint64(bid); // current bid
return true;
}
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index 4892821cb94..5b5b172b2d4 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -165,7 +165,7 @@ class AuctionHouseMgr
void SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionExpiredMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans);
- void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans);
+ void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans, Item* item);
static uint32 GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count);
static AuctionHouseEntry const* GetAuctionHouseEntry(uint32 factionTemplateId);
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index 9f04f0e3d3f..cd1bade2bd9 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -38,6 +38,7 @@ Battlefield::Battlefield()
m_isActive = false;
m_DefenderTeam = TEAM_NEUTRAL;
+ m_Guid = 0;
m_TypeId = 0;
m_BattleId = 0;
m_ZoneId = 0;
@@ -105,7 +106,7 @@ void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone*/)
if (m_PlayersInWar[player->GetTeamId()].find(player->GetGUID()) != m_PlayersInWar[player->GetTeamId()].end())
{
m_PlayersInWar[player->GetTeamId()].erase(player->GetGUID());
- player->GetSession()->SendBfLeaveMessage(m_BattleId);
+ player->GetSession()->SendBfLeaveMessage(m_Guid);
if (Group* group = player->GetGroup()) // Remove the player from the raid group
group->RemoveMember(player->GetGUID());
@@ -209,7 +210,7 @@ void Battlefield::InvitePlayerToQueue(Player* player)
return;
if (m_PlayersInQueue[player->GetTeamId()].size() <= m_MinPlayer || m_PlayersInQueue[GetOtherTeam(player->GetTeamId())].size() >= m_MinPlayer)
- player->GetSession()->SendBfInvitePlayerToQueue(m_BattleId);
+ player->GetSession()->SendBfInvitePlayerToQueue(m_Guid);
}
void Battlefield::InvitePlayersInQueueToWar()
@@ -278,7 +279,7 @@ void Battlefield::InvitePlayerToWar(Player* player)
m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
m_InvitedPlayers[player->GetTeamId()][player->GetGUID()] = time(NULL) + m_TimeForAcceptInvite;
- player->GetSession()->SendBfInvitePlayerToWar(m_BattleId, m_ZoneId, m_TimeForAcceptInvite);
+ player->GetSession()->SendBfInvitePlayerToWar(m_Guid, m_ZoneId, m_TimeForAcceptInvite);
}
void Battlefield::InitStalker(uint32 entry, float x, float y, float z, float o)
@@ -356,6 +357,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID)
WorldPacket data;
data.Initialize(SMSG_PLAY_SOUND, 4);
data << uint32(SoundID);
+ data << uint64(0);
for (int team = 0; team < BG_TEAMS_COUNT; team++)
for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
@@ -374,7 +376,7 @@ void Battlefield::PlayerAcceptInviteToQueue(Player* player)
// Add player in queue
m_PlayersInQueue[player->GetTeamId()].insert(player->GetGUID());
// Send notification
- player->GetSession()->SendBfQueueInviteResponse(m_BattleId, m_ZoneId);
+ player->GetSession()->SendBfQueueInviteResponse(m_Guid, m_ZoneId);
}
// Called in WorldSession::HandleBfExitRequest
@@ -392,7 +394,7 @@ void Battlefield::PlayerAcceptInviteToWar(Player* player)
if (AddOrSetPlayerToCorrectBfGroup(player))
{
- player->GetSession()->SendBfEntered(m_BattleId);
+ player->GetSession()->SendBfEntered(m_Guid);
m_PlayersInWar[player->GetTeamId()].insert(player->GetGUID());
m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
@@ -457,6 +459,8 @@ WorldPacket Battlefield::BuildWarningAnnPacket(std::string const& msg)
data << uint32(msg.length() + 1);
data << msg;
data << uint8(0);
+ data << float(0);
+ data << uint8(0);
return data;
}
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 534bfd620f0..9b3542fca65 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -28,7 +28,8 @@
enum BattlefieldTypes
{
- BATTLEFIELD_WG // Wintergrasp
+ BATTLEFIELD_WG, // Wintergrasp
+ BATTLEFIELD_TB // Tol Barad (cataclysm)
};
enum BattlefieldIDs
@@ -227,6 +228,7 @@ class Battlefield : public ZoneScript
uint32 GetTypeId() { return m_TypeId; }
uint32 GetZoneId() { return m_ZoneId; }
+ uint64 GetGUID() { return m_Guid; }
void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
@@ -349,6 +351,8 @@ class Battlefield : public ZoneScript
void InitStalker(uint32 entry, float x, float y, float z, float o);
protected:
+ uint64 m_Guid;
+
uint64 StalkerGuid;
uint32 m_Timer; // Global timer for event
bool m_IsEnabled;
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index 8044cb96984..28a72152e9d 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -117,6 +117,15 @@ Battlefield *BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleid)
return NULL;
}
+Battlefield* BattlefieldMgr::GetBattlefieldByGUID(uint64 guid)
+{
+ for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
+ if ((*itr)->GetGUID() == guid)
+ return (*itr);
+
+ return NULL;
+}
+
void BattlefieldMgr::Update(uint32 diff)
{
m_UpdateTimer += diff;
diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h
index af1cea763df..20522e858ea 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.h
+++ b/src/server/game/Battlefield/BattlefieldMgr.h
@@ -47,6 +47,7 @@ class BattlefieldMgr
// return assigned battlefield
Battlefield* GetBattlefieldToZoneId(uint32 zoneid);
Battlefield* GetBattlefieldByBattleId(uint32 battleid);
+ Battlefield *GetBattlefieldByGUID(uint64 guid);
ZoneScript* GetZoneScript(uint32 zoneId);
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 0b7999fcf57..f2d96c1d1a0 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -76,7 +76,7 @@ enum WintergraspSpells
// Other spells
SPELL_WINTERGRASP_WATER = 36444,
SPELL_ESSENCE_OF_WINTERGRASP = 58045,
- SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 58730,
+ SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 91604,
// Phasing spells
SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT = 56618, // ADDS PHASE 16
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index a84e7ec30db..9639e36f204 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -41,14 +41,16 @@ ArenaTeam::ArenaTeam()
ArenaTeam::~ArenaTeam()
{ }
-bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor)
+bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& arenaTeamName,
+ uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor,
+ uint8 borderStyle, uint32 borderColor)
{
// Check if captain is present
if (!ObjectAccessor::FindPlayer(captainGuid))
return false;
// Check if arena team name is already taken
- if (sArenaTeamMgr->GetArenaTeamByName(teamName))
+ if (sArenaTeamMgr->GetArenaTeamByName(arenaTeamName))
return false;
// Generate new arena team id
@@ -57,7 +59,7 @@ bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamNa
// Assign member variables
CaptainGuid = captainGuid;
Type = type;
- TeamName = teamName;
+ TeamName = arenaTeamName;
BackgroundColor = backgroundColor;
EmblemStyle = emblemStyle;
EmblemColor = emblemColor;
@@ -82,7 +84,7 @@ bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamNa
// Add captain as member
AddMember(CaptainGuid);
- TC_LOG_INFO(LOG_FILTER_ARENAS, "New ArenaTeam created [Id: %u] [Type: %u] [Captain low GUID: %u]", GetId(), GetType(), captainLowGuid);
+ TC_LOG_DEBUG(LOG_FILTER_ARENAS, "New ArenaTeam created [Id: %u] [Type: %u] [Captain low GUID: %u]", GetId(), GetType(), captainLowGuid);
return true;
}
@@ -179,7 +181,7 @@ bool ArenaTeam::AddMember(uint64 playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
- TC_LOG_INFO(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str());
return true;
}
@@ -304,7 +306,7 @@ void ArenaTeam::SetCaptain(uint64 guid)
newCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0);
if (oldCaptain)
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].",
+ TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].",
oldCaptain->GetName().c_str(), oldCaptain->GetGUIDLow(), newCaptain->GetName().c_str(),
newCaptain->GetGUIDLow(), GetId(), GetType());
}
@@ -321,10 +323,9 @@ void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
break;
}
- // Inform player and remove arena team info from player data
+ // Remove arena team info from player data
if (Player* player = ObjectAccessor::FindPlayer(guid))
{
- player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
// delete all info regarding this team
for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
@@ -343,19 +344,18 @@ void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
void ArenaTeam::Disband(WorldSession* session)
{
- // Remove all members from arena team
- while (!Members.empty())
- DelMember(Members.front().Guid, false);
-
// Broadcast update
if (session)
{
BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, 0, 2, session->GetPlayerName(), GetName(), "");
-
if (Player* player = session->GetPlayer())
TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId());
}
+ // Remove all members from arena team
+ while (!Members.empty())
+ DelMember(Members.front().Guid, false);
+
// Update database
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -580,6 +580,20 @@ uint8 ArenaTeam::GetSlotByType(uint32 type)
return 0xFF;
}
+uint8 ArenaTeam::GetTypeBySlot(uint8 slot)
+{
+ switch (slot)
+ {
+ case 0: return ARENA_TEAM_2v2;
+ case 1: return ARENA_TEAM_3v3;
+ case 2: return ARENA_TEAM_5v5;
+ default:
+ break;
+ }
+ TC_LOG_ERROR(LOG_FILTER_ARENAS, "FATAL: Unknown arena team slot %u for some arena team", slot);
+ return 0xFF;
+}
+
bool ArenaTeam::IsMember(uint64 guid) const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -589,32 +603,6 @@ bool ArenaTeam::IsMember(uint64 guid) const
return false;
}
-uint32 ArenaTeam::GetPoints(uint32 memberRating)
-{
- // Returns how many points would be awarded with this team type with this rating
- float points;
-
- uint32 rating = memberRating + 150 < Stats.Rating ? memberRating : Stats.Rating;
-
- if (rating <= 1500)
- {
- if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6)
- points = (float)rating * 0.22f + 14.0f;
- else
- points = 344;
- }
- else
- points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
-
- // Type penalties for teams < 5v5
- if (Type == ARENA_TEAM_2v2)
- points *= 0.76f;
- else if (Type == ARENA_TEAM_3v3)
- points *= 0.88f;
-
- return (uint32) points;
-}
-
uint32 ArenaTeam::GetAverageMMR(Group* group) const
{
if (!group)
@@ -628,7 +616,7 @@ uint32 ArenaTeam::GetAverageMMR(Group* group) const
if (!ObjectAccessor::FindPlayer(itr->Guid))
continue;
- // Skip if player is not member of group
+ // Skip if player is not a member of group
if (!group->IsMember(itr->Guid))
continue;
@@ -652,7 +640,7 @@ float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
}
-int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/)
+int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
@@ -731,17 +719,17 @@ void ArenaTeam::FinishGame(int32 mod)
}
}
-int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
+int32 ArenaTeam::WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
{
// Called when the team has won
// Change in Matchmaker rating
- int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true);
+ int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, true);
// Change in Team Rating
- rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true);
+ ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, true);
// Modify the team stats accordingly
- FinishGame(rating_change);
+ FinishGame(ratingChange);
// Update number of wins per season and week
Stats.WeekWins += 1;
@@ -751,23 +739,23 @@ int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32
return mod;
}
-int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
+int32 ArenaTeam::LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
{
// Called when the team has lost
// Change in Matchmaker Rating
- int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false);
+ int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, false);
// Change in Team Rating
- rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false);
+ ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, false);
// Modify the team stats accordingly
- FinishGame(rating_change);
+ FinishGame(ratingChange);
// return the rating change, used to display it on the results screen
return mod;
}
-void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// Called for each participant of a match after losing
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -779,7 +767,7 @@ void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32
itr->ModifyPersonalRating(player, mod, GetType());
// Update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// Update personal played stats
itr->WeekGames +=1;
@@ -793,7 +781,7 @@ void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32
}
}
-void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// Called for offline player after ending rated arena match!
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -805,7 +793,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, i
itr->ModifyPersonalRating(NULL, mod, GetType());
// update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// update personal played stats
itr->WeekGames += 1;
@@ -815,7 +803,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, i
}
}
-void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// called for each participant after winning a match
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -827,7 +815,7 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32
itr->ModifyPersonalRating(player, mod, GetType());
// update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// update personal stats
itr->WeekGames +=1;
@@ -842,36 +830,6 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32
}
}
-void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& playerPoints)
-{
- // Called after a match has ended and the stats are already modified
- // Helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
- // 10 played games per week is a minimum
- if (Stats.WeekGames < 10)
- return;
-
- // To get points, a player has to participate in at least 30% of the matches
- uint32 requiredGames = (uint32)ceil(Stats.WeekGames * 0.3f);
-
- for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
- {
- // The player participated in enough games, update his points
- uint32 pointsToAdd = 0;
- if (itr->WeekGames >= requiredGames)
- pointsToAdd = GetPoints(itr->PersonalRating);
-
- std::map<uint32, uint32>::iterator plr_itr = playerPoints.find(GUID_LOPART(itr->Guid));
- if (plr_itr != playerPoints.end())
- {
- // Check if there is already more points
- if (plr_itr->second < pointsToAdd)
- playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
- }
- else
- playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
- }
-}
-
void ArenaTeam::SaveToDB()
{
// Save team and member stats to db
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index 0d37351583d..197e6af68c6 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -19,9 +19,10 @@
#ifndef TRINITYCORE_ARENATEAM_H
#define TRINITYCORE_ARENATEAM_H
+#include "Define.h"
#include "QueryResult.h"
-#include <ace/Singleton.h>
#include <list>
+#include <string>
#include <map>
class WorldSession;
@@ -39,6 +40,7 @@ enum ArenaTeamCommandTypes
enum ArenaTeamCommandErrors
{
+ ERR_ARENA_TEAM_CREATED = 0x00,
ERR_ARENA_TEAM_INTERNAL = 0x01,
ERR_ALREADY_IN_ARENA_TEAM = 0x02,
ERR_ALREADY_IN_ARENA_TEAM_S = 0x03,
@@ -57,7 +59,8 @@ enum ArenaTeamCommandErrors
ERR_ARENA_TEAM_TARGET_TOO_HIGH_S = 0x16,
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S = 0x17,
ERR_ARENA_TEAM_NOT_FOUND = 0x1B,
- ERR_ARENA_TEAMS_LOCKED = 0x1E
+ ERR_ARENA_TEAMS_LOCKED = 0x1E,
+ ERR_ARENA_TEAM_TOO_MANY_CREATE = 0x21,
};
enum ArenaTeamEvents
@@ -70,14 +73,6 @@ enum ArenaTeamEvents
ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name
};
-/*
-need info how to send these ones:
-ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite
-ERR_ARENA_TEAM_TARGET_TOO_LOW_S
-ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S
-ERR_ARENA_TEAM_LEVEL_TOO_LOW_I
-*/
-
enum ArenaTeamTypes
{
ARENA_TEAM_2v2 = 2,
@@ -119,18 +114,21 @@ class ArenaTeam
ArenaTeam();
~ArenaTeam();
- bool Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor);
+ bool Create(uint64 captainGuid, uint8 type, std::string const& teamName,
+ uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor,
+ uint8 borderStyle, uint32 borderColor);
void Disband(WorldSession* session);
void Disband();
typedef std::list<ArenaTeamMember> MemberList;
- uint32 GetId() const { return TeamId; }
- uint32 GetType() const { return Type; }
- uint8 GetSlot() const { return GetSlotByType(GetType()); }
+ uint32 GetId() const { return TeamId; }
+ uint32 GetType() const { return Type; }
+ uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
- uint64 GetCaptain() const { return CaptainGuid; }
- std::string const& GetName() const { return TeamName; }
+ static uint8 GetTypeBySlot(uint8 slot);
+ uint64 GetCaptain() const { return CaptainGuid; }
+ std::string const& GetName() const { return TeamName; }
const ArenaTeamStats& GetStats() const { return Stats; }
uint32 GetRating() const { return Stats.Rating; }
@@ -139,9 +137,6 @@ class ArenaTeam
void SetCaptain(uint64 guid);
bool SetName(std::string const& name);
bool AddMember(uint64 PlayerGuid);
-
- // Shouldn't be uint64 ed, because than can reference guid from members on Disband
- // and this method removes given record from list. So invalid reference can happen.
void DelMember(uint64 guid, bool cleanDb);
size_t GetMembersSize() const { return Members.size(); }
@@ -171,27 +166,26 @@ class ArenaTeam
void SendStats(WorldSession* session);
void Inspect(WorldSession* session, uint64 guid);
- uint32 GetPoints(uint32 MemberRating);
- int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
- int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
- float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
- int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
- void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange);
- int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
- void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
- void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
+ static int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
+ static int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
+ static float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
+
+ int32 WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& rating_change);
+ void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = 12);
- void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
+ int32 LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& rating_change);
+ void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = -12);
+ void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = -12);
void FinishWeek();
void FinishGame(int32 mod);
protected:
- uint32 TeamId;
- uint8 Type;
+ uint32 TeamId;
+ uint8 Type;
std::string TeamName;
- uint64 CaptainGuid;
+ uint64 CaptainGuid;
uint32 BackgroundColor; // ARGB format
uint8 EmblemStyle; // icon id
@@ -199,7 +193,7 @@ class ArenaTeam
uint8 BorderStyle; // border image id
uint32 BorderColor; // ARGB format
- MemberList Members;
+ MemberList Members;
ArenaTeamStats Stats;
};
#endif
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
index cb3388151bd..f544f9d8b75 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
@@ -134,59 +134,3 @@ void ArenaTeamMgr::LoadArenaTeams()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u arena teams in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-
-void ArenaTeamMgr::DistributeArenaPoints()
-{
- // Used to distribute arena points based on last week's stats
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_START);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
-
- // Temporary structure for storing maximum points to add values for all players
- std::map<uint32, uint32> PlayerPoints;
-
- // At first update all points for all team members
- for (ArenaTeamContainer::iterator teamItr = GetArenaTeamMapBegin(); teamItr != GetArenaTeamMapEnd(); ++teamItr)
- if (ArenaTeam* at = teamItr->second)
- at->UpdateArenaPointsHelper(PlayerPoints);
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
- PreparedStatement* stmt;
-
- // Cycle that gives points to all players
- for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr)
- {
- // Add points to player if online
- if (Player* player = HashMapHolder<Player>::Find(playerItr->first))
- player->ModifyArenaPoints(playerItr->second, &trans);
- else // Update database
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS);
- stmt->setUInt32(0, playerItr->second);
- stmt->setUInt32(1, playerItr->first);
- trans->Append(stmt);
- }
- }
-
- CharacterDatabase.CommitTransaction(trans);
-
- PlayerPoints.clear();
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
- for (ArenaTeamContainer::iterator titr = GetArenaTeamMapBegin(); titr != GetArenaTeamMapEnd(); ++titr)
- {
- if (ArenaTeam* at = titr->second)
- {
- at->FinishWeek();
- at->SaveToDB();
- at->NotifyStatsChanged();
- }
- }
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_END);
-}
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h
index 589877a150d..99df6226d26 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.h
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h
@@ -40,8 +40,6 @@ public:
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
- void DistributeArenaPoints();
-
uint32 GenerateArenaTeamId();
void SetNextArenaTeamId(uint32 Id) { NextArenaTeamId = Id; }
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 54df2d6cc27..3e98c68efcd 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -24,6 +24,8 @@
#include "Formulas.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
+#include "Guild.h"
+#include "GuildMgr.h"
#include "MapManager.h"
#include "Object.h"
#include "ObjectMgr.h"
@@ -129,6 +131,7 @@ void Battleground::BroadcastWorker(Do& _do)
Battleground::Battleground()
{
+ m_Guid = 0;
m_TypeID = BATTLEGROUND_TYPE_NONE;
m_RandomTypeID = BATTLEGROUND_TYPE_NONE;
m_InstanceID = 0;
@@ -143,6 +146,7 @@ Battleground::Battleground()
m_IsArena = false;
m_Winner = 2;
m_StartTime = 0;
+ m_CountdownTimer = 0;
m_ResetStatTimer = 0;
m_ValidStartPositionTimer = 0;
m_Events = 0;
@@ -270,7 +274,7 @@ void Battleground::Update(uint32 diff)
// after 47 minutes without one team losing, the arena closes with no winner and no rating change
if (isArena())
{
- if (GetStartTime() >= 47 * MINUTE*IN_MILLISECONDS)
+ if (GetElapsedTime() >= 47 * MINUTE*IN_MILLISECONDS)
{
UpdateArenaWorldState();
CheckArenaAfterTimerConditions();
@@ -294,8 +298,12 @@ void Battleground::Update(uint32 diff)
}
// Update start time and reset stats timer
- m_StartTime += diff;
- m_ResetStatTimer += diff;
+ SetElapsedTime(GetElapsedTime() + diff);
+ if (GetStatus() == STATUS_WAIT_JOIN)
+ {
+ m_ResetStatTimer += diff;
+ m_CountdownTimer += diff;
+ }
PostUpdateImpl(diff);
}
@@ -458,6 +466,9 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// *********************************************************
ModifyStartDelayTime(diff);
+ if (!isArena())
+ SetRemainingTime(300000);
+
if (m_ResetStatTimer > 5000)
{
m_ResetStatTimer = 0;
@@ -466,6 +477,23 @@ inline void Battleground::_ProcessJoin(uint32 diff)
player->ResetAllPowers();
}
+ // Send packet every 10 seconds until the 2nd field reach 0
+ if (m_CountdownTimer >= 10000)
+ {
+ uint32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
+
+ WorldPacket data(SMSG_START_TIMER, 4+4+4);
+ data << uint32(0); // unk
+ data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
+ data << uint32(countdownMaxForBGType);
+
+ for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(itr->first))
+ player->GetSession()->SendPacket(&data);
+
+ m_CountdownTimer = 0;
+ }
+
if (!(m_Events & BG_STARTING_EVENT_1))
{
m_Events |= BG_STARTING_EVENT_1;
@@ -523,9 +551,12 @@ inline void Battleground::_ProcessJoin(uint32 diff)
WorldPacket status;
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
player->GetSession()->SendPacket(&status);
+ // Correctly display EnemyUnitFrame
+ player->SetByteValue(PLAYER_BYTES_3, 3, player->GetBGTeam());
+
player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
player->ResetAllPowers();
if (!player->isGameMaster())
@@ -565,6 +596,9 @@ inline void Battleground::_ProcessJoin(uint32 diff)
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
+
+ if (GetRemainingTime() > 0 && (m_EndTime -= diff) > 0)
+ SetRemainingTime(GetRemainingTime() - diff);
}
inline void Battleground::_ProcessLeave(uint32 diff)
@@ -573,10 +607,10 @@ inline void Battleground::_ProcessLeave(uint32 diff)
// *** BATTLEGROUND ENDING SYSTEM ***
// *********************************************************
// remove all players from battleground after 2 minutes
- m_EndTime -= diff;
- if (m_EndTime <= 0)
+ SetRemainingTime(GetRemainingTime() - diff);
+ if (GetRemainingTime() <= 0)
{
- m_EndTime = 0;
+ SetRemainingTime(0);
BattlegroundPlayerMap::iterator itr, next;
for (itr = m_Players.begin(); itr != m_Players.end(); itr = next)
{
@@ -768,7 +802,7 @@ void Battleground::EndBattleground(uint32 winner)
SetStatus(STATUS_WAIT_LEAVE);
//we must set it this way, because end time is sent in packet!
- m_EndTime = TIME_TO_AUTOREMOVE;
+ SetRemainingTime(TIME_AUTOCLOSE_BATTLEGROUND);
// arena rating calculation
if (isArena() && isRated())
@@ -819,6 +853,7 @@ void Battleground::EndBattleground(uint32 winner)
}
}
+ bool guildAwarded = false;
WorldPacket pvpLogData;
sBattlegroundMgr->BuildPvpLogDataPacket(&pvpLogData, this);
@@ -875,6 +910,7 @@ void Battleground::EndBattleground(uint32 winner)
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD));
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
}
@@ -889,7 +925,10 @@ void Battleground::EndBattleground(uint32 winner)
uint32 winner_kills = player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST;
uint32 loser_kills = player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST;
- uint32 winner_arena = player->GetRandomWinner() ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST;
+
+ // remove temporary currency bonus auras before rewarding player
+ player->RemoveAura(SPELL_HONORABLE_DEFENDER_25Y);
+ player->RemoveAura(SPELL_HONORABLE_DEFENDER_60Y);
// Reward winner team
if (team == winner)
@@ -897,13 +936,28 @@ void Battleground::EndBattleground(uint32 winner)
if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID()))
{
UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winner_kills));
- if (CanAwardArenaPoints())
- player->ModifyArenaPoints(winner_arena);
if (!player->GetRandomWinner())
+ {
+ // 100cp awarded for the first random battleground won each day
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, BG_REWARD_WINNER_CONQUEST_FIRST);
player->SetRandomWinner(true);
+ }
}
+ else // 50cp awarded for each non-rated battleground won
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, BG_REWARD_WINNER_CONQUEST_LAST);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1);
+ if (!guildAwarded)
+ {
+ guildAwarded = true;
+ if (uint32 guildId = GetBgMap()->GetOwnerGuildId(player->GetTeam()))
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ {
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1, 0, 0, NULL, player);
+ if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winnerArenaTeam->GetRating(), 1), 0, 0, NULL, player);
+ }
+ }
}
else
{
@@ -919,8 +973,9 @@ void Battleground::EndBattleground(uint32 winner)
player->GetSession()->SendPacket(&pvpLogData);
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
player->GetSession()->SendPacket(&data);
+
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
@@ -991,10 +1046,11 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
RemovePlayer(player, guid, team); // BG subclass specific code
+ BattlegroundTypeId bgTypeId = GetTypeID();
+ BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
+
if (participant) // if the player was a match participant, remove auras, calc rating, update queue
{
- BattlegroundTypeId bgTypeId = GetTypeID();
- BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
if (player)
{
player->ClearAfkReports();
@@ -1022,7 +1078,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if (SendPacket)
{
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_NONE, player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0);
player->GetSession()->SendPacket(&data);
}
@@ -1070,6 +1126,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
// reset destination bg team
player->SetBGTeam(0);
+ player->RemoveBattlegroundQueueJoinTime(bgTypeId);
if (Transport)
player->TeleportToBGEntryPoint();
@@ -1085,8 +1142,8 @@ void Battleground::Reset()
{
SetWinner(WINNER_NONE);
SetStatus(STATUS_WAIT_QUEUE);
- SetStartTime(0);
- SetEndTime(0);
+ SetElapsedTime(0);
+ SetRemainingTime(0);
SetLastResurrectTime(0);
m_Events = 0;
@@ -1109,7 +1166,7 @@ void Battleground::Reset()
void Battleground::StartBattleground()
{
- SetStartTime(0);
+ SetElapsedTime(0);
SetLastResurrectTime(0);
// add BG to free slot queue
AddToBGFreeSlotQueue();
@@ -1144,9 +1201,16 @@ void Battleground::AddPlayer(Player* player)
UpdatePlayersCountByTeam(team, false); // +1 player
WorldPacket data;
- sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player);
+ sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player->GetGUID());
SendPacketToTeam(team, &data, player, false);
+ // BG Status packet
+ BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
+ uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
+
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
+ player->GetSession()->SendPacket(&data);
+
player->RemoveAurasByType(SPELL_AURA_MOUNTED);
// add arena specific auras
@@ -1180,7 +1244,16 @@ void Battleground::AddPlayer(Player* player)
else
{
if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
+ {
player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
+
+ int32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
+ WorldPacket data(SMSG_START_TIMER, 4+4+4);
+ data << uint32(0); // unk
+ data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
+ data << uint32(countdownMaxForBGType);
+ player->GetSession()->SendPacket(&data);
+ }
}
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
@@ -1642,6 +1715,7 @@ bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float
creature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
// correct cast speed
creature->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ creature->SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
//creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
return true;
}
@@ -1702,6 +1776,8 @@ void Battleground::SendWarningToAll(int32 entry, ...)
data << (uint32)(msg.length() + 1);
data << msg.c_str();
data << (uint8)0;
+ data << (float)0.0f; // added in 4.2.0, unk
+ data << (uint8)0; // added in 4.2.0, unk
for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
if (player->GetSession())
@@ -1719,7 +1795,7 @@ void Battleground::EndNow()
{
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE);
- SetEndTime(0);
+ SetRemainingTime(0);
}
// To be removed
@@ -1839,7 +1915,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player)
sBattlegroundMgr->BuildPvpLogDataPacket(&data, this);
player->GetSession()->SendPacket(&data);
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
player->GetSession()->SendPacket(&data);
}
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index dd8fbb6710c..13479e7ff30 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -108,12 +108,14 @@ enum BattlegroundTimeIntervals
RESURRECTION_INTERVAL = 30000, // ms
//REMIND_INTERVAL = 10000, // ms
INVITATION_REMIND_TIME = 20000, // ms
- INVITE_ACCEPT_WAIT_TIME = 60000, // ms
- TIME_TO_AUTOREMOVE = 120000, // ms
+ INVITE_ACCEPT_WAIT_TIME = 90000, // ms
+ TIME_AUTOCLOSE_BATTLEGROUND = 120000, // ms
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
RESPAWN_IMMEDIATELY = 0, // secs
- BUFF_RESPAWN_TIME = 180 // secs
+ BUFF_RESPAWN_TIME = 180, // secs
+ BATTLEGROUND_COUNTDOWN_MAX = 120, // secs
+ ARENA_COUNTDOWN_MAX = 60 // secs
};
enum BattlegroundStartTimeIntervals
@@ -132,14 +134,15 @@ enum BattlegroundBuffObjects
BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905
};
+/// Battleground currency rewards. Should be with precision mod.
enum BattlegroundRandomRewards
{
- BG_REWARD_WINNER_HONOR_FIRST = 30,
- BG_REWARD_WINNER_ARENA_FIRST = 25,
- BG_REWARD_WINNER_HONOR_LAST = 15,
- BG_REWARD_WINNER_ARENA_LAST = 0,
- BG_REWARD_LOSER_HONOR_FIRST = 5,
- BG_REWARD_LOSER_HONOR_LAST = 5
+ BG_REWARD_WINNER_HONOR_FIRST = 27000,
+ BG_REWARD_WINNER_CONQUEST_FIRST = 10000,
+ BG_REWARD_WINNER_HONOR_LAST = 13500,
+ BG_REWARD_WINNER_CONQUEST_LAST = 5000,
+ BG_REWARD_LOSER_HONOR_FIRST = 4500,
+ BG_REWARD_LOSER_HONOR_LAST = 3500
};
const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY };
@@ -295,13 +298,14 @@ class Battleground
/* Battleground */
// Get methods:
char const* GetName() const { return m_Name; }
+ uint64 GetGUID() { return m_Guid; }
BattlegroundTypeId GetTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_TypeID; }
BattlegroundBracketId GetBracketId() const { return m_BracketId; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattlegroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
- uint32 GetStartTime() const { return m_StartTime; }
- uint32 GetEndTime() const { return m_EndTime; }
+ uint32 GetElapsedTime() const { return m_StartTime; }
+ uint32 GetRemainingTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
uint32 GetMaxPlayers() const { return m_MaxPlayers; }
uint32 GetMinPlayers() const { return m_MinPlayers; }
@@ -320,6 +324,7 @@ class Battleground
bool IsRandom() const { return m_IsRandom; }
// Set methods:
+ void SetGuid(uint64 newGuid) { m_Guid = newGuid; }
void SetName(char const* Name) { m_Name = Name; }
void SetTypeID(BattlegroundTypeId TypeID) { m_TypeID = TypeID; }
void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; }
@@ -328,8 +333,8 @@ class Battleground
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattlegroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
- void SetStartTime(uint32 Time) { m_StartTime = Time; }
- void SetEndTime(uint32 Time) { m_EndTime = Time; }
+ void SetElapsedTime(uint32 Time) { m_StartTime = Time; }
+ void SetRemainingTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
void SetMaxPlayers(uint32 MaxPlayers) { m_MaxPlayers = MaxPlayers; }
void SetMinPlayers(uint32 MinPlayers) { m_MinPlayers = MinPlayers; }
@@ -578,6 +583,7 @@ class Battleground
BattlegroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
+ uint32 m_CountdownTimer;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
@@ -593,6 +599,7 @@ class Battleground
bool m_PrematureCountDown;
uint32 m_PrematureCountDownTimer;
char const* m_Name;
+ uint64 m_Guid;
/* Pre- and post-update hooks */
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index efd7e0f3d73..9352b2d5710 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -35,6 +35,8 @@
#include "BattlegroundDS.h"
#include "BattlegroundRV.h"
#include "BattlegroundIC.h"
+#include "BattlegroundTP.h"
+#include "BattlegroundBFG.h"
#include "Chat.h"
#include "Map.h"
#include "MapInstanced.h"
@@ -52,7 +54,7 @@
BattlegroundMgr::BattlegroundMgr() :
m_NextRatedArenaUpdate(sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER)),
- m_AutoDistributionTimeChecker(0), m_ArenaTesting(false), m_Testing(false)
+ m_ArenaTesting(false), m_Testing(false)
{ }
BattlegroundMgr::~BattlegroundMgr()
@@ -144,221 +146,377 @@ void BattlegroundMgr::Update(uint32 diff)
else
m_NextRatedArenaUpdate -= diff;
}
-
- if (sWorld->getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
- {
- if (m_AutoDistributionTimeChecker < diff)
- {
- if (time(NULL) > m_NextAutoDistributionTime)
- {
- sArenaTeamMgr->DistributeArenaPoints();
- m_NextAutoDistributionTime = m_NextAutoDistributionTime + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld->getIntConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS);
- sWorld->setWorldState(WS_ARENA_DISTRIBUTION_TIME, uint64(m_NextAutoDistributionTime));
- }
- m_AutoDistributionTimeChecker = 600000; // check 10 minutes
- }
- else
- m_AutoDistributionTimeChecker -= diff;
- }
}
-void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype, uint32 arenaFaction)
+void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
{
- // we can be in 2 queues in same time...
+ ObjectGuid playerGuid = player->GetGUID();
+ ObjectGuid bgGuid;
- if (StatusID == 0 || !bg)
- {
- data->Initialize(SMSG_BATTLEFIELD_STATUS, 4+8);
- *data << uint32(QueueSlot); // queue id (0...1)
- *data << uint64(0);
- return;
- }
+ if (bg)
+ bgGuid = bg->GetGUID();
+ else
+ StatusID = STATUS_NONE;
- data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+8+1+1+4+1+4+4+4));
- *data << uint32(QueueSlot); // queue id (0...1) - player can be in 2 queues in time
- // The following segment is read as uint64 in client but can be appended as their original type.
- *data << uint8(arenatype);
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "BattlegroundMgr::BuildBattlegroundStatusPacket: arenatype = %u for bg instanceID %u, TypeID %u.", arenatype, bg->GetClientInstanceID(), bg->GetTypeID());
- *data << uint8(bg->isArena() ? 0xE : 0x0);
- *data << uint32(bg->GetTypeID());
- *data << uint16(0x1F90);
- // End of uint64 segment, decomposed this way for simplicity
- *data << uint8(bg->GetMinLevel());
- *data << uint8(bg->GetMaxLevel());
- *data << uint32(bg->GetClientInstanceID());
- // alliance/horde for BG and skirmish/rated for Arenas
- // following displays the minimap-icon 0 = faction icon 1 = arenaicon
- *data << uint8(bg->isRated()); // 1 for rated match, 0 for bg or non rated match
-
- *data << uint32(StatusID); // status
switch (StatusID)
{
- case STATUS_WAIT_QUEUE: // status_in_queue
- *data << uint32(Time1); // average wait time, milliseconds
- *data << uint32(Time2); // time in queue, updated every minute!, milliseconds
+ case STATUS_NONE:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS);
+
+ data->WriteBit(playerGuid[0]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(playerGuid[2]);
+
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint32(1); // unk, always 1
+ data->WriteByteSeq(playerGuid[3]);
+ data->WriteByteSeq(playerGuid[1]);
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint32(Time1); // Join Time
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[4]);
break;
- case STATUS_WAIT_JOIN: // status_invite
- *data << uint32(bg->GetMapId()); // map id
- *data << uint64(0); // 3.3.5, unknown
- *data << uint32(Time1); // time to remove from queue, milliseconds
+ }
+ case STATUS_WAIT_QUEUE:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_QUEUED);
+
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[0]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(1); // Eligible In Queue
+ data->WriteBit(0); // Join Failed, 1 when it's arena ...
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(0); // Waiting On Other Activity
+ data->WriteBit(bgGuid[1]);
+
+ data->FlushBits();
+
+ data->WriteByteSeq(playerGuid[0]);
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(playerGuid[3]);
+ *data << uint32(Time1); // Estimated Wait Time
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(bgGuid[2]);
+ *data << uint8(0); // unk
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint8(0); // unk
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(bgGuid[0]);
+ *data << uint32(Time2); // Join Time
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(GetMSTimeDiffToNow(Time2)); // Time since joined
+ data->WriteByteSeq(playerGuid[1]);
+ data->WriteByteSeq(playerGuid[5]);
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
+ data->WriteByteSeq(playerGuid[4]);
break;
- case STATUS_IN_PROGRESS: // status_in_progress
- *data << uint32(bg->GetMapId()); // map id
- *data << uint64(0); // 3.3.5, unknown
- *data << uint32(Time1); // time to bg auto leave, 0 at bg start, 120000 after bg end, milliseconds
- *data << uint32(Time2); // time from bg start, milliseconds
- *data << uint8(arenaFaction == ALLIANCE ? 1 : 0); // arenafaction (0 for horde, 1 for alliance)
+ }
+ case STATUS_WAIT_JOIN:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION);
+
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
+ *data << uint32(Time1); // Time until closed
+ *data << uint8(0); // unk
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint32(Time2); // Join Time
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ *data << uint32(bg->GetMapId()); // Map Id
+ *data << uint8(0); // unk
+
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(bgGuid[1]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(playerGuid[0]);
+
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(bgGuid[2]);
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(playerGuid[1]);
+ data->WriteByteSeq(bgGuid[0]);
+ data->WriteByteSeq(playerGuid[4]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(playerGuid[2]);
+ data->WriteByteSeq(playerGuid[3]);
break;
- default:
- TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Unknown BG status!");
+ }
+ case STATUS_IN_PROGRESS:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_ACTIVE);
+
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[1]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[0]);
+
+ data->FlushBits();
+
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(playerGuid[6]);
+
+ *data << uint32(Time1); // Join Time
+ *data << uint8(0); // unk
+
+ data->WriteByteSeq(playerGuid[4]);
+ data->WriteByteSeq(playerGuid[1]);
+
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint8(0); // unk
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ *data << uint32(bg->GetMapId()); // Map Id
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(Time2); // Elapsed Time
+
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint32(bg->GetRemainingTime()); // Remaining Time
+
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[3]);
+ data->WriteByteSeq(bgGuid[2]);
+
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID or faction ?
+
+ data->WriteByteSeq(bgGuid[0]);
+ data->WriteByteSeq(playerGuid[7]);
+ break;
+ }
+ case STATUS_WAIT_LEAVE:
break;
}
}
void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg)
{
- uint8 type = (bg->isArena() ? 1 : 0);
+ ByteBuffer buff;
+ uint8 isRated = (bg->isRated() ? 1 : 0); // type (normal=0/rated=1) -- ATM arena or bg, RBG NYI
+ uint8 isArena = (bg->isArena() ? 1 : 0); // Arena names
- data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
- *data << uint8(type); // type (battleground=0/arena=1)
+ data->Initialize(SMSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
+ data->WriteBit(isArena);
+ data->WriteBit(isRated);
- if (type) // arena
+ if (isArena)
{
- // it seems this must be according to BG_WINNER_A/H and _NOT_ TEAM_A/H
- for (int8 i = 1; i >= 0; --i)
- {
- int32 rating_change = bg->GetArenaTeamRatingChangeByIndex(i);
-
- uint32 pointsLost = rating_change < 0 ? -rating_change : 0;
- uint32 pointsGained = rating_change > 0 ? rating_change : 0;
- uint32 MatchmakerRating = bg->GetArenaMatchmakerRatingByIndex(i);
-
- *data << uint32(pointsLost); // Rating Lost
- *data << uint32(pointsGained); // Rating gained
- *data << uint32(MatchmakerRating); // Matchmaking Value
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "rating change: %d", rating_change);
- }
- for (int8 i = 1; i >= 0; --i)
+ for (int8 i = 0; i < BG_TEAMS_COUNT; ++i)
{
if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdByIndex(i)))
- *data << at->GetName();
+ data->WriteBits(at->GetName().length(), 8);
else
- *data << uint8(0);
+ data->WriteBits(0, 8);
}
}
- if (bg->GetStatus() != STATUS_WAIT_LEAVE)
- *data << uint8(0); // bg not ended
- else
- {
- *data << uint8(1); // bg ended
- *data << uint8(bg->GetWinner()); // who win
- }
-
- size_t wpos = data->wpos();
- uint32 scoreCount = 0;
- *data << uint32(scoreCount); // placeholder
-
- Battleground::BattlegroundScoreMap::const_iterator itr2 = bg->GetPlayerScoresBegin();
- for (Battleground::BattlegroundScoreMap::const_iterator itr = itr2; itr != bg->GetPlayerScoresEnd();)
+ data->WriteBits(bg->GetPlayerScoresSize(), 21);
+ for (Battleground::BattlegroundScoreMap::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
{
- itr2 = itr++;
- if (!bg->IsPlayerInBattleground(itr2->first))
+ if (!bg->IsPlayerInBattleground(itr->first))
{
TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Player " UI64FMTD " has scoreboard entry for battleground %u but is not in battleground!", itr->first, bg->GetTypeID(true));
continue;
}
-
- *data << uint64(itr2->first);
- *data << uint32(itr2->second->KillingBlows);
- if (type == 0)
- {
- *data << uint32(itr2->second->HonorableKills);
- *data << uint32(itr2->second->Deaths);
- *data << uint32(itr2->second->BonusHonor);
- }
- else
+ Player* player = ObjectAccessor::FindPlayer(itr->first);
+ ObjectGuid playerGUID = itr->first;
+
+ data->WriteBit(0); // Unk 1
+ data->WriteBit(0); // Unk 2
+ data->WriteBit(playerGUID[2]);
+ data->WriteBit(!isArena);
+ data->WriteBit(0); // Unk 4
+ data->WriteBit(0); // Unk 5
+ data->WriteBit(0); // Unk 6
+ data->WriteBit(playerGUID[3]);
+ data->WriteBit(playerGUID[0]);
+ data->WriteBit(playerGUID[5]);
+ data->WriteBit(playerGUID[1]);
+ data->WriteBit(playerGUID[6]);
+ data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1);
+ data->WriteBit(playerGUID[7]);
+
+ buff << uint32(itr->second->HealingDone); // healing done
+ buff << uint32(itr->second->DamageDone); // damage done
+
+ if (!isArena)
{
- Player* player = ObjectAccessor::FindPlayer(itr2->first);
- uint32 team = bg->GetPlayerTeam(itr2->first);
- if (!team && player)
- team = player->GetBGTeam();
- *data << uint8(team == ALLIANCE ? 1 : 0); // green or yellow
+ buff << uint32(itr->second->BonusHonor / 100);
+ buff << uint32(itr->second->Deaths);
+ buff << uint32(itr->second->HonorableKills);
}
- *data << uint32(itr2->second->DamageDone); // damage done
- *data << uint32(itr2->second->HealingDone); // healing done
- switch (bg->GetTypeID(true)) // battleground specific things
+
+ buff.WriteByteSeq(playerGUID[4]);
+ buff << uint32(itr->second->KillingBlows);
+ // if (unk 5) << uint32() unk
+ buff.WriteByteSeq(playerGUID[5]);
+ // if (unk 6) << uint32() unk
+ // if (unk 2) << uint32() unk
+ buff.WriteByteSeq(playerGUID[1]);
+ buff.WriteByteSeq(playerGUID[6]);
+
+
+ buff << int32(player->GetPrimaryTalentTree(player->GetActiveSpec()));
+
+ switch (bg->GetTypeID(true)) // Custom values
{
case BATTLEGROUND_RB:
switch (bg->GetMapId())
{
case 489:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundWGScore*)itr2->second)->FlagCaptures); // flag captures
- *data << uint32(((BattlegroundWGScore*)itr2->second)->FlagReturns); // flag returns
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundWGScore*)itr->second)->FlagCaptures); // flag captures
+ buff << uint32(((BattlegroundWGScore*)itr->second)->FlagReturns); // flag returns
break;
case 566:
- *data << uint32(0x00000001); // count of next fields
- *data << uint32(((BattlegroundEYScore*)itr2->second)->FlagCaptures); // flag captures
+ data->WriteBits(0x00000001, 24);
+ buff << uint32(((BattlegroundEYScore*)itr->second)->FlagCaptures); // flag captures
break;
case 529:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundABScore*)itr2->second)->BasesAssaulted); // bases asssulted
- *data << uint32(((BattlegroundABScore*)itr2->second)->BasesDefended); // bases defended
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundABScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundABScore*)itr->second)->BasesDefended); // bases defended
break;
case 30:
- *data << uint32(0x00000005); // count of next fields
- *data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsAssaulted); // GraveyardsAssaulted
- *data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsDefended); // GraveyardsDefended
- *data << uint32(((BattlegroundAVScore*)itr2->second)->TowersAssaulted); // TowersAssaulted
- *data << uint32(((BattlegroundAVScore*)itr2->second)->TowersDefended); // TowersDefended
- *data << uint32(((BattlegroundAVScore*)itr2->second)->MinesCaptured); // MinesCaptured
+ data->WriteBits(0x00000005, 24);
+ buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted); // GraveyardsAssaulted
+ buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsDefended); // GraveyardsDefended
+ buff << uint32(((BattlegroundAVScore*)itr->second)->TowersAssaulted); // TowersAssaulted
+ buff << uint32(((BattlegroundAVScore*)itr->second)->TowersDefended); // TowersDefended
+ buff << uint32(((BattlegroundAVScore*)itr->second)->MinesCaptured); // MinesCaptured
break;
case 607:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundSAScore*)itr2->second)->demolishers_destroyed);
- *data << uint32(((BattlegroundSAScore*)itr2->second)->gates_destroyed);
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed);
+ buff << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed);
break;
case 628: // IC
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases asssulted
- *data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundICScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundICScore*)itr->second)->BasesDefended); // bases defended
+ break;
+ case 726:
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundTPScore*)itr->second)->FlagCaptures); // flag captures
+ buff << uint32(((BattlegroundTPScore*)itr->second)->FlagReturns); // flag returns
+ break;
+ case 761:
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesDefended); // bases defended
+ break;
default:
- *data << uint32(0);
+ data->WriteBits(0, 24);
break;
}
break;
case BATTLEGROUND_AV:
- *data << uint32(0x00000005); // count of next fields
- *data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsAssaulted); // GraveyardsAssaulted
- *data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsDefended); // GraveyardsDefended
- *data << uint32(((BattlegroundAVScore*)itr2->second)->TowersAssaulted); // TowersAssaulted
- *data << uint32(((BattlegroundAVScore*)itr2->second)->TowersDefended); // TowersDefended
- *data << uint32(((BattlegroundAVScore*)itr2->second)->MinesCaptured); // MinesCaptured
+ data->WriteBits(0x00000005, 24);
+ buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted); // GraveyardsAssaulted
+ buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsDefended); // GraveyardsDefended
+ buff << uint32(((BattlegroundAVScore*)itr->second)->TowersAssaulted); // TowersAssaulted
+ buff << uint32(((BattlegroundAVScore*)itr->second)->TowersDefended); // TowersDefended
+ buff << uint32(((BattlegroundAVScore*)itr->second)->MinesCaptured); // MinesCaptured
break;
case BATTLEGROUND_WS:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundWGScore*)itr2->second)->FlagCaptures); // flag captures
- *data << uint32(((BattlegroundWGScore*)itr2->second)->FlagReturns); // flag returns
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundWGScore*)itr->second)->FlagCaptures); // flag captures
+ buff << uint32(((BattlegroundWGScore*)itr->second)->FlagReturns); // flag returns
break;
case BATTLEGROUND_AB:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundABScore*)itr2->second)->BasesAssaulted); // bases assaulted
- *data << uint32(((BattlegroundABScore*)itr2->second)->BasesDefended); // bases defended
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundABScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundABScore*)itr->second)->BasesDefended); // bases defended
break;
case BATTLEGROUND_EY:
- *data << uint32(0x00000001); // count of next fields
- *data << uint32(((BattlegroundEYScore*)itr2->second)->FlagCaptures); // flag captures
+ data->WriteBits(0x00000001, 24);
+ buff << uint32(((BattlegroundEYScore*)itr->second)->FlagCaptures); // flag captures
break;
case BATTLEGROUND_SA:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundSAScore*)itr2->second)->demolishers_destroyed);
- *data << uint32(((BattlegroundSAScore*)itr2->second)->gates_destroyed);
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed);
+ buff << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed);
break;
case BATTLEGROUND_IC:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases assaulted
- *data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundICScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundICScore*)itr->second)->BasesDefended); // bases defended
+ break;
+ case BATTLEGROUND_TP:
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundTPScore*)itr->second)->FlagCaptures); // flag captures
+ buff << uint32(((BattlegroundTPScore*)itr->second)->FlagReturns); // flag returns
+ break;
+ case BATTLEGROUND_BFG:
+ data->WriteBits(0x00000002, 24);
+ buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesAssaulted); // bases assaulted
+ buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesDefended); // bases defended
break;
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
@@ -366,30 +524,128 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg)
case BATTLEGROUND_RL:
case BATTLEGROUND_DS:
case BATTLEGROUND_RV:
- *data << uint32(0);
+ data->WriteBits(0, 24);
break;
default:
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID());
- *data << uint32(0);
+ data->WriteBits(0, 24);
break;
}
- // should never happen
- if (++scoreCount >= bg->GetMaxPlayers() && itr != bg->GetPlayerScoresEnd())
+
+ data->WriteBit(playerGUID[4]);
+
+ buff.WriteByteSeq(playerGUID[0]);
+ buff.WriteByteSeq(playerGUID[3]);
+ // if (unk 4) << uint32() unk
+ buff.WriteByteSeq(playerGUID[7]);
+ buff.WriteByteSeq(playerGUID[2]);
+ }
+
+ data->WriteBit(bg->GetStatus() == STATUS_WAIT_LEAVE); // If Ended
+
+ if (isRated) // arena
+ {
+ // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
+ for (int8 i = 0; i < BG_TEAMS_COUNT; ++i)
{
- TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Battleground %u scoreboard has more entries (%u) than allowed players in this bg (%u)", bg->GetTypeID(true), bg->GetPlayerScoresSize(), bg->GetMaxPlayers());
- break;
+ int32 rating_change = bg->GetArenaTeamRatingChangeByIndex(i);
+
+ uint32 pointsLost = rating_change < 0 ? -rating_change : 0;
+ uint32 pointsGained = rating_change > 0 ? rating_change : 0;
+ uint32 MatchmakerRating = bg->GetArenaMatchmakerRatingByIndex(i);
+
+ *data << uint32(MatchmakerRating); // Matchmaking Value
+ *data << uint32(pointsLost); // Rating Lost
+ *data << uint32(pointsGained); // Rating gained
+
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "rating change: %d", rating_change);
}
}
- data->put(wpos, scoreCount);
+ data->FlushBits();
+ data->append(buff);
+
+ if (isArena)
+ for (int8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdByIndex(i)))
+ data->WriteString(at->GetName());
+
+ *data << uint8(bg->GetPlayersCountByTeam(HORDE));
+
+ if (bg->GetStatus() == STATUS_WAIT_LEAVE)
+ *data << uint8(bg->GetWinner());
+
+ *data << uint8(bg->GetPlayersCountByTeam(ALLIANCE));
}
-void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result)
+void BattlegroundMgr::BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 QueueSlot, GroupJoinBattlegroundResult result)
{
- data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
- *data << int32(result);
- if (result == ERR_BATTLEGROUND_JOIN_TIMED_OUT || result == ERR_BATTLEGROUND_JOIN_FAILED)
- *data << uint64(0); // player guid
+ ObjectGuid guidBytes1 = player->GetGUID(); // player who caused the error
+ ObjectGuid guidBytes2 = bg->GetGUID();
+ ObjectGuid unkGuid3 = 0;
+
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_FAILED);
+
+ data->WriteBit(guidBytes2[3]);
+ data->WriteBit(unkGuid3[3]);
+ data->WriteBit(guidBytes1[3]);
+ data->WriteBit(unkGuid3[0]);
+ data->WriteBit(guidBytes2[6]);
+ data->WriteBit(guidBytes1[5]);
+ data->WriteBit(guidBytes1[6]);
+ data->WriteBit(guidBytes1[4]);
+
+ data->WriteBit(guidBytes1[2]);
+ data->WriteBit(unkGuid3[1]);
+ data->WriteBit(guidBytes2[1]);
+ data->WriteBit(unkGuid3[5]);
+ data->WriteBit(unkGuid3[6]);
+ data->WriteBit(guidBytes1[1]);
+ data->WriteBit(guidBytes2[7]);
+ data->WriteBit(unkGuid3[4]);
+
+ data->WriteBit(guidBytes2[2]);
+ data->WriteBit(guidBytes2[5]);
+ data->WriteBit(unkGuid3[7]);
+ data->WriteBit(guidBytes2[4]);
+ data->WriteBit(guidBytes2[0]);
+ data->WriteBit(guidBytes1[0]);
+ data->WriteBit(unkGuid3[2]);
+ data->WriteBit(guidBytes1[7]);
+
+ data->WriteByteSeq(guidBytes2[1]);
+
+ *data << uint32(1); // Unk, always 1
+ *data << uint32(QueueSlot); // Queue slot
+
+ data->WriteByteSeq(guidBytes1[6]);
+ data->WriteByteSeq(guidBytes1[3]);
+ data->WriteByteSeq(guidBytes1[7]);
+ data->WriteByteSeq(guidBytes1[4]);
+ data->WriteByteSeq(guidBytes2[0]);
+ data->WriteByteSeq(guidBytes1[5]);
+ data->WriteByteSeq(guidBytes2[7]);
+ data->WriteByteSeq(guidBytes2[6]);
+ data->WriteByteSeq(guidBytes2[2]);
+ data->WriteByteSeq(unkGuid3[6]);
+ data->WriteByteSeq(unkGuid3[3]);
+ data->WriteByteSeq(guidBytes1[1]);
+ data->WriteByteSeq(guidBytes2[3]);
+ data->WriteByteSeq(unkGuid3[0]);
+ data->WriteByteSeq(unkGuid3[1]);
+ data->WriteByteSeq(unkGuid3[4]);
+ data->WriteByteSeq(guidBytes1[0]);
+ data->WriteByteSeq(guidBytes2[5]);
+ data->WriteByteSeq(unkGuid3[7]);
+ data->WriteByteSeq(guidBytes2[4]);
+ data->WriteByteSeq(guidBytes1[2]);
+
+ *data << uint32(result); // Result
+
+ data->WriteByteSeq(unkGuid3[2]);
+
+ *data << uint32(player->GetBattlegroundQueueJoinTime(bg->GetTypeID())); // Join Time
+
+ data->WriteByteSeq(unkGuid3[5]);
}
void BattlegroundMgr::BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value)
@@ -403,18 +659,57 @@ void BattlegroundMgr::BuildPlaySoundPacket(WorldPacket* data, uint32 soundid)
{
data->Initialize(SMSG_PLAY_SOUND, 4);
*data << uint32(soundid);
+ *data << uint64(0);
}
void BattlegroundMgr::BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8);
- *data << uint64(guid);
+
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(guidBytes[1]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(guidBytes[0]);
+
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[5]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[6]);
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[3]);
}
-void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player)
+void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8);
- *data << uint64(player->GetGUID());
+
+ data->WriteBit(guidBytes[0]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[1]);
+
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[5]);
+ data->WriteByteSeq(guidBytes[3]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[6]);
}
Battleground* BattlegroundMgr::GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId)
@@ -479,7 +774,7 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType
return NULL;
BattlegroundContainer const& bgs = itr->second.m_Battlegrounds;
- //map is sorted and we can be sure that lowest instance id has only BG template
+ // map is sorted and we can be sure that lowest instance id has only BG template
return bgs.empty() ? NULL : bgs.begin()->second;
}
@@ -572,6 +867,12 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
case BATTLEGROUND_IC:
bg = new BattlegroundIC(*(BattlegroundIC*)bg_template);
break;
+ case BATTLEGROUND_TP:
+ bg = new BattlegroundTP(*(BattlegroundTP*)bg_template);
+ break;
+ case BATTLEGROUND_BFG:
+ bg = new BattlegroundBFG(*(BattlegroundBFG*)bg_template);
+ break;
case BATTLEGROUND_RB:
case BATTLEGROUND_AA:
bg = new Battleground(*bg_template);
@@ -590,6 +891,7 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
bg->SetRandomTypeID(bgTypeId);
bg->SetRated(isRated);
bg->SetRandom(isRandom);
+ bg->SetGuid(MAKE_NEW_GUID(bgTypeId, 0, HIGHGUID_BATTLEGROUND));
// Set up correct min/max player counts for scoreboards
if (bg->isArena())
@@ -662,6 +964,12 @@ bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg = new Battleground;
bg->SetRandom(true);
break;
+ case BATTLEGROUND_TP:
+ bg = new BattlegroundTP;
+ break;
+ case BATTLEGROUND_BFG:
+ bg = new BattlegroundBFG;
+ break;
default:
return false;
}
@@ -680,6 +988,7 @@ bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId);
+ bg->SetGuid(MAKE_NEW_GUID(data.bgTypeId, 0, HIGHGUID_BATTLEGROUND));
AddBattleground(bg);
@@ -727,7 +1036,7 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
data.StartMaxDist = dist * dist;
data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
- data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()];
+ data.BattlegroundName = bl->name;
data.MapID = bl->mapid[0];
if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
@@ -804,86 +1113,75 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u battlegrounds in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void BattlegroundMgr::InitAutomaticArenaPointDistribution()
+void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId)
{
- if (!sWorld->getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
+ if (!player)
return;
- time_t wstime = time_t(sWorld->getWorldState(WS_ARENA_DISTRIBUTION_TIME));
- time_t curtime = time(NULL);
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Initializing Automatic Arena Point Distribution");
- if (wstime < curtime)
- {
- m_NextAutoDistributionTime = curtime; // reset will be called in the next update
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: Next arena point distribution time in the past, reseting it now.");
- }
- else
- m_NextAutoDistributionTime = wstime;
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Automatic Arena Point Distribution initialized.");
-}
+ BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
+ if (it == bgDataStore.end())
+ return;
-void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere)
-{
- if (!player)
+ PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second.m_Battlegrounds.begin()->second->GetMapId(), player->getLevel());
+ if (!bracketEntry)
return;
- uint32 winner_kills = player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST;
- uint32 winner_arena = player->GetRandomWinner() ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST;
- uint32 loser_kills = player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST;
+ uint32 winner_conquest = (player->GetRandomWinner() ? BG_REWARD_WINNER_CONQUEST_FIRST : BG_REWARD_WINNER_CONQUEST_LAST) / CURRENCY_PRECISION;
+ uint32 winner_honor = (player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_FIRST : BG_REWARD_WINNER_HONOR_LAST) / CURRENCY_PRECISION;
+ uint32 loser_honor = (!player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_FIRST : BG_REWARD_LOSER_HONOR_LAST) / CURRENCY_PRECISION;
- winner_kills = Trinity::Honor::hk_honor_at_level(player->getLevel(), float(winner_kills));
- loser_kills = Trinity::Honor::hk_honor_at_level(player->getLevel(), float(loser_kills));
+ ObjectGuid guidBytes = guid;
data->Initialize(SMSG_BATTLEFIELD_LIST);
- *data << uint64(guid); // battlemaster guid
- *data << uint8(fromWhere); // from where you joined
- *data << uint32(bgTypeId); // battleground id
- *data << uint8(0); // unk
- *data << uint8(0); // unk
-
- // Rewards
- *data << uint8(player->GetRandomWinner()); // 3.3.3 hasWin
- *data << uint32(winner_kills); // 3.3.3 winHonor
- *data << uint32(winner_arena); // 3.3.3 winArena
- *data << uint32(loser_kills); // 3.3.3 lossHonor
-
- uint8 isRandom = bgTypeId == BATTLEGROUND_RB;
-
- *data << uint8(isRandom); // 3.3.3 isRandom
- if (isRandom)
- {
- // Rewards (random)
- *data << uint8(player->GetRandomWinner()); // 3.3.3 hasWin_Random
- *data << uint32(winner_kills); // 3.3.3 winHonor_Random
- *data << uint32(winner_arena); // 3.3.3 winArena_Random
- *data << uint32(loser_kills); // 3.3.3 lossHonor_Random
- }
+ *data << uint32(winner_conquest) // Winner Conquest Reward or Random Winner Conquest Reward
+ << uint32(winner_conquest) // Winner Conquest Reward or Random Winner Conquest Reward
+ << uint32(loser_honor) // Loser Honor Reward or Random Loser Honor Reward
+ << uint32(bgTypeId) // battleground id
+ << uint32(loser_honor) // Loser Honor Reward or Random Loser Honor Reward
+ << uint32(winner_honor) // Winner Honor Reward or Random Winner Honor Reward
+ << uint32(winner_honor) // Winner Honor Reward or Random Winner Honor Reward
+ << uint8(bracketEntry->maxLevel) // max level
+ << uint8(bracketEntry->minLevel); // min level
+
+ data->WriteBit(guidBytes[0]);
+ data->WriteBit(guidBytes[1]);
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(0); // unk
+ data->WriteBit(0); // unk
+
+ data->FlushBits();
+ size_t count_pos = data->bitwpos();
+ data->WriteBits(0, 24); // placeholder
+
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(0); // unk
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(0); // unk
+
+ data->FlushBits();
+
+ data->WriteByteSeq(guidBytes[6]);
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[5]);
- if (bgTypeId == BATTLEGROUND_AA) // arena
- *data << uint32(0); // unk (count?)
- else // battleground
+ uint32 count = 0;
+ BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
+ BattlegroundClientIdsContainer& clientIds = it->second.m_ClientBattlegroundIds[bracketId];
+ for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr)
{
- size_t count_pos = data->wpos();
- *data << uint32(0); // number of bg instances
-
- BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
- if (it != bgDataStore.end())
- {
- // expected bracket entry
- if (PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second.m_Battlegrounds.begin()->second->GetMapId(), player->getLevel()))
- {
- uint32 count = 0;
- BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
- BattlegroundClientIdsContainer& clientIds = it->second.m_ClientBattlegroundIds[bracketId];
- for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr)
- {
- *data << uint32(*itr);
- ++count;
- }
- data->put<uint32>(count_pos, count);
- }
- }
+ *data << uint32(*itr);
+ ++count;
}
+ data->PutBits(count_pos, count, 24); // bg instance count
+
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[3]);
}
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
@@ -893,8 +1191,6 @@ void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, Batt
float x, y, z, O;
uint32 mapid = bg->GetMapId();
uint32 team = player->GetBGTeam();
- if (team == 0)
- team = player->GetTeam();
bg->GetTeamStartLoc(team, x, y, z, O);
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "BattlegroundMgr::SendToBattleground: Sending %s to map %u, X %f, Y %f, Z %f, O %f (bgType %u)", player->GetName().c_str(), mapid, x, y, z, O, bgTypeId);
@@ -936,6 +1232,10 @@ BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgType
return BATTLEGROUND_QUEUE_EY;
case BATTLEGROUND_IC:
return BATTLEGROUND_QUEUE_IC;
+ case BATTLEGROUND_TP:
+ return BATTLEGROUND_QUEUE_TP;
+ case BATTLEGROUND_BFG:
+ return BATTLEGROUND_QUEUE_BFG;
case BATTLEGROUND_RB:
return BATTLEGROUND_QUEUE_RB;
case BATTLEGROUND_SA:
@@ -980,6 +1280,10 @@ BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueue
return BATTLEGROUND_SA;
case BATTLEGROUND_QUEUE_IC:
return BATTLEGROUND_IC;
+ case BATTLEGROUND_QUEUE_TP:
+ return BATTLEGROUND_TP;
+ case BATTLEGROUND_QUEUE_BFG:
+ return BATTLEGROUND_BFG;
case BATTLEGROUND_QUEUE_RB:
return BATTLEGROUND_RB;
case BATTLEGROUND_QUEUE_2v2:
@@ -1104,6 +1408,8 @@ HolidayIds BattlegroundMgr::BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId
case BATTLEGROUND_SA: return HOLIDAY_CALL_TO_ARMS_SA;
case BATTLEGROUND_AB: return HOLIDAY_CALL_TO_ARMS_AB;
case BATTLEGROUND_IC: return HOLIDAY_CALL_TO_ARMS_IC;
+ case BATTLEGROUND_TP: return HOLIDAY_CALL_TO_ARMS_TP;
+ case BATTLEGROUND_BFG: return HOLIDAY_CALL_TO_ARMS_BFG;
default: return HOLIDAY_NONE;
}
}
@@ -1118,6 +1424,8 @@ BattlegroundTypeId BattlegroundMgr::WeekendHolidayIdToBGType(HolidayIds holiday)
case HOLIDAY_CALL_TO_ARMS_SA: return BATTLEGROUND_SA;
case HOLIDAY_CALL_TO_ARMS_AB: return BATTLEGROUND_AB;
case HOLIDAY_CALL_TO_ARMS_IC: return BATTLEGROUND_IC;
+ case HOLIDAY_CALL_TO_ARMS_TP: return BATTLEGROUND_TP;
+ case HOLIDAY_CALL_TO_ARMS_BFG: return BATTLEGROUND_BFG;
default: return BATTLEGROUND_TYPE_NONE;
}
}
@@ -1207,4 +1515,3 @@ void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 ins
{
bgDataStore[bgTypeId].m_Battlegrounds.erase(instanceId);
}
-
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index c66d9d64ab8..03feb57edd3 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -30,8 +30,7 @@ typedef std::set<uint32> BattlegroundClientIdsContainer;
typedef UNORDERED_MAP<uint32, BattlegroundTypeId> BattleMastersMap;
-#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
-#define WS_ARENA_DISTRIBUTION_TIME 20001 // Custom worldstate
+#define WS_CURRENCY_RESET_TIME 20001 // Custom worldstate
struct CreateBattlegroundData
{
@@ -74,13 +73,13 @@ class BattlegroundMgr
void Update(uint32 diff);
/* Packet Building */
- void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player);
+ void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, uint64 guid);
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid);
- void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
- void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
+ void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId);
+ void BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* pPlayer, uint8 QueueSlot, GroupJoinBattlegroundResult result);
void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg);
- void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, uint32 arenaFaction);
+ void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundId);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, uint64 guid);
@@ -124,7 +123,6 @@ class BattlegroundMgr
uint32 GetMaxRatingDifference() const;
uint32 GetRatingDiscardTimer() const;
- void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{
@@ -150,8 +148,6 @@ class BattlegroundMgr
BattlegroundSelectionWeightMap m_BGSelectionWeights;
std::vector<uint64> m_QueueUpdateScheduler;
uint32 m_NextRatedArenaUpdate;
- time_t m_NextAutoDistributionTime;
- uint32 m_AutoDistributionTimeChecker;
bool m_ArenaTesting;
bool m_Testing;
BattleMastersMap mBattleMastersMap;
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 1dc9189d80c..5d6bab27070 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -392,10 +392,11 @@ void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId);
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType);
uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId);
+
plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
// queue->removeplayer, it causes bugs
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, plr2, queueSlot, STATUS_NONE, plr2->GetBattlegroundQueueJoinTime(group->BgTypeId), 0, 0);
plr2->GetSession()->SendPacket(&data);
}
// then actually delete, this may delete the group as well!
@@ -480,7 +481,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg,
player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
// send status packet
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, player->GetBattlegroundQueueJoinTime(bgTypeId), ginfo->ArenaType);
player->GetSession()->SendPacket(&data);
}
return true;
@@ -630,7 +631,7 @@ bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint
}
// this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
-bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
+bool BattlegroundQueue::CheckNormalMatch(Battleground* /*bg_template*/, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
{
GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
@@ -666,7 +667,7 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, Battleground
return false;
}
//allow 1v0 if debug bg
- if (sBattlegroundMgr->isTesting() && bg_template->isBattleground() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
+ if (sBattlegroundMgr->isTesting() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
return true;
//return true if there are enough players in selection pools - enable to work .debug bg command correctly
return m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers;
@@ -1002,7 +1003,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
WorldPacket data;
//we must send remaining time in queue
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, m_ArenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, player->GetBattlegroundQueueJoinTime(m_BgTypeId), m_ArenaType);
player->GetSession()->SendPacket(&data);
}
}
@@ -1050,7 +1051,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId());
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_NONE, player->GetBattlegroundQueueJoinTime(m_BgTypeId), 0, 0);
player->GetSession()->SendPacket(&data);
}
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp
new file mode 100644
index 00000000000..d067967e682
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Battleground.h"
+#include "BattlegroundBFG.h"
+#include "Creature.h"
+#include "GameObject.h"
+#include "Language.h"
+#include "Object.h"
+#include "ObjectMgr.h"
+#include "BattlegroundMgr.h"
+#include "Player.h"
+#include "World.h"
+#include "WorldPacket.h"
+
+BattlegroundBFG::BattlegroundBFG()
+{
+}
+
+BattlegroundBFG::~BattlegroundBFG()
+{
+}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
new file mode 100644
index 00000000000..088fe3bc142
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BATTLEGROUNDBFG_H
+#define __BATTLEGROUNDBFG_H
+
+#include "Battleground.h"
+
+class BattlegroundBFGScore : public BattlegroundScore
+{
+ public:
+ BattlegroundBFGScore(): BasesAssaulted(0), BasesDefended(0) {};
+ virtual ~BattlegroundBFGScore() {};
+
+ uint32 BasesAssaulted;
+ uint32 BasesDefended;
+};
+
+class BattlegroundBFG : public Battleground
+{
+ public:
+ BattlegroundBFG();
+ ~BattlegroundBFG();
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index da43c492738..a73eee25ac1 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -76,7 +76,7 @@ void BattlegroundIC::SendTransportInit(Player* player)
if (!gunshipAlliance || !gunshipHorde)
return;
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
gunshipAlliance->BuildCreateUpdateBlockForPlayer(&transData, player);
gunshipHorde->BuildCreateUpdateBlockForPlayer(&transData, player);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 08eb582b954..0fd963cc0cf 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -270,7 +270,7 @@ void BattlegroundSA::StartShips()
{
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
{
- UpdateData data;
+ UpdateData data(p->GetMapId());
WorldPacket pkt;
GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p);
data.BuildPacket(&pkt);
@@ -940,8 +940,9 @@ void BattlegroundSA::SendTransportInit(Player* player)
{
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
{
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
if (BgObjects[BG_SA_BOAT_ONE])
+
GetBGObject(BG_SA_BOAT_ONE)->BuildCreateUpdateBlockForPlayer(&transData, player);
if (BgObjects[BG_SA_BOAT_TWO])
GetBGObject(BG_SA_BOAT_TWO)->BuildCreateUpdateBlockForPlayer(&transData, player);
@@ -955,7 +956,7 @@ void BattlegroundSA::SendTransportsRemove(Player* player)
{
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
{
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
if (BgObjects[BG_SA_BOAT_ONE])
GetBGObject(BG_SA_BOAT_ONE)->BuildOutOfRangeUpdateBlock(&transData);
if (BgObjects[BG_SA_BOAT_TWO])
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp
new file mode 100644
index 00000000000..05fbc723cac
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Battleground.h"
+#include "BattlegroundTP.h"
+#include "Creature.h"
+#include "GameObject.h"
+#include "Language.h"
+#include "Object.h"
+#include "ObjectMgr.h"
+#include "BattlegroundMgr.h"
+#include "Player.h"
+#include "World.h"
+#include "WorldPacket.h"
+
+BattlegroundTP::BattlegroundTP()
+{
+}
+
+BattlegroundTP::~BattlegroundTP()
+{
+}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
new file mode 100644
index 00000000000..c5706fd7ccc
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BATTLEGROUNDTP_H
+#define __BATTLEGROUNDTP_H
+
+#include "Battleground.h"
+
+class BattlegroundTPScore : public BattlegroundScore
+{
+ public:
+ BattlegroundTPScore() : FlagCaptures(0), FlagReturns(0) {};
+ virtual ~BattlegroundTPScore() {};
+
+ uint32 FlagCaptures;
+ uint32 FlagReturns;
+};
+
+class BattlegroundTP : public Battleground
+{
+ public:
+ BattlegroundTP();
+ ~BattlegroundTP();
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 03027b8500f..c35b39719fc 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -64,7 +64,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
- if (GetStartTime() >= 27*MINUTE*IN_MILLISECONDS)
+ if (GetElapsedTime() >= 27*MINUTE*IN_MILLISECONDS)
{
if (GetTeamScore(TEAM_ALLIANCE) == 0)
{
@@ -83,7 +83,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
EndBattleground(ALLIANCE);
}
// first update needed after 1 minute of game already in progress
- else if (GetStartTime() > uint32(_minutesElapsed * MINUTE * IN_MILLISECONDS) + 3 * MINUTE * IN_MILLISECONDS)
+ else if (GetElapsedTime() > uint32(_minutesElapsed * MINUTE * IN_MILLISECONDS) + 3 * MINUTE * IN_MILLISECONDS)
{
++_minutesElapsed;
UpdateWorldState(BG_WS_STATE_TIMER, 25 - _minutesElapsed);
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index f455610666e..c8d1a94ff32 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -130,7 +130,6 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Addons
${CMAKE_CURRENT_SOURCE_DIR}/AI
${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI
- ${CMAKE_CURRENT_SOURCE_DIR}/AI/EventAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
@@ -146,6 +145,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/DataStores
${CMAKE_CURRENT_SOURCE_DIR}/DungeonFinding
${CMAKE_CURRENT_SOURCE_DIR}/Entities
+ ${CMAKE_CURRENT_SOURCE_DIR}/Entities/AreaTrigger
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Corpse
${CMAKE_CURRENT_SOURCE_DIR}/Entities/DynamicObject
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index d2a166c492c..0aa46d0d10b 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -521,6 +521,10 @@ void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEven
data << uint32(calendarEvent.GetType());
data << int32(calendarEvent.GetDungeonId());
data << uint64(invite.GetInviteId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
+
data << uint8(invite.GetStatus());
data << uint8(invite.GetRank());
data.appendPackGUID(calendarEvent.GetCreatorGUID());
@@ -557,7 +561,9 @@ void CalendarMgr::SendCalendarEvent(uint64 guid, CalendarEvent const& calendarEv
data << uint32(calendarEvent.GetFlags());
data.AppendPackedTime(calendarEvent.GetEventTime());
data.AppendPackedTime(calendarEvent.GetTimeZoneTime());
- data << uint32(calendarEvent.GetGuildId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
data << uint32(eventInviteeList.size());
for (CalendarInviteStore::const_iterator itr = eventInviteeList.begin(); itr != eventInviteeList.end(); ++itr)
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index d1b3d0a9dd6..fac5a59d2f1 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -58,7 +58,8 @@ enum CalendarEventType
CALENDAR_TYPE_DUNGEON = 1,
CALENDAR_TYPE_PVP = 2,
CALENDAR_TYPE_MEETING = 3,
- CALENDAR_TYPE_OTHER = 4
+ CALENDAR_TYPE_OTHER = 4,
+ CALENDAR_TYPE_HEROIC = 5
};
enum CalendarRepeatType
diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp
index 62b3416f72e..aab67fb03bd 100644
--- a/src/server/game/Chat/Channels/ChannelMgr.cpp
+++ b/src/server/game/Chat/Channels/ChannelMgr.cpp
@@ -19,6 +19,7 @@
#include "ChannelMgr.h"
#include "Player.h"
#include "World.h"
+#include "WorldSession.h"
ChannelMgr::~ChannelMgr()
{
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 5218c9c9e55..1515c75597f 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -652,7 +652,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
}
//Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored)
-void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker)
+void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker, const char* addonPrefix /*= NULL*/)
{
uint32 messageLength = (message ? strlen(message) : 0) + 1;
@@ -706,6 +706,13 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint
*data << uint32(messageLength);
*data << message;
*data << uint8(0);
+
+ if (type == CHAT_MSG_RAID_BOSS_WHISPER || type == CHAT_MSG_RAID_BOSS_EMOTE)
+ {
+ *data << float(0.0f); // Added in 4.2.0, unk
+ *data << uint8(0); // Added in 4.2.0, unk
+ }
+
return;
}
default:
@@ -721,9 +728,16 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint
{
ASSERT(channelName);
*data << channelName;
+ *data << uint64(target_guid);
}
+ else if (type == uint8(CHAT_MSG_ADDON))
+ {
+ ASSERT(addonPrefix);
+ *data << addonPrefix;
+ }
+ else
+ *data << uint64(target_guid);
- *data << uint64(target_guid);
*data << uint32(messageLength);
*data << message;
if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK)
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index b6798a9e391..298bb91692b 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -52,7 +52,7 @@ class ChatHandler
explicit ChatHandler(WorldSession* session) : m_session(session), sentErrorMessage(false) {}
virtual ~ChatHandler() {}
- static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker);
+ static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker, const char* addonPrefix = NULL);
void FillMessageData(WorldPacket* data, uint8 type, uint32 language, uint64 target_guid, const char* message)
{
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index 729bbb60bf7..9febb365c16 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -167,7 +167,7 @@ bool ItemChatLink::Initialize(std::istringstream& iss)
return true;
}
-inline std::string ItemChatLink::FormatName(uint8 index, ItemLocale const* locale, char* const* suffixStrings) const
+inline std::string ItemChatLink::FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const
{
std::stringstream ss;
if (locale == NULL || index >= locale->Name.size())
@@ -183,7 +183,7 @@ bool ItemChatLink::ValidateName(char* buffer, const char* context)
{
ChatLink::ValidateName(buffer, context);
- char* const* suffixStrings = _suffix ? _suffix->nameSuffix : (_property ? _property->nameSuffix : NULL);
+ char* suffixStrings = _suffix ? _suffix->nameSuffix : (_property ? _property->nameSuffix : NULL);
bool res = (FormatName(LOCALE_enUS, NULL, suffixStrings) == buffer);
if (!res)
@@ -306,22 +306,18 @@ bool SpellChatLink::ValidateName(char* buffer, const char* context)
return false;
}
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
+ uint32 skillLineNameLength = strlen(skillLine->name);
+ if (skillLineNameLength > 0 && strncmp(skillLine->name, buffer, skillLineNameLength) == 0)
{
- uint32 skillLineNameLength = strlen(skillLine->name[i]);
- if (skillLineNameLength > 0 && strncmp(skillLine->name[i], buffer, skillLineNameLength) == 0)
- {
- // found the prefix, remove it to perform spellname validation below
- // -2 = strlen(": ")
- uint32 spellNameLength = strlen(buffer) - skillLineNameLength - 2;
- memcpy(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1);
- }
+ // found the prefix, remove it to perform spellname validation below
+ // -2 = strlen(": ")
+ uint32 spellNameLength = strlen(buffer) - skillLineNameLength - 2;
+ memcpy(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1);
}
}
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
- if (*_spell->SpellName[i] && strcmp(_spell->SpellName[i], buffer) == 0)
- return true;
+ if (*_spell->SpellName && strcmp(_spell->SpellName, buffer) == 0)
+ return true;
TC_LOG_TRACE(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked spell (id: %u) name wasn't found in any localization", context, _spell->Id);
return false;
@@ -376,9 +372,8 @@ bool AchievementChatLink::ValidateName(char* buffer, const char* context)
{
ChatLink::ValidateName(buffer, context);
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
- if (*_achievement->name[i] && strcmp(_achievement->name[i], buffer) == 0)
- return true;
+ if (*_achievement->name && strcmp(_achievement->name, buffer) == 0)
+ return true;
TC_LOG_TRACE(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked achievement (id: %u) name wasn't found in any localization", context, _achievement->ID);
return false;
diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h
index 57785fbe1a0..76ce4662d6f 100644
--- a/src/server/game/Chat/ChatLink.h
+++ b/src/server/game/Chat/ChatLink.h
@@ -61,7 +61,7 @@ public:
virtual bool ValidateName(char* buffer, const char* context);
protected:
- std::string FormatName(uint8 index, ItemLocale const* locale, char* const* suffixStrings) const;
+ std::string FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const;
ItemTemplate const* _item;
int32 _data[8];
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index e17582ecc9a..d6fb6905985 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -30,7 +30,7 @@
#include "Spell.h"
// Checks if object meets the condition
-// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
+// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: SmartAI)
bool Condition::Meets(ConditionSourceInfo& sourceInfo)
{
ASSERT(ConditionTarget < MAX_CONDITION_TARGETS);
@@ -428,6 +428,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case TYPEID_CORPSE:
mask |= GRID_MAP_TYPE_MASK_CORPSE;
break;
+ case TYPEID_AREATRIGGER:
+ mask |= GRID_MAP_TYPE_MASK_AREATRIGGER;
+ break;
default:
break;
}
@@ -441,6 +444,8 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
if (ConditionValue1 & TYPEMASK_CORPSE)
mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ if (ConditionValue1 & TYPEMASK_AREATRIGGER)
+ mask |= GRID_MAP_TYPE_MASK_AREATRIGGER;
break;
case CONDITION_RELATION_TO:
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
@@ -651,6 +656,7 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT ||
+ sourceType == CONDITION_SOURCE_TYPE_PHASE_DEFINITION ||
sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR);
}
@@ -726,6 +732,22 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32
return cond;
}
+ConditionList const* ConditionMgr::GetConditionsForPhaseDefinition(uint32 zone, uint32 entry)
+{
+ PhaseDefinitionConditionContainer::const_iterator itr = PhaseDefinitionsConditionStore.find(zone);
+ if (itr != PhaseDefinitionsConditionStore.end())
+ {
+ ConditionTypeContainer::const_iterator i = itr->second.find(entry);
+ if (i != itr->second.end())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_CONDITIONSYS, "GetConditionsForPhaseDefinition: found conditions for zone %u entry %u", zone, entry);
+ return &i->second;
+ }
+ }
+
+ return NULL;
+}
+
ConditionList ConditionMgr::GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId)
{
ConditionList cond;
@@ -965,6 +987,13 @@ void ConditionMgr::LoadConditions(bool isReload)
++count;
continue;
}
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ {
+ PhaseDefinitionsConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
+ valid = true;
+ ++count;
+ continue;
+ }
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
@@ -1476,6 +1505,13 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return false;
}
break;
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ if (!PhaseMgr::IsConditionTypeSupported(cond->ConditionType))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Condition source type `CONDITION_SOURCE_TYPE_PHASE_DEFINITION` does not support condition type %u, ignoring.", cond->ConditionType);
+ return false;
+ }
+ break;
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
@@ -2061,6 +2097,19 @@ void ConditionMgr::Clean()
SpellClickEventConditionStore.clear();
+ for (PhaseDefinitionConditionContainer::iterator itr = PhaseDefinitionsConditionStore.begin(); itr != PhaseDefinitionsConditionStore.end(); ++itr)
+ {
+ for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ {
+ for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ delete *i;
+ it->second.clear();
+ }
+ itr->second.clear();
+ }
+
+ PhaseDefinitionsConditionStore.clear();
+
for (NpcVendorConditionContainer::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index b49626747a6..2547e6bc8a8 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -129,7 +129,8 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
CONDITION_SOURCE_TYPE_NPC_VENDOR = 23,
CONDITION_SOURCE_TYPE_SPELL_PROC = 24,
- CONDITION_SOURCE_TYPE_MAX = 25 // MAX
+ CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 25,
+ CONDITION_SOURCE_TYPE_MAX = 26 // MAX
};
enum ComparisionType
@@ -226,6 +227,7 @@ typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer
typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> NpcVendorConditionContainer;
typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
+typedef std::map<int32 /*zoneId*/, ConditionTypeContainer> PhaseDefinitionConditionContainer;
typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
@@ -252,6 +254,7 @@ class ConditionMgr
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
+ ConditionList const* GetConditionsForPhaseDefinition(uint32 zone, uint32 entry);
ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId);
private:
@@ -271,6 +274,7 @@ class ConditionMgr
CreatureSpellConditionContainer SpellClickEventConditionStore;
NpcVendorConditionContainer NpcVendorConditionContainerStore;
SmartEventConditionContainer SmartEventConditionStore;
+ PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore;
};
template <class T> bool CompareValues(ComparisionType type, T val1, T val2)
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
new file mode 100644
index 00000000000..450ddd72d91
--- /dev/null
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DB2Stores.h"
+#include "DB2fmt.h"
+#include "DB2Utility.h"
+#include "Common.h"
+#include "Log.h"
+#include "World.h"
+
+DB2Storage<ItemEntry> sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply);
+DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostfmt);
+DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
+DB2Storage<ItemSparseEntry> sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply);
+DB2Storage<KeyChainEntry> sKeyChainStore(KeyChainfmt);
+
+typedef std::list<std::string> DB2StoreProblemList;
+
+typedef std::map<uint32 /*hash*/, DB2StorageBase*> DB2StorageMap;
+DB2StorageMap DB2Stores;
+
+uint32 DB2FilesCount = 0;
+
+static bool LoadDB2_assert_print(uint32 fsize, uint32 rsize, std::string const& filename)
+{
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).", filename.c_str(), fsize, rsize);
+
+ // ASSERT must fail after function call
+ return false;
+}
+
+template<class T>
+inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Storage<T>& storage, std::string const& db2_path, std::string const& filename)
+{
+ // compatibility format and C++ structure sizes
+ ASSERT(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDB2_assert_print(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()), sizeof(T), filename));
+
+ ++DB2FilesCount;
+
+ std::string db2_filename = db2_path + filename;
+ if (storage.Load(db2_filename.c_str(), uint32(sWorld->GetDefaultDbcLocale())))
+ {
+ for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
+ {
+ if (!(availableDb2Locales & (1 << i)))
+ continue;
+
+ if (uint32(sWorld->GetDefaultDbcLocale()) == i)
+ continue;
+
+ std::string localizedName(db2_path);
+ localizedName.append(localeNames[i]);
+ localizedName.push_back('/');
+ localizedName.append(filename);
+
+ if (!storage.LoadStringsFrom(localizedName.c_str(), i))
+ availableDb2Locales &= ~(1<<i); // mark as not available for speedup next checks
+ }
+ }
+ else
+ {
+ // sort problematic db2 to (1) non compatible and (2) nonexistent
+ if (FILE* f = fopen(db2_filename.c_str(), "rb"))
+ {
+ char buf[100];
+ snprintf(buf, 100,"(exist, but have %d fields instead " SIZEFMTD ") Wrong client version DBC file?", storage.GetFieldCount(), strlen(storage.GetFormat()));
+ errlist.push_back(db2_filename + buf);
+ fclose(f);
+ }
+ else
+ errlist.push_back(db2_filename);
+ }
+
+ DB2Stores[storage.GetHash()] = &storage;
+}
+
+void LoadDB2Stores(std::string const& dataPath)
+{
+ std::string db2Path = dataPath + "dbc/";
+
+ DB2StoreProblemList bad_db2_files;
+ uint32 availableDb2Locales = 0xFF;
+
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemStore, db2Path, "Item.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemSparseStore, db2Path, "Item-sparse.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sKeyChainStore, db2Path, "KeyChain.db2");
+
+ // error checks
+ if (bad_db2_files.size() >= DB2FilesCount)
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "\nIncorrect DataDir value in worldserver.conf or ALL required *.db2 files (%d) not found by path: %sdb2", DB2FilesCount, dataPath.c_str());
+ exit(1);
+ }
+ else if (!bad_db2_files.empty())
+ {
+ std::string str;
+ for (std::list<std::string>::iterator i = bad_db2_files.begin(); i != bad_db2_files.end(); ++i)
+ str += *i + "\n";
+
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "\nSome required *.db2 files (%u from %d) not found or not compatible:\n%s", (uint32)bad_db2_files.size(), DB2FilesCount, str.c_str());
+ exit(1);
+ }
+
+ // Check loaded DB2 files proper version
+ if (!sItemStore.LookupEntry(83086) || // last item added in 4.3.4 (15595)
+ !sItemExtendedCostStore.LookupEntry(3872) ) // last item extended cost added in 4.3.4 (15595)
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Please extract correct db2 files from client 4.3.4 15595.");
+ exit(1);
+ }
+
+ TC_LOG_INFO(LOG_FILTER_GENERAL, ">> Initialized %d DB2 data stores.", DB2FilesCount);
+}
+
+DB2StorageBase const* GetDB2Storage(uint32 type)
+{
+ DB2StorageMap::const_iterator itr = DB2Stores.find(type);
+ if (itr != DB2Stores.end())
+ return itr->second;
+
+ return NULL;
+}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
new file mode 100644
index 00000000000..17a92f98cde
--- /dev/null
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2STORES_H
+#define TRINITY_DB2STORES_H
+
+#include "DB2Store.h"
+#include "DB2Structure.h"
+#include <string>
+
+extern DB2Storage<ItemEntry> sItemStore;
+extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
+extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
+extern DB2Storage<ItemSparseEntry> sItemSparseStore;
+extern DB2Storage<KeyChainEntry> sKeyChainStore;
+
+void LoadDB2Stores(std::string const& dataPath);
+
+DB2StorageBase const* GetDB2Storage(uint32 type);
+
+#endif
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
new file mode 100644
index 00000000000..81b3301ade0
--- /dev/null
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2STRUCTURE_H
+#define TRINITY_DB2STRUCTURE_H
+
+#include "Common.h"
+#include "ItemPrototype.h"
+
+// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+// Structures used to access raw DB2 data and required packing to portability
+struct ItemEntry
+{
+ uint32 ID; // 0
+ uint32 Class; // 1
+ uint32 SubClass; // 2
+ int32 SoundOverrideSubclass; // 3
+ int32 Material; // 4
+ uint32 DisplayId; // 5
+ uint32 InventoryType; // 6
+ uint32 Sheath; // 7
+};
+
+struct ItemCurrencyCostEntry
+{
+ //uint32 Id;
+ uint32 ItemId;
+};
+
+struct ItemSparseEntry
+{
+ uint32 ID; // 0
+ uint32 Quality; // 1
+ uint32 Flags; // 2
+ uint32 Flags2; // 3
+ float Unk430_1;
+ float Unk430_2;
+ uint32 BuyCount;
+ uint32 BuyPrice; // 4
+ uint32 SellPrice; // 5
+ uint32 InventoryType; // 6
+ int32 AllowableClass; // 7
+ int32 AllowableRace; // 8
+ uint32 ItemLevel; // 9
+ int32 RequiredLevel; // 10
+ uint32 RequiredSkill; // 11
+ uint32 RequiredSkillRank; // 12
+ uint32 RequiredSpell; // 13
+ uint32 RequiredHonorRank; // 14
+ uint32 RequiredCityRank; // 15
+ uint32 RequiredReputationFaction; // 16
+ uint32 RequiredReputationRank; // 17
+ uint32 MaxCount; // 18
+ uint32 Stackable; // 19
+ uint32 ContainerSlots; // 20
+ int32 ItemStatType[MAX_ITEM_PROTO_STATS]; // 21 - 30
+ uint32 ItemStatValue[MAX_ITEM_PROTO_STATS]; // 31 - 40
+ int32 ItemStatUnk1[MAX_ITEM_PROTO_STATS]; // 41 - 50
+ int32 ItemStatUnk2[MAX_ITEM_PROTO_STATS]; // 51 - 60
+ uint32 ScalingStatDistribution; // 61
+ uint32 DamageType; // 62
+ uint32 Delay; // 63
+ float RangedModRange; // 64
+ int32 SpellId[MAX_ITEM_PROTO_SPELLS]; // 65 - 69
+ int32 SpellTrigger[MAX_ITEM_PROTO_SPELLS]; // 70 - 74
+ int32 SpellCharges[MAX_ITEM_PROTO_SPELLS]; // 75 - 79
+ int32 SpellCooldown[MAX_ITEM_PROTO_SPELLS]; // 80 - 84
+ int32 SpellCategory[MAX_ITEM_PROTO_SPELLS]; // 85 - 89
+ int32 SpellCategoryCooldown[MAX_ITEM_PROTO_SPELLS]; // 90 - 94
+ uint32 Bonding; // 95
+ LocalizedString* Name; // 96
+ LocalizedString* Name2; // 97
+ LocalizedString* Name3; // 98
+ LocalizedString* Name4; // 99
+ LocalizedString* Description; // 100
+ uint32 PageText; // 101
+ uint32 LanguageID; // 102
+ uint32 PageMaterial; // 103
+ uint32 StartQuest; // 104
+ uint32 LockID; // 105
+ int32 Material; // 106
+ uint32 Sheath; // 107
+ uint32 RandomProperty; // 108
+ uint32 RandomSuffix; // 109
+ uint32 ItemSet; // 110
+ uint32 Area; // 112
+ uint32 Map; // 113
+ uint32 BagFamily; // 114
+ uint32 TotemCategory; // 115
+ uint32 Color[MAX_ITEM_PROTO_SOCKETS]; // 116 - 118
+ uint32 Content[MAX_ITEM_PROTO_SOCKETS]; // 119 - 121
+ int32 SocketBonus; // 122
+ uint32 GemProperties; // 123
+ float ArmorDamageModifier; // 124
+ uint32 Duration; // 125
+ uint32 ItemLimitCategory; // 126
+ uint32 HolidayId; // 127
+ float StatScalingFactor; // 128
+ int32 CurrencySubstitutionId; // 129
+ int32 CurrencySubstitutionCount; // 130
+};
+
+#define MAX_ITEM_EXT_COST_ITEMS 5
+#define MAX_ITEM_EXT_COST_CURRENCIES 5
+
+struct ItemExtendedCostEntry
+{
+ uint32 ID; // 0 extended-cost entry id
+ //uint32 reqhonorpoints; // 1 required honor points
+ //uint32 reqarenapoints; // 2 required arena points
+ uint32 RequiredArenaSlot; // 3 arena slot restrictions (min slot value)
+ uint32 RequiredItem[MAX_ITEM_EXT_COST_ITEMS]; // 4-8 required item id
+ uint32 RequiredItemCount[MAX_ITEM_EXT_COST_ITEMS]; // 9-13 required count of 1st item
+ uint32 RequiredPersonalArenaRating; // 14 required personal arena rating
+ //uint32 ItemPurchaseGroup; // 15
+ uint32 RequiredCurrency[MAX_ITEM_EXT_COST_CURRENCIES];// 16-20 required curency id
+ uint32 RequiredCurrencyCount[MAX_ITEM_EXT_COST_CURRENCIES];// 21-25 required curency count
+ //uint32 Unknown[5]; // 26-30
+};
+
+#define KEYCHAIN_SIZE 32
+
+struct KeyChainEntry
+{
+ uint32 Id;
+ uint8 Key[KEYCHAIN_SIZE];
+};
+
+// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/server/game/DataStores/DB2Utility.cpp b/src/server/game/DataStores/DB2Utility.cpp
new file mode 100644
index 00000000000..3cb0f40cf3d
--- /dev/null
+++ b/src/server/game/DataStores/DB2Utility.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DB2Utility.h"
+#include "ObjectMgr.h"
+
+inline bool ItemExists(uint32 id)
+{
+ return sObjectMgr->GetItemTemplate(id) != NULL;
+}
+
+bool DB2Utilities::HasItemEntry(DB2Storage<ItemEntry> const& /*store*/, uint32 id)
+{
+ return ItemExists(id);
+}
+
+bool DB2Utilities::HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& /*store*/, uint32 id)
+{
+ return ItemExists(id);
+}
+
+void DB2Utilities::WriteItemDbReply(DB2Storage<ItemEntry> const& /*store*/, uint32 id, uint32 /*locale*/, ByteBuffer& buffer)
+{
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id);
+ ASSERT(proto);
+
+ buffer << uint32(proto->ItemId);
+ buffer << uint32(proto->Class);
+ buffer << uint32(proto->SubClass);
+ buffer << int32(proto->SoundOverrideSubclass);
+ buffer << uint32(proto->Material);
+ buffer << uint32(proto->DisplayInfoID);
+ buffer << uint32(proto->InventoryType);
+ buffer << uint32(proto->Sheath);
+}
+
+void DB2Utilities::WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> const& /*store*/, uint32 id, uint32 locale, ByteBuffer& buffer)
+{
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id);
+ ASSERT(proto);
+
+ ItemLocale const* localeData = locale ? sObjectMgr->GetItemLocale(id) : NULL;
+
+ buffer << uint32(proto->ItemId);
+ buffer << uint32(proto->Quality);
+ buffer << uint32(proto->Flags);
+ buffer << uint32(proto->Flags2);
+ buffer << float(proto->Unk430_1);
+ buffer << float(proto->Unk430_2);
+ buffer << uint32(proto->BuyCount);
+ buffer << int32(proto->BuyPrice);
+ buffer << uint32(proto->SellPrice);
+ buffer << uint32(proto->InventoryType);
+ buffer << int32(proto->AllowableClass);
+ buffer << int32(proto->AllowableRace);
+ buffer << uint32(proto->ItemLevel);
+ buffer << uint32(proto->RequiredLevel);
+ buffer << uint32(proto->RequiredSkill);
+ buffer << uint32(proto->RequiredSkillRank);
+ buffer << uint32(proto->RequiredSpell);
+ buffer << uint32(proto->RequiredHonorRank);
+ buffer << uint32(proto->RequiredCityRank);
+ buffer << uint32(proto->RequiredReputationFaction);
+ buffer << uint32(proto->RequiredReputationRank);
+ buffer << int32(proto->MaxCount);
+ buffer << int32(proto->Stackable);
+ buffer << uint32(proto->ContainerSlots);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << uint32(proto->ItemStat[x].ItemStatType);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatValue);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatUnk1);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatUnk2);
+
+ buffer << uint32(proto->ScalingStatDistribution);
+ buffer << uint32(proto->DamageType);
+ buffer << uint32(proto->Delay);
+ buffer << float(proto->RangedModRange);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellId);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << uint32(proto->Spells[x].SpellTrigger);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCharges);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCooldown);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << uint32(proto->Spells[x].SpellCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCategoryCooldown);
+
+ buffer << uint32(proto->Bonding);
+
+ // item name
+ std::string name = proto->Name1;
+ if (localeData)
+ ObjectMgr::GetLocaleString(localeData->Name, locale, name);
+
+ buffer << uint16(name.length());
+ if (name.length())
+ buffer << name;
+
+ for (uint32 i = 0; i < 3; ++i) // other 3 names
+ buffer << uint16(0);
+
+ std::string desc = proto->Description;
+ if (localeData)
+ ObjectMgr::GetLocaleString(localeData->Description, locale, desc);
+
+ buffer << uint16(desc.length());
+ if (desc.length())
+ buffer << desc;
+
+ buffer << uint32(proto->PageText);
+ buffer << uint32(proto->LanguageID);
+ buffer << uint32(proto->PageMaterial);
+ buffer << uint32(proto->StartQuest);
+ buffer << uint32(proto->LockID);
+ buffer << int32(proto->Material);
+ buffer << uint32(proto->Sheath);
+ buffer << int32(proto->RandomProperty);
+ buffer << int32(proto->RandomSuffix);
+ buffer << uint32(proto->ItemSet);
+
+ buffer << uint32(proto->Area);
+ buffer << uint32(proto->Map);
+ buffer << uint32(proto->BagFamily);
+ buffer << uint32(proto->TotemCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ buffer << uint32(proto->Socket[x].Color);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ buffer << uint32(proto->Socket[x].Content);
+
+ buffer << uint32(proto->socketBonus);
+ buffer << uint32(proto->GemProperties);
+ buffer << float(proto->ArmorDamageModifier);
+ buffer << int32(proto->Duration);
+ buffer << uint32(proto->ItemLimitCategory);
+ buffer << uint32(proto->HolidayId);
+ buffer << float(proto->StatScalingFactor); // StatScalingFactor
+ buffer << uint32(proto->CurrencySubstitutionId);
+ buffer << uint32(proto->CurrencySubstitutionCount);
+}
diff --git a/src/server/game/DataStores/DB2Utility.h b/src/server/game/DataStores/DB2Utility.h
new file mode 100644
index 00000000000..82ef692d320
--- /dev/null
+++ b/src/server/game/DataStores/DB2Utility.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DB2PACKETWRITER_H
+#define DB2PACKETWRITER_H
+
+#include "Define.h"
+
+template<class T>
+class DB2Storage;
+class ByteBuffer;
+struct ItemEntry;
+struct ItemSparseEntry;
+
+namespace DB2Utilities
+{
+ //
+ bool HasItemEntry(DB2Storage<ItemEntry> const& store, uint32 id);
+ bool HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& store, uint32 id);
+
+ //
+ void WriteItemDbReply(DB2Storage<ItemEntry> const& store, uint32 id, uint32 locale, ByteBuffer& buffer);
+ void WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> const& store, uint32 id, uint32 locale, ByteBuffer& buffer);
+}
+
+#endif // DB2PACKETWRITER_H
diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h
new file mode 100644
index 00000000000..e4b6801f36c
--- /dev/null
+++ b/src/server/game/DataStores/DB2fmt.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2SFRM_H
+#define TRINITY_DB2SFRM_H
+
+char const Itemfmt[]="niiiiiii";
+char const ItemCurrencyCostfmt[]="xn";
+char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii";
+char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiixxxxx";
+char const KeyChainfmt[]="nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+
+#endif
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index c4283bbca8a..1daf69f0b5f 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -24,7 +24,7 @@ enum LevelLimit
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
// use as default max player level, must be fit max level for used client
// also see MAX_LEVEL and STRONG_MAX_LEVEL define
- DEFAULT_MAX_LEVEL = 80,
+ DEFAULT_MAX_LEVEL = 85,
// client supported max level for player/pets/etc. Avoid overflow or client stability affected.
// also see GT_MAX_LEVEL define
@@ -63,17 +63,28 @@ enum AchievementFlags
{
ACHIEVEMENT_FLAG_COUNTER = 0x00000001, // Just count statistic (never stop and complete)
ACHIEVEMENT_FLAG_HIDDEN = 0x00000002, // Not sent to client - internal use only
- ACHIEVEMENT_FLAG_STORE_MAX_VALUE = 0x00000004, // Store only max value? used only in "Reach level xx"
+ ACHIEVEMENT_FLAG_PLAY_NO_VISUAL = 0x00000004, // Client does not play achievement earned visual
ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all requirements (and calculate max value)
ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max value ??)
ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max value)
ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, // Show as average value (value / time_in_days) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_BAR = 0x00000080, // Show as progress bar (value / max vale) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, //
- ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200 //
+ ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, //
+ ACHIEVEMENT_FLAG_UNK3 = 0x00000400, // ACHIEVEMENT_FLAG_HIDE_NAME_IN_TIE
+ ACHIEVEMENT_FLAG_REALM_FIRST_GUILD = 0x00000800, // first guild on realm done something
+ ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS = 0x00001000, // Shows in guild news
+ ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER = 0x00002000, // Shows in guild news header
+ ACHIEVEMENT_FLAG_GUILD = 0x00004000, //
+ ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS = 0x00008000, //
+ ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS = 0x00010000 //
};
-#define MAX_CRITERIA_REQUIREMENTS 2
+enum AchievementCriteriaLimits
+{
+ MAX_CRITERIA_REQUIREMENTS = 2,
+ MAX_ADDITIONAL_CRITERIA_CONDITIONS = 3
+};
enum AchievementCriteriaCondition
{
@@ -82,11 +93,60 @@ enum AchievementCriteriaCondition
ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 2, // only used in "Complete a daily quest every day for five consecutive days"
ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK5 = 5, // Have spell?
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK8 = 8,
ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
ACHIEVEMENT_CRITERIA_CONDITION_UNK13 = 13 // unk
};
+enum AchievementCriteriaAdditionalCondition
+{
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK2 = 2,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL = 3, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY = 4,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER = 5,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD = 6,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY = 7,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA = 8,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE = 11,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN = 14,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS = 15,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK16 = 16,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE = 17,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE = 18,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 20,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE = 24, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE = 25,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS = 26,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE = 27,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS = 28,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS = 29,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE = 30,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP = 32,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS = 33, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_SUBCLASS = 34, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_COMPLETE_QUEST_NOT_IN_GROUP = 35, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_PERSONAL_RATING = 37, // NYI (when implementing don't forget about ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX = 38,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL = 39,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL = 40,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE = 41,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW = 46,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK55 = 55,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_LFG_GROUP = 58, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK60 = 60,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_GUILD_GROUP = 61, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION = 62, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
+};
+
enum AchievementCriteriaFlags
{
ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar
@@ -105,6 +165,7 @@ enum AchievementCriteriaTimedTypes
ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_ITEM = 9, // Timer is started by using item with entry in timerStartEvent
+ ACHIEVEMENT_TIMED_TYPE_UNK = 10, // Unknown
ACHIEVEMENT_TIMED_TYPE_MAX
};
@@ -113,12 +174,14 @@ enum AchievementCriteriaTypes
{
ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
+ ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
@@ -192,12 +255,6 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH = 95,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR = 99,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100,
ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
@@ -213,18 +270,27 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
+ ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
+ ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
+ ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139 //struct { uint32 count; } Guild Challenge
};
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 120
-
-enum AchievementCategory
-{
- CATEGORY_CHILDRENS_WEEK = 163
-};
+#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 140
enum AreaFlags
{
- AREA_FLAG_UNK0 = 0x00000001, // Unknown
+ AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
@@ -252,7 +318,8 @@ enum AreaFlags
AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
- AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly
+ AREA_FLAG_NO_FLY_ZONE = 0x20000000, // Marks zones where you cannot fly
+ AREA_FLAG_UNK9 = 0x40000000,
};
enum Difficulty
@@ -344,6 +411,12 @@ enum ItemLimitCategoryMode
ITEM_LIMIT_CATEGORY_MODE_EQUIP = 1 // limit applied to amount equipped items (including used gems)
};
+enum MountFlags
+{
+ MOUNT_FLAG_CAN_PITCH = 0x4, // client checks MOVEMENTFLAG2_FULL_SPEED_PITCHING
+ MOUNT_FLAG_CAN_SWIM = 0x8, // client checks MOVEMENTFLAG_SWIMMING
+};
+
enum TotemCategoryType
{
TOTEM_CATEGORY_TYPE_KNIFE = 1,
@@ -365,6 +438,25 @@ enum SummonPropGroup
SUMMON_PROP_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts
};
+// SummonProperties.dbc, col 3
+enum SummonPropType
+{
+ SUMMON_PROP_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3
+ SUMMON_PROP_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3
+ SUMMON_PROP_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3
+ SUMMON_PROP_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3
+ SUMMON_PROP_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3
+ SUMMON_PROP_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3
+ SUMMON_PROP_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3
+ SUMMON_PROP_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3
+ SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3
+ SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3
+ SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells
+ SUMMON_PROP_TYPE_LIGHTWELL = 11, // summon lightwell, 6 spells in 3.0.3
+ SUMMON_PROP_TYPE_JEEVES = 12, // summon Jeeves, 1 spell in 3.3.5a
+ SUMMON_PROP_TYPE_LASHTAIL = 13 // Lashtail Hatchling, 1 spell in 4.2.2
+};
+
// SummonProperties.dbc, col 5
enum SummonPropFlags
{
@@ -384,7 +476,12 @@ enum SummonPropFlags
SUMMON_PROP_FLAG_UNK13 = 0x00001000, // Lightwell, Jeeves, Gnomish Alarm-o-bot, Build vehicles(wintergrasp)
SUMMON_PROP_FLAG_UNK14 = 0x00002000, // Guides, player follows
SUMMON_PROP_FLAG_UNK15 = 0x00004000, // Force of Nature, Shadowfiend, Feral Spirit, Summon Water Elemental
- SUMMON_PROP_FLAG_UNK16 = 0x00008000 // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related?
+ SUMMON_PROP_FLAG_UNK16 = 0x00008000, // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related?
+ SUMMON_PROP_FLAG_UNK17 = 0x00010000,
+ SUMMON_PROP_FLAG_UNK18 = 0x00020000,
+ SUMMON_PROP_FLAG_UNK19 = 0x00040000,
+ SUMMON_PROP_FLAG_UNK20 = 0x00080000,
+ SUMMON_PROP_FLAG_UNK21 = 0x00100000 // Totems
};
enum VehicleSeatFlags
@@ -436,4 +533,15 @@ enum VehicleSeatFlagsB
VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000 // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000
};
+// CurrencyTypes.dbc
+enum CurrencyTypes
+{
+ CURRENCY_TYPE_CONQUEST_POINTS = 390,
+ CURRENCY_TYPE_HONOR_POINTS = 392,
+ CURRENCY_TYPE_JUSTICE_POINTS = 395,
+ CURRENCY_TYPE_VALOR_POINTS = 396,
+ CURRENCY_TYPE_CONQUEST_META_ARENA = 483,
+ CURRENCY_TYPE_CONQUEST_META_RBG = 484,
+};
+
#endif
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 71fbf1c62b2..bb7eb802ef4 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -21,6 +21,7 @@
#include "SharedDefines.h"
#include "SpellMgr.h"
#include "DBCfmt.h"
+#include "ItemPrototype.h"
#include "Timer.h"
#include "ObjectDefines.h"
@@ -59,6 +60,7 @@ static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt);
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
+DBCStorage <ArmorLocationEntry> sArmorLocationStore(ArmorLocationfmt);
DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore(BannedAddOnsfmt);
@@ -70,6 +72,7 @@ DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
+DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore(ChrClassesXPowerTypesfmt);
DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt);
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
@@ -77,6 +80,7 @@ DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore(CreatureModelDatafmt
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
+uint32 PowersByClass[MAX_CLASSES][MAX_POWERS];
DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore(DestructibleModelDatafmt);
DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore(DungeonEncounterfmt);
@@ -106,16 +110,36 @@ DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore(GtNPCManaCos
DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore(GtOCTClassCombatRatingScalarfmt);
DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
-DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
+DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore(GtOCTHpPerStaminafmt);
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
+DBCStorage <GtSpellScalingEntry> sGtSpellScalingStore(GtSpellScalingfmt);
+DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore(GtOCTBaseHPByClassfmt);
+DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore(GtOCTBaseMPByClassfmt);
+DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore(GuildPerkSpellsfmt);
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
-DBCStorage <ItemEntry> sItemStore(Itemfmt);
+DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore(ImportPriceArmorfmt);
+DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore(ImportPriceQualityfmt);
+DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore(ImportPriceShieldfmt);
+DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore(ImportPriceWeaponfmt);
+DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore(ItemPriceBasefmt);
+DBCStorage <ItemReforgeEntry> sItemReforgeStore(ItemReforgefmt);
+DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore(ItemArmorQualityfmt);
+DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore(ItemArmorShieldfmt);
+DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore(ItemArmorTotalfmt);
+DBCStorage <ItemClassEntry> sItemClassStore(ItemClassfmt);
DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
-//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
+DBCStorage <ItemDamageEntry> sItemDamageAmmoStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageOneHandStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageOneHandCasterStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageRangedStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageThrownStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageWandStore(ItemDamagefmt);
+DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore(ItemDisenchantLootfmt);
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
-DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
@@ -133,6 +157,12 @@ DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // o
MapDifficultyMap sMapDifficultyMap;
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
+DBCStorage <MountCapabilityEntry> sMountCapabilityStore(MountCapabilityfmt);
+DBCStorage <MountTypeEntry> sMountTypeStore(MountTypefmt);
+
+DBCStorage <NameGenEntry> sNameGenStore(NameGenfmt);
+NameGenVectorArraysMap sGenNameVectoArraysMap;
+DBCStorage <NumTalentsAtLevelEntry> sNumTalentsAtLevelStore(NumTalentsAtLevelfmt);
DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt);
@@ -156,19 +186,39 @@ DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
SpellCategoryStore sSpellCategoryStore;
PetFamilySpellsStore sPetFamilySpellsStore;
+
+DBCStorage <SpellReagentsEntry> sSpellReagentsStore(SpellReagentsEntryfmt);
+DBCStorage <SpellScalingEntry> sSpellScalingStore(SpellScalingEntryfmt);
+DBCStorage <SpellTotemsEntry> sSpellTotemsStore(SpellTotemsEntryfmt);
+DBCStorage <SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore(SpellTargetRestrictionsEntryfmt);
+DBCStorage <SpellPowerEntry> sSpellPowerStore(SpellPowerEntryfmt);
+DBCStorage <SpellLevelsEntry> sSpellLevelsStore(SpellLevelsEntryfmt);
+DBCStorage <SpellInterruptsEntry> sSpellInterruptsStore(SpellInterruptsEntryfmt);
+DBCStorage <SpellEquippedItemsEntry> sSpellEquippedItemsStore(SpellEquippedItemsEntryfmt);
+DBCStorage <SpellClassOptionsEntry> sSpellClassOptionsStore(SpellClassOptionsEntryfmt);
+DBCStorage <SpellCooldownsEntry> sSpellCooldownsStore(SpellCooldownsEntryfmt);
+DBCStorage <SpellAuraOptionsEntry> sSpellAuraOptionsStore(SpellAuraOptionsEntryfmt);
+DBCStorage <SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore(SpellAuraRestrictionsEntryfmt);
+DBCStorage <SpellCastingRequirementsEntry> sSpellCastingRequirementsStore(SpellCastingRequirementsEntryfmt);
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
+DBCStorage <SpellCategoriesEntry> sSpellCategoriesStore(SpellCategoriesEntryfmt);
+DBCStorage <SpellEffectEntry> sSpellEffectStore(SpellEffectEntryfmt);
DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore(SpellDifficultyfmt);
DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt);
-DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
+DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftEntryfmt);
+DBCStorage <SpellShapeshiftFormEntry> sSpellShapeshiftFormStore(SpellShapeshiftFormfmt);
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
TalentSpellPosMap sTalentSpellPosMap;
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
+DBCStorage <TalentTreePrimarySpellsEntry> sTalentTreePrimarySpellsStore(TalentTreePrimarySpellsfmt);
+typedef std::map<uint32, std::vector<uint32> > TalentTreePrimarySpellsMap;
+TalentTreePrimarySpellsMap sTalentTreePrimarySpellsMap;
// store absolute bit position for first rank for talent inspect
static uint32 sTalentTabPages[MAX_CLASSES][3];
@@ -188,14 +238,15 @@ DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
TaxiPathNodesByPath sTaxiPathNodesByPath;
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
-DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore(TeamContributionPointsfmt);
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
+DBCStorage <UnitPowerBarEntry> sUnitPowerBarStore(UnitPowerBarfmt);
DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt);
DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt);
DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore(WMOAreaTableEntryfmt);
DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
+DBCStorage <PhaseEntry> sPhaseStores(PhaseEntryfmt);
typedef std::list<std::string> StoreProblemList;
@@ -280,39 +331,58 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex);
- LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sBannedAddOnsStore, dbcPath, "BannedAddOns.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");//15595
for (uint32 i = 0; i < sCharStartOutfitStore.GetNumRows(); ++i)
if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i))
sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit;
- LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrPowerTypesStore, dbcPath, "ChrClassesXPowerTypes.dbc");//15595
+ for (uint32 i = 0; i < MAX_CLASSES; ++i)
+ for (uint32 j = 0; j < MAX_POWERS; ++j)
+ PowersByClass[i][j] = MAX_POWERS;
+
+ for (uint32 i = 0; i < sChrPowerTypesStore.GetNumRows(); ++i)
+ {
+ if (ChrPowerTypesEntry const* power = sChrPowerTypesStore.LookupEntry(i))
+ {
+ uint32 index = 0;
+ for (uint32 j = 0; j < MAX_POWERS; ++j)
+ if (PowersByClass[power->classId][j] != MAX_POWERS)
+ ++index;
+
+ PowersByClass[power->classId][power->power] = index;
+ }
+ }
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");//15595
for (uint32 i=0; i<sFactionStore.GetNumRows(); ++i)
{
FactionEntry const* faction = sFactionStore.LookupEntry(i);
@@ -323,8 +393,8 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc");//15595
for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i)
{
if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i))
@@ -338,84 +408,154 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sGtNPCManaCostScalerStore, dbcPath, "gtNPCManaCostScaler.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");//15595
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTHpPerStaminaStore, dbcPath, "gtOCTHpPerStamina.dbc");//15595
//LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sGtOCTRegenMPStore, dbcPath, "gtOCTRegenMP.dbc"); -- not used currently
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenHPPerSptStore, dbcPath, "gtRegenHPPerSpt.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemStore, dbcPath, "Item.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtSpellScalingStore, dbcPath, "gtSpellScaling.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTBaseHPByClassStore, dbcPath, "gtOCTBaseHPByClass.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTBaseMPByClassStore, dbcPath, "gtOCTBaseMPByClass.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGuildPerkSpellsStore, dbcPath, "GuildPerkSpells.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceArmorStore, dbcPath, "ImportPriceArmor.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceQualityStore, dbcPath, "ImportPriceQuality.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceShieldStore, dbcPath, "ImportPriceShield.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceWeaponStore, dbcPath, "ImportPriceWeapon.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemPriceBaseStore, dbcPath, "ItemPriceBase.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemReforgeStore, dbcPath, "ItemReforge.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemClassStore, dbcPath, "ItemClass.dbc"); // 15595
//LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); -- not used currently
- //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemExtendedCostStore, dbcPath, "ItemExtendedCost.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorQualityStore, dbcPath, "ItemArmorQuality.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorShieldStore, dbcPath, "ItemArmorShield.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorTotalStore, dbcPath, "ItemArmorTotal.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageAmmoStore, dbcPath, "ItemDamageAmmo.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandStore, dbcPath, "ItemDamageOneHand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandCasterStore, dbcPath, "ItemDamageOneHandCaster.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageRangedStore, dbcPath, "ItemDamageRanged.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageThrownStore, dbcPath, "ItemDamageThrown.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandStore, dbcPath, "ItemDamageTwoHand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandCasterStore, dbcPath, "ItemDamageTwoHandCaster.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageWandStore, dbcPath, "ItemDamageWand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisenchantLootStore, dbcPath, "ItemDisenchantLoot.dbc");
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPhaseStores, dbcPath, "Phase.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");//15595
// fill data
- for (uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i)
+ sMapDifficultyMap[MAKE_PAIR32(0, 0)] = MapDifficulty(0, 0, false);//map 0 is missingg from MapDifficulty.dbc use this till its ported to sql
+ for (uint32 i = 0; i < sMapDifficultyStore.GetNumRows(); ++i)
if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i))
- sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0');
+ sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] > 0);
sMapDifficultyStore.Clear();
- LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMountCapabilityStore, dbcPath, "MountCapability.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMountTypeStore, dbcPath, "MountType.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNameGenStore, dbcPath, "NameGen.dbc");//15595
+ for (uint32 i = 0; i < sNameGenStore.GetNumRows(); ++i)
+ if (NameGenEntry const* entry = sNameGenStore.LookupEntry(i))
+ sGenNameVectoArraysMap[entry->race].stringVectorArray[entry->gender].push_back(std::string(entry->name));
+ sNameGenStore.Clear();
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNumTalentsAtLevelStore, dbcPath, "NumTalentsAtLevel.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");//15595
for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS)
ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
+ LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);//
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const* spell = sSpellStore.LookupEntry(i);
- if (spell && spell->Category)
- sSpellCategoryStore[spell->Category].insert(i);
+ if (!spell)
+ continue;
+
+ if (SpellCategoriesEntry const* category = sSpellCategoriesStore.LookupEntry(spell->SpellCategoriesId))
+ sSpellCategoryStore[category->Category].insert(i);
}
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellReagentsStore, dbcPath,"SpellReagents.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellScalingStore, dbcPath,"SpellScaling.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTotemsStore, dbcPath,"SpellTotems.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTargetRestrictionsStore, dbcPath,"SpellTargetRestrictions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellPowerStore, dbcPath,"SpellPower.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellLevelsStore, dbcPath,"SpellLevels.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellInterruptsStore, dbcPath,"SpellInterrupts.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEquippedItemsStore, dbcPath,"SpellEquippedItems.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellClassOptionsStore, dbcPath,"SpellClassOptions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCooldownsStore, dbcPath,"SpellCooldowns.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraOptionsStore, dbcPath,"SpellAuraOptions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraRestrictionsStore, dbcPath,"SpellAuraRestrictions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastingRequirementsStore, dbcPath,"SpellCastingRequirements.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath,"SpellCategories.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEffectStore, dbcPath,"SpellEffect.dbc", &CustomSpellEffectEntryfmt, &CustomSpellEffectEntryIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshift.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftFormStore, dbcPath, "SpellShapeshiftForm.dbc");//15595
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//15595
+
+ // Must be done when sSkillLineAbilityStore, sSpellStore, sSpellLevelsStore and sCreatureFamilyStore are all loaded
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j);
-
if (!skillLine)
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
+ if (!spellInfo)
+ continue;
+
+ SpellLevelsEntry const* levels = sSpellLevelsStore.LookupEntry(spellInfo->SpellLevelsId);
+ if (spellInfo->SpellLevelsId && (!levels || levels->spellLevel))
+ continue;
if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE)
{
@@ -427,8 +567,6 @@ void LoadDBCStores(const std::string& dataPath)
if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1])
continue;
- if (spellInfo->spellLevel)
- continue;
if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL)
continue;
@@ -438,20 +576,7 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex);
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshiftForm.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//15595
// Create Spelldifficulty searcher
for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i)
@@ -462,7 +587,7 @@ void LoadDBCStores(const std::string& dataPath)
SpellDifficultyEntry newEntry;
memset(newEntry.SpellID, 0, 4*sizeof(uint32));
- for (int x = 0; x < MAX_DIFFICULTY; ++x)
+ for (uint32 x = 0; x < MAX_DIFFICULTY; ++x)
{
if (spellDiff->SpellID[x] <= 0 || !sSpellStore.LookupEntry(spellDiff->SpellID[x]))
{
@@ -473,10 +598,11 @@ void LoadDBCStores(const std::string& dataPath)
else
newEntry.SpellID[x] = spellDiff->SpellID[x];
}
+
if (newEntry.SpellID[0] <= 0 || newEntry.SpellID[1] <= 0)//id0-1 must be always set!
continue;
- for (int x = 0; x < MAX_DIFFICULTY; ++x)
+ for (uint32 x = 0; x < MAX_DIFFICULTY; ++x)
sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID);
}
@@ -492,7 +618,7 @@ void LoadDBCStores(const std::string& dataPath)
sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i, j);
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc");//15595
// prepare fast data access to bit pos of talent ranks for use at inspecting
{
@@ -514,15 +640,21 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTreePrimarySpellsStore, dbcPath, "TalentTreePrimarySpells.dbc");
+ for (uint32 i = 0; i < sTalentTreePrimarySpellsStore.GetNumRows(); ++i)
+ if (TalentTreePrimarySpellsEntry const* talentSpell = sTalentTreePrimarySpellsStore.LookupEntry(i))
+ sTalentTreePrimarySpellsMap[talentSpell->TalentTree].push_back(talentSpell->SpellId);
+ sTalentTreePrimarySpellsStore.Clear();
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");//15595
for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price);
uint32 pathCount = sTaxiPathStore.GetNumRows();
//## TaxiPathNode.dbc ## Loaded only for initialization different structures
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc");//15595
// Calculate path nodes count
std::vector<uint32> pathLength;
pathLength.resize(pathCount); // 0 and some other indexes not used
@@ -545,11 +677,10 @@ void LoadDBCStores(const std::string& dataPath)
// include existed nodes that have at least single not spell base (scripted) path
{
std::set<uint32> spellPaths;
- for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
- if (SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
- for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
- if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI)
- spellPaths.insert(sInfo->EffectMiscValue[j]);
+ for (uint32 i = 1; i < sSpellEffectStore.GetNumRows(); ++i)
+ if (SpellEffectEntry const* sInfo = sSpellEffectStore.LookupEntry (i))
+ if (sInfo->Effect == SPELL_EFFECT_SEND_TAXI)
+ spellPaths.insert(sInfo->EffectMiscValue);
memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask));
memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask));
@@ -581,10 +712,10 @@ void LoadDBCStores(const std::string& dataPath)
}
// valid taxi network node
- uint8 field = (uint8)((i - 1) / 32);
- uint32 submask = 1<<((i-1)%32);
- sTaxiNodesMask[field] |= submask;
+ uint8 field = (uint8)((i - 1) / 8);
+ uint32 submask = 1 << ((i-1) % 8);
+ sTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981)
sHordeTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981)
@@ -602,19 +733,21 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc");
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sUnitPowerBarStore, dbcPath, "UnitPowerBar.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc");//15595
for (uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i)
if (WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i))
sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry));
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");//15595
// error checks
if (bad_dbc_files.size() >= DBCFileCount)
@@ -633,20 +766,25 @@ void LoadDBCStores(const std::string& dataPath)
}
// Check loaded DBC files proper version
- if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) added in 3.3.5a
- !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a
- !sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a
- !sItemStore.LookupEntry(56806) || // last gem property added in 3.3.5a
- !sItemExtendedCostStore.LookupEntry(2997) || // last item extended cost added in 3.3.5a
- !sMapStore.LookupEntry(724) || // last map added in 3.3.5a
- !sSpellStore.LookupEntry(80864) ) // last client known item added in 3.3.5a
+ if (!sAreaStore.LookupEntry(4713) || // last area (areaflag) added in 4.3.4 (15595)
+ !sCharTitlesStore.LookupEntry(287) || // last char title added in 4.3.4 (15595)
+ !sGemPropertiesStore.LookupEntry(2250) || // last gem property added in 4.3.4 (15595)
+ !sMapStore.LookupEntry(980) || // last map added in 4.3.4 (15595)
+ !sSpellStore.LookupEntry(121820) ) // last spell added in 4.3.4 (15595)
{
TC_LOG_ERROR(LOG_FILTER_GENERAL, "You have _outdated_ DBC files. Please extract correct versions from current using client.");
exit(1);
}
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Initialized %d DBC data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
+}
+
+const std::string* GetRandomCharacterName(uint8 race, uint8 gender)
+{
+ uint32 size = sGenNameVectoArraysMap[race].stringVectorArray[gender].size();
+ uint32 randPos = urand(0, size-1);
+ return &sGenNameVectoArraysMap[race].stringVectorArray[gender][randPos];
}
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
@@ -658,14 +796,14 @@ SimpleFactionsList const* GetFactionTeamList(uint32 faction)
return NULL;
}
-char* GetPetName(uint32 petfamily, uint32 dbclang)
+char const* GetPetName(uint32 petfamily, uint32 /*dbclang*/)
{
if (!petfamily)
return NULL;
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(petfamily);
if (!pet_family)
return NULL;
- return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL;
+ return pet_family->Name ? pet_family->Name : NULL;
}
TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
@@ -722,16 +860,16 @@ AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_
return NULL;
}
-char const* GetRaceName(uint8 race, uint8 locale)
+char const* GetRaceName(uint8 race, uint8 /*locale*/)
{
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
- return raceEntry ? raceEntry->name[locale] : NULL;
+ return raceEntry ? raceEntry->name : NULL;
}
-char const* GetClassName(uint8 class_, uint8 locale)
+char const* GetClassName(uint8 class_, uint8 /*locale*/)
{
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
- return classEntry ? classEntry->name[locale] : NULL;
+ return classEntry ? classEntry->name : NULL;
}
uint32 GetAreaFlagByMapId(uint32 mapid)
@@ -745,7 +883,7 @@ uint32 GetAreaFlagByMapId(uint32 mapid)
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
{
- if (mapid != 530 && mapid != 571) // speed for most cases
+ if (mapid != 530 && mapid != 571 && mapid != 732) // speed for most cases
return mapid;
if (WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
@@ -754,6 +892,28 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
return mapid;
}
+uint32 GetMaxLevelForExpansion(uint32 expansion)
+{
+ switch (expansion)
+ {
+ case CONTENT_1_60:
+ return 60;
+ case CONTENT_61_70:
+ return 70;
+ case CONTENT_71_80:
+ return 80;
+ case CONTENT_81_85:
+ return 85;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+Used only for calculate xp gain by content lvl.
+Calculation on Gilneas and group maps of LostIslands calculated as CONTENT_1_60.
+*/
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
{
mapid = GetVirtualMapForMapAndZone(mapid, zoneId);
@@ -764,11 +924,17 @@ ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
if (!mapEntry)
return CONTENT_1_60;
- switch (mapEntry->Expansion())
+ // no need enum all maps from phasing
+ if (mapEntry->rootPhaseMap >= 0)
+ mapid = mapEntry->rootPhaseMap;
+
+ switch (mapid)
{
- default: return CONTENT_1_60;
- case 1: return CONTENT_61_70;
- case 2: return CONTENT_71_80;
+ case 648: //LostIslands
+ case 654: //Gilneas
+ return CONTENT_1_60;
+ default:
+ return ContentLevels(mapEntry->Expansion());
}
}
@@ -887,6 +1053,15 @@ uint32 const* GetTalentTabPages(uint8 cls)
return sTalentTabPages[cls];
}
+std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree)
+{
+ TalentTreePrimarySpellsMap::const_iterator itr = sTalentTreePrimarySpellsMap.find(talentTree);
+ if (itr == sTalentTreePrimarySpellsMap.end())
+ return NULL;
+
+ return &itr->second;
+}
+
uint32 GetLiquidFlags(uint32 liquidType)
{
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquidType))
@@ -904,6 +1079,163 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui
return itr->second;
}
+uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId)
+{
+ return PowersByClass[classId][powerType];
+}
+
+uint32 ScalingStatValuesEntry::GetStatMultiplier(uint32 inventoryType) const
+{
+ if (inventoryType < MAX_INVTYPE)
+ {
+ switch (inventoryType)
+ {
+ case INVTYPE_NON_EQUIP:
+ case INVTYPE_BODY:
+ case INVTYPE_BAG:
+ case INVTYPE_TABARD:
+ case INVTYPE_AMMO:
+ case INVTYPE_QUIVER:
+ return 0;
+ case INVTYPE_HEAD:
+ case INVTYPE_CHEST:
+ case INVTYPE_LEGS:
+ case INVTYPE_2HWEAPON:
+ case INVTYPE_ROBE:
+ return StatMultiplier[0];
+ case INVTYPE_SHOULDERS:
+ case INVTYPE_WAIST:
+ case INVTYPE_FEET:
+ case INVTYPE_HANDS:
+ case INVTYPE_TRINKET:
+ return StatMultiplier[1];
+ case INVTYPE_NECK:
+ case INVTYPE_WRISTS:
+ case INVTYPE_FINGER:
+ case INVTYPE_SHIELD:
+ case INVTYPE_CLOAK:
+ case INVTYPE_HOLDABLE:
+ return StatMultiplier[2];
+ case INVTYPE_RANGED:
+ case INVTYPE_THROWN:
+ case INVTYPE_RANGEDRIGHT:
+ case INVTYPE_RELIC:
+ return StatMultiplier[3];
+ case INVTYPE_WEAPON:
+ case INVTYPE_WEAPONMAINHAND:
+ case INVTYPE_WEAPONOFFHAND:
+ return StatMultiplier[4];
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+uint32 ScalingStatValuesEntry::GetArmor(uint32 inventoryType, uint32 armorType) const
+{
+ if (inventoryType <= INVTYPE_ROBE && armorType < 4)
+ {
+ switch (inventoryType)
+ {
+ case INVTYPE_NON_EQUIP:
+ case INVTYPE_NECK:
+ case INVTYPE_BODY:
+ case INVTYPE_FINGER:
+ case INVTYPE_TRINKET:
+ case INVTYPE_WEAPON:
+ case INVTYPE_SHIELD:
+ case INVTYPE_RANGED:
+ case INVTYPE_2HWEAPON:
+ case INVTYPE_BAG:
+ case INVTYPE_TABARD:
+ break;
+ case INVTYPE_SHOULDERS:
+ return Armor[0][armorType];
+ case INVTYPE_CHEST:
+ case INVTYPE_ROBE:
+ return Armor[1][armorType];
+ case INVTYPE_HEAD:
+ return Armor[2][armorType];
+ case INVTYPE_LEGS:
+ return Armor[3][armorType];
+ case INVTYPE_FEET:
+ return Armor[4][armorType];
+ case INVTYPE_WAIST:
+ return Armor[5][armorType];
+ case INVTYPE_HANDS:
+ return Armor[6][armorType];
+ case INVTYPE_WRISTS:
+ return Armor[7][armorType];
+ case INVTYPE_CLOAK:
+ return CloakArmor;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+uint32 ScalingStatValuesEntry::GetDPSAndDamageMultiplier(uint32 subClass, bool isCasterWeapon, float* damageMultiplier) const
+{
+ if (!isCasterWeapon)
+ {
+ switch (subClass)
+ {
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ *damageMultiplier = 0.3f;
+ return dpsMod[0];
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
+ *damageMultiplier = 0.2f;
+ return dpsMod[1];
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ *damageMultiplier = 0.3f;
+ return dpsMod[4];
+ case ITEM_SUBCLASS_WEAPON_Obsolete:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC2:
+ case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
+ case ITEM_SUBCLASS_WEAPON_MISCELLANEOUS:
+ case ITEM_SUBCLASS_WEAPON_SPEAR:
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ break;
+ }
+ }
+ else
+ {
+ if (subClass <= ITEM_SUBCLASS_WEAPON_WAND)
+ {
+ uint32 mask = 1 << subClass;
+ // two-handed weapons
+ if (mask & 0x562)
+ {
+ *damageMultiplier = 0.2f;
+ return dpsMod[3];
+ }
+
+ if (mask & (1 << ITEM_SUBCLASS_WEAPON_WAND))
+ {
+ *damageMultiplier = 0.3f;
+ return dpsMod[5];
+ }
+ }
+ *damageMultiplier = 0.3f;
+ return dpsMod[2];
+ }
+ return 0;
+}
+
/// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery)
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty)
{
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index cac93a120a5..c52af7e1b22 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -28,7 +28,7 @@
typedef std::list<uint32> SimpleFactionsList;
SimpleFactionsList const* GetFactionTeamList(uint32 faction);
-char* GetPetName(uint32 petfamily, uint32 dbclang);
+char const* GetPetName(uint32 petfamily, uint32 dbclang);
uint32 GetTalentSpellCost(uint32 spellId);
TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
@@ -44,12 +44,19 @@ WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
+const std::string* GetRandomCharacterName(uint8 race, uint8 gender);
+
enum ContentLevels
{
- CONTENT_1_60 = 0,
- CONTENT_61_70,
- CONTENT_71_80
+ CONTENT_1_60 = 0,
+ CONTENT_61_70 = 1,
+ CONTENT_71_80 = 2,
+ CONTENT_81_85 = 3,
+ MAX_CONTENT
};
+
+uint32 GetMaxLevelForExpansion(uint32 expansion);
+
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
@@ -62,6 +69,7 @@ MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
uint32 const* /*[MAX_TALENT_TABS]*/ GetTalentTabPages(uint8 cls);
+std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree);
uint32 GetLiquidFlags(uint32 liquidType);
@@ -70,6 +78,7 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB
CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
+uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId);
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
extern DBCStorage <AchievementEntry> sAchievementStore;
@@ -78,6 +87,7 @@ extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access
extern DBCStorage <AreaGroupEntry> sAreaGroupStore;
extern DBCStorage <AreaPOIEntry> sAreaPOIStore;
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
+extern DBCStorage <ArmorLocationEntry> sArmorLocationStore;
extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
extern DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore;
@@ -88,6 +98,7 @@ extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
+extern DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore;
extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
@@ -116,15 +127,35 @@ extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
extern DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore;
extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore;
-extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
-extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
+extern DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore;
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
+extern DBCStorage <GtSpellScalingEntry> sGtSpellScalingStore;
+extern DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore;
+extern DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore;
+extern DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore;
extern DBCStorage <HolidaysEntry> sHolidaysStore;
-extern DBCStorage <ItemEntry> sItemStore;
+extern DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore;
+extern DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore;
+extern DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore;
+extern DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore;
+extern DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore;
+extern DBCStorage <ItemReforgeEntry> sItemReforgeStore;
+extern DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore;
+extern DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore;
+extern DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore;
+extern DBCStorage <ItemClassEntry> sItemClassStore;
extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageAmmoStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageOneHandStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageOneHandCasterStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageRangedStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageThrownStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageWandStore;
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
-extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
+extern DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore;
extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
@@ -134,6 +165,11 @@ extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore;
extern DBCStorage <LockEntry> sLockStore;
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
extern DBCStorage <MapEntry> sMapStore;
+extern DBCStorage <MountCapabilityEntry> sMountCapabilityStore;
+extern DBCStorage <MountTypeEntry> sMountTypeStore;
+extern DBCStorage <NameGenEntry> sNameGenStore;
+extern DBCStorage <NumTalentsAtLevelEntry> sNumTalentsAtLevelStore;
+extern DBCStorage <PhaseEntry> sPhaseStore;
//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
extern MapDifficultyMap sMapDifficultyMap;
extern DBCStorage <MovieEntry> sMovieStore;
@@ -159,8 +195,24 @@ extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore;
extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
+extern DBCStorage <SpellShapeshiftFormEntry> sSpellShapeshiftFormStore;
extern DBCStorage <SpellEntry> sSpellStore;
-extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
+extern DBCStorage <SpellAuraOptionsEntry> sSpellAuraOptionsStore;
+extern DBCStorage <SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore;
+extern DBCStorage <SpellCastingRequirementsEntry> sSpellCastingRequirementsStore;
+extern DBCStorage <SpellCategoriesEntry> sSpellCategoriesStore;
+extern DBCStorage <SpellClassOptionsEntry> sSpellClassOptionsStore;
+extern DBCStorage <SpellCooldownsEntry> sSpellCooldownsStore;
+extern DBCStorage <SpellEffectEntry> sSpellEffectStore;
+extern DBCStorage <SpellEquippedItemsEntry> sSpellEquippedItemsStore;
+extern DBCStorage <SpellInterruptsEntry> sSpellInterruptsStore;
+extern DBCStorage <SpellLevelsEntry> sSpellLevelsStore;
+extern DBCStorage <SpellPowerEntry> sSpellPowerStore;
+extern DBCStorage <SpellReagentsEntry> sSpellReagentsStore;
+extern DBCStorage <SpellScalingEntry> sSpellScalingStore;
+extern DBCStorage <SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore;
+extern DBCStorage <SpellTotemsEntry> sSpellTotemsStore;
+//extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
extern DBCStorage <TalentEntry> sTalentStore;
extern DBCStorage <TalentTabEntry> sTalentTabStore;
@@ -173,8 +225,8 @@ extern TaxiMask sAllianceTaxiNodesMask;
extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
-extern DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore;
extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
+extern DBCStorage <UnitPowerBarEntry> sUnitPowerBarStore;
extern DBCStorage <VehicleEntry> sVehicleStore;
extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore;
extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index c371fc781fd..a9afe7bafa6 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -44,35 +44,31 @@ struct AchievementEntry
int32 requiredFaction; // 1 -1=all, 0=horde, 1=alliance
int32 mapID; // 2 -1=none
//uint32 parentAchievement; // 3 its Achievement parent (can`t start while parent uncomplete, use its Criteria if don`t have own, use its progress on begin)
- char *name[16]; // 4-19
- //uint32 name_flags; // 20
- //char *description[16]; // 21-36
- //uint32 desc_flags; // 37
- uint32 categoryId; // 38
- uint32 points; // 39 reward points
- //uint32 OrderInCategory; // 40
- uint32 flags; // 41
- //uint32 icon; // 42 icon (from SpellIcon.dbc)
- //char *titleReward[16]; // 43-58
- //uint32 titleReward_flags; // 59
- uint32 count; // 60 - need this count of completed criterias (own or referenced achievement criterias)
- uint32 refAchievement; // 61 - referenced achievement (counting of all completed criterias)
+ char* name; // 4
+ //char* description; // 5
+ uint32 categoryId; // 6
+ uint32 points; // 7 reward points
+ //uint32 OrderInCategory; // 8
+ uint32 flags; // 9
+ //uint32 icon; // 10 icon (from SpellIcon.dbc)
+ //char* reward; // 11
+ uint32 count; // 12 - need this count of completed criterias (own or referenced achievement criterias)
+ uint32 refAchievement; // 13 - referenced achievement (counting of all completed criterias)
};
struct AchievementCategoryEntry
{
uint32 ID; // 0
uint32 parentCategory; // 1 -1 for main category
- //char *name[16]; // 2-17
- //uint32 name_flags; // 18
- //uint32 sortOrder; // 19
+ //char* name; // 2
+ //uint32 sortOrder; // 3
};
struct AchievementCriteriaEntry
{
uint32 ID; // 0
- uint32 referredAchievement; // 1
- uint32 requiredType; // 2
+ uint32 achievement; // 1
+ uint32 type; // 2
union
{
// ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0
@@ -91,6 +87,7 @@ struct AchievementCriteriaEntry
} win_bg;
// ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5
+ // ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125
struct
{
uint32 unused; // 3
@@ -131,6 +128,13 @@ struct AchievementCriteriaEntry
uint32 questCount; // 4
} complete_quests_in_zone;
+ // ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12
+ struct
+ {
+ uint32 currency;
+ uint32 count;
+ } currencyGain;
+
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14
struct
{
@@ -261,7 +265,14 @@ struct AchievementCriteriaEntry
struct
{
uint32 teamtype; // 3 {2, 3, 5}
- uint32 PersonalRating; // 4
+ uint32 teamrating; // 4
+ } reach_team_rating;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39
+ struct
+ {
+ uint32 teamtype; // 3 {2, 3, 5}
+ uint32 PersonalRating; // 4
} highest_personal_rating;
// ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40
@@ -371,6 +382,7 @@ struct AchievementCriteriaEntry
} do_emote;
// ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13
// ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55
+ // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56
struct
{
uint32 unused; // 3
@@ -499,21 +511,27 @@ struct AchievementCriteriaEntry
} raw;
};
+ //uint32 unk; // 5
+
struct
{
uint32 additionalRequirement_type;
uint32 additionalRequirement_value;
} additionalRequirements[MAX_CRITERIA_REQUIREMENTS];
- //char* name[16]; // 9-24
- //uint32 name_flags; // 25
- uint32 flags; // 26
- uint32 timedType; // 27
- uint32 timerStartEvent; // 28 Alway appears with timed events
- // for timed spells it is spell id for
- // timed kills it is creature id
- uint32 timeLimit; // 29 time limit in seconds
- //uint32 showOrder; // 30 show order
+ char* name; // 10 m_description_lang
+ uint32 completionFlag; // 11 m_flags
+ uint32 timedCriteriaStartType; // 12 m_timer_start_event Only appears with timed achievements, seems to be the type of starting a timed Achievement, only type 1 and some of type 6 need manual starting
+ // 1: ByEventId(?) (serverside IDs), 2: ByQuestId, 5: ByCastSpellId(?)
+ // 6: BySpellIdTarget(some of these are unknown spells, some not, some maybe spells)
+ // 7: ByKillNpcId, 9: ByUseItemId
+ uint32 timedCriteriaMiscId; // 13 m_timer_asset_id Alway appears with timed events, used internally to start the achievement, store
+ uint32 timeLimit; // 14 m_timer_time time limit in seconds
+ uint32 showOrder; // 15 m_ui_order also used in achievement shift-links as index in state bitmask
+ //uint32 unk1; // 16 only one value, still unknown
+ //uint32 unk2; // 17 all zeros
+ uint32 additionalConditionType[MAX_ADDITIONAL_CRITERIA_CONDITIONS]; // 18-20
+ uint32 additionalConditionValue[MAX_ADDITIONAL_CRITERIA_CONDITIONS - 1]; // 21-22 WTF one column was cut off here in 4.3.4
};
struct AreaTableEntry
@@ -522,13 +540,25 @@ struct AreaTableEntry
uint32 mapid; // 1
uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area
uint32 exploreFlag; // 3, main index
- uint32 flags; // 4, unknown value but 312 for all cities
- // 5-9 unused
+ uint32 flags; // 4,
+ //uint32 unk5; // 5,
+ //uint32 unk6; // 6,
+ //uint32 unk7; // 7,
+ //uint32 unk8; // 8,
+ //uint32 unk9; // 9,
int32 area_level; // 10
- char* area_name[16]; // 11-26
- // 27, string flags, unused
- uint32 team; // 28
- uint32 LiquidTypeOverride[4]; // 29-32 liquid override by type
+ char* area_name; // 11
+ uint32 team; // 12
+ uint32 LiquidTypeOverride[4]; // 13-16 liquid override by type
+ float MaxDepth; // 17,
+ float AmbientMultiplier; // 18 client only?
+ uint32 LightId; // 19
+ //uint32 unk20; // 20 4.0.0 - Mounting related
+ //uint32 unk21; // 21 4.0.0
+ //uint32 unk22; // 22 4.0.0
+ //uint32 unk23; // 23 4.0.0
+ //uint32 unk24; // 24 - worldStateId
+ //uint32 unk25 // 25
// helpers
bool IsSanctuary() const
@@ -554,16 +584,14 @@ struct AreaPOIEntry
uint32 icon[11]; //1-11
float x; //12
float y; //13
- float z; //14
- uint32 mapId; //15
- //uint32 val1; //16
- uint32 zoneId; //17
- //char* name[16]; //18-33
- //uint32 name_flag; //34
- //char* name2[16]; //35-50
- //uint32 name_flag2; //51
- uint32 worldState; //52
- //uint32 val2; //53
+ uint32 mapId; //14
+ //uint32 val1; //15
+ uint32 zoneId; //16
+ //char* name; //17 - name
+ //char* name2; //18 - name2
+ uint32 worldState; //19
+ //uint32 val2; //20
+ //uint32 unk; //21
};
struct AreaTriggerEntry
@@ -573,11 +601,20 @@ struct AreaTriggerEntry
float x; // 2 m_x
float y; // 3 m_y
float z; // 4 m_z
- float radius; // 5 m_radius
- float box_x; // 6 m_box_length
- float box_y; // 7 m_box_width
- float box_z; // 8 m_box_heigh
- float box_orientation; // 9 m_box_yaw
+ //uint32 // 5
+ //uint32 // 6
+ //uint32 // 7
+ float radius; // 8 m_radius
+ float box_x; // 9 m_box_length
+ float box_y; // 10 m_box_width
+ float box_z; // 11 m_box_heigh
+ float box_orientation; // 12 m_box_yaw
+};
+
+struct ArmorLocationEntry
+{
+ uint32 InventoryType; // 0
+ float Value[5]; // 1-5 multiplier for armor types (cloth...plate, no armor?)
};
struct AuctionHouseEntry
@@ -586,8 +623,7 @@ struct AuctionHouseEntry
uint32 faction; // 1 id of faction.dbc for player factions associated with city
uint32 depositPercent; // 2 1/3 from real
uint32 cutPercent; // 3
- //char* name[16]; // 4-19
- // 20 string flag, unused
+ //char* name; // 4
};
struct BankBagSlotPricesEntry
@@ -609,14 +645,12 @@ struct BarberShopStyleEntry
{
uint32 Id; // 0
uint32 type; // 1 value 0 -> hair, value 2 -> facialhair
- //char* name[16]; // 2-17 name of hair style
- //uint32 name_flags; // 18
- //uint32 unk_name[16]; // 19-34, all empty
- //uint32 unk_flags; // 35
- //float CostMultiplier; // 36 values 1 and 0.75
- uint32 race; // 37 race
- uint32 gender; // 38 0 -> male, 1 -> female
- uint32 hair_id; // 39 real ID to hair/facial hair
+ //char* name; // 2 m_DisplayName_lang
+ //uint32 unk_name; // 3 m_Description_lang
+ //float CostMultiplier; // 4 m_Cost_Modifier
+ uint32 race; // 5 m_race
+ uint32 gender; // 6 m_sex
+ uint32 hair_id; // 7 m_data (real ID to hair/facial hair)
};
struct BattlemasterListEntry
@@ -625,12 +659,15 @@ struct BattlemasterListEntry
int32 mapid[8]; // 1-8 mapid
uint32 type; // 9 (3 - BG, 4 - arena)
//uint32 canJoinAsGroup; // 10 (0 or 1)
- char* name[16]; // 11-26
- //uint32 nameFlags // 27 string flag, unused
- uint32 maxGroupSize; // 28 maxGroupSize, used for checking if queue as group
- uint32 HolidayWorldStateId; // 29 new 3.1
- //uint32 MinLevel; // 30
- //uint32 SomeLevel; // 31, may be max level
+ char* name; // 11
+ uint32 maxGroupSize; // 12 maxGroupSize, used for checking if queue as group
+ uint32 HolidayWorldStateId; // 13 new 3.1
+ uint32 minLevel; // 14, min level (sync with PvPDifficulty.dbc content)
+ uint32 maxLevel; // 15, max level (sync with PvPDifficulty.dbc content)
+ //uint32 maxGroupSizeRated; // 16 4.0.1
+ //uint32 unk; // 17 - 4.0.6.13596
+ //uint32 maxPlayers; // 18 4.0.1
+ //uint32 unk1; // 19 4.0.3, value 2 for Rated Battlegrounds
};
#define MAX_OUTFIT_ITEMS 24
@@ -645,46 +682,45 @@ struct CharStartOutfitEntry
int32 ItemId[MAX_OUTFIT_ITEMS]; // 5-28
//int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 29-52 not required at server side
//int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side
+ uint32 PetDisplayId; // 77 Pet Model ID for starting pet
+ uint32 PetFamilyEntry; // 78 Pet Family Entry for starting pet
};
struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
//uint32 unk1; // 1 flags?
- char* name[16]; // 2-17
- // 18 string flag, unused
- //char* name2[16]; // 19-34, unused
- // 35 string flag, unused
- uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
+ char* name; // 2 m_name_lang
+ //char* name2; // 3 m_name1_lang
+ uint32 bit_index; // 4 m_mask_ID used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
+ //uint32 // 5
};
struct ChatChannelsEntry
{
uint32 ChannelID; // 0
uint32 flags; // 1
- char* pattern[16]; // 3-18
- // 19 string flags, unused
- //char* name[16]; // 20-35 unused
- // 36 string flag, unused
+ //uint32 // 2 m_factionGroup
+ char* pattern; // 3 m_name_lang
+ //char* name; // 4 m_shortcut_lang
};
struct ChrClassesEntry
{
uint32 ClassID; // 0
- // 1, unused
- uint32 powerType; // 2
- // 3-4, unused
- char* name[16]; // 5-20 unused
- // 21 string flag, unused
- //char* nameFemale[16]; // 21-36 unused, if different from base (male) case
- // 37 string flag, unused
- //char* nameNeutralGender[16]; // 38-53 unused, if different from base (male) case
- // 54 string flag, unused
- // 55, unused
- uint32 spellfamily; // 56
- // 57, unused
- uint32 CinematicSequence; // 58 id from CinematicSequences.dbc
- uint32 expansion; // 59 (0 - original race, 1 - tbc addon, ...)
+ uint32 powerType; // 1 m_DisplayPower
+ // 2 m_petNameToken
+ char* name; // 3 m_name_lang
+ //char* nameFemale; // 4 m_name_female_lang
+ //char* nameNeutralGender; // 5 m_name_male_lang
+ //char* capitalizedName // 6, m_filename
+ uint32 spellfamily; // 7 m_spellClassSet
+ //uint32 flags2; // 8 m_flags (0x08 HasRelicSlot)
+ uint32 CinematicSequence; // 9 m_cinematicSequenceID
+ uint32 expansion; // 10 m_required_expansion
+ uint32 APPerStrenth; // 11 Attack Power bonus per point of strength
+ uint32 APPerAgility; // 12 Attack Power bonus per point of agility
+ uint32 RAPPerAgility; // 13 Ranged Attack Power bonus per point of agility
};
struct ChrRacesEntry
@@ -699,15 +735,23 @@ struct ChrRacesEntry
uint32 TeamID; // 7 (7-Alliance 1-Horde)
// 8-11 unused
uint32 CinematicSequence; // 12 id from CinematicSequences.dbc
- //uint32 unk_322; // 13 faction (0 alliance, 1 horde, 2 not available?)
- char* name[16]; // 14-29 used for DBC language detection/selection
- // 30 string flags, unused
- //char* nameFemale[16]; // 31-46, if different from base (male) case
- // 47 string flags, unused
- //char* nameNeutralGender[16]; // 48-63, if different from base (male) case
- // 64 string flags, unused
- // 65-67 unused
- uint32 expansion; // 68 (0 - original race, 1 - tbc addon, ...)
+ //uint32 unk_322; // 13 m_alliance (0 alliance, 1 horde, 2 not available?)
+ char* name; // 14 m_name_lang used for DBC language detection/selection
+ //char* nameFemale; // 15 m_name_female_lang
+ //char* nameNeutralGender; // 16 m_name_male_lang
+ // 17-18 m_facialHairCustomization[2]
+ // 19 m_hairCustomization
+ uint32 expansion; // 20 m_required_expansion
+ //uint32 // 21 (23 for worgens)
+ //uint32 // 22 4.0.0
+ //uint32 // 23 4.0.0
+};
+
+struct ChrPowerTypesEntry
+{
+ uint32 entry; // 0
+ uint32 classId; // 1
+ uint32 power; // 2
};
/* not used
@@ -747,6 +791,7 @@ struct CreatureDisplayInfoEntry
// 13 m_particleColorID
// 14 m_creatureGeosetData
// 15 m_objectEffectPackageID
+ // 16
};
struct CreatureFamilyEntry
@@ -760,18 +805,17 @@ struct CreatureFamilyEntry
uint32 petFoodMask; // 7 m_petFoodMask
int32 petTalentType; // 8 m_petTalentType
// 9 m_categoryEnumID
- char* Name[16]; // 10-25 m_name_lang
- // 26 string flags
- // 27 m_iconFile
+ char* Name; // 10 m_name_lang
+ // 11 m_iconFile
};
struct CreatureModelDataEntry
{
uint32 Id;
//uint32 Flags;
- //char* ModelPath[16]
+ //char* ModelPath
//uint32 Unk1;
- float Scale; // Used in calculation of unit collision data
+ //float Scale; // Used in calculation of unit collision data
//int32 Unk2
//int32 Unk3
//uint32 Unk4
@@ -799,9 +843,8 @@ struct CreatureSpellDataEntry
struct CreatureTypeEntry
{
uint32 ID; // 0 m_ID
- //char* Name[16]; // 1-16 name
- // 17 string flags
- //uint32 no_expirience; // 18 no exp? critters, non-combat pets, gas cloud.
+ //char* Name; // 1 m_name_lang
+ //uint32 no_expirience; // 2 m_flags no exp? critters, non-combat pets, gas cloud.
};
/* not used
@@ -816,33 +859,45 @@ struct CurrencyCategoryEntry
struct CurrencyTypesEntry
{
- //uint32 ID; // 0 not used
- uint32 ItemId; // 1 used as real index
- //uint32 Category; // 2 may be category
- uint32 BitIndex; // 3 bit index in PLAYER_FIELD_KNOWN_CURRENCIES (1 << (index-1))
+ uint32 ID; // 0 not used
+ uint32 Category; // 1 may be category
+ //char* name; // 2
+ //char* iconName; // 3
+ //uint32 unk4; // 4 all 0
+ uint32 HasSubstitution; // 5 archaeology-related (?)
+ uint32 SubstitutionId; // 6
+ uint32 TotalCap; // 7
+ uint32 WeekCap; // 8
+ uint32 Flags; // 9
+ //char* description; // 10
};
struct DestructibleModelDataEntry
{
uint32 Id;
+ uint32 DamagedDisplayId;
//uint32 DamagedUnk1;
//uint32 DamagedUnk2;
- uint32 DamagedDisplayId;
//uint32 DamagedUnk3;
+ uint32 DestroyedDisplayId;
//uint32 DestroyedUnk1;
//uint32 DestroyedUnk2;
- uint32 DestroyedDisplayId;
//uint32 DestroyedUnk3;
+ //uint32 DestroyedUnk4;
+ uint32 RebuildingDisplayId;
//uint32 RebuildingUnk1;
//uint32 RebuildingUnk2;
- uint32 RebuildingDisplayId;
//uint32 RebuildingUnk3;
+ //uint32 RebuildingUnk4;
+ uint32 SmokeDisplayId;
//uint32 SmokeUnk1;
//uint32 SmokeUnk2;
- uint32 SmokeDisplayId;
//uint32 SmokeUnk3;
- //uint32 Unk4;
- //uint32 Unk5;
+ //uint32 SmokeUnk4;
+ //uint32 UnkDisplayid;
+ //uint32 Unk6;
+ //uint32 Unk7;
+ //uint32 Unk8;
};
struct DungeonEncounterEntry
@@ -852,7 +907,7 @@ struct DungeonEncounterEntry
uint32 difficulty; // 2 instance mode
//uint32 unk0; // 3
uint32 encounterIndex; // 4 encounter index for creating completed mask
- char* encounterName[16]; // 5-20 encounter name
+ char* encounterName; // 5 encounter name
//uint32 nameFlags; // 21
//uint32 unk1; // 22
};
@@ -872,12 +927,13 @@ struct DurabilityQualityEntry
struct EmotesEntry
{
uint32 Id; // 0
- //char* Name; // 1, internal name
- //uint32 AnimationId; // 2, ref to animationData
+ //char* Name; // 1, internal name
+ //uint32 AnimationId; // 2, ref to animationData
uint32 Flags; // 3, bitmask, may be unit_flags
uint32 EmoteType; // 4, Can be 0, 1 or 2 (determine how emote are shown)
uint32 UnitStandState; // 5, uncomfirmed, may be enum UnitStandStateType
- //uint32 SoundId; // 6, ref to soundEntries
+ //uint32 SoundId; // 6, ref to soundEntries
+ //uint32 unk7 // 7
};
struct EmotesTextEntry
@@ -899,10 +955,9 @@ struct FactionEntry
float spilloverRateOut; // 20 Faction outputs rep * spilloverRateOut as spillover reputation
uint32 spilloverMaxRankIn; // 21 The highest rank the faction will profit from incoming spillover
//uint32 spilloverRank_unk; // 22 It does not seem to be the max standing at which a faction outputs spillover ...so no idea
- char* name[16]; // 23-38 m_name_lang
- // 39 string flags
- //char* description[16]; // 40-55 m_description_lang
- // 56 string flags
+ char* name; // 23 m_name_lang
+ //char* description; // 24 m_description_lang
+ uint32 GroupExpansion; // 25 m_factionGroupExpansion
// helpers
bool CanHaveReputation() const
@@ -928,6 +983,8 @@ struct FactionTemplateEntry
// helpers
bool IsFriendlyTo(FactionTemplateEntry const& entry) const
{
+ if (ID == entry.ID)
+ return true;
if (entry.faction)
{
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
@@ -941,6 +998,8 @@ struct FactionTemplateEntry
}
bool IsHostileTo(FactionTemplateEntry const& entry) const
{
+ if (ID == entry.ID)
+ return false;
if (entry.faction)
{
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
@@ -966,22 +1025,25 @@ struct FactionTemplateEntry
struct GameObjectDisplayInfoEntry
{
uint32 Displayid; // 0 m_ID
- char* filename; // 1
- //uint32 unk1[10]; //2-11
+ char* filename; // 1
+ //uint32 unk1[10]; //2-11
float minX;
float minY;
float minZ;
float maxX;
float maxY;
float maxZ;
- //uint32 transport; //18
+ //uint32 transport; //18
};
struct GemPropertiesEntry
{
- uint32 ID;
- uint32 spellitemenchantement;
- uint32 color;
+ uint32 ID; // 0 m_id
+ uint32 spellitemenchantement; // 1 m_enchant_id
+ // 2 m_maxcount_inv
+ // 3 m_maxcount_item
+ uint32 color; // 4 m_type
+ uint32 minJewelCraftingSkill; // 5 m_minJewelCraftingSkill
};
struct GlyphPropertiesEntry
@@ -989,7 +1051,7 @@ struct GlyphPropertiesEntry
uint32 Id;
uint32 SpellId;
uint32 TypeFlags;
- uint32 Unk1; // GlyphIconId (SpellIcon.dbc)
+ uint32 IconId; // GlyphIconId (SpellIcon.dbc)
};
struct GlyphSlotEntry
@@ -1006,21 +1068,25 @@ struct GlyphSlotEntry
struct GtBarberShopCostBaseEntry
{
+ //uint32 level;
float cost;
};
struct GtCombatRatingsEntry
{
+ //uint32 level;
float ratio;
};
struct GtChanceToMeleeCritBaseEntry
{
+ //uint32 level;
float base;
};
struct GtChanceToMeleeCritEntry
{
+ //uint32 level;
float ratio;
};
@@ -1049,10 +1115,15 @@ struct GtOCTRegenHPEntry
float ratio;
};
-//struct GtOCTRegenMPEntry
-//{
-// float ratio;
-//};
+struct GtOCTRegenMPEntry
+{
+ float ratio;
+};
+
+struct gtOCTHpPerStaminaEntry
+{
+ float ratio;
+};
struct GtRegenHPPerSptEntry
{
@@ -1064,12 +1135,33 @@ struct GtRegenMPPerSptEntry
float ratio;
};
+struct GtSpellScalingEntry
+{
+ float value;
+};
+
+struct GtOCTBaseHPByClassEntry
+{
+ float ratio;
+};
+
+struct GtOCTBaseMPByClassEntry
+{
+ float ratio;
+};
+
+struct GuildPerkSpellsEntry
+{
+ //uint32 Id;
+ uint32 Level;
+ uint32 SpellId;
+};
+
/* no used
struct HolidayDescriptionsEntry
{
uint32 ID; // 0, m_holidayDescriptionID
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
+ //char* name // 1 m_name_lang
};
*/
@@ -1077,8 +1169,7 @@ struct HolidayDescriptionsEntry
struct HolidayNamesEntry
{
uint32 ID; // 0, m_holidayNameID
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
+ //char* name // 1 m_name_lang
};
*/
@@ -1102,23 +1193,105 @@ struct HolidaysEntry
//uint32 flags; // 54 m_flags (0 = Darkmoon Faire, Fishing Contest and Wotlk Launch, rest is 1)
};
-struct ItemEntry
+// ImportPriceArmor.dbc
+struct ImportPriceArmorEntry
+{
+ uint32 InventoryType; // 1 Id/InventoryType
+ float ClothFactor; // 2 Price factor cloth
+ float LeatherFactor; // 3 Price factor leather
+ float MailFactor; // 4 Price factor mail
+ float PlateFactor; // 5 Price factor plate
+};
+
+// ImportPriceQuality.dbc
+struct ImportPriceQualityEntry
+{
+ uint32 QualityId; // 1 Quality Id (+1?)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceShield.dbc
+struct ImportPriceShieldEntry
+{
+ uint32 Id; // 1 Unk id (only 1 and 2)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceWeapon.dbc
+struct ImportPriceWeaponEntry
+{
+ uint32 Id; // 1 Unk id (mainhand - 0, offhand - 1, weapon - 2, 2hweapon - 3, ranged/rangedright/relic - 4)
+ float Factor; // 2 Price factor
+};
+
+// ItemPriceBase.dbc
+struct ItemPriceBaseEntry
+{
+ uint32 ItemLevel; // 2 Item level (1 - 1000)
+ float ArmorFactor; // 3 Price factor for armor
+ float WeaponFactor; // 4 Price factor for weapons
+};
+
+struct ItemReforgeEntry
+{
+ uint32 Id;
+ uint32 SourceStat;
+ float SourceMultiplier;
+ uint32 FinalStat;
+ float FinalMultiplier;
+};
+
+// common struct for:
+// ItemDamageAmmo.dbc
+// ItemDamageOneHand.dbc
+// ItemDamageOneHandCaster.dbc
+// ItemDamageRanged.dbc
+// ItemDamageThrown.dbc
+// ItemDamageTwoHand.dbc
+// ItemDamageTwoHandCaster.dbc
+// ItemDamageWand.dbc
+struct ItemDamageEntry
+{
+ uint32 Id; // 0 item level
+ float DPS[7]; // 1-7 multiplier for item quality
+ uint32 Id2; // 8 item level
+};
+
+struct ItemArmorQualityEntry
+{
+ uint32 Id; // 0 item level
+ float Value[7]; // 1-7 multiplier for item quality
+ uint32 Id2; // 8 item level
+};
+
+struct ItemArmorShieldEntry
{
- uint32 ID; // 0
- uint32 Class; // 1
- uint32 SubClass; // 2 some items have strange subclasses
- int32 SoundOverrideSubclass; // 3
- int32 Material; // 4
- uint32 DisplayId; // 5
- uint32 InventoryType; // 6
- uint32 Sheath; // 7
+ uint32 Id; // 0 item level
+ uint32 Id2; // 1 item level
+ float Value[7]; // 2-8 multiplier for item quality
+};
+
+struct ItemArmorTotalEntry
+{
+ uint32 Id; // 0 item level
+ uint32 Id2; // 1 item level
+ float Value[4]; // 2-5 multiplier for armor types (cloth...plate)
+};
+
+// ItemClass.dbc
+struct ItemClassEntry
+{
+ uint32 Class; // 1 item class id
+ //uint32 Unk; // 2 unk
+ //uint32 IsWeapon; // 3 1 for weapon, 0 for everything else
+ float PriceFactor; // 4 used to calculate certain prices
+ //char* Name; // class name
};
struct ItemBagFamilyEntry
{
uint32 ID; // 0
- //char* name[16] // 1-16 m_name_lang
- // // 17 name flags
+ //char* name; // 1 m_name_lang
};
struct ItemDisplayInfoEntry
@@ -1137,34 +1310,23 @@ struct ItemDisplayInfoEntry
// 11 m_particleColorID
};
-//struct ItemCondExtCostsEntry
-//{
-// uint32 ID;
-// uint32 condExtendedCost; // ItemTemplate::CondExtendedCost
-// uint32 itemextendedcostentry; // ItemTemplate::ExtendedCost
-// uint32 arenaseason; // arena season number(1-4)
-//};
-
-#define MAX_ITEM_EXTENDED_COST_REQUIREMENTS 5
-
-struct ItemExtendedCostEntry
+struct ItemDisenchantLootEntry
{
- uint32 ID; // 0 extended-cost entry id
- uint32 reqhonorpoints; // 1 required honor points
- uint32 reqarenapoints; // 2 required arena points
- uint32 reqarenaslot; // 3 arena slot restrctions (min slot value)
- uint32 reqitem[MAX_ITEM_EXTENDED_COST_REQUIREMENTS]; // 4-8 required item id
- uint32 reqitemcount[MAX_ITEM_EXTENDED_COST_REQUIREMENTS]; // 9-14 required count of 1st item
- uint32 reqpersonalarenarating; // 15 required personal arena rating};
+ uint32 Id;
+ uint32 ItemClass;
+ int32 ItemSubClass;
+ uint32 ItemQuality;
+ uint32 MinItemLevel;
+ uint32 MaxItemLevel;
+ uint32 RequiredDisenchantSkill;
};
struct ItemLimitCategoryEntry
{
uint32 ID; // 0 Id
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
- uint32 maxCount; // 18, max allowed equipped as item or in gem slot
- uint32 mode; // 19, 0 = have, 1 = equip (enum ItemLimitCategoryMode)
+ //char* name; // 1 m_name_lang
+ uint32 maxCount; // 2, m_quantity max allowed equipped as item or in gem slot
+ uint32 mode; // 3, m_flags 0 = have, 1 = equip (enum ItemLimitCategoryMode)
};
#define MAX_ITEM_ENCHANTMENT_EFFECTS 3
@@ -1172,23 +1334,19 @@ struct ItemLimitCategoryEntry
struct ItemRandomPropertiesEntry
{
uint32 ID; // 0 m_ID
- //char* internalName // 1 m_Name
+ //char* internalName // 1 m_Name
uint32 enchant_id[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 2-4 m_Enchantment
// 5-6 unused
- char* nameSuffix[16]; // 7-22 m_name_lang
- // 23 name flags
+ char* nameSuffix; // 7 m_name_lang
};
struct ItemRandomSuffixEntry
{
uint32 ID; // 0 m_ID
- char* nameSuffix[16]; // 1-16 m_name_lang
- // 17, name flags
- // 18 m_internalName
- uint32 enchant_id[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 19-21 m_enchantment
- //uint32 unk1[2] // 22-23 unknown
- uint32 prefix[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 24-26 m_allocationPct
- //uint32 unk2[2] // 27-28 unknown
+ char* nameSuffix; // 1 m_name_lang
+ // 2 m_internalName
+ uint32 enchant_id[5]; // 3-7 m_enchantment
+ uint32 prefix[5]; // 8-12 m_allocationPct
};
#define MAX_ITEM_SET_ITEMS 10
@@ -1197,35 +1355,34 @@ struct ItemRandomSuffixEntry
struct ItemSetEntry
{
//uint32 id // 0 m_ID
- char* name[16]; // 1-16 m_name_lang
- // 17 string flags, unused
- uint32 itemId[MAX_ITEM_SET_ITEMS]; // 18-27 m_itemID
- //uint32 unknown[7]; // 28-34 unk, all 0
- uint32 spells[MAX_ITEM_SET_SPELLS]; // 35-42 m_setSpellID
- uint32 items_to_triggerspell[MAX_ITEM_SET_SPELLS]; // 43-50 m_setThreshold
- uint32 required_skill_id; // 51 m_requiredSkill
- uint32 required_skill_value; // 52 m_requiredSkillRank
+ char* name; // 1 m_name_lang
+ uint32 itemId[MAX_ITEM_SET_ITEMS]; // 2-18 m_itemID
+ uint32 spells[MAX_ITEM_SET_SPELLS]; // 19-26 m_setSpellID
+ uint32 items_to_triggerspell[MAX_ITEM_SET_SPELLS]; // 27-34 m_setThreshold
+ uint32 required_skill_id; // 35 m_requiredSkill
+ uint32 required_skill_value; // 36 m_requiredSkillRank
};
struct LFGDungeonEntry
{
uint32 ID; // 0
- char* name[16]; // 1-17 Name lang
- uint32 minlevel; // 18
- uint32 maxlevel; // 19
- uint32 reclevel; // 20
- uint32 recminlevel; // 21
- uint32 recmaxlevel; // 22
- int32 map; // 23
- uint32 difficulty; // 24
- uint32 flags; // 25
- uint32 type; // 26
- //uint32 unk; // 27
- //char* iconname; // 28
- uint32 expansion; // 29
- //uint32 unk4; // 30
- uint32 grouptype; // 31
- //char* desc[16]; // 32-47 Description
+ char* name; // 1
+ uint32 minlevel; // 2
+ uint32 maxlevel; // 3
+ uint32 reclevel; // 4
+ uint32 recminlevel; // 5
+ uint32 recmaxlevel; // 6
+ int32 map; // 7
+ uint32 difficulty; // 8
+ uint32 flags; // 9
+ uint32 type; // 10
+ //uint32 unk2; // 11
+ //char* iconname; // 12
+ uint32 expansion; // 13
+ //uint32 unk4; // 14
+ uint32 grouptype; // 15
+ //char* desc; // 16 Description
+ uint32 randomCategoryId; // 17 RandomDungeonID assigned for this dungeon
// Helpers
uint32 Entry() const { return ID + (type << 24); }
};
@@ -1265,12 +1422,18 @@ struct LockEntry
//uint32 Action[MAX_LOCK_CASE]; // 25-32 m_Action
};
+struct PhaseEntry
+{
+ uint32 ID; // 0
+ char* Name; // 1
+ uint32 flag; // 2
+};
+
struct MailTemplateEntry
{
uint32 ID; // 0
- //char* subject[16]; // 1-16
- // 17 name flags, unused
- char* content[16]; // 18-33
+ //char* subject; // 1 m_subject_lang
+ char* content; // 2 m_body_lang
};
struct MapEntry
@@ -1279,23 +1442,22 @@ struct MapEntry
//char* internalname; // 1 unused
uint32 map_type; // 2
//uint32 unk_330; // 3
- // 4 0 or 1 for battlegrounds (not arenas)
- char* name[16]; // 5-20
- // 21 name flags, unused
- uint32 linked_zone; // 22 common zone for instance and continent map
- //char* hordeIntro[16]; // 23-38 text for PvP Zones
- // 39 intro text flags
- //char* allianceIntro[16]; // 40-55 text for PvP Zones
- // 56 intro text flags
- uint32 multimap_id; // 57
- // 58
- int32 entrance_map; // 59 map_id of entrance map
- float entrance_x; // 60 entrance x coordinate (if exist single entry)
- float entrance_y; // 61 entrance y coordinate (if exist single entry)
- // 62 -1, 0 and 720
- uint32 addon; // 63 (0-original maps, 1-tbc addon)
- uint32 unk_time; // 64 some kind of time?
- //uint32 maxPlayers; // 65 max players
+ //uint32 unk4; // 4 4.0.1
+ //uint32 isPvP; // 5 m_PVP 0 or 1 for battlegrounds (not arenas)
+ char* name; // 6 m_MapName_lang
+ uint32 linked_zone; // 7 m_areaTableID
+ //char* hordeIntro; // 8 m_MapDescription0_lang
+ //char* allianceIntro; // 9 m_MapDescription1_lang
+ uint32 multimap_id; // 10 m_LoadingScreenID (LoadingScreens.dbc)
+ //float BattlefieldMapIconScale; // 11 m_minimapIconScale
+ int32 entrance_map; // 12 m_corpseMapID map_id of entrance map in ghost mode (continent always and in most cases = normal entrance)
+ float entrance_x; // 13 m_corpseX entrance x coordinate in ghost mode (in most cases = normal entrance)
+ float entrance_y; // 14 m_corpseY entrance y coordinate in ghost mode (in most cases = normal entrance)
+ //uint32 timeOfDayOverride; // 15 m_timeOfDayOverride
+ uint32 addon; // 16 m_expansionID
+ uint32 expireTime; // 17 m_raidOffset
+ //uint32 maxPlayers; // 18 m_maxPlayers
+ int32 rootPhaseMap; // 19 new 4.0.0, mapid, related to phasing
// Helpers
uint32 Expansion() const { return addon; }
@@ -1330,18 +1492,52 @@ struct MapDifficultyEntry
//uint32 Id; // 0
uint32 MapId; // 1
uint32 Difficulty; // 2 (for arenas: arena slot)
- char* areaTriggerText; // 3-18 text showed when transfer to map failed (missing requirements)
- //uint32 textFlags; // 19
- uint32 resetTime; // 20
- uint32 maxPlayers; // 21
- //char* difficultyString; // 22
+ char* areaTriggerText; // 3 m_message_lang (text showed when transfer to map failed)
+ uint32 resetTime; // 4, m_raidDuration in secs, 0 if no fixed reset time
+ uint32 maxPlayers; // 5, m_maxPlayers some heroic versions have 0 when expected same amount as in normal version
+ //char* difficultyString; // 6 m_difficultystring
+};
+
+struct MountCapabilityEntry
+{
+ uint32 Id;
+ uint32 Flags;
+ uint32 RequiredRidingSkill;
+ uint32 RequiredArea;
+ uint32 RequiredAura;
+ uint32 RequiredSpell;
+ uint32 SpeedModSpell;
+ int32 RequiredMap;
+};
+
+#define MAX_MOUNT_CAPABILITIES 24
+
+struct MountTypeEntry
+{
+ uint32 Id;
+ uint32 MountCapability[MAX_MOUNT_CAPABILITIES];
};
struct MovieEntry
{
uint32 Id; // 0 index
//char* filename; // 1
- //uint32 unk2; // 2 always 100
+ //uint32 unk1; // 2 m_volume
+ //uint32 unk2; // 3 4.0.0
+};
+
+struct NameGenEntry
+{
+ //uint32 id;
+ char* name;
+ uint32 race;
+ uint32 gender;
+};
+
+struct NumTalentsAtLevelEntry
+{
+ //uint32 Level; // 0 index
+ float Talents; // 1 talent count
};
#define MAX_OVERRIDE_SPELL 10
@@ -1351,6 +1547,7 @@ struct OverrideSpellDataEntry
uint32 id; // 0
uint32 spellId[MAX_OVERRIDE_SPELL]; // 1-10
//uint32 unk0; // 11
+ //char* SpellBarName; // 12
};
struct PvPDifficultyEntry
@@ -1369,8 +1566,7 @@ struct PvPDifficultyEntry
struct QuestSortEntry
{
uint32 id; // 0 m_ID
- //char* name[16]; // 1-16 m_SortName_lang
- // 17 name flags
+ //char* name; // 1 m_SortName_lang
};
struct QuestXPEntry
@@ -1399,78 +1595,23 @@ struct ScalingStatDistributionEntry
uint32 Id; // 0
int32 StatMod[10]; // 1-10
uint32 Modifier[10]; // 11-20
- uint32 MaxLevel; // 21
+ //uint32 unk1; // 21
+ uint32 MaxLevel; // 22 m_maxlevel
};
struct ScalingStatValuesEntry
{
- uint32 Id; // 0
- uint32 Level; // 1
- uint32 ssdMultiplier[4]; // 2-5 Multiplier for ScalingStatDistribution
- uint32 armorMod[4]; // 6-9 Armor for level
- uint32 dpsMod[6]; // 10-15 DPS mod for level
- uint32 spellPower; // 16 spell power for level
- uint32 ssdMultiplier2; // 17 there's data from 3.1 dbc ssdMultiplier[3]
- uint32 ssdMultiplier3; // 18 3.3
- uint32 armorMod2[5]; // 19-23 Armor for level
-
- uint32 getssdMultiplier(uint32 mask) const
- {
- if (mask & 0x4001F)
- {
- if (mask & 0x00000001) return ssdMultiplier[0]; // Shoulder
- if (mask & 0x00000002) return ssdMultiplier[1]; // Trinket
- if (mask & 0x00000004) return ssdMultiplier[2]; // Weapon1H
- if (mask & 0x00000008) return ssdMultiplier2;
- if (mask & 0x00000010) return ssdMultiplier[3]; // Ranged
- if (mask & 0x00040000) return ssdMultiplier3;
- }
- return 0;
- }
-
- uint32 getArmorMod(uint32 mask) const
- {
- if (mask & 0x00F001E0)
- {
- if (mask & 0x00000020) return armorMod[0]; // Cloth shoulder
- if (mask & 0x00000040) return armorMod[1]; // Leather shoulder
- if (mask & 0x00000080) return armorMod[2]; // Mail shoulder
- if (mask & 0x00000100) return armorMod[3]; // Plate shoulder
-
- if (mask & 0x00080000) return armorMod2[0]; // cloak
- if (mask & 0x00100000) return armorMod2[1]; // cloth
- if (mask & 0x00200000) return armorMod2[2]; // leather
- if (mask & 0x00400000) return armorMod2[3]; // mail
- if (mask & 0x00800000) return armorMod2[4]; // plate
- }
- return 0;
- }
-
- uint32 getDPSMod(uint32 mask) const
- {
- if (mask & 0x7E00)
- {
- if (mask & 0x00000200) return dpsMod[0]; // Weapon 1h
- if (mask & 0x00000400) return dpsMod[1]; // Weapon 2h
- if (mask & 0x00000800) return dpsMod[2]; // Caster dps 1h
- if (mask & 0x00001000) return dpsMod[3]; // Caster dps 2h
- if (mask & 0x00002000) return dpsMod[4]; // Ranged
- if (mask & 0x00004000) return dpsMod[5]; // Wand
- }
- return 0;
- }
-
- uint32 getSpellBonus(uint32 mask) const
- {
- if (mask & 0x00008000) return spellPower;
- return 0;
- }
+ uint32 Id; // 0
+ uint32 Level; // 1
+ uint32 dpsMod[6]; // 2-7 DPS mod for level
+ uint32 Spellpower; // 8 spell power for level
+ uint32 StatMultiplier[5]; // 9-13 Multiplier for ScalingStatDistribution
+ uint32 Armor[8][4]; // 14-46 Armor for level
+ uint32 CloakArmor; // 47 armor for cloak
- uint32 getFeralBonus(uint32 mask) const // removed in 3.2.x?
- {
- if (mask & 0x00010000) return 0; // not used?
- return 0;
- }
+ uint32 GetStatMultiplier(uint32 inventoryType) const;
+ uint32 GetArmor(uint32 inventoryType, uint32 armorType) const;
+ uint32 GetDPSAndDamageMultiplier(uint32 subClass, bool isCasterWeapon, float* damageMultiplier) const;
};
//struct SkillLineCategoryEntry{
@@ -1502,14 +1643,11 @@ struct SkillLineEntry
uint32 id; // 0 m_ID
int32 categoryId; // 1 m_categoryID
//uint32 skillCostID; // 2 m_skillCostsID
- char* name[16]; // 3-18 m_displayName_lang
- // 19 string flags
- //char* description[16]; // 20-35 m_description_lang
- // 36 string flags
- uint32 spellIcon; // 37 m_spellIconID
- //char* alternateVerb[16]; // 38-53 m_alternateVerb_lang
- // 54 string flags
- uint32 canLink; // 55 m_canLink (prof. with recipes
+ char* name; // 3 m_displayName_lang
+ //char* description; // 4 m_description_lang
+ uint32 spellIcon; // 5 m_spellIconID
+ //char* alternateVerb; // 6 m_alternateVerb_lang
+ uint32 canLink; // 7 m_canLink (prof. with recipes)
};
struct SkillLineAbilityEntry
@@ -1526,7 +1664,7 @@ struct SkillLineAbilityEntry
uint32 learnOnGetSkill; // 9 m_acquireMethod
uint32 max_value; // 10 m_trivialSkillLineRankHigh
uint32 min_value; // 11 m_trivialSkillLineRankLow
- //uint32 characterPoints[2]; // 12-13 m_characterPoints[2]
+ uint32 character_points[2]; // 12-13 m_characterPoints
};
struct SoundEntriesEntry
@@ -1542,124 +1680,155 @@ struct SoundEntriesEntry
// 26 m_minDistance
// 27 m_distanceCutoff
// 28 m_EAXDef
- // 29 new in 3.1
+ // 29 m_soundEntriesAdvancedID, new in 3.1
+ //unk // 30 4.0.0
+ //unk // 31 4.0.0
+ //unk // 32 4.0.0
+ //unk // 33 4.0.0
+};
+
+// SpellEffect.dbc
+struct SpellEffectEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 Effect; // 1 m_effect
+ float EffectValueMultiplier; // 2 m_effectAmplitude
+ uint32 EffectApplyAuraName; // 3 m_effectAura
+ uint32 EffectAmplitude; // 4 m_effectAuraPeriod
+ int32 EffectBasePoints; // 5 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
+ float EffectBonusMultiplier; // 6 m_effectBonus
+ float EffectDamageMultiplier; // 7 m_effectChainAmplitude
+ uint32 EffectChainTarget; // 8 m_effectChainTargets
+ int32 EffectDieSides; // 9 m_effectDieSides
+ uint32 EffectItemType; // 10 m_effectItemType
+ uint32 EffectMechanic; // 11 m_effectMechanic
+ int32 EffectMiscValue; // 12 m_effectMiscValue
+ int32 EffectMiscValueB; // 13 m_effectMiscValueB
+ float EffectPointsPerComboPoint; // 14 m_effectPointsPerCombo
+ uint32 EffectRadiusIndex; // 15 m_effectRadiusIndex - spellradius.dbc
+ uint32 EffectRadiusMaxIndex; // 16 4.0.0
+ float EffectRealPointsPerLevel; // 17 m_effectRealPointsPerLevel
+ flag96 EffectSpellClassMask; // 18 19 20 m_effectSpellClassMask1(2/3), effect 0
+ uint32 EffectTriggerSpell; // 21 m_effectTriggerSpell
+ uint32 EffectImplicitTargetA; // 22 m_implicitTargetA
+ uint32 EffectImplicitTargetB; // 23 m_implicitTargetB
+ uint32 EffectSpellId; // 24 new 4.0.0
+ uint32 EffectIndex; // 25 new 4.0.0
+ //uint32 Unk0 // 26 4.2.0 only 0 or 1
};
#define MAX_SPELL_EFFECTS 3
#define MAX_EFFECT_MASK 7
#define MAX_SPELL_REAGENTS 8
+// SpellAuraOptions.dbc
+struct SpellAuraOptionsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 StackAmount; // 1 m_cumulativeAura
+ uint32 procChance; // 2 m_procChance
+ uint32 procCharges; // 3 m_procCharges
+ uint32 procFlags; // 4 m_procTypeMask
+};
+
+// SpellAuraRestrictions.dbc/
+struct SpellAuraRestrictionsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 CasterAuraState; // 1 m_casterAuraState
+ uint32 TargetAuraState; // 2 m_targetAuraState
+ uint32 CasterAuraStateNot; // 3 m_excludeCasterAuraState
+ uint32 TargetAuraStateNot; // 4 m_excludeTargetAuraState
+ uint32 casterAuraSpell; // 5 m_casterAuraSpell
+ uint32 targetAuraSpell; // 6 m_targetAuraSpell
+ uint32 excludeCasterAuraSpell; // 7 m_excludeCasterAuraSpell
+ uint32 excludeTargetAuraSpell; // 8 m_excludeTargetAuraSpell
+};
+
+// SpellCastingRequirements.dbc
+struct SpellCastingRequirementsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 FacingCasterFlags; // 1 m_facingCasterFlags
+ //uint32 MinFactionId; // 2 m_minFactionID not used
+ //uint32 MinReputation; // 3 m_minReputation not used
+ int32 AreaGroupId; // 4 m_requiredAreaGroupId
+ //uint32 RequiredAuraVision; // 5 m_requiredAuraVision not used
+ uint32 RequiresSpellFocus; // 6 m_requiresSpellFocus
+};
+
+#define MAX_SPELL_TOTEMS 2
+
+// SpellTotems.dbc
+struct SpellTotemsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 TotemCategory[MAX_SPELL_TOTEMS]; // 1 m_requiredTotemCategoryID
+ uint32 Totem[MAX_SPELL_TOTEMS]; // 2 m_totem
+};
+
+// Spell.dbc
struct SpellEntry
{
uint32 Id; // 0 m_ID
+ uint32 Attributes; // 1 m_attribute
+ uint32 AttributesEx; // 2 m_attributesEx
+ uint32 AttributesEx2; // 3 m_attributesExB
+ uint32 AttributesEx3; // 4 m_attributesExC
+ uint32 AttributesEx4; // 5 m_attributesExD
+ uint32 AttributesEx5; // 6 m_attributesExE
+ uint32 AttributesEx6; // 7 m_attributesExF
+ uint32 AttributesEx7; // 8 m_attributesExG
+ uint32 AttributesEx8; // 9 m_attributesExH
+ uint32 AttributesEx9; // 10 m_attributesExI
+ uint32 AttributesEx10; // 11 m_attributesExJ
+ uint32 CastingTimeIndex; // 12 m_castingTimeIndex
+ uint32 DurationIndex; // 13 m_durationIndex
+ uint32 powerType; // 14 m_powerType
+ uint32 rangeIndex; // 15 m_rangeIndex
+ float speed; // 16 m_speed
+ uint32 SpellVisual[2]; // 17-18 m_spellVisualID
+ uint32 SpellIconID; // 19 m_spellIconID
+ uint32 activeIconID; // 20 m_activeIconID
+ char* SpellName; // 21 m_name_lang
+ char* Rank; // 22 m_nameSubtext_lang
+ //char* Description; // 23 m_description_lang not used
+ //char* ToolTip; // 24 m_auraDescription_lang not used
+ uint32 SchoolMask; // 25 m_schoolMask
+ uint32 runeCostID; // 26 m_runeCostID
+ //uint32 spellMissileID; // 27 m_spellMissileID not used
+ //uint32 spellDescriptionVariableID; // 28 m_spellDescriptionVariableID, 3.2.0
+ uint32 SpellDifficultyId; // 29 m_spellDifficultyID - id from SpellDifficulty.dbc
+ float SpellCoef; // 30
+ uint32 SpellScalingId; // 31 SpellScaling.dbc
+ uint32 SpellAuraOptionsId; // 32 SpellAuraOptions.dbc
+ uint32 SpellAuraRestrictionsId; // 33 SpellAuraRestrictions.dbc
+ uint32 SpellCastingRequirementsId; // 34 SpellCastingRequirements.dbc
+ uint32 SpellCategoriesId; // 35 SpellCategories.dbc
+ uint32 SpellClassOptionsId; // 36 SpellClassOptions.dbc
+ uint32 SpellCooldownsId; // 37 SpellCooldowns.dbc
+ //uint32 unkIndex7; // 38 all zeros...
+ uint32 SpellEquippedItemsId; // 39 SpellEquippedItems.dbc
+ uint32 SpellInterruptsId; // 40 SpellInterrupts.dbc
+ uint32 SpellLevelsId; // 41 SpellLevels.dbc
+ uint32 SpellPowerId; // 42 SpellPower.dbc
+ uint32 SpellReagentsId; // 43 SpellReagents.dbc
+ uint32 SpellShapeshiftId; // 44 SpellShapeshift.dbc
+ uint32 SpellTargetRestrictionsId; // 45 SpellTargetRestrictions.dbc
+ uint32 SpellTotemsId; // 46 SpellTotems.dbc
+ //uint32 ResearchProject; // 47 ResearchProject.dbc
+};
+
+// SpellCategories.dbc
+struct SpellCategoriesEntry
+{
+ //uint32 Id; // 0 m_ID
uint32 Category; // 1 m_category
+ uint32 DmgClass; // 153 m_defenseType
uint32 Dispel; // 2 m_dispelType
uint32 Mechanic; // 3 m_mechanic
- uint32 Attributes; // 4 m_attributes
- uint32 AttributesEx; // 5 m_attributesEx
- uint32 AttributesEx2; // 6 m_attributesExB
- uint32 AttributesEx3; // 7 m_attributesExC
- uint32 AttributesEx4; // 8 m_attributesExD
- uint32 AttributesEx5; // 9 m_attributesExE
- uint32 AttributesEx6; // 10 m_attributesExF
- uint32 AttributesEx7; // 11 m_attributesExG
- uint32 Stances; // 12 m_shapeshiftMask
- // uint32 unk_320_2; // 13 3.2.0
- uint32 StancesNot; // 14 m_shapeshiftExclude
- // uint32 unk_320_3; // 15 3.2.0
- uint32 Targets; // 16 m_targets
- uint32 TargetCreatureType; // 17 m_targetCreatureType
- uint32 RequiresSpellFocus; // 18 m_requiresSpellFocus
- uint32 FacingCasterFlags; // 19 m_facingCasterFlags
- uint32 CasterAuraState; // 20 m_casterAuraState
- uint32 TargetAuraState; // 21 m_targetAuraState
- uint32 CasterAuraStateNot; // 22 m_excludeCasterAuraState
- uint32 TargetAuraStateNot; // 23 m_excludeTargetAuraState
- uint32 casterAuraSpell; // 24 m_casterAuraSpell
- uint32 targetAuraSpell; // 25 m_targetAuraSpell
- uint32 excludeCasterAuraSpell; // 26 m_excludeCasterAuraSpell
- uint32 excludeTargetAuraSpell; // 27 m_excludeTargetAuraSpell
- uint32 CastingTimeIndex; // 28 m_castingTimeIndex
- uint32 RecoveryTime; // 29 m_recoveryTime
- uint32 CategoryRecoveryTime; // 30 m_categoryRecoveryTime
- uint32 InterruptFlags; // 31 m_interruptFlags
- uint32 AuraInterruptFlags; // 32 m_auraInterruptFlags
- uint32 ChannelInterruptFlags; // 33 m_channelInterruptFlags
- uint32 procFlags; // 34 m_procTypeMask
- uint32 procChance; // 35 m_procChance
- uint32 procCharges; // 36 m_procCharges
- uint32 maxLevel; // 37 m_maxLevel
- uint32 baseLevel; // 38 m_baseLevel
- uint32 spellLevel; // 39 m_spellLevel
- uint32 DurationIndex; // 40 m_durationIndex
- uint32 powerType; // 41 m_powerType
- uint32 manaCost; // 42 m_manaCost
- uint32 manaCostPerlevel; // 43 m_manaCostPerLevel
- uint32 manaPerSecond; // 44 m_manaPerSecond
- uint32 manaPerSecondPerLevel; // 45 m_manaPerSecondPerLeve
- uint32 rangeIndex; // 46 m_rangeIndex
- float speed; // 47 m_speed
- //uint32 modalNextSpell; // 48 m_modalNextSpell not used
- uint32 StackAmount; // 49 m_cumulativeAura
- uint32 Totem[2]; // 50-51 m_totem
- int32 Reagent[MAX_SPELL_REAGENTS]; // 52-59 m_reagent
- uint32 ReagentCount[MAX_SPELL_REAGENTS]; // 60-67 m_reagentCount
- int32 EquippedItemClass; // 68 m_equippedItemClass (value)
- int32 EquippedItemSubClassMask; // 69 m_equippedItemSubclass (mask)
- int32 EquippedItemInventoryTypeMask; // 70 m_equippedItemInvTypes (mask)
- uint32 Effect[MAX_SPELL_EFFECTS]; // 71-73 m_effect
- int32 EffectDieSides[MAX_SPELL_EFFECTS]; // 74-76 m_effectDieSides
- float EffectRealPointsPerLevel[MAX_SPELL_EFFECTS]; // 77-79 m_effectRealPointsPerLevel
- int32 EffectBasePoints[MAX_SPELL_EFFECTS]; // 80-82 m_effectBasePoints (must not be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
- uint32 EffectMechanic[MAX_SPELL_EFFECTS]; // 83-85 m_effectMechanic
- uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]; // 86-88 m_implicitTargetA
- uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]; // 89-91 m_implicitTargetB
- uint32 EffectRadiusIndex[MAX_SPELL_EFFECTS]; // 92-94 m_effectRadiusIndex - spellradius.dbc
- uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]; // 95-97 m_effectAura
- uint32 EffectAmplitude[MAX_SPELL_EFFECTS]; // 98-100 m_effectAuraPeriod
- float EffectValueMultiplier[MAX_SPELL_EFFECTS]; // 101-103
- uint32 EffectChainTarget[MAX_SPELL_EFFECTS]; // 104-106 m_effectChainTargets
- uint32 EffectItemType[MAX_SPELL_EFFECTS]; // 107-109 m_effectItemType
- int32 EffectMiscValue[MAX_SPELL_EFFECTS]; // 110-112 m_effectMiscValue
- int32 EffectMiscValueB[MAX_SPELL_EFFECTS]; // 113-115 m_effectMiscValueB
- uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]; // 116-118 m_effectTriggerSpell
- float EffectPointsPerComboPoint[MAX_SPELL_EFFECTS]; // 119-121 m_effectPointsPerCombo
- flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; // 122-130
- uint32 SpellVisual[2]; // 131-132 m_spellVisualID
- uint32 SpellIconID; // 133 m_spellIconID
- uint32 activeIconID; // 134 m_activeIconID
- //uint32 spellPriority; // 135 not used
- char* SpellName[16]; // 136-151 m_name_lang
- //uint32 SpellNameFlag; // 152 not used
- char* Rank[16]; // 153-168 m_nameSubtext_lang
- //uint32 RankFlags; // 169 not used
- //char* Description[16]; // 170-185 m_description_lang not used
- //uint32 DescriptionFlags; // 186 not used
- //char* ToolTip[16]; // 187-202 m_auraDescription_lang not used
- //uint32 ToolTipFlags; // 203 not used
- uint32 ManaCostPercentage; // 204 m_manaCostPct
- uint32 StartRecoveryCategory; // 205 m_startRecoveryCategory
- uint32 StartRecoveryTime; // 206 m_startRecoveryTime
- uint32 MaxTargetLevel; // 207 m_maxTargetLevel
- uint32 SpellFamilyName; // 208 m_spellClassSet
- flag96 SpellFamilyFlags; // 209-211
- uint32 MaxAffectedTargets; // 212 m_maxTargets
- uint32 DmgClass; // 213 m_defenseType
- uint32 PreventionType; // 214 m_preventionType
- //uint32 StanceBarOrder; // 215 m_stanceBarOrder not used
- float EffectDamageMultiplier[MAX_SPELL_EFFECTS]; // 216-218 m_effectChainAmplitude
- //uint32 MinFactionId; // 219 m_minFactionID not used
- //uint32 MinReputation; // 220 m_minReputation not used
- //uint32 RequiredAuraVision; // 221 m_requiredAuraVision not used
- uint32 TotemCategory[2]; // 222-223 m_requiredTotemCategoryID
- int32 AreaGroupId; // 224 m_requiredAreaGroupId
- uint32 SchoolMask; // 225 m_schoolMask
- uint32 runeCostID; // 226 m_runeCostID
- //uint32 spellMissileID; // 227 m_spellMissileID not used
- //uint32 PowerDisplayId; // 228 PowerDisplay.dbc, new in 3.1
- float EffectBonusMultiplier[MAX_SPELL_EFFECTS]; // 229-231 3.2.0
- //uint32 spellDescriptionVariableID; // 232 3.2.0
- //uint32 SpellDifficultyId; // 233 3.3.0
+ uint32 PreventionType; // 154 m_preventionType
+ uint32 StartRecoveryCategory; // 145 m_startRecoveryCategory
};
typedef std::set<uint32> SpellCategorySet;
@@ -1684,8 +1853,7 @@ struct SpellDifficultyEntry
struct SpellFocusObjectEntry
{
uint32 ID; // 0
- //char* Name[16]; // 1-15 unused
- // 16 string flags, unused
+ //char* Name; // 1 m_name_lang
};
struct SpellRadiusEntry
@@ -1702,12 +1870,71 @@ struct SpellRangeEntry
float minRangeHostile;
float minRangeFriend;
float maxRangeHostile;
- float maxRangeFriend;
+ float maxRangeFriend; //friend means unattackable unit here
uint32 type;
- //char* Name[16]; // 7-23 unused
- // 24 string flags, unused
- //char* Name2[16]; // 25-40 unused
- // 41 string flags, unused
+ //char* Name; // 6-21 m_displayName_lang
+ //char* ShortName; // 23-38 m_displayNameShort_lang
+};
+
+// SpellEquippedItems.dbc
+struct SpellEquippedItemsEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 EquippedItemClass; // 70 m_equippedItemClass (value)
+ int32 EquippedItemInventoryTypeMask; // 72 m_equippedItemInvTypes (mask)
+ int32 EquippedItemSubClassMask; // 71 m_equippedItemSubclass (mask)
+};
+
+// SpellCooldowns.dbc
+struct SpellCooldownsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 CategoryRecoveryTime; // 31 m_categoryRecoveryTime
+ uint32 RecoveryTime; // 30 m_recoveryTime
+ uint32 StartRecoveryTime; // 146 m_startRecoveryTime
+};
+
+// SpellClassOptions.dbc
+struct SpellClassOptionsEntry
+{
+ //uint32 Id; // 0 m_ID
+ //uint32 modalNextSpell; // 1 m_modalNextSpell not used
+ flag96 SpellFamilyFlags; // 2-4
+ uint32 SpellFamilyName; // 5 m_spellClassSet
+ //char* Description; // 6 4.0.0
+};
+
+// SpellInterrupts.dbc
+struct SpellInterruptsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 AuraInterruptFlags; // 1 m_auraInterruptFlags
+ //uint32 // 2 4.0.0
+ uint32 ChannelInterruptFlags; // 3 m_channelInterruptFlags
+ //uint32 // 4 4.0.0
+ uint32 InterruptFlags; // 5 m_interruptFlags
+};
+
+// SpellLevels.dbc
+struct SpellLevelsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 baseLevel; // 1 m_baseLevel
+ uint32 maxLevel; // 2 m_maxLevel
+ uint32 spellLevel; // 3 m_spellLevel
+};
+
+// SpellPower.dbc
+struct SpellPowerEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 manaCost; // 1 m_manaCost
+ uint32 manaCostPerlevel; // 2 m_manaCostPerLevel
+ uint32 ManaCostPercentage; // 3 m_manaCostPct
+ uint32 manaPerSecond; // 4 m_manaPerSecond
+ uint32 manaPerSecondPerLevel; // 5 m_manaPerSecondPerLevel
+ //uint32 PowerDisplayId; // 6 m_powerDisplayID - id from PowerDisplay.dbc, new in 3.1
+ float ManaCostPercentageFloat; // 7 4.3.0
};
struct SpellRuneCostEntry
@@ -1722,21 +1949,67 @@ struct SpellRuneCostEntry
#define MAX_SHAPESHIFT_SPELLS 8
-struct SpellShapeshiftEntry
+struct SpellShapeshiftFormEntry
{
uint32 ID; // 0
//uint32 buttonPosition; // 1 unused
- //char* Name[16]; // 2-17 unused
- //uint32 NameFlags; // 18 unused
- uint32 flags1; // 19
- int32 creatureType; // 20 <= 0 humanoid, other normal creature types
- //uint32 unk1; // 21 unused
- uint32 attackSpeed; // 22
- uint32 modelID_A; // 23 alliance modelid
- uint32 modelID_H; // 24 horde modelid (only one form)
- //uint32 unk3; // 25 unused
- //uint32 unk4; // 26 unused
- uint32 stanceSpell[MAX_SHAPESHIFT_SPELLS]; // 27 - 34 unused
+ //char* Name; // 2 unused
+ uint32 flags1; // 3
+ int32 creatureType; // 4 <=0 humanoid, other normal creature types
+ //uint32 spellIcon; // 5 unused, related to next field
+ uint32 attackSpeed; // 6
+ // Models changed, 0 is main model, the rest 3 are unused.
+ uint32 modelID_A; // 7 alliance modelid (0 means no model)
+ uint32 modelID_H; // 8 horde modelid (but only for one form)
+ //uint32 unk3; // 9 unused always 0
+ //uint32 unk4; // 10 unused always 0
+ uint32 stanceSpell[MAX_SHAPESHIFT_SPELLS]; // 11-18 spells which appear in the bar after shapeshifting
+ //uint32 unk5; // 19
+ //uint32 unk6; // 20
+};
+
+// SpellShapeshift.dbc
+struct SpellShapeshiftEntry
+{
+ uint32 Id; // 0 - m_ID
+ uint32 StancesNot; // 3 - m_shapeshiftExclude
+ // uint32 unk_320_2; // 2 - 3.2.0
+ uint32 Stances; // 1 - m_shapeshiftMask
+ // uint32 unk_320_3; // 4 - 3.2.0
+ // uint32 StanceBarOrder; // 5 - m_stanceBarOrder not used
+};
+
+// SpellTargetRestrictions.dbc
+struct SpellTargetRestrictionsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 MaxAffectedTargets; // 1 m_maxTargets
+ uint32 MaxTargetLevel; // 2 m_maxTargetLevel
+ uint32 TargetCreatureType; // 3 m_targetCreatureType
+ uint32 Targets; // 4 m_targets
+};
+
+// SpellReagents.dbc
+struct SpellReagentsEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 Reagent[MAX_SPELL_REAGENTS]; // 54-61 m_reagent
+ uint32 ReagentCount[MAX_SPELL_REAGENTS]; // 62-69 m_reagentCount
+};
+
+// SpellScaling.dbc
+struct SpellScalingEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 CastTimeMin; // 1
+ int32 CastTimeMax; // 2
+ int32 CastTimeMaxLevel; // 3
+ int32 ScalingClass; // 4 (index * 100) + charLevel - 1 => gtSpellScaling.dbc
+ float Multiplier[3]; // 5-7
+ float RandomMultiplier[3]; // 8-10
+ float OtherMultiplier[3]; // 11-13
+ float CoefBase; // 14 some coefficient, mostly 1.0f
+ int32 CoefLevelBase; // 15 some level
};
struct SpellDurationEntry
@@ -1753,15 +2026,15 @@ struct SpellItemEnchantmentEntry
uint32 amount[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 5-7 m_effectPointsMin[MAX_ITEM_ENCHANTMENT_EFFECTS]
//uint32 amount2[MAX_ITEM_ENCHANTMENT_EFFECTS] // 8-10 m_effectPointsMax[MAX_ITEM_ENCHANTMENT_EFFECTS]
uint32 spellid[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 11-13 m_effectArg[MAX_ITEM_ENCHANTMENT_EFFECTS]
- char* description[16]; // 14-29 m_name_lang[16]
- //uint32 descriptionFlags; // 30 name flags
- uint32 aura_id; // 31 m_itemVisual
- uint32 slot; // 32 m_flags
- uint32 GemID; // 33 m_src_itemID
- uint32 EnchantmentCondition; // 34 m_condition_id
- uint32 requiredSkill; // 35 m_requiredSkillID
- uint32 requiredSkillValue; // 36 m_requiredSkillRank
- uint32 requiredLevel; // 37 m_requiredLevel
+ char* description; // 14 m_name_lang
+ uint32 aura_id; // 15 m_itemVisual
+ uint32 slot; // 16 m_flags
+ uint32 GemID; // 17 m_src_itemID
+ uint32 EnchantmentCondition; // 18 m_condition_id
+ uint32 requiredSkill; // 19 m_requiredSkillID
+ uint32 requiredSkillValue; // 20 m_requiredSkillRank
+ uint32 requiredLevel; // 21 new in 3.1
+ // 22 new in 3.1
};
struct SpellItemEnchantmentConditionEntry
@@ -1787,7 +2060,7 @@ struct SummonPropertiesEntry
uint32 Category; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount?
uint32 Faction; // 2, 14 rows > 0
uint32 Type; // 3, see enum
- uint32 Slot; // 4, 0-6
+ int32 Slot; // 4, 0-6
uint32 Flags; // 5
};
@@ -1802,27 +2075,37 @@ struct TalentEntry
uint32 Row; // 2
uint32 Col; // 3
uint32 RankID[MAX_TALENT_RANK]; // 4-8
- // 9-12 not used, always 0, maybe not used high ranks
- uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry)
- // 14-15 not used
- uint32 DependsOnRank; // 16
- // 17-18 not used
- //uint32 needAddInSpellBook; // 19 also need disable higest ranks on reset talent tree
- //uint32 unk2; // 20, all 0
- //uint64 allowForPet; // 21 its a 64 bit mask for pet 1<<m_categoryEnumID in CreatureFamily.dbc
+ uint32 DependsOn; // 9 m_prereqTalent (Talent.dbc)
+ // 10-11 part of prev field
+ uint32 DependsOnRank; // 12 m_prereqRank
+ // 13-14 part of prev field
+ //uint32 needAddInSpellBook; // 15 m_flags also need disable higest ranks on reset talent tree
+ //uint32 unk2; // 16 m_requiredSpellID
+ //uint64 allowForPet; // 17 m_categoryMask its a 64 bit mask for pet 1<<m_categoryEnumID in CreatureFamily.dbc
};
+#define MAX_MASTERY_SPELLS 2
+
struct TalentTabEntry
{
uint32 TalentTabID; // 0
- //char* name[16]; // 1-16, unused
- //uint32 nameFlags; // 17, unused
- //unit32 spellicon; // 18
- // 19 not used
- uint32 ClassMask; // 20
- uint32 petTalentMask; // 21
- uint32 tabpage; // 22
- //char* internalname; // 23
+ //char* name; // 1 m_name_lang
+ //unit32 spellicon; // 2 m_spellIconID
+ uint32 ClassMask; // 3 m_classMask
+ uint32 petTalentMask; // 4 m_petTalentMask
+ uint32 tabpage; // 5 m_orderIndex
+ //char* internalname; // 6 m_backgroundFile
+ //char* description; // 7
+ //uint32 rolesMask; // 8 4.0.0
+ uint32 MasterySpellId[MAX_MASTERY_SPELLS]; // 9-10 passive mastery bonus spells?
+};
+
+struct TalentTreePrimarySpellsEntry
+{
+ //uint32 Id; // 0 index
+ uint32 TalentTree; // 1 entry from TalentTab.dbc
+ uint32 SpellId; // 2 spell id to learn
+ //uint32 Flags; // 3 some kind of flags
};
struct TaxiNodesEntry
@@ -1832,9 +2115,9 @@ struct TaxiNodesEntry
float x; // 2 m_x
float y; // 3 m_y
float z; // 4 m_z
- char* name[16]; // 5-21 m_Name_lang
- // 22 string flags
- uint32 MountCreatureID[2]; // 23-24 m_MountCreatureID[2]
+ char* name; // 5 m_Name_lang
+ uint32 MountCreatureID[2]; // 6-7 m_MountCreatureID[2]
+ uint32 Flags; // 8 m_Flags
};
struct TaxiPathEntry
@@ -1860,19 +2143,33 @@ struct TaxiPathNodeEntry
uint32 departureEventID; // 10 m_departureEventID
};
-struct TeamContributionPointsEntry
+struct TotemCategoryEntry
{
- //uint32 entry; // 0
- float value; // 1 (???)
+ uint32 ID; // 0
+ //char* name; // 1 m_name_lang
+ uint32 categoryType; // 2 m_totemCategoryType (one for specialization)
+ uint32 categoryMask; // 3 m_totemCategoryMask (compatibility mask for same type: different for totems, compatible from high to low for rods)
};
-struct TotemCategoryEntry
+struct UnitPowerBarEntry
{
- uint32 ID; // 0
- //char* name[16]; // 1-16
- // 17 string flags, unused
- uint32 categoryType; // 18 (one for specialization)
- uint32 categoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods)
+ uint32 Id;
+ uint32 MinPower;
+ uint32 MaxPower;
+ //uint32 Unk0;
+ //uint32 Unk1;
+ //float Unk2;
+ //float Unk3;
+ //uint32 BarType;
+ //uint32 TextureFile[6];
+ //uint32 Unk4[6];
+ //uint32 DisplayFlags;
+ //char* PowerName;
+ //char* CostString;
+ //char* EmptyMessage;
+ //char* Tooltip;
+ //float StartInset;
+ //float EndInset;
};
#define MAX_VEHICLE_SEATS 8
@@ -1902,9 +2199,9 @@ struct VehicleEntry
float m_msslTrgtArcRepeat; // 25
float m_msslTrgtArcWidth; // 26
float m_msslTrgtImpactRadius[2]; // 27-28
- char* m_msslTrgtArcTexture; // 29
- char* m_msslTrgtImpactTexture; // 30
- char* m_msslTrgtImpactModel[2]; // 31-32
+ char* m_msslTrgtArcTexture; // 29
+ char* m_msslTrgtImpactTexture; // 30
+ char* m_msslTrgtImpactModel[2]; // 31-32
float m_cameraYawOffset; // 33
uint32 m_uiLocomotionType; // 34
float m_msslTrgtImpactTexRadius; // 35
@@ -1985,8 +2282,10 @@ struct WMOAreaTableEntry
//uint32 field8;
uint32 Flags; // 9 used for indoor/outdoor determination
uint32 areaId; // 10 link to AreaTableEntry.ID
- //char *Name[16];
- //uint32 nameFlags;
+ //char *Name; // 11 m_AreaName_lang
+ //uint32 field12; // 12
+ //uint32 field13; // 13
+ //uint32 field14; // 14
};
struct WorldMapAreaEntry
@@ -2002,6 +2301,9 @@ struct WorldMapAreaEntry
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
// int32 dungeonMap_id; // 9 pointer to DungeonMap.dbc (owerride x1, x2, y1, y2 coordinates)
// uint32 parentMapID; // 10
+
+ // uint32 minRecommendedLevel; // 12 Minimum recommended level displayed on world map
+ // uint32 maxRecommendedLevel; // 13 Maximum recommended level displayed on world map
};
#define MAX_WORLD_MAP_OVERLAY_AREA_IDX 4
@@ -2011,9 +2313,15 @@ struct WorldMapOverlayEntry
uint32 ID; // 0
//uint32 worldMapAreaId; // 1 idx in WorldMapArea.dbc
uint32 areatableID[MAX_WORLD_MAP_OVERLAY_AREA_IDX]; // 2-5
- // 6-7 always 0, possible part of areatableID[]
- //char* internal_name // 8
- // 9-16 some ints
+ //char* internal_name // 6 m_textureName
+ // 7 m_textureWidth
+ // 8 m_textureHeight
+ // 9 m_offsetX
+ // 10 m_offsetY
+ // 11 m_hitRectTop
+ // 12 m_hitRectLeft
+ // 13 m_hitRectBottom
+ // 14 m_hitRectRight
};
struct WorldSafeLocsEntry
@@ -2023,8 +2331,7 @@ struct WorldSafeLocsEntry
float x; // 2
float y; // 3
float z; // 4
- //char* name[16] // 5-20 name, unused
- // 21 name flags, unused
+ //char* name; // 5 m_AreaName_lang
};
/*
@@ -2070,6 +2377,13 @@ struct WorldStateUI
#pragma pack(pop)
#endif
+struct VectorArray
+{
+ std::vector<std::string> stringVectorArray[2];
+};
+
+typedef std::map<uint32, VectorArray> NameGenVectorArraysMap;
+
// Structures not used for casting to loaded DBC data and not required then packing
struct MapDifficulty
{
@@ -2114,7 +2428,6 @@ struct TaxiPathNodePtr
typedef Path<TaxiPathNodePtr, TaxiPathNodeEntry const> TaxiPathNodeList;
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
-#define TaxiMaskSize 14
-typedef uint32 TaxiMask[TaxiMaskSize];
+#define TaxiMaskSize 114
+typedef uint8 TaxiMask[TaxiMaskSize];
#endif
-
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index a81eec51338..7b523c8999f 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -19,112 +19,156 @@
#ifndef TRINITY_DBCSFRM_H
#define TRINITY_DBCSFRM_H
-char const Achievementfmt[] = "niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii";
-const std::string CustomAchievementfmt = "pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp";
+// x - skip<uint32>, X - skip<uint8>, s - char*, f - float, i - uint32, b - uint8, d - index (not included)
+// n - index (included), l - bool, p - field present in sql dbc, a - field absent in sql dbc
+
+char const Achievementfmt[] = "niixsxiixixxii";
+const std::string CustomAchievementfmt = "pppaaaapapaapp";
const std::string CustomAchievementIndex = "ID";
-char const AchievementCriteriafmt[] = "niiiiiiiixxxxxxxxxxxxxxxxxiiiix";
-char const AreaTableEntryfmt[] = "iiinixxxxxissssssssssssssssxiiiiixxx";
+char const AchievementCriteriafmt[] = "niiiixiiiisiiiiixxiiiii";
+char const AreaTableEntryfmt[] = "iiinixxxxxisiiiiiffixxxxxx";
char const AreaGroupEntryfmt[] = "niiiiiii";
-char const AreaPOIEntryfmt[] = "niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
-char const AreaTriggerEntryfmt[] = "niffffffff";
-char const AuctionHouseEntryfmt[] = "niiixxxxxxxxxxxxxxxxx";
+char const AreaPOIEntryfmt[] = "niiiiiiiiiiiffixixxixx";
+char const AreaTriggerEntryfmt[] = "nifffxxxfffff";
+char const ArmorLocationfmt[] = "nfffff";
+char const AuctionHouseEntryfmt[] = "niiix";
char const BankBagSlotPricesEntryfmt[] = "ni";
char const BannedAddOnsfmt[] = "nxxxxxxxxxx";
-char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
-char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
-char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
-char const CharTitlesEntryfmt[] = "nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
-char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
-char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
-char const ChrRacesEntryfmt[] = "nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
+char const BarberShopStyleEntryfmt[] = "nixxxiii";
+char const BattlemasterListEntryfmt[] = "niiiiiiiiixsiiiixxxx";
+char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxii";
+char const CharTitlesEntryfmt[] = "nxsxix";
+char const ChatChannelsEntryfmt[] = "nixsx";
+char const ChrClassesEntryfmt[] = "nixsxxxixiiiii";
+char const ChrRacesEntryfmt[] = "nxixiixixxxxixsxxxxxixxx";
+char const ChrClassesXPowerTypesfmt[] = "nii";
char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx";
-char const CreatureDisplayInfofmt[] = "nixxfxxxxxxxxxxx";
-char const CreatureFamilyfmt[] = "nfifiiiiixssssssssssssssssxx";
-char const CreatureModelDatafmt[] = "nxxxfxxxxxxxxxxffxxxxxxxxxxx";
+char const CreatureDisplayInfofmt[] = "nixxfxxxxxxxxxxxx";
+char const CreatureModelDatafmt[] = "nxxxxxxxxxxxxxffxxxxxxxxxxxxxxx";
+char const CreatureFamilyfmt[] = "nfifiiiiixsx";
char const CreatureSpellDatafmt[] = "niiiixxxx";
-char const CreatureTypefmt[] = "nxxxxxxxxxxxxxxxxxx";
-char const CurrencyTypesfmt[] = "xnxi";
-char const DestructibleModelDatafmt[] = "nxxixxxixxxixxxixxx";
-char const DungeonEncounterfmt[] = "niixissssssssssssssssxx";
+char const CreatureTypefmt[] = "nxx";
+char const CurrencyTypesfmt[] = "nixxxiiiiix";
+char const DestructibleModelDatafmt[] = "ixxixxxixxxixxxixxxxxxxx";
+char const DungeonEncounterfmt[] = "iiixisxx";
char const DurabilityCostsfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
char const DurabilityQualityfmt[] = "nf";
-char const EmotesEntryfmt[] = "nxxiiix";
+char const EmotesEntryfmt[] = "nxxiiixx";
char const EmotesTextEntryfmt[] = "nxixxxxxxxxxxxxxxxx";
-char const FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
+char const FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixsxi";
char const FactionTemplateEntryfmt[] = "niiiiiiiiiiiii";
-char const GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffx";
-char const GemPropertiesEntryfmt[] = "nixxi";
+char const GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffxxx";
+char const GemPropertiesEntryfmt[] = "nixxii";
char const GlyphPropertiesfmt[] = "niii";
char const GlyphSlotfmt[] = "nii";
-char const GtBarberShopCostBasefmt[] = "f";
-char const GtCombatRatingsfmt[] = "f";
-char const GtChanceToMeleeCritBasefmt[] = "f";
-char const GtChanceToMeleeCritfmt[] = "f";
-char const GtChanceToSpellCritBasefmt[] = "f";
-char const GtChanceToSpellCritfmt[] = "f";
-char const GtNPCManaCostScalerfmt[] = "f";
+char const GtBarberShopCostBasefmt[] = "xf";
+char const GtCombatRatingsfmt[] = "xf";
+char const GtOCTHpPerStaminafmt[] = "df";
+char const GtChanceToMeleeCritBasefmt[] = "xf";
+char const GtChanceToMeleeCritfmt[] = "xf";
+char const GtChanceToSpellCritBasefmt[] = "xf";
+char const GtChanceToSpellCritfmt[] = "xf";
+char const GtNPCManaCostScalerfmt[] = "xf";
char const GtOCTClassCombatRatingScalarfmt[] = "df";
char const GtOCTRegenHPfmt[] = "f";
//char const GtOCTRegenMPfmt[] = "f";
-char const GtRegenHPPerSptfmt[] = "f";
-char const GtRegenMPPerSptfmt[] = "f";
+char const GtRegenMPPerSptfmt[] = "xf";
+char const GtSpellScalingfmt[] = "df";
+char const GtOCTBaseHPByClassfmt[] = "df";
+char const GtOCTBaseMPByClassfmt[] = "df";
+char const GuildPerkSpellsfmt[] = "dii";
char const Holidaysfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix";
-char const Itemfmt[] = "niiiiiii";
-char const ItemBagFamilyfmt[] = "nxxxxxxxxxxxxxxxxx";
+char const ImportPriceArmorfmt[] = "nffff";
+char const ImportPriceQualityfmt[] = "nf";
+char const ImportPriceShieldfmt[] = "nf";
+char const ImportPriceWeaponfmt[] = "nf";
+char const ItemPriceBasefmt[] = "diff";
+char const ItemReforgefmt[] = "nifif";
+char const ItemBagFamilyfmt[] = "nx";
+char const ItemArmorQualityfmt[] = "nfffffffi";
+char const ItemArmorShieldfmt[] = "nifffffff";
+char const ItemArmorTotalfmt[] = "niffff";
+char const ItemClassfmt[] = "dixxfx";
+char const ItemDamagefmt[] = "nfffffffi";
+char const ItemDisenchantLootfmt[] = "niiiiii";
//char const ItemDisplayTemplateEntryfmt[] = "nxxxxxxxxxxixxxxxxxxxxx";
-//char const ItemCondExtCostsEntryfmt[] = "xiii";
-char const ItemExtendedCostEntryfmt[] = "niiiiiiiiiiiiiix";
-char const ItemLimitCategoryEntryfmt[] = "nxxxxxxxxxxxxxxxxxii";
-char const ItemRandomPropertiesfmt[] = "nxiiixxssssssssssssssssx";
-char const ItemRandomSuffixfmt[] = "nssssssssssssssssxxiiixxiiixx";
-char const ItemSetEntryfmt[] = "dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
-char const LFGDungeonEntryfmt[] = "nssssssssssssssssxiiiiiiiiixxixixxxxxxxxxxxxxxxxx";
+char const ItemLimitCategoryEntryfmt[] = "nxii";
+char const ItemRandomPropertiesfmt[] = "nxiiixxs";
+char const ItemRandomSuffixfmt[] = "nsxiiiiiiiiii";
+char const ItemSetEntryfmt[] = "dsiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
+char const LFGDungeonEntryfmt[] = "nsiiiiiiiiixxixixixxx";
char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
-char const MailTemplateEntryfmt[] = "nxxxxxxxxxxxxxxxxxssssssssssssssssx";
-char const MapEntryfmt[] = "nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix";
-char const MapDifficultyEntryfmt[] = "diisxxxxxxxxxxxxxxxxiix";
-char const MovieEntryfmt[] = "nxx";
-char const OverrideSpellDatafmt[] = "niiiiiiiiiix";
+char const PhaseEntryfmt[] = "nsi";
+char const MailTemplateEntryfmt[] = "nxs";
+char const MapEntryfmt[] = "nxixxxsixxixiffxiixi";
+char const MapDifficultyEntryfmt[] = "diisiix";
+char const MovieEntryfmt[] = "nxxx";
+char const MountCapabilityfmt[] = "niiiiiii";
+char const MountTypefmt[] = "niiiiiiiiiiiiiiiiiiiiiiii";
+char const NameGenfmt[] = "dsii";
+char const NumTalentsAtLevelfmt[] = "df";
+char const OverrideSpellDatafmt[] = "niiiiiiiiiixx";
char const QuestFactionRewardfmt[] = "niiiiiiiiii";
-char const QuestSortEntryfmt[] = "nxxxxxxxxxxxxxxxxx";
+char const QuestSortEntryfmt[] = "nx";
char const QuestXPfmt[] = "niiiiiiiiii";
char const PvPDifficultyfmt[] = "diiiii";
char const RandomPropertiesPointsfmt[] = "niiiiiiiiiiiiiii";
-char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiii";
-char const ScalingStatValuesfmt[] = "iniiiiiiiiiiiiiiiiiiiiii";
-char const SkillLinefmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
-char const SkillLineAbilityfmt[] = "niiiixxiiiiixx";
-char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiixi";
+char const ScalingStatValuesfmt[] = "iniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii";
+char const SkillLinefmt[] = "nisxixi";
+char const SkillLineAbilityfmt[] = "niiiixxiiiiiii";
+char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const SpellCastTimefmt[] = "nixx";
+char const SpellCategoriesEntryfmt[] = "diiiiii";
char const SpellDifficultyfmt[] = "niiii";
const std::string CustomSpellDifficultyfmt = "ppppp";
const std::string CustomSpellDifficultyIndex = "id";
char const SpellDurationfmt[] = "niii";
-char const SpellEntryfmt[] = "niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
-const std::string CustomSpellEntryfmt = "papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
+// 0 10 20 26
+char const SpellEffectEntryfmt[] = "nifiiiffiiiiiifiifiiiiiiiix";
+const std::string CustomSpellEffectEntryfmt = "ppppppppppapppappppppppppp";
+const std::string CustomSpellEffectEntryIndex = "Id";
+// 0 10 20 30 40 47
+char const SpellEntryfmt[] = "niiiiiiiiiiiiiiifiiiissxxiixxifiiiiiiixiiiiiiiix";
+const std::string CustomSpellEntryfmt = "ppppppppppppppapaaaaaaaaapaaaaaapapppaapppaaapa";
const std::string CustomSpellEntryIndex = "Id";
-char const SpellFocusObjectfmt[] = "nxxxxxxxxxxxxxxxxx";
-char const SpellItemEnchantmentfmt[] = "nxiiiiiixxxiiissssssssssssssssxiiiiiii";
+char const SpellFocusObjectfmt[] = "nx";
+char const SpellItemEnchantmentfmt[] = "nxiiiiiixxxiiisiiiiiiix";
char const SpellItemEnchantmentConditionfmt[] = "nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
char const SpellRadiusfmt[] = "nfff";
-char const SpellRangefmt[] = "nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+char const SpellRangefmt[] = "nffffixx";
+char const SpellReagentsEntryfmt[] = "diiiiiiiiiiiiiiii";
+char const SpellScalingEntryfmt[] = "diiiiffffffffffi";
+char const SpellTotemsEntryfmt[] = "niiii";
+char const SpellTargetRestrictionsEntryfmt[] = "nxiiii";
+char const SpellPowerEntryfmt[] = "diiiiixf";
+char const SpellInterruptsEntryfmt[] = "dixixi";
+char const SpellEquippedItemsEntryfmt[] = "diii";
+char const SpellAuraOptionsEntryfmt[] = "niiii";
+char const SpellAuraRestrictionsEntryfmt[] = "diiiiiiii";
+char const SpellCastingRequirementsEntryfmt[] = "dixxixi";
+char const SpellClassOptionsEntryfmt[] = "dxiiiix";
+char const SpellCooldownsEntryfmt[] = "diii";
+char const SpellLevelsEntryfmt[] = "diii";
char const SpellRuneCostfmt[] = "niiii";
-char const SpellShapeshiftfmt[] = "nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii";
+char const SpellShapeshiftEntryfmt[] = "nixixx";
+char const SpellShapeshiftFormfmt[] = "nxxiixiiixxiiiiiiiixx";
char const StableSlotPricesfmt[] = "ni";
char const SummonPropertiesfmt[] = "niiiii";
-char const TalentEntryfmt[] = "niiiiiiiixxxxixxixxxxxx";
-char const TalentTabEntryfmt[] = "nxxxxxxxxxxxxxxxxxxxiiix";
-char const TaxiNodesEntryfmt[] = "nifffssssssssssssssssxii";
+char const TalentEntryfmt[] = "niiiiiiiiixxixxxxxx";
+char const TalentTabEntryfmt[] = "nxxiiixxxii";
+char const TalentTreePrimarySpellsfmt[] = "diix";
+char const TaxiNodesEntryfmt[] = "nifffsiiixx";
char const TaxiPathEntryfmt[] = "niii";
char const TaxiPathNodeEntryfmt[] = "diiifffiiii";
-char const TeamContributionPointsfmt[] = "df";
-char const TotemCategoryEntryfmt[] = "nxxxxxxxxxxxxxxxxxii";
+char const TotemCategoryEntryfmt[] = "nxii";
+char const UnitPowerBarfmt[] = "niixxxxxxxxxxxxxxxxxxxxxxxx";
char const VehicleEntryfmt[] = "niffffiiiiiiiifffffffffffffffssssfifiixx";
-char const VehicleSeatEntryfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
-char const WMOAreaTableEntryfmt[] = "niiixxxxxiixxxxxxxxxxxxxxxxx";
-char const WorldMapAreaEntryfmt[] = "xinxffffixx";
-char const WorldMapOverlayEntryfmt[] = "nxiiiixxxxxxxxxxx";
-char const WorldSafeLocsEntryfmt[] = "nifffxxxxxxxxxxxxxxxxx";
+char const VehicleSeatEntryfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxxxxxxxxxx";
+char const WMOAreaTableEntryfmt[] = "niiixxxxxiixxxx";
+char const WorldMapAreaEntryfmt[] = "xinxffffixxxxx";
+char const WorldMapOverlayEntryfmt[] = "nxiiiixxxxxxxxx";
+char const WorldSafeLocsEntryfmt[] = "nifffx";
#endif
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 52e3ab25319..a2cf3d48a17 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -235,7 +235,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
// No teleport coords in database, load from areatriggers
if (dungeon.type != LFG_TYPE_RANDOM && dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f)
{
- AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
+ AreaTriggerStruct const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
if (!at)
{
TC_LOG_ERROR(LOG_FILTER_LFG, "LFGMgr::LoadLFGDungeons: Failed to load dungeon %s, cant find areatrigger for map %u", dungeon.name.c_str(), dungeon.map);
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 96fedb65547..0795e6e22d5 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -268,7 +268,7 @@ struct LFGDungeonData
LFGDungeonData(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0),
maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
{ }
- LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map),
+ LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name), map(dbc->map),
type(dbc->type), expansion(dbc->expansion), group(dbc->grouptype),
minlevel(dbc->minlevel), maxlevel(dbc->maxlevel), difficulty(Difficulty(dbc->difficulty)),
seasonal(dbc->flags & LFG_FLAG_SEASONAL), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
new file mode 100644
index 00000000000..771b9d64f79
--- /dev/null
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectAccessor.h"
+#include "Unit.h"
+#include "SpellInfo.h"
+#include "Log.h"
+#include "AreaTrigger.h"
+
+AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0)
+{
+ m_objectType |= TYPEMASK_AREATRIGGER;
+ m_objectTypeId = TYPEID_AREATRIGGER;
+
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
+
+ m_valuesCount = AREATRIGGER_END;
+}
+
+AreaTrigger::~AreaTrigger()
+{
+}
+
+void AreaTrigger::AddToWorld()
+{
+ ///- Register the AreaTrigger for guid lookup and for caster
+ if (!IsInWorld())
+ {
+ sObjectAccessor->AddObject(this);
+ WorldObject::AddToWorld();
+ }
+}
+
+void AreaTrigger::RemoveFromWorld()
+{
+ ///- Remove the AreaTrigger from the accessor and from all lists of objects in world
+ if (IsInWorld())
+ {
+ if (!IsInWorld())
+ return;
+
+ WorldObject::RemoveFromWorld();
+ sObjectAccessor->RemoveObject(this);
+ }
+}
+
+bool AreaTrigger::CreateAreaTrigger(uint32 guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos)
+{
+ SetMap(caster->GetMap());
+ Relocate(pos);
+ if (!IsPositionValid())
+ {
+ sLog->outError(LOG_FILTER_GENERAL, "AreaTrigger (spell %u) not created. Invalid coordinates (X: %f Y: %f)", spell->Id, GetPositionX(), GetPositionY());
+ return false;
+ }
+
+ WorldObject::_Create(guidlow, HIGHGUID_AREATRIGGER, caster->GetPhaseMask());
+
+ SetEntry(triggerEntry);
+ SetDuration(spell->GetDuration());
+ SetObjectScale(1);
+
+ SetUInt32Value(AREATRIGGER_SPELLID, spell->Id);
+ SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->SpellVisual[0]);
+ SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 0, pos.GetPositionX());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 1, pos.GetPositionY());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 2, pos.GetPositionZ());
+
+ if (!GetMap()->AddToMap(this))
+ return false;
+
+ return true;
+}
+
+void AreaTrigger::Update(uint32 p_time)
+{
+ if (GetDuration() > int32(p_time))
+ _duration -= p_time;
+ else
+ Remove(); // expired
+
+ WorldObject::Update(p_time);
+}
+
+void AreaTrigger::Remove()
+{
+ if (IsInWorld())
+ {
+ SendObjectDeSpawnAnim(GetGUID());
+ RemoveFromWorld();
+ AddObjectToRemoveList();
+ }
+}
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
new file mode 100644
index 00000000000..43c75fdb262
--- /dev/null
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_AREATRIGGER_H
+#define TRINITYCORE_AREATRIGGER_H
+
+#include "Object.h"
+
+class Unit;
+class SpellInfo;
+
+class AreaTrigger : public WorldObject, public GridObject<AreaTrigger>
+{
+ public:
+ AreaTrigger();
+ ~AreaTrigger();
+
+ void AddToWorld();
+ void RemoveFromWorld();
+
+ bool CreateAreaTrigger(uint32 guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos);
+ void Update(uint32 p_time);
+ void Remove();
+ uint32 GetSpellId() const { return GetUInt32Value(AREATRIGGER_SPELLID); }
+ int32 GetDuration() const { return _duration; }
+ void SetDuration(int32 newDuration) { _duration = newDuration; }
+ void Delay(int32 delaytime) { SetDuration(GetDuration() - delaytime); }
+
+ protected:
+ int32 _duration;
+};
+#endif
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index c38082bb542..de12809fdde 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -31,7 +31,7 @@ Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES), m_type(type
m_objectType |= TYPEMASK_CORPSE;
m_objectTypeId = TYPEID_CORPSE;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
m_valuesCount = CORPSE_END;
@@ -116,7 +116,6 @@ void Corpse::SaveToDB()
stmt->setString(index++, _ConcatFields(CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END)); // itemCache
stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_BYTES_1)); // bytes1
stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_BYTES_2)); // bytes2
- stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_GUILD)); // guildId
stmt->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_FLAGS)); // flags
stmt->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS)); // dynFlags
stmt->setUInt32(index++, uint32(m_time)); // time
@@ -162,10 +161,10 @@ void Corpse::DeleteFromDB(SQLTransaction& trans)
bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
- uint32 ownerGuid = fields[17].GetUInt32();
+ uint32 ownerGuid = fields[16].GetUInt32();
float posX = fields[0].GetFloat();
float posY = fields[1].GetFloat();
float posZ = fields[2].GetFloat();
@@ -178,15 +177,14 @@ bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
_LoadIntoDataField(fields[6].GetCString(), CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END);
SetUInt32Value(CORPSE_FIELD_BYTES_1, fields[7].GetUInt32());
SetUInt32Value(CORPSE_FIELD_BYTES_2, fields[8].GetUInt32());
- SetUInt32Value(CORPSE_FIELD_GUILD, fields[9].GetUInt32());
- SetUInt32Value(CORPSE_FIELD_FLAGS, fields[10].GetUInt8());
- SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[11].GetUInt8());
+ SetUInt32Value(CORPSE_FIELD_FLAGS, fields[9].GetUInt8());
+ SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[10].GetUInt8());
SetUInt64Value(CORPSE_FIELD_OWNER, MAKE_NEW_GUID(ownerGuid, 0, HIGHGUID_PLAYER));
- m_time = time_t(fields[12].GetUInt32());
+ m_time = time_t(fields[11].GetUInt32());
- uint32 instanceId = fields[14].GetUInt32();
- uint32 phaseMask = fields[15].GetUInt16();
+ uint32 instanceId = fields[13].GetUInt32();
+ uint32 phaseMask = fields[14].GetUInt16();
// place
SetLocationInstanceId(instanceId);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 9077e045cef..f0b21a29bd2 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -63,12 +63,12 @@ TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
return NULL;
}
-bool VendorItemData::RemoveItem(uint32 item_id)
+bool VendorItemData::RemoveItem(uint32 item_id, uint8 type)
{
bool found = false;
for (VendorItemList::iterator i = m_items.begin(); i != m_items.end();)
{
- if ((*i)->item == item_id)
+ if ((*i)->item == item_id && (*i)->Type == type)
{
i = m_items.erase(i++);
found = true;
@@ -79,10 +79,10 @@ bool VendorItemData::RemoveItem(uint32 item_id)
return found;
}
-VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost) const
+VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const
{
for (VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i)
- if ((*i)->item == item_id && (*i)->ExtendedCost == extendedCost)
+ if ((*i)->item == item_id && (*i)->ExtendedCost == extendedCost && (*i)->Type == type)
return *i;
return NULL;
}
@@ -331,6 +331,7 @@ bool Creature::InitEntry(uint32 entry, uint32 /*team*/, const CreatureData* data
SetName(normalInfo->Name); // at normal entry always
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
SetSpeed(MOVE_WALK, cinfo->speed_walk);
SetSpeed(MOVE_RUN, cinfo->speed_run);
@@ -600,13 +601,10 @@ void Creature::RegenerateMana()
// Combat and any controlled creature
if (isInCombat() || GetCharmerOrOwnerGUID())
{
- if (!IsUnderLastManaUseEffect())
- {
- float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
- float Spirit = GetStat(STAT_SPIRIT);
+ float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
+ float Spirit = GetStat(STAT_SPIRIT);
- addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
- }
+ addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
}
else
addvalue = maxValue / 3;
@@ -1045,26 +1043,35 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo)
// mana
uint32 mana = stats->GenerateMana(cinfo);
-
SetCreateMana(mana);
- SetMaxPower(POWER_MANA, mana); //MAX Mana
- SetPower(POWER_MANA, mana);
- /// @todo set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
+ switch (getClass())
+ {
+ case CLASS_WARRIOR:
+ setPowerType(POWER_RAGE);
+ break;
+ case CLASS_ROGUE:
+ setPowerType(POWER_ENERGY);
+ break;
+ default:
+ SetMaxPower(POWER_MANA, mana);
+ SetPower(POWER_MANA, mana);
+ break;
+ }
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
//damage
- float damagemod = 1.0f;//_GetDamageMod(rank);
+ //float damagemod = _GetDamageMod(rank); // Set during loading templates into dmg_multiplier field
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg);
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg);
- SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->minrangedmg * damagemod);
- SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->maxrangedmg * damagemod);
+ SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->minrangedmg);
+ SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->maxrangedmg);
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod);
+ SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower);
}
@@ -1640,7 +1647,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim)
if (bcontinue)
continue;
- if (spellInfo->ManaCost > GetPower(POWER_MANA))
+ if (spellInfo->ManaCost > (uint32)GetPower(POWER_MANA))
continue;
float range = spellInfo->GetMaxRange(false);
float minrange = spellInfo->GetMinRange(false);
@@ -1684,7 +1691,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim)
if (bcontinue)
continue;
- if (spellInfo->ManaCost > GetPower(POWER_MANA))
+ if (spellInfo->ManaCost > (uint32)GetPower(POWER_MANA))
continue;
float range = spellInfo->GetMaxRange(true);
@@ -2095,11 +2102,6 @@ void Creature::SetInCombatWithZone()
}
}
-uint32 Creature::GetShieldBlockValue() const //dunno mob block value
-{
- return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20));
-}
-
void Creature::_AddCreatureSpellCooldown(uint32 spell_id, time_t end_time)
{
m_CreatureSpellCooldowns[spell_id] = end_time;
@@ -2419,9 +2421,10 @@ bool Creature::SetWalk(bool enable)
if (!Unit::SetWalk(enable))
return false;
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
+ if (!movespline->Initialized())
+ return true;
+
+ SendMovementWalkMode();
return true;
}
@@ -2435,9 +2438,7 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=false*/)
if (!movespline->Initialized())
return true;
- WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
+ SendMovementDisableGravity();
return true;
}
@@ -2455,10 +2456,10 @@ bool Creature::SetHover(bool enable)
if (!movespline->Initialized())
return true;
- //! Not always a packet is sent
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
+ // If creature hovers using aura, the hover movement opcode is sent from aura handler
+ if (!HasAuraType(SPELL_AURA_HOVER))
+ SendMovementHover();
+
return true;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index d96cbd0eb26..df4031f521f 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -88,6 +88,7 @@ struct CreatureTemplate
uint8 minlevel;
uint8 maxlevel;
uint32 expansion;
+ uint32 expansionUnknown; // either 0 or 3, sent to the client / wdb
uint32 faction_A;
uint32 faction_H;
uint32 npcflag;
@@ -108,7 +109,6 @@ struct CreatureTemplate
uint32 dynamicflags;
uint32 family; // enum CreatureFamily values (optional)
uint32 trainer_type;
- uint32 trainer_spell;
uint32 trainer_class;
uint32 trainer_race;
float minrangedmg;
@@ -116,6 +116,7 @@ struct CreatureTemplate
uint32 rangedattackpower;
uint32 type; // enum CreatureType values
uint32 type_flags; // enum CreatureTypeFlags mask values
+ uint32 type_flags2; // unknown enum, only set for 4 creatures (with value 1)
uint32 lootid;
uint32 pickpocketLootId;
uint32 SkinLootId;
@@ -131,6 +132,7 @@ struct CreatureTemplate
float HoverHeight;
float ModHealth;
float ModMana;
+ float ModManaExtra; // Added in 4.x, this value is usually 2 for a small group of creatures with double mana
float ModArmor;
bool RacialLeader;
uint32 questItems[MAX_CREATURE_QUEST_ITEMS];
@@ -173,10 +175,6 @@ struct CreatureTemplate
// Benchmarked: Faster than std::map (insert/find)
typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer;
-// Represents max amount of expansions.
-/// @todo: Add MAX_EXPANSION constant.
-#define MAX_CREATURE_BASE_HP 3
-
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack(1)
@@ -204,7 +202,7 @@ struct CreatureBaseStats
if (!BaseMana)
return 0;
- return uint32((BaseMana * info->ModMana) + 0.5f);
+ return uint32((BaseMana * info->ModMana * info->ModManaExtra) + 0.5f);
}
uint32 GenerateArmor(CreatureTemplate const* info) const
@@ -324,13 +322,14 @@ typedef UNORDERED_MAP<uint32, CreatureAddon> CreatureAddonContainer;
// Vendors
struct VendorItem
{
- VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost)
- : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost) {}
+ VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost, uint8 _Type)
+ : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost), Type(_Type) {}
uint32 item;
uint32 maxcount; // 0 for infinity item amount
uint32 incrtime; // time for restore items amount if maxcount != 0
uint32 ExtendedCost;
+ uint8 Type;
//helpers
bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->Flags2 & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; }
@@ -350,12 +349,12 @@ struct VendorItemData
}
bool Empty() const { return m_items.empty(); }
uint8 GetItemCount() const { return m_items.size(); }
- void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost)
+ void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type)
{
- m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost));
+ m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost, type));
}
- bool RemoveItem(uint32 item_id);
- VendorItem const* FindItemCostPair(uint32 item_id, uint32 extendedCost) const;
+ bool RemoveItem(uint32 item_id, uint8 type);
+ VendorItem const* FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const;
void Clear()
{
for (VendorItemList::const_iterator itr = m_items.begin(); itr != m_items.end(); ++itr)
@@ -413,7 +412,7 @@ typedef std::map<uint32, time_t> CreatureSpellCooldowns;
// max different by z coordinate for creature aggro reaction
#define CREATURE_Z_ATTACK_RANGE 3
-#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
+#define MAX_VENDOR_ITEMS 300 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY
enum CreatureCellMoveState
{
@@ -508,8 +507,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
bool SetDisableGravity(bool disable, bool packetOnly = false);
bool SetHover(bool enable);
- uint32 GetShieldBlockValue() const;
-
SpellSchoolMask GetMeleeDamageSchoolMask() const { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index d59015fd359..3cefc5881e9 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -344,11 +344,11 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u", GUID_LOPART(npcGUID));
}
-void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const
+void PlayerMenu::SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const
{
- WorldPacket data(SMSG_QUESTGIVER_STATUS, 9);
+ WorldPacket data(SMSG_QUESTGIVER_STATUS, 8 + 4);
data << uint64(npcGUID);
- data << uint8(questStatus);
+ data << uint32(questStatus);
_session->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u", GUID_LOPART(npcGUID), questStatus);
@@ -356,10 +356,14 @@ void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID, bool activateAccept) const
{
- std::string questTitle = quest->GetTitle();
- std::string questDetails = quest->GetDetails();
- std::string questObjectives = quest->GetObjectives();
- std::string questEndText = quest->GetEndText();
+ std::string questTitle = quest->GetTitle();
+ std::string questDetails = quest->GetDetails();
+ std::string questObjectives = quest->GetObjectives();
+ std::string questEndText = quest->GetEndText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
int32 locale = _session->GetSessionDbLocaleIndex();
if (locale >= 0)
@@ -370,6 +374,10 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
ObjectMgr::GetLocaleString(localeData->Details, locale, questDetails);
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
}
}
@@ -378,81 +386,28 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size
data << uint64(npcGUID);
- data << uint64(0); // wotlk, something todo with quest sharing?
+ data << uint64(0); // either 0 or a npc guid (quest giver)
data << uint32(quest->GetQuestId());
data << questTitle;
data << questDetails;
data << questObjectives;
+ data << questGiverTextWindow; // 4.x
+ data << questGiverTargetName; // 4.x
+ data << questTurnTextWindow; // 4.x
+ data << questTurnTargetName; // 4.x
+ data << uint32(quest->GetQuestGiverPortrait()); // 4.x
+ data << uint32(quest->GetQuestTurnInPortrait()); // 4.x
data << uint8(activateAccept ? 1 : 0); // auto finish
data << uint32(quest->GetFlags()); // 3.3.3 questFlags
data << uint32(quest->GetSuggestedPlayers());
data << uint8(0); // IsFinished? value is sent back to server in quest accept packet
+ data << uint8(0); // 4.x FIXME: Starts at AreaTrigger
+ data << uint32(quest->GetRequiredSpell()); // 4.x
- if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
- {
- data << uint32(0); // Rewarded chosen items hidden
- data << uint32(0); // Rewarded items hidden
- data << uint32(0); // Rewarded money hidden
- data << uint32(0); // Rewarded XP hidden
- }
- else
- {
- data << uint32(quest->GetRewChoiceItemsCount());
- for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- {
- if (!quest->RewardChoiceItemId[i])
- continue;
-
- data << uint32(quest->RewardChoiceItemId[i]);
- data << uint32(quest->RewardChoiceItemCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0x00);
- }
-
- data << uint32(quest->GetRewItemsCount());
-
- for (uint32 i=0; i < QUEST_REWARDS_COUNT; ++i)
- {
- if (!quest->RewardItemId[i])
- continue;
-
- data << uint32(quest->RewardItemId[i]);
- data << uint32(quest->RewardItemIdCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
- }
-
- // rewarded honor points. Multiply with 10 to satisfy client
- data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
- data << float(0.0f); // unk, honor multiplier?
- data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
- data << int32(quest->GetRewSpellCast()); // casted spell
- data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // reward arena points
- data << uint32(0); // unk
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << uint32(quest->RewardFactionId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueIdOverride[i]);
+ quest->BuildExtraQuestInfo(data, _session->GetPlayer());
data << uint32(QUEST_EMOTE_COUNT);
- for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i)
{
data << uint32(quest->DetailsEmote[i]);
data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms)
@@ -469,6 +424,10 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
std::string questObjectives = quest->GetObjectives();
std::string questEndText = quest->GetEndText();
std::string questCompletedText = quest->GetCompletedText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
std::string questObjectiveText[QUEST_OBJECTIVES_COUNT];
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
@@ -484,6 +443,10 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
ObjectMgr::GetLocaleString(localeData->CompletedText, locale, questCompletedText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], locale, questObjectiveText[i]);
@@ -524,11 +487,16 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << float(quest->GetRewHonorMultiplier());
data << uint32(quest->GetSrcItemId()); // source item id
data << uint32(quest->GetFlags() & 0xFFFF); // quest flags
+ data << uint32(quest->GetMinimapTargetMark()); // minimap target mark (skull, etc. missing enum)
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
data << uint32(quest->GetPlayersSlain()); // players slain
data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // bonus arena points
- data << uint32(0); // review rep show mask
+ data << uint32(quest->GetRewArenaPoints()); // bonus arena points FIXME: arena points were removed, right?
+ data << uint32(quest->GetRewardSkillId()); // reward skill id
+ data << uint32(quest->GetRewardSkillPoints()); // reward skill points
+ data << uint32(quest->GetRewardReputationMask()); // rep mask (unsure on what it does)
+ data << uint32(quest->GetQuestGiverPortrait()); // quest giver entry ?
+ data << uint32(quest->GetQuestTurnInPortrait()); // quest turnin entry ?
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
{
@@ -557,7 +525,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid+1 QuestFactionReward.dbc?
data << int32(quest->RewardFactionValueId[i]);
- for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0)
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unknown usage
data << int32(quest->RewardFactionValueIdOverride[i]);
data << uint32(quest->GetPointMapId());
@@ -572,7 +540,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << questObjectives;
data << questDetails;
data << questEndText;
- data << questCompletedText; // display in quest objectives window once all objectives are completed
+ data << questCompletedText;
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
{
@@ -583,7 +551,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->RequiredNpcOrGoCount[i]);
data << uint32(quest->RequiredSourceItemId[i]);
- data << uint32(0); // req source count?
+ data << uint32(quest->RequiredSourceItemCount[i]);
}
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
@@ -592,9 +560,30 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->RequiredItemCount[i]);
}
+ data << uint32(quest->GetRequiredSpell()); // Is it required to be cast, learned or what?
+
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
data << questObjectiveText[i];
+ for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ {
+ data << uint32(quest->RewardCurrencyId[i]);
+ data << uint32(quest->RewardCurrencyCount[i]);
+ }
+
+ for (uint32 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ {
+ data << uint32(quest->RequiredCurrencyId[i]);
+ data << uint32(quest->RequiredCurrencyCount[i]);
+ }
+
+ data << questGiverTextWindow;
+ data << questGiverTargetName;
+ data << questTurnTextWindow;
+ data << questTurnTargetName;
+ data << uint32(quest->GetSoundAccept());
+ data << uint32(quest->GetSoundTurnIn());
+
_session->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", quest->GetQuestId());
}
@@ -603,6 +592,10 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
{
std::string questTitle = quest->GetTitle();
std::string questOfferRewardText = quest->GetOfferRewardText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
int32 locale = _session->GetSessionDbLocaleIndex();
if (locale >= 0)
@@ -611,6 +604,10 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
{
ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle);
ObjectMgr::GetLocaleString(localeData->OfferRewardText, locale, questOfferRewardText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
}
}
@@ -623,6 +620,13 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
data << questTitle;
data << questOfferRewardText;
+ data << questGiverTextWindow;
+ data << questGiverTargetName;
+ data << questTurnTextWindow;
+ data << questTurnTargetName;
+ data << uint32(quest->GetQuestGiverPortrait());
+ data << uint32(quest->GetQuestTurnInPortrait());
+
data << uint8(enableNext ? 1 : 0); // Auto Finish
data << uint32(quest->GetFlags()); // 3.3.3 questFlags
data << uint32(quest->GetSuggestedPlayers()); // SuggestedGroupNum
@@ -642,52 +646,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
data << uint32(quest->OfferRewardEmote[i]);
}
- data << uint32(quest->GetRewChoiceItemsCount());
- for (uint32 i=0; i < quest->GetRewChoiceItemsCount(); ++i)
- {
- data << uint32(quest->RewardChoiceItemId[i]);
- data << uint32(quest->RewardChoiceItemCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewItemsCount());
- for (uint32 i = 0; i < quest->GetRewItemsCount(); ++i)
- {
- data << uint32(quest->RewardItemId[i]);
- data << uint32(quest->RewardItemIdCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
-
- // rewarded honor points. Multiply with 10 to satisfy client
- data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
- data << float(0.0f); // unk, honor multiplier?
- data << uint32(0x08); // unused by client?
- data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
- data << int32(quest->GetRewSpellCast()); // casted spell
- data << uint32(0); // unknown
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // arena points
- data << uint32(0);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
- data << uint32(quest->RewardFactionId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (zero based)?
- data << int32(quest->RewardFactionValueId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override?
- data << uint32(quest->RewardFactionValueIdOverride[i]);
+ quest->BuildExtraQuestInfo(data, _session->GetPlayer());
_session->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId());
@@ -757,14 +716,25 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID,
data << uint32(0);
}
- if (!canComplete)
- data << uint32(0x00);
+ data << uint32(quest->GetReqCurrencyCount());
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ {
+ if (!quest->RequiredCurrencyId[i])
+ continue;
+
+ data << uint32(quest->RequiredCurrencyId[i]);
+ data << uint32(quest->RequiredCurrencyCount[i]);
+ }
+
+ if (!canComplete) // Experimental; there are 6 similar flags, if any of them
+ data << uint32(0x00); // of them is 0 player can't complete quest (still unknown meaning)
else
- data << uint32(0x03);
+ data << uint32(0x02);
data << uint32(0x04);
data << uint32(0x08);
data << uint32(0x10);
+ data << uint32(0x40);
_session->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId());
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index b43ab8ec332..c76febc0165 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -271,7 +271,7 @@ class PlayerMenu
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
- void SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const;
+ void SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const;
void SendQuestGiverQuestList(QEmote eEmote, const std::string& Title, uint64 npcGUID);
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index eb6bc1bba88..4e21faf2a6c 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -196,7 +196,8 @@ void TempSummon::InitStats(uint32 duration)
if (owner)
{
- if (uint32 slot = m_Properties->Slot)
+ int32 slot = m_Properties->Slot;
+ if (slot > 0)
{
if (owner->m_SummonSlot[slot] && owner->m_SummonSlot[slot] != GetGUID())
{
@@ -268,10 +269,13 @@ void TempSummon::RemoveFromWorld()
return;
if (m_Properties)
- if (uint32 slot = m_Properties->Slot)
+ {
+ int32 slot = m_Properties->Slot;
+ if (slot > 0)
if (Unit* owner = GetSummoner())
if (owner->m_SummonSlot[slot] == GetGUID())
owner->m_SummonSlot[slot] = 0;
+ }
//if (GetOwnerGUID())
// TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit %u has owner guid when removed from world", GetEntry());
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index 92eab703155..ce9ac112132 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -33,7 +33,7 @@ DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject),
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
m_valuesCount = DYNAMICOBJECT_END;
}
@@ -79,29 +79,23 @@ void DynamicObject::RemoveFromWorld()
}
}
-bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type)
+bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, SpellInfo const* spell, Position const& pos, float radius, DynamicObjectType type)
{
SetMap(caster->GetMap());
Relocate(pos);
if (!IsPositionValid())
{
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", spellId, GetPositionX(), GetPositionY());
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", spell->Id, GetPositionX(), GetPositionY());
return false;
}
WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask());
- SetEntry(spellId);
+ SetEntry(spell->Id);
SetObjectScale(1);
SetUInt64Value(DYNAMICOBJECT_CASTER, caster->GetGUID());
-
- // The lower word of DYNAMICOBJECT_BYTES must be 0x0001. This value means that the visual radius will be overriden
- // by client for most of the "ground patch" visual effect spells and a few "skyfall" ones like Hurricane.
- // If any other value is used, the client will _always_ use the radius provided in DYNAMICOBJECT_RADIUS, but
- // precompensation is necessary (eg radius *= 2) for many spells. Anyway, blizz sends 0x0001 for all the spells
- // I saw sniffed...
- SetByteValue(DYNAMICOBJECT_BYTES, 0, type);
- SetUInt32Value(DYNAMICOBJECT_SPELLID, spellId);
+ SetUInt32Value(DYNAMICOBJECT_BYTES, spell->SpellVisual[0] | (type << 28));
+ SetUInt32Value(DYNAMICOBJECT_SPELLID, spell->Id);
SetFloatValue(DYNAMICOBJECT_RADIUS, radius);
SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime());
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index 0522bc67aff..7d05d2083df 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -41,7 +41,7 @@ class DynamicObject : public WorldObject, public GridObject<DynamicObject>
void AddToWorld();
void RemoveFromWorld();
- bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
+ bool CreateDynamicObject(uint32 guidlow, Unit* caster, SpellInfo const* spell, Position const& pos, float radius, DynamicObjectType type);
void Update(uint32 p_time);
void Remove();
void SetDuration(int32 newDuration);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 1556703e45b..8d15e6ab39a 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -29,7 +29,7 @@
#include "ScriptMgr.h"
#include "CreatureAISelector.h"
#include "Group.h"
-
+#include "MapManager.h"
#include "GameObjectModel.h"
#include "DynamicTree.h"
@@ -38,7 +38,7 @@ GameObject::GameObject(): WorldObject(false), m_model(NULL), m_goValue(), m_AI(N
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION | UPDATEFLAG_ROTATION);
+ m_updateFlag = (UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);
m_valuesCount = GAMEOBJECT_END;
m_respawnTime = 0;
@@ -235,6 +235,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
m_goValue.Building.Health = goinfo->building.intactNumHits + goinfo->building.damagedNumHits;
m_goValue.Building.MaxHealth = m_goValue.Building.Health;
SetGoAnimProgress(255);
+ SetUInt32Value(GAMEOBJECT_PARENTROTATION, m_goInfo->building.destructibleData);
break;
case GAMEOBJECT_TYPE_TRANSPORT:
SetUInt32Value(GAMEOBJECT_LEVEL, goinfo->transport.pause);
@@ -320,7 +321,7 @@ void GameObject::Update(uint32 diff)
SetGoState(GO_STATE_ACTIVE);
SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
- UpdateData udata;
+ UpdateData udata(caster->GetMapId());
WorldPacket packet;
BuildValuesUpdateBlockForPlayer(&udata, caster->ToPlayer());
udata.BuildPacket(&packet);
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 164735a56b5..b1d55a6b200 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -45,6 +45,7 @@ struct GameObjectTemplate
uint32 flags;
float size;
uint32 questItems[MAX_GAMEOBJECT_QUEST_ITEMS];
+ int32 unkInt32;
union // different GO types have different data field
{
//0 GAMEOBJECT_TYPE_DOOR
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index d87e1e8fbbc..86d02132eca 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -28,6 +28,7 @@
#include "ConditionMgr.h"
#include "Player.h"
#include "Opcodes.h"
+#include "WorldSession.h"
void AddItemsSetItem(Player* player, Item* item)
{
@@ -213,6 +214,10 @@ bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
if (!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
return false;
return true;
+ case ITEM_SUBCLASS_TACKLE_CONTAINER:
+ if (!(pProto->BagFamily & BAG_FAMILY_MASK_FISHING_SUPP))
+ return false;
+ return true;
default:
return false;
}
@@ -239,7 +244,7 @@ Item::Item()
m_objectType |= TYPEMASK_ITEM;
m_objectTypeId = TYPEID_ITEM;
- m_updateFlag = UPDATEFLAG_LOWGUID;
+ m_updateFlag = 0;
m_valuesCount = ITEM_END;
m_slot = 0;
@@ -553,46 +558,6 @@ uint32 Item::GetSkill()
}
}
-uint32 Item::GetSpell()
-{
- ItemTemplate const* proto = GetTemplate();
-
- switch (proto->Class)
- {
- case ITEM_CLASS_WEAPON:
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_AXE: return 196;
- case ITEM_SUBCLASS_WEAPON_AXE2: return 197;
- case ITEM_SUBCLASS_WEAPON_BOW: return 264;
- case ITEM_SUBCLASS_WEAPON_GUN: return 266;
- case ITEM_SUBCLASS_WEAPON_MACE: return 198;
- case ITEM_SUBCLASS_WEAPON_MACE2: return 199;
- case ITEM_SUBCLASS_WEAPON_POLEARM: return 200;
- case ITEM_SUBCLASS_WEAPON_SWORD: return 201;
- case ITEM_SUBCLASS_WEAPON_SWORD2: return 202;
- case ITEM_SUBCLASS_WEAPON_STAFF: return 227;
- case ITEM_SUBCLASS_WEAPON_DAGGER: return 1180;
- case ITEM_SUBCLASS_WEAPON_THROWN: return 2567;
- case ITEM_SUBCLASS_WEAPON_SPEAR: return 3386;
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:return 5011;
- case ITEM_SUBCLASS_WEAPON_WAND: return 5009;
- default: return 0;
- }
- case ITEM_CLASS_ARMOR:
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_ARMOR_CLOTH: return 9078;
- case ITEM_SUBCLASS_ARMOR_LEATHER: return 9077;
- case ITEM_SUBCLASS_ARMOR_MAIL: return 8737;
- case ITEM_SUBCLASS_ARMOR_PLATE: return 750;
- case ITEM_SUBCLASS_ARMOR_SHIELD: return 9116;
- default: return 0;
- }
- }
- return 0;
-}
-
int32 Item::GenerateItemRandomPropertyId(uint32 item_id)
{
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
@@ -654,8 +619,8 @@ void Item::SetItemRandomProperties(int32 randomPropId)
SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, item_rand->ID);
SetState(ITEM_CHANGED, GetOwner());
}
- for (uint32 i = PROP_ENCHANTMENT_SLOT_2; i < PROP_ENCHANTMENT_SLOT_2 + 3; ++i)
- SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_2], 0, 0);
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_1; i < PROP_ENCHANTMENT_SLOT_1 + 3; ++i)
+ SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_1], 0, 0);
}
}
else
@@ -671,7 +636,7 @@ void Item::SetItemRandomProperties(int32 randomPropId)
SetState(ITEM_CHANGED, GetOwner());
}
- for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i)
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i <= PROP_ENCHANTMENT_SLOT_4; ++i)
SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
}
}
@@ -791,10 +756,15 @@ bool Item::HasEnchantRequiredSkill(const Player* player) const
{
// Check all enchants for required skill
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT || enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->requiredSkill && player->GetSkillValue(enchantEntry->requiredSkill) < enchantEntry->requiredSkillValue)
return false;
+ }
return true;
}
@@ -805,10 +775,15 @@ uint32 Item::GetEnchantRequiredLevel() const
// Check all enchants for required level
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT || enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->requiredLevel > level)
level = enchantEntry->requiredLevel;
+ }
return level;
}
@@ -817,10 +792,16 @@ bool Item::IsBoundByEnchant() const
{
// Check all enchants for soulbound
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT || enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
return true;
+ }
+
return false;
}
@@ -828,15 +809,15 @@ InventoryResult Item::CanBeMergedPartlyWith(ItemTemplate const* proto) const
{
// not allow merge looting currently items
if (m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// check item type
if (GetEntry() != proto->ItemId)
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
// check free space (full stacks can't be target of merge
if (GetCount() >= proto->GetMaxStackSize())
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
return EQUIP_ERR_OK;
}
@@ -848,8 +829,8 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
if (spellInfo->EquippedItemClass != -1) // -1 == any item class
{
// Special case - accept vellum for armor/weapon requirements
- if ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
- ||(spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum()))
+ if ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR ||
+ spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON) && proto->IsVellum())
if (spellInfo->IsAbilityOfSkillType(SKILL_ENCHANTING)) // only for enchanting spells
return true;
@@ -1227,6 +1208,305 @@ bool Item::CheckSoulboundTradeExpire()
return false;
}
+bool Item::CanBeTransmogrified() const
+{
+ ItemTemplate const* proto = GetTemplate();
+
+ if (!proto)
+ return false;
+
+ if (proto->Quality == ITEM_QUALITY_LEGENDARY)
+ return false;
+
+ if (proto->Class != ITEM_CLASS_ARMOR &&
+ proto->Class != ITEM_CLASS_WEAPON)
+ return false;
+
+ if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG)
+ return false;
+
+ if (!HasStats())
+ return false;
+
+ return true;
+}
+
+bool Item::CanTransmogrify() const
+{
+ ItemTemplate const* proto = GetTemplate();
+
+ if (!proto)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG)
+ return false;
+
+ if (proto->Quality == ITEM_QUALITY_LEGENDARY)
+ return false;
+
+ if (proto->Class != ITEM_CLASS_ARMOR &&
+ proto->Class != ITEM_CLASS_WEAPON)
+ return false;
+
+ if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CAN_TRANSMOG)
+ return true;
+
+ if (!HasStats())
+ return false;
+
+ return true;
+}
+
+bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier)
+{
+ if (!transmogrifier || !transmogrified)
+ return false;
+
+ ItemTemplate const* proto1 = transmogrifier->GetTemplate(); // source
+ ItemTemplate const* proto2 = transmogrified->GetTemplate(); // dest
+
+ if (proto1->ItemId == proto2->ItemId)
+ return false;
+
+ if (!transmogrified->CanTransmogrify() || !transmogrifier->CanBeTransmogrified())
+ return false;
+
+ if (proto1->InventoryType == INVTYPE_BAG ||
+ proto1->InventoryType == INVTYPE_RELIC ||
+ proto1->InventoryType == INVTYPE_BODY ||
+ proto1->InventoryType == INVTYPE_FINGER ||
+ proto1->InventoryType == INVTYPE_TRINKET ||
+ proto1->InventoryType == INVTYPE_AMMO ||
+ proto1->InventoryType == INVTYPE_QUIVER)
+ return false;
+
+ if (proto1->SubClass != proto2->SubClass && (proto1->Class != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon()))
+ return false;
+
+ if (proto1->InventoryType != proto2->InventoryType &&
+ (proto1->Class != ITEM_CLASS_WEAPON || (proto2->InventoryType != INVTYPE_WEAPONMAINHAND && proto2->InventoryType != INVTYPE_WEAPONOFFHAND)) &&
+ (proto1->Class != ITEM_CLASS_ARMOR || (proto1->InventoryType != INVTYPE_CHEST && proto2->InventoryType != INVTYPE_ROBE && proto1->InventoryType != INVTYPE_ROBE && proto2->InventoryType != INVTYPE_CHEST)))
+ return false;
+
+ return true;
+}
+
+bool Item::HasStats() const
+{
+ if (GetItemRandomPropertyId() != 0)
+ return true;
+
+ ItemTemplate const* proto = GetTemplate();
+ for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if (proto->ItemStat[i].ItemStatValue != 0)
+ return true;
+
+ return false;
+}
+
+// used by mail items, transmog cost, stationeryinfo and others
+uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice)
+{
+ normalSellPrice = true;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ {
+ return proto->BuyPrice;
+ }
+ else
+ {
+ ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(proto->Quality + 1);
+ ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(proto->ItemLevel);
+
+ if (!qualityPrice || !basePrice)
+ return 0;
+
+ float qualityFactor = qualityPrice->Factor;
+ float baseFactor = 0.0f;
+
+ uint32 inventoryType = proto->InventoryType;
+
+ if (inventoryType == INVTYPE_WEAPON ||
+ inventoryType == INVTYPE_2HWEAPON ||
+ inventoryType == INVTYPE_WEAPONMAINHAND ||
+ inventoryType == INVTYPE_WEAPONOFFHAND ||
+ inventoryType == INVTYPE_RANGED ||
+ inventoryType == INVTYPE_THROWN ||
+ inventoryType == INVTYPE_RANGEDRIGHT)
+ baseFactor = basePrice->WeaponFactor;
+ else
+ baseFactor = basePrice->ArmorFactor;
+
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
+
+ float typeFactor = 0.0f;
+ int8 weapType = -1;
+
+ switch (inventoryType)
+ {
+ case INVTYPE_HEAD:
+ case INVTYPE_SHOULDERS:
+ case INVTYPE_CHEST:
+ case INVTYPE_WAIST:
+ case INVTYPE_LEGS:
+ case INVTYPE_FEET:
+ case INVTYPE_WRISTS:
+ case INVTYPE_HANDS:
+ case INVTYPE_CLOAK:
+ {
+ ImportPriceArmorEntry const* armorPrice = sImportPriceArmorStore.LookupEntry(inventoryType);
+ if (!armorPrice)
+ return 0;
+
+ switch (proto->SubClass)
+ {
+ case ITEM_SUBCLASS_ARMOR_MISCELLANEOUS:
+ case ITEM_SUBCLASS_ARMOR_CLOTH:
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_LEATHER:
+ typeFactor = armorPrice->LeatherFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_MAIL:
+ typeFactor = armorPrice->MailFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_PLATE:
+ typeFactor = armorPrice->PlateFactor;
+ break;
+ default:
+ return 0;
+ }
+
+ break;
+ }
+ case INVTYPE_SHIELD:
+ {
+ ImportPriceShieldEntry const* shieldPrice = sImportPriceShieldStore.LookupEntry(1); // it only has two rows, it's unclear which is the one used
+ if (!shieldPrice)
+ return 0;
+
+ typeFactor = shieldPrice->Factor;
+ break;
+ }
+ case INVTYPE_WEAPONMAINHAND:
+ weapType = 0;
+ break;
+ case INVTYPE_WEAPONOFFHAND:
+ weapType = 1;
+ break;
+ case INVTYPE_WEAPON:
+ weapType = 2;
+ break;
+ case INVTYPE_2HWEAPON:
+ weapType = 3;
+ break;
+ case INVTYPE_RANGED:
+ case INVTYPE_RANGEDRIGHT:
+ case INVTYPE_RELIC:
+ weapType = 4;
+ break;
+ default:
+ return proto->BuyPrice;
+ }
+
+ if (weapType != -1)
+ {
+ ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(weapType + 1);
+ if (!weaponPrice)
+ return 0;
+
+ typeFactor = weaponPrice->Factor;
+ }
+
+ normalSellPrice = false;
+ return uint32(qualityFactor * proto->Unk430_2 * proto->Unk430_1 * typeFactor * baseFactor);
+ }
+}
+
+uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= 10000*/)
+{
+ uint32 cost = 0;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ cost = proto->SellPrice;
+ else
+ {
+ bool normalPrice;
+ cost = Item::GetSellPrice(proto, normalPrice);
+
+ if (!normalPrice)
+ {
+ if (proto->BuyCount <= 1)
+ {
+ ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->Class);
+ if (classEntry)
+ cost *= classEntry->PriceFactor;
+ else
+ cost = 0;
+ }
+ else
+ cost /= 4 * proto->BuyCount;
+ }
+ else
+ cost = proto->SellPrice;
+ }
+
+ if (cost < minimumPrice)
+ cost = minimumPrice;
+
+ return cost;
+}
+
+int32 Item::GetReforgableStat(ItemModType statType) const
+{
+ ItemTemplate const* proto = GetTemplate();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if (ItemModType(proto->ItemStat[i].ItemStatType) == statType)
+ return proto->ItemStat[i].ItemStatValue;
+
+ int32 randomPropId = GetItemRandomPropertyId();
+ if (!randomPropId)
+ return 0;
+
+ if (randomPropId < 0)
+ {
+ ItemRandomSuffixEntry const* randomSuffix = sItemRandomSuffixStore.LookupEntry(-randomPropId);
+ if (!randomSuffix)
+ return 0;
+
+ for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e)
+ if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e))))
+ for (uint32 f = 0; f < MAX_ITEM_ENCHANTMENT_EFFECTS; ++f)
+ if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && ItemModType(enchant->spellid[f]) == statType)
+ for (int k = 0; k < 5; ++k)
+ if (randomSuffix->enchant_id[k] == enchant->ID)
+ return int32((randomSuffix->prefix[k] * GetItemSuffixFactor()) / 10000);
+ }
+ else
+ {
+ ItemRandomPropertiesEntry const* randomProp = sItemRandomPropertiesStore.LookupEntry(randomPropId);
+ if (!randomProp)
+ return 0;
+
+ for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e)
+ if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e))))
+ for (uint32 f = 0; f < MAX_ITEM_ENCHANTMENT_EFFECTS; ++f)
+ if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && ItemModType(enchant->spellid[f]) == statType)
+ for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ if (randomProp->enchant_id[k] == enchant->ID)
+ return int32(enchant->amount[k]);
+ }
+
+ return 0;
+}
+
void Item::ItemContainerSaveLootToDB()
{
// Saves the money and item loot associated with an openable item to the DB
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index b18dfe694d6..cdc79d96d67 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -38,95 +38,99 @@ struct ItemSetEffect
enum InventoryResult
{
- EQUIP_ERR_OK = 0,
- EQUIP_ERR_CANT_EQUIP_LEVEL_I = 1,
- EQUIP_ERR_CANT_EQUIP_SKILL = 2,
- EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT = 3,
- EQUIP_ERR_BAG_FULL = 4,
- EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG = 5,
- EQUIP_ERR_CANT_TRADE_EQUIP_BAGS = 6,
- EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE = 7,
- EQUIP_ERR_NO_REQUIRED_PROFICIENCY = 8,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE = 9,
- EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM = 10,
- EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM2 = 11,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE2 = 12,
- EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED = 13,
- EQUIP_ERR_CANT_DUAL_WIELD = 14,
- EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG = 15,
- EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG2 = 16,
- EQUIP_ERR_CANT_CARRY_MORE_OF_THIS = 17,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE3 = 18,
- EQUIP_ERR_ITEM_CANT_STACK = 19,
- EQUIP_ERR_ITEM_CANT_BE_EQUIPPED = 20,
- EQUIP_ERR_ITEMS_CANT_BE_SWAPPED = 21,
- EQUIP_ERR_SLOT_IS_EMPTY = 22,
- EQUIP_ERR_ITEM_NOT_FOUND = 23,
- EQUIP_ERR_CANT_DROP_SOULBOUND = 24,
- EQUIP_ERR_OUT_OF_RANGE = 25,
- EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT = 26,
- EQUIP_ERR_COULDNT_SPLIT_ITEMS = 27,
- EQUIP_ERR_MISSING_REAGENT = 28,
- EQUIP_ERR_NOT_ENOUGH_MONEY = 29,
- EQUIP_ERR_NOT_A_BAG = 30,
- EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS = 31,
- EQUIP_ERR_DONT_OWN_THAT_ITEM = 32,
- EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER = 33,
- EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT = 34,
- EQUIP_ERR_TOO_FAR_AWAY_FROM_BANK = 35,
- EQUIP_ERR_ITEM_LOCKED = 36,
- EQUIP_ERR_YOU_ARE_STUNNED = 37,
- EQUIP_ERR_YOU_ARE_DEAD = 38,
- EQUIP_ERR_CANT_DO_RIGHT_NOW = 39,
- EQUIP_ERR_INT_BAG_ERROR = 40,
- EQUIP_ERR_CAN_EQUIP_ONLY1_BOLT = 41,
- EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH = 42,
- EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED = 43,
- EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED = 44,
- EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED = 45,
- EQUIP_ERR_BOUND_CANT_BE_WRAPPED = 46,
- EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED = 47,
- EQUIP_ERR_BAGS_CANT_BE_WRAPPED = 48,
- EQUIP_ERR_ALREADY_LOOTED = 49,
- EQUIP_ERR_INVENTORY_FULL = 50,
- EQUIP_ERR_BANK_FULL = 51,
- EQUIP_ERR_ITEM_IS_CURRENTLY_SOLD_OUT = 52,
- EQUIP_ERR_BAG_FULL3 = 53,
- EQUIP_ERR_ITEM_NOT_FOUND2 = 54,
- EQUIP_ERR_ITEM_CANT_STACK2 = 55,
- EQUIP_ERR_BAG_FULL4 = 56,
- EQUIP_ERR_ITEM_SOLD_OUT = 57,
- EQUIP_ERR_OBJECT_IS_BUSY = 58,
- EQUIP_ERR_NONE = 59,
- EQUIP_ERR_NOT_IN_COMBAT = 60,
- EQUIP_ERR_NOT_WHILE_DISARMED = 61,
- EQUIP_ERR_BAG_FULL6 = 62,
- EQUIP_ERR_CANT_EQUIP_RANK = 63,
- EQUIP_ERR_CANT_EQUIP_REPUTATION = 64,
- EQUIP_ERR_TOO_MANY_SPECIAL_BAGS = 65,
- EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW = 66,
- EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE = 67,
- EQUIP_ERR_VENDOR_MISSING_TURNINS = 68,
- EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS = 69,
- EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS = 70,
- EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED = 71,
- EQUIP_ERR_MAIL_BOUND_ITEM = 72,
- EQUIP_ERR_NO_SPLIT_WHILE_PROSPECTING = 73,
- EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED = 75,
- EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED = 76,
- EQUIP_ERR_TOO_MUCH_GOLD = 77,
- EQUIP_ERR_NOT_DURING_ARENA_MATCH = 78,
- EQUIP_ERR_CANNOT_TRADE_THAT = 79,
- EQUIP_ERR_PERSONAL_ARENA_RATING_TOO_LOW = 80,
- EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM = 81,
- EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS = 82,
- // no output = 83,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED = 84,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED = 85,
- EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_EXCEEDED = 86,
- EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW = 87,
- EQUIP_ERR_CANT_EQUIP_NEED_TALENT = 88,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED = 89
+ EQUIP_ERR_OK = 0,
+ EQUIP_ERR_CANT_EQUIP_LEVEL_I = 1, // You must reach level %d to use that item.
+ EQUIP_ERR_CANT_EQUIP_SKILL = 2, // You aren't skilled enough to use that item.
+ EQUIP_ERR_WRONG_SLOT = 3, // That item does not go in that slot.
+ EQUIP_ERR_BAG_FULL = 4, // That bag is full.
+ EQUIP_ERR_BAG_IN_BAG = 5, // Can't put non-empty bags in other bags.
+ EQUIP_ERR_TRADE_EQUIPPED_BAG = 6, // You can't trade equipped bags.
+ EQUIP_ERR_AMMO_ONLY = 7, // Only ammo can go there.
+ EQUIP_ERR_PROFICIENCY_NEEDED = 8, // You do not have the required proficiency for that item.
+ EQUIP_ERR_NO_SLOT_AVAILABLE = 9, // No equipment slot is available for that item.
+ EQUIP_ERR_CANT_EQUIP_EVER = 10, // You can never use that item.
+ EQUIP_ERR_CANT_EQUIP_EVER_2 = 11, // You can never use that item.
+ EQUIP_ERR_NO_SLOT_AVAILABLE_2 = 12, // No equipment slot is available for that item.
+ EQUIP_ERR_2HANDED_EQUIPPED = 13, // Cannot equip that with a two-handed weapon.
+ EQUIP_ERR_2HSKILLNOTFOUND = 14, // You cannot dual-wield
+ EQUIP_ERR_WRONG_BAG_TYPE = 15, // That item doesn't go in that container.
+ EQUIP_ERR_WRONG_BAG_TYPE_2 = 16, // That item doesn't go in that container.
+ EQUIP_ERR_ITEM_MAX_COUNT = 17, // You can't carry any more of those items.
+ EQUIP_ERR_NO_SLOT_AVAILABLE_3 = 18, // No equipment slot is available for that item.
+ EQUIP_ERR_CANT_STACK = 19, // This item cannot stack.
+ EQUIP_ERR_NOT_EQUIPPABLE = 20, // This item cannot be equipped.
+ EQUIP_ERR_CANT_SWAP = 21, // These items can't be swapped.
+ EQUIP_ERR_SLOT_EMPTY = 22, // That slot is empty.
+ EQUIP_ERR_ITEM_NOT_FOUND = 23, // The item was not found.
+ EQUIP_ERR_DROP_BOUND_ITEM = 24, // You can't drop a soulbound item.
+ EQUIP_ERR_OUT_OF_RANGE = 25, // Out of range.
+ EQUIP_ERR_TOO_FEW_TO_SPLIT = 26, // Tried to split more than number in stack.
+ EQUIP_ERR_SPLIT_FAILED = 27, // Couldn't split those items.
+ EQUIP_ERR_SPELL_FAILED_REAGENTS_GENERIC = 28, // Missing reagent
+ EQUIP_ERR_NOT_ENOUGH_MONEY = 29, // You don't have enough money.
+ EQUIP_ERR_NOT_A_BAG = 30, // Not a bag.
+ EQUIP_ERR_DESTROY_NONEMPTY_BAG = 31, // You can only do that with empty bags.
+ EQUIP_ERR_NOT_OWNER = 32, // You don't own that item.
+ EQUIP_ERR_ONLY_ONE_QUIVER = 33, // You can only equip one quiver.
+ EQUIP_ERR_NO_BANK_SLOT = 34, // You must purchase that bag slot first
+ EQUIP_ERR_NO_BANK_HERE = 35, // You are too far away from a bank.
+ EQUIP_ERR_ITEM_LOCKED = 36, // Item is locked.
+ EQUIP_ERR_GENERIC_STUNNED = 37, // You are stunned
+ EQUIP_ERR_PLAYER_DEAD = 38, // You can't do that when you're dead.
+ EQUIP_ERR_CLIENT_LOCKED_OUT = 39, // You can't do that right now.
+ EQUIP_ERR_INTERNAL_BAG_ERROR = 40, // Internal Bag Error
+ EQUIP_ERR_ONLY_ONE_BOLT = 41, // You can only equip one quiver.
+ EQUIP_ERR_ONLY_ONE_AMMO = 42, // You can only equip one ammo pouch.
+ EQUIP_ERR_CANT_WRAP_STACKABLE = 43, // Stackable items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_EQUIPPED = 44, // Equipped items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_WRAPPED = 45, // Wrapped items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_BOUND = 46, // Bound items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_UNIQUE = 47, // Unique items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_BAGS = 48, // Bags can't be wrapped.
+ EQUIP_ERR_LOOT_GONE = 49, // Already looted
+ EQUIP_ERR_INV_FULL = 50, // Inventory is full.
+ EQUIP_ERR_BANK_FULL = 51, // Your bank is full
+ EQUIP_ERR_VENDOR_SOLD_OUT = 52, // That item is currently sold out.
+ EQUIP_ERR_BAG_FULL_2 = 53, // That bag is full.
+ EQUIP_ERR_ITEM_NOT_FOUND_2 = 54, // The item was not found.
+ EQUIP_ERR_CANT_STACK_2 = 55, // This item cannot stack.
+ EQUIP_ERR_BAG_FULL_3 = 56, // That bag is full.
+ EQUIP_ERR_VENDOR_SOLD_OUT_2 = 57, // That item is currently sold out.
+ EQUIP_ERR_OBJECT_IS_BUSY = 58, // That object is busy.
+ EQUIP_ERR_CANT_BE_DISENCHANTED = 59,
+ EQUIP_ERR_NOT_IN_COMBAT = 60, // You can't do that while in combat
+ EQUIP_ERR_NOT_WHILE_DISARMED = 61, // You can't do that while disarmed
+ EQUIP_ERR_BAG_FULL_4 = 62, // That bag is full.
+ EQUIP_ERR_CANT_EQUIP_RANK = 63, // You don't have the required rank for that item
+ EQUIP_ERR_CANT_EQUIP_REPUTATION = 64, // You don't have the required reputation for that item
+ EQUIP_ERR_TOO_MANY_SPECIAL_BAGS = 65, // You cannot equip another bag of that type
+ EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW = 66, // You can't loot that item now.
+ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE = 67, // You cannot equip more than one of those.
+ EQUIP_ERR_VENDOR_MISSING_TURNINS = 68, // You do not have the required items for that purchase
+ EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS = 69, // You don't have enough honor points
+ EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS = 70, // You don't have enough arena points
+ EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED = 71, // You have the maximum number of those gems in your inventory or socketed into items.
+ EQUIP_ERR_MAIL_BOUND_ITEM = 72, // You can't mail soulbound items.
+ EQUIP_ERR_INTERNAL_BAG_ERROR_2 = 73, // Internal Bag Error
+ EQUIP_ERR_BAG_FULL_5 = 74, // That bag is full.
+ EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED = 75, // You have the maximum number of those gems socketed into equipped items.
+ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED = 76, // You cannot socket more than one of those gems into a single item.
+ EQUIP_ERR_TOO_MUCH_GOLD = 77, // At gold limit
+ EQUIP_ERR_NOT_DURING_ARENA_MATCH = 78, // You can't do that while in an arena match
+ EQUIP_ERR_TRADE_BOUND_ITEM = 79, // You can't trade a soulbound item.
+ EQUIP_ERR_CANT_EQUIP_RATING = 80, // You don't have the personal, team, or battleground rating required to buy that item
+ EQUIP_ERR_NO_OUTPUT = 81,
+ EQUIP_ERR_NOT_SAME_ACCOUNT = 82, // Account-bound items can only be given to your own characters.
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS = 84, // You can only carry %d %s
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED_IS = 85, // You can only equip %d |4item:items in the %s category
+ EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_EXCEEDED = 86, // Your level is too high to use that item
+ EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW = 87, // You must reach level %d to purchase that item.
+ EQUIP_ERR_CANT_EQUIP_NEED_TALENT = 88, // You do not have the required talent to equip that.
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS = 89, // You can only equip %d |4item:items in the %s category
+ EQUIP_ERR_SHAPESHIFT_FORM_CANNOT_EQUIP = 90, // Cannot equip item in this form
+ EQUIP_ERR_ITEM_INVENTORY_FULL_SATCHEL = 91, // Your inventory is full. Your satchel has been delivered to your mailbox.
+ EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_TOO_LOW = 92, // Your level is too low to use that item
+ EQUIP_ERR_CANT_BUY_QUANTITY = 93, // You can't buy the specified quantity of that item.
};
enum BuyResult
@@ -162,14 +166,17 @@ enum EnchantmentSlot
SOCK_ENCHANTMENT_SLOT_3 = 4,
BONUS_ENCHANTMENT_SLOT = 5,
PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment
- MAX_INSPECTED_ENCHANTMENT_SLOT = 7,
-
- PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix
- PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix
- PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty
- PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty
- PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty
- MAX_ENCHANTMENT_SLOT = 12
+ //TODO: 7,
+ REFORGE_ENCHANTMENT_SLOT = 8,
+ TRANSMOGRIFY_ENCHANTMENT_SLOT = 9,
+ MAX_INSPECTED_ENCHANTMENT_SLOT = 10,
+
+ PROP_ENCHANTMENT_SLOT_0 = 10, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_1 = 11, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_2 = 12, // used with RandomSuffix and RandomProperty
+ PROP_ENCHANTMENT_SLOT_3 = 13, // used with RandomProperty
+ PROP_ENCHANTMENT_SLOT_4 = 14, // used with RandomProperty
+ MAX_ENCHANTMENT_SLOT = 15
};
#define MAX_VISIBLE_ITEM_OFFSET 2 // 2 fields per visible item (entry+enchantment)
@@ -281,7 +288,6 @@ class Item : public Object
bool IsEquipped() const;
uint32 GetSkill();
- uint32 GetSpell();
// RandomPropertyId (signed but stored as unsigned)
int32 GetItemRandomPropertyId() const { return GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); }
@@ -326,10 +332,11 @@ class Item : public Object
bool hasQuest(uint32 quest_id) const { return GetTemplate()->StartQuest == quest_id; }
bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; }
+ bool HasStats() const;
bool IsPotion() const { return GetTemplate()->IsPotion(); }
- bool IsWeaponVellum() const { return GetTemplate()->IsWeaponVellum(); }
- bool IsArmorVellum() const { return GetTemplate()->IsArmorVellum(); }
+ bool IsVellum() const { return GetTemplate()->IsVellum(); }
bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); }
+ bool IsRangedWeapon() const { return GetTemplate()->IsRangedWeapon(); }
// Item Refund system
void SetNotRefundable(Player* owner, bool changestate = true, SQLTransaction* trans = NULL);
@@ -353,6 +360,24 @@ class Item : public Object
void BuildUpdate(UpdateDataMapType&);
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
+
+ bool CanBeTransmogrified() const;
+ bool CanTransmogrify() const;
+ static bool CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier);
+ static uint32 GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice = 10000);
+ uint32 GetSpecialPrice(uint32 minimumPrice = 10000) const { return Item::GetSpecialPrice(GetTemplate(), minimumPrice); }
+
+ uint32 GetVisibleEntry() const
+ {
+ if (uint32 transmogrification = GetEnchantmentId(TRANSMOGRIFY_ENCHANTMENT_SLOT))
+ return transmogrification;
+ return GetEntry();
+ }
+
+ static uint32 GetSellPrice(ItemTemplate const* proto, bool& success);
+
+ int32 GetReforgableStat(ItemModType statType) const;
+
private:
std::string m_text;
uint8 m_slot;
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index 5fc49c99f0a..9393b32d48a 100644
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -59,18 +59,23 @@ enum ItemModType
ITEM_MOD_EXPERTISE_RATING = 37,
ITEM_MOD_ATTACK_POWER = 38,
ITEM_MOD_RANGED_ATTACK_POWER = 39,
- //ITEM_MOD_FERAL_ATTACK_POWER = 40, not in 3.3
- ITEM_MOD_SPELL_HEALING_DONE = 41, // deprecated
- ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
ITEM_MOD_MANA_REGENERATION = 43,
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
ITEM_MOD_SPELL_POWER = 45,
ITEM_MOD_HEALTH_REGEN = 46,
ITEM_MOD_SPELL_PENETRATION = 47,
- ITEM_MOD_BLOCK_VALUE = 48
+ ITEM_MOD_BLOCK_VALUE = 48,
+ ITEM_MOD_MASTERY_RATING = 49,
+ ITEM_MOD_EXTRA_ARMOR = 50,
+ ITEM_MOD_FIRE_RESISTANCE = 51,
+ ITEM_MOD_FROST_RESISTANCE = 52,
+ ITEM_MOD_HOLY_RESISTANCE = 53,
+ ITEM_MOD_SHADOW_RESISTANCE = 54,
+ ITEM_MOD_NATURE_RESISTANCE = 55,
+ ITEM_MOD_ARCANE_RESISTANCE = 56,
};
-#define MAX_ITEM_MOD 49
+#define MAX_ITEM_MOD 57
enum ItemSpelltriggerType
{
@@ -138,7 +143,7 @@ enum ItemProtoFlags
ITEM_PROTO_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag
ITEM_PROTO_FLAG_MILLABLE = 0x20000000, // Item can be milled
ITEM_PROTO_FLAG_UNK11 = 0x40000000, // ?
- ITEM_PROTO_FLAG_UNK12 = 0x80000000 // ?
+ ITEM_PROTO_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded
};
enum ItemFieldFlags
@@ -184,7 +189,13 @@ enum ItemFlagsExtra
ITEM_FLAGS_EXTRA_HORDE_ONLY = 0x00000001,
ITEM_FLAGS_EXTRA_ALLIANCE_ONLY = 0x00000002,
ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required
- ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100
+ ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100,
+ ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200,
+ ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE = 0x00004000,
+ ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000,
+ ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG = 0x00200000,
+ ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG = 0x00400000,
+ ITEM_FLAGS_EXTRA_CAN_TRANSMOG = 0x00800000,
};
enum ItemFlagsCustom
@@ -194,6 +205,28 @@ enum ItemFlagsCustom
ITEM_FLAGS_CU_FOLLOW_LOOT_RULES = 0x0004 // Item will always follow group/master/need before greed looting rules
};
+enum CurrencyFlags
+{
+ CURRENCY_FLAG_TRADEABLE = 0x01,
+ // ...
+ CURRENCY_FLAG_HIGH_PRECISION = 0x08,
+ // ...
+ CURRENCY_FLAG_COUNT_SEASON_TOTAL = 0x80,
+};
+
+enum CurrencyCategory
+{
+ // ...
+ CURRENCY_CATEGORY_META_CONQUEST = 89,
+ // ...
+};
+
+enum ItemVendorType
+{
+ ITEM_VENDOR_TYPE_ITEM = 1,
+ ITEM_VENDOR_TYPE_CURRENCY = 2,
+};
+
enum BAG_FAMILY_MASK
{
BAG_FAMILY_MASK_NONE = 0x00000000,
@@ -211,7 +244,8 @@ enum BAG_FAMILY_MASK
BAG_FAMILY_MASK_SOULBOUND_EQUIPMENT = 0x00000800,
BAG_FAMILY_MASK_VANITY_PETS = 0x00001000,
BAG_FAMILY_MASK_CURRENCY_TOKENS = 0x00002000,
- BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000
+ BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000,
+ BAG_FAMILY_MASK_FISHING_SUPP = 0x00008000,
};
enum SocketColor
@@ -219,10 +253,12 @@ enum SocketColor
SOCKET_COLOR_META = 1,
SOCKET_COLOR_RED = 2,
SOCKET_COLOR_YELLOW = 4,
- SOCKET_COLOR_BLUE = 8
+ SOCKET_COLOR_BLUE = 8,
+ SOCKET_COLOR_HYDRAULIC = 16, // not used
+ SOCKET_COLOR_COGWHEEL = 32,
};
-#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE)
+#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE | SOCKET_COLOR_COGWHEEL)
enum InventoryType
{
@@ -269,14 +305,14 @@ enum ItemClass
ITEM_CLASS_REAGENT = 5,
ITEM_CLASS_PROJECTILE = 6,
ITEM_CLASS_TRADE_GOODS = 7,
- ITEM_CLASS_GENERIC = 8,
+ ITEM_CLASS_GENERIC = 8, // OBSOLETE
ITEM_CLASS_RECIPE = 9,
- ITEM_CLASS_MONEY = 10,
+ ITEM_CLASS_MONEY = 10, // OBSOLETE
ITEM_CLASS_QUIVER = 11,
ITEM_CLASS_QUEST = 12,
ITEM_CLASS_KEY = 13,
- ITEM_CLASS_PERMANENT = 14,
- ITEM_CLASS_MISC = 15,
+ ITEM_CLASS_PERMANENT = 14, // OBSOLETE
+ ITEM_CLASS_MISCELLANEOUS = 15,
ITEM_CLASS_GLYPH = 16
};
@@ -289,7 +325,7 @@ enum ItemSubclassConsumable
ITEM_SUBCLASS_ELIXIR = 2,
ITEM_SUBCLASS_FLASK = 3,
ITEM_SUBCLASS_SCROLL = 4,
- ITEM_SUBCLASS_FOOD = 5,
+ ITEM_SUBCLASS_FOOD_DRINK = 5,
ITEM_SUBCLASS_ITEM_ENHANCEMENT = 6,
ITEM_SUBCLASS_BANDAGE = 7,
ITEM_SUBCLASS_CONSUMABLE_OTHER = 8
@@ -307,28 +343,29 @@ enum ItemSubclassContainer
ITEM_SUBCLASS_GEM_CONTAINER = 5,
ITEM_SUBCLASS_MINING_CONTAINER = 6,
ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7,
- ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8
+ ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8,
+ ITEM_SUBCLASS_TACKLE_CONTAINER = 9
};
-#define MAX_ITEM_SUBCLASS_CONTAINER 9
+#define MAX_ITEM_SUBCLASS_CONTAINER 10
enum ItemSubclassWeapon
{
- ITEM_SUBCLASS_WEAPON_AXE = 0,
- ITEM_SUBCLASS_WEAPON_AXE2 = 1,
+ ITEM_SUBCLASS_WEAPON_AXE = 0, // One-Handed Axes
+ ITEM_SUBCLASS_WEAPON_AXE2 = 1, // Two-Handed Axes
ITEM_SUBCLASS_WEAPON_BOW = 2,
ITEM_SUBCLASS_WEAPON_GUN = 3,
- ITEM_SUBCLASS_WEAPON_MACE = 4,
- ITEM_SUBCLASS_WEAPON_MACE2 = 5,
+ ITEM_SUBCLASS_WEAPON_MACE = 4, // One-Handed Maces
+ ITEM_SUBCLASS_WEAPON_MACE2 = 5, // Two-Handed Maces
ITEM_SUBCLASS_WEAPON_POLEARM = 6,
- ITEM_SUBCLASS_WEAPON_SWORD = 7,
- ITEM_SUBCLASS_WEAPON_SWORD2 = 8,
- ITEM_SUBCLASS_WEAPON_obsolete = 9,
+ ITEM_SUBCLASS_WEAPON_SWORD = 7, // One-Handed Swords
+ ITEM_SUBCLASS_WEAPON_SWORD2 = 8, // Two-Handed Swords
+ ITEM_SUBCLASS_WEAPON_Obsolete = 9,
ITEM_SUBCLASS_WEAPON_STAFF = 10,
- ITEM_SUBCLASS_WEAPON_EXOTIC = 11,
- ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12,
- ITEM_SUBCLASS_WEAPON_FIST = 13,
- ITEM_SUBCLASS_WEAPON_MISC = 14,
+ ITEM_SUBCLASS_WEAPON_EXOTIC = 11, // One-Handed Exotics
+ ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12, // Two-Handed Exotics
+ ITEM_SUBCLASS_WEAPON_FIST_WEAPON = 13,
+ ITEM_SUBCLASS_WEAPON_MISCELLANEOUS = 14,
ITEM_SUBCLASS_WEAPON_DAGGER = 15,
ITEM_SUBCLASS_WEAPON_THROWN = 16,
ITEM_SUBCLASS_WEAPON_SPEAR = 17,
@@ -353,27 +390,30 @@ enum ItemSubclassGem
ITEM_SUBCLASS_GEM_ORANGE = 5,
ITEM_SUBCLASS_GEM_META = 6,
ITEM_SUBCLASS_GEM_SIMPLE = 7,
- ITEM_SUBCLASS_GEM_PRISMATIC = 8
+ ITEM_SUBCLASS_GEM_PRISMATIC = 8,
+ ITEM_SUBCLASS_GEM_HYDRAULIC = 9,
+ ITEM_SUBCLASS_GEM_COGWHEEL = 10
};
-#define MAX_ITEM_SUBCLASS_GEM 9
+#define MAX_ITEM_SUBCLASS_GEM 11
enum ItemSubclassArmor
{
- ITEM_SUBCLASS_ARMOR_MISC = 0,
+ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS = 0,
ITEM_SUBCLASS_ARMOR_CLOTH = 1,
ITEM_SUBCLASS_ARMOR_LEATHER = 2,
ITEM_SUBCLASS_ARMOR_MAIL = 3,
ITEM_SUBCLASS_ARMOR_PLATE = 4,
- ITEM_SUBCLASS_ARMOR_BUCKLER = 5,
+ ITEM_SUBCLASS_ARMOR_BUCKLER = 5, // OBSOLETE
ITEM_SUBCLASS_ARMOR_SHIELD = 6,
ITEM_SUBCLASS_ARMOR_LIBRAM = 7,
ITEM_SUBCLASS_ARMOR_IDOL = 8,
ITEM_SUBCLASS_ARMOR_TOTEM = 9,
- ITEM_SUBCLASS_ARMOR_SIGIL = 10
+ ITEM_SUBCLASS_ARMOR_SIGIL = 10,
+ ITEM_SUBCLASS_ARMOR_RELIC = 11,
};
-#define MAX_ITEM_SUBCLASS_ARMOR 11
+#define MAX_ITEM_SUBCLASS_ARMOR 12
enum ItemSubclassReagent
{
@@ -384,11 +424,11 @@ enum ItemSubclassReagent
enum ItemSubclassProjectile
{
- ITEM_SUBCLASS_WAND = 0, // ABS
- ITEM_SUBCLASS_BOLT = 1, // ABS
+ ITEM_SUBCLASS_WAND = 0, // OBSOLETE
+ ITEM_SUBCLASS_BOLT = 1, // OBSOLETE
ITEM_SUBCLASS_ARROW = 2,
ITEM_SUBCLASS_BULLET = 3,
- ITEM_SUBCLASS_THROWN = 4 // ABS
+ ITEM_SUBCLASS_THROWN = 4 // OBSOLETE
};
#define MAX_ITEM_SUBCLASS_PROJECTILE 5
@@ -409,15 +449,14 @@ enum ItemSubclassTradeGoods
ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11,
ITEM_SUBCLASS_ENCHANTING = 12,
ITEM_SUBCLASS_MATERIAL = 13,
- ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14,
- ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15
+ ITEM_SUBCLASS_ENCHANTMENT = 14,
};
-#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16
+#define MAX_ITEM_SUBCLASS_TRADE_GOODS 15
enum ItemSubclassGeneric
{
- ITEM_SUBCLASS_GENERIC = 0
+ ITEM_SUBCLASS_GENERIC = 0 // OBSOLETE
};
#define MAX_ITEM_SUBCLASS_GENERIC 1
@@ -434,22 +473,24 @@ enum ItemSubclassRecipe
ITEM_SUBCLASS_FIRST_AID_MANUAL = 7,
ITEM_SUBCLASS_ENCHANTING_FORMULA = 8,
ITEM_SUBCLASS_FISHING_MANUAL = 9,
- ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10
+ ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10,
+ ITEM_SUBCLASS_INSCRIPTION_TECHNIQUE = 11
};
-#define MAX_ITEM_SUBCLASS_RECIPE 11
+#define MAX_ITEM_SUBCLASS_RECIPE 12
enum ItemSubclassMoney
{
- ITEM_SUBCLASS_MONEY = 0
+ ITEM_SUBCLASS_MONEY = 0, // OBSOLETE
+ ITEM_SUBCLASS_MONEY_UNK_7 = 7, // OBSOLETE, 1 item (41749)
};
-#define MAX_ITEM_SUBCLASS_MONEY 1
+#define MAX_ITEM_SUBCLASS_MONEY 8
enum ItemSubclassQuiver
{
- ITEM_SUBCLASS_QUIVER0 = 0, // ABS
- ITEM_SUBCLASS_QUIVER1 = 1, // ABS
+ ITEM_SUBCLASS_QUIVER0 = 0, // OBSOLETE
+ ITEM_SUBCLASS_QUIVER1 = 1, // OBSOLETE
ITEM_SUBCLASS_QUIVER = 2,
ITEM_SUBCLASS_AMMO_POUCH = 3
};
@@ -458,10 +499,12 @@ enum ItemSubclassQuiver
enum ItemSubclassQuest
{
- ITEM_SUBCLASS_QUEST = 0
+ ITEM_SUBCLASS_QUEST = 0,
+ ITEM_SUBCLASS_QUEST_UNK3 = 3, // 1 item (33604)
+ ITEM_SUBCLASS_QUEST_UNK8 = 8, // 2 items (37445, 49700)
};
-#define MAX_ITEM_SUBCLASS_QUEST 1
+#define MAX_ITEM_SUBCLASS_QUEST 9
enum ItemSubclassKey
{
@@ -485,10 +528,11 @@ enum ItemSubclassJunk
ITEM_SUBCLASS_JUNK_PET = 2,
ITEM_SUBCLASS_JUNK_HOLIDAY = 3,
ITEM_SUBCLASS_JUNK_OTHER = 4,
- ITEM_SUBCLASS_JUNK_MOUNT = 5
+ ITEM_SUBCLASS_JUNK_MOUNT = 5,
+ ITEM_SUBCLASS_JUNK_UNK12 = 12, // 1 item (37677)
};
-#define MAX_ITEM_SUBCLASS_JUNK 6
+#define MAX_ITEM_SUBCLASS_JUNK 13
enum ItemSubclassGlyph
{
@@ -544,24 +588,19 @@ inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemS
#pragma pack(push, 1)
#endif
-struct _Damage
-{
- float DamageMin;
- float DamageMax;
- uint32 DamageType; // id from Resistances.dbc
-};
-
struct _ItemStat
{
uint32 ItemStatType;
int32 ItemStatValue;
+ int32 ItemStatUnk1;
+ int32 ItemStatUnk2;
};
+
struct _Spell
{
int32 SpellId; // id from Spell.dbc
uint32 SpellTrigger;
int32 SpellCharges;
- float SpellPPMRate;
int32 SpellCooldown;
uint32 SpellCategory; // id from SpellCategory.dbc
int32 SpellCategoryCooldown;
@@ -596,6 +635,8 @@ struct ItemTemplate
uint32 Quality;
uint32 Flags;
uint32 Flags2;
+ float Unk430_1;
+ float Unk430_2;
uint32 BuyCount;
int32 BuyPrice;
uint32 SellPrice;
@@ -614,24 +655,14 @@ struct ItemTemplate
int32 MaxCount; // <= 0: no limit
int32 Stackable; // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot)
uint32 ContainerSlots;
- uint32 StatsCount;
_ItemStat ItemStat[MAX_ITEM_PROTO_STATS];
uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc
- uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc
- _Damage Damage[MAX_ITEM_PROTO_DAMAGES];
- uint32 Armor;
- uint32 HolyRes;
- uint32 FireRes;
- uint32 NatureRes;
- uint32 FrostRes;
- uint32 ShadowRes;
- uint32 ArcaneRes;
+ uint32 DamageType; // id from Resistances.dbc
uint32 Delay;
- uint32 AmmoType;
float RangedModRange;
_Spell Spells[MAX_ITEM_PROTO_SPELLS];
uint32 Bonding;
- std::string Description;
+ std::string Description;
uint32 PageText;
uint32 LanguageID;
uint32 PageMaterial;
@@ -641,7 +672,6 @@ struct ItemTemplate
uint32 Sheath;
int32 RandomProperty; // id from ItemRandomProperties.dbc
int32 RandomSuffix; // id from ItemRandomSuffix.dbc
- uint32 Block;
uint32 ItemSet; // id from ItemSet.dbc
uint32 MaxDurability;
uint32 Area; // id from AreaTable.dbc
@@ -651,13 +681,23 @@ struct ItemTemplate
_Socket Socket[MAX_ITEM_PROTO_SOCKETS];
uint32 socketBonus; // id from SpellItemEnchantment.dbc
uint32 GemProperties; // id from GemProperties.dbc
- uint32 RequiredDisenchantSkill;
float ArmorDamageModifier;
uint32 Duration;
uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc
uint32 HolidayId; // id from Holidays.dbc
+ float StatScalingFactor;
+ uint32 CurrencySubstitutionId; // May be used instead of a currency
+ uint32 CurrencySubstitutionCount;
+
+ // extra fields, not part of db2 files
+ float DamageMin;
+ float DamageMax;
+ float DPS;
+ uint32 Armor;
+ float SpellPPMRate;
uint32 ScriptId;
uint32 DisenchantID;
+ uint32 RequiredDisenchantSkill;
uint32 FoodType;
uint32 MinMoneyLoot;
uint32 MaxMoneyLoot;
@@ -691,29 +731,6 @@ struct ItemTemplate
return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable);
}
- float getDPS() const
- {
- if (Delay == 0)
- return 0;
- float temp = 0;
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- temp+=Damage[i].DamageMin + Damage[i].DamageMax;
- return temp*500/Delay;
- }
-
- int32 getFeralBonus(int32 extraDPS = 0) const
- {
- // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
- if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
- {
- int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
- if (bonus < 0)
- return 0;
- return bonus;
- }
- return 0;
- }
-
float GetItemLevelIncludingQuality() const
{
float itemLevel = (float)ItemLevel;
@@ -738,9 +755,16 @@ struct ItemTemplate
}
bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; }
- bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; }
- bool IsArmorVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT; }
+ bool IsVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ENCHANTMENT; }
bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_PROTO_FLAG_CONJURED); }
+
+ bool IsRangedWeapon() const
+ {
+ return Class == ITEM_CLASS_WEAPON ||
+ SubClass == ITEM_SUBCLASS_WEAPON_BOW ||
+ SubClass == ITEM_SUBCLASS_WEAPON_GUN ||
+ SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW;
+ }
};
// Benchmarked: Faster than std::map (insert/find)
@@ -752,15 +776,4 @@ struct ItemLocale
StringVector Description;
};
-struct ItemSetNameEntry
-{
- std::string name;
- uint32 InventoryType;
-};
-
-struct ItemSetNameLocale
-{
- StringVector Name;
-};
-
#endif
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 262d1b1a475..96248f067de 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -47,6 +47,7 @@
#include "OutdoorPvPMgr.h"
#include "MovementPacketBuilder.h"
#include "DynamicTree.h"
+#include "Unit.h"
#include "Group.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
@@ -63,6 +64,7 @@ uint32 GuidHigh2TypeId(uint32 guid_hi)
case HIGHGUID_GAMEOBJECT: return TYPEID_GAMEOBJECT;
case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT;
case HIGHGUID_CORPSE: return TYPEID_CORPSE;
+ case HIGHGUID_AREATRIGGER: return TYPEID_AREATRIGGER;
case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
case HIGHGUID_VEHICLE: return TYPEID_UNIT;
}
@@ -137,21 +139,8 @@ void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh);
SetUInt64Value(OBJECT_FIELD_GUID, guid);
- uint32 type = 0;
- switch (m_objectType)
- {
- //case TYPEID_ITEM: type = 3; break;
- //case TYPEID_CONTAINER: type = 7; break; //+4
- //case TYPEID_UNIT: type = 9; break; //+2
- //case TYPEID_PLAYER: type = 25; break; //+16
- //case TYPEID_GAMEOBJECT: type = 33; break; //+8
- case TYPEID_DYNAMICOBJECT: type = 65; break; //+32
- //case TYPEID_CORPSE: type = 129; break; //+64
- default: type = m_objectType; break;
- }
- SetUInt32Value(OBJECT_FIELD_TYPE, type);
- //SetUInt32Value(OBJECT_FIELD_TYPE, m_objectType);
- m_PackGUID.wpos(0);
+ SetUInt16Value(OBJECT_FIELD_TYPE, 0, m_objectType);
+ m_PackGUID.clear();
m_PackGUID.appendPackGUID(GetGUID());
}
@@ -187,18 +176,6 @@ void Object::RemoveFromWorld()
ClearUpdateMask(true);
}
-void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const
-{
- ByteBuffer buf(500);
-
- buf << uint8(UPDATETYPE_MOVEMENT);
- buf.append(GetPackGUID());
-
- _BuildMovementUpdate(&buf, flags);
-
- data->AddUpdateBlock(buf);
-}
-
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
{
if (!target)
@@ -207,20 +184,44 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
uint8 updateType = UPDATETYPE_CREATE_OBJECT;
uint16 flags = m_updateFlag;
+ uint32 valCount = m_valuesCount;
+
/** lower flag1 **/
if (target == this) // building packet for yourself
flags |= UPDATEFLAG_SELF;
+ else if (GetTypeId() == TYPEID_PLAYER)
+ valCount = PLAYER_END_NOT_SELF;
- if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ switch (GetGUIDHigh())
{
- // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
- if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
+ case HIGHGUID_PLAYER:
+ case HIGHGUID_PET:
+ case HIGHGUID_CORPSE:
+ case HIGHGUID_DYNAMICOBJECT:
+ case HIGHGUID_AREATRIGGER:
updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ case HIGHGUID_UNIT:
+ case HIGHGUID_VEHICLE:
+ {
+ if (TempSummon const* summon = ToUnit()->ToTempSummon())
+ if (IS_PLAYER_GUID(summon->GetSummonerGUID()))
+ updateType = UPDATETYPE_CREATE_OBJECT2;
- // UPDATETYPE_CREATE_OBJECT2 for pets...
- if (target->GetPetGUID() == GetGUID())
- updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ }
+ case HIGHGUID_GAMEOBJECT:
+ {
+ if (IS_PLAYER_GUID(ToGameObject()->GetOwnerGUID()))
+ updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ }
+ default:
+ break;
+ }
+ if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ {
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
if (isType(TYPEMASK_GAMEOBJECT))
{
@@ -239,15 +240,11 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
break;
}
}
-
- if (isType(TYPEMASK_UNIT))
- {
- if (ToUnit()->getVictim())
- flags |= UPDATEFLAG_HAS_TARGET;
- }
}
- //TC_LOG_DEBUG("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updateType, m_objectTypeId, flags, flags2);
+ if (Unit const* unit = ToUnit())
+ if (unit->getVictim())
+ flags |= UPDATEFLAG_HAS_TARGET;
ByteBuffer buf(500);
buf << uint8(updateType);
@@ -257,7 +254,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
_BuildMovementUpdate(&buf, flags);
UpdateMask updateMask;
- updateMask.SetCount(m_valuesCount);
+ updateMask.SetCount(valCount);
_SetCreateBits(&updateMask, target);
_BuildValuesUpdate(updateType, &buf, &updateMask, target);
data->AddUpdateBlock(buf);
@@ -266,7 +263,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
void Object::SendUpdateToPlayer(Player* player)
{
// send create update to player
- UpdateData upd;
+ UpdateData upd(player->GetMapId());
WorldPacket packet;
BuildCreateUpdateBlockForPlayer(&upd, player);
@@ -282,7 +279,11 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c
buf.append(GetPackGUID());
UpdateMask updateMask;
- updateMask.SetCount(m_valuesCount);
+ uint32 valCount = m_valuesCount;
+ if (GetTypeId() == TYPEID_PLAYER && target != this)
+ valCount = PLAYER_END_NOT_SELF;
+
+ updateMask.SetCount(valCount);
_SetUpdateBits(&updateMask, target);
_BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target);
@@ -360,154 +361,331 @@ uint16 Object::GetUInt16Value(uint16 index, uint8 offset) const
void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
- Unit const* unit = NULL;
- WorldObject const* object = NULL;
-
- if (isType(TYPEMASK_UNIT))
- unit = ToUnit();
- else
- object = ((WorldObject*)this);
-
- *data << uint16(flags); // update flags
+ Unit const* self = NULL;
+ ObjectGuid guid = GetGUID();
+ uint32 movementFlags = 0;
+ uint16 movementFlagsExtra = 0;
+
+ bool hasTransportTime2 = false;
+ bool hasTransportTime3 = false;
+ bool hasFallDirection = false;
+ bool hasFallData = false;
+ bool hasPitch = false;
+ bool hasSpline = false;
+ bool hasSplineElevation = false;
+
+ uint32 unkLoopCounter = 0;
+ // Bit content
+ data->WriteBit(0);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_ROTATION);
+ data->WriteBit(flags & UPDATEFLAG_ANIMKITS);
+ data->WriteBit(flags & UPDATEFLAG_HAS_TARGET);
+ data->WriteBit(flags & UPDATEFLAG_SELF);
+ data->WriteBit(flags & UPDATEFLAG_VEHICLE);
+ data->WriteBit(flags & UPDATEFLAG_LIVING);
+ data->WriteBits(unkLoopCounter, 24);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_GO_TRANSPORT_POSITION);
+ data->WriteBit(flags & UPDATEFLAG_STATIONARY_POSITION);
+ data->WriteBit(flags & UPDATEFLAG_UNK5);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_TRANSPORT);
- // 0x20
if (flags & UPDATEFLAG_LIVING)
{
- unit->BuildMovementPacket(data);
+ self = ToUnit();
+ movementFlags = self->m_movementInfo.GetMovementFlags();
+ movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags();
+ hasSpline = self->IsSplineEnabled();
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ hasTransportTime2 = self->m_movementInfo.bits.hasTransportTime2;
+ hasTransportTime3 = self->m_movementInfo.bits.hasTransportTime3;
+ hasPitch = self->m_movementInfo.bits.hasPitch;
+ hasFallData = self->m_movementInfo.bits.hasFallData;
+ hasFallDirection = self->m_movementInfo.bits.hasFallDirection;
+ hasSplineElevation = self->m_movementInfo.bits.hasSplineElevation;
+ }
+ else
+ {
+ hasTransportTime2 = self->HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT);
+ hasPitch = ((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) ||
+ (movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING));
+ hasFallDirection = movementFlags & MOVEMENTFLAG_FALLING;
+ hasFallData = hasFallDirection; // FallDirection implies that FallData is set as well
+ hasSplineElevation = movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION;
+
+ movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED;
+ }
- *data << unit->GetSpeed(MOVE_WALK)
- << unit->GetSpeed(MOVE_RUN)
- << unit->GetSpeed(MOVE_RUN_BACK)
- << unit->GetSpeed(MOVE_SWIM)
- << unit->GetSpeed(MOVE_SWIM_BACK)
- << unit->GetSpeed(MOVE_FLIGHT)
- << unit->GetSpeed(MOVE_FLIGHT_BACK)
- << unit->GetSpeed(MOVE_TURN_RATE)
- << unit->GetSpeed(MOVE_PITCH_RATE);
+ data->WriteBit(!movementFlags);
+ data->WriteBit(G3D::fuzzyEq(self->GetOrientation(), 0.0f)); // Has Orientation
+ data->WriteBit(guid[7]);
+ data->WriteBit(guid[3]);
+ data->WriteBit(guid[2]);
+ if (movementFlags)
+ data->WriteBits(movementFlags, 30);
+
+ data->WriteBit(0);
+ data->WriteBit(!hasPitch); // Has pitch
+ data->WriteBit(hasSpline); // Has spline data
+ data->WriteBit(hasFallData); // Has fall data
+ data->WriteBit(!hasSplineElevation); // Has spline elevation
+ data->WriteBit(guid[5]);
+ data->WriteBit(self->m_movementInfo.t_guid); // Has transport data
+ data->WriteBit(0); // Is missing time
+
+ if (self->m_movementInfo.t_guid)
+ {
+ ObjectGuid transGuid = self->m_movementInfo.t_guid;
+
+ data->WriteBit(transGuid[1]);
+ data->WriteBit(hasTransportTime2); // Has transport time 2
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(hasTransportTime3); // Has transport time 3
+ data->WriteBit(transGuid[7]);
+ data->WriteBit(transGuid[5]);
+ data->WriteBit(transGuid[3]);
+ data->WriteBit(transGuid[2]);
+ }
+
+ data->WriteBit(guid[4]);
+
+ if (hasSpline)
+ Movement::PacketBuilder::WriteCreateBits(*self->movespline, *data);
- // 0x08000000
- if (unit->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED)
- Movement::PacketBuilder::WriteCreate(*unit->movespline, *data);
+ data->WriteBit(guid[6]);
+ if (hasFallData)
+ data->WriteBit(hasFallDirection);
+
+ data->WriteBit(guid[0]);
+ data->WriteBit(guid[1]);
+ data->WriteBit(0);
+ data->WriteBit(!movementFlagsExtra);
+ if (movementFlagsExtra)
+ data->WriteBits(movementFlagsExtra, 12);
}
- else
+
+ if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION)
{
- if (flags & UPDATEFLAG_POSITION)
- {
- Transport* transport = object->GetTransport();
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ ObjectGuid transGuid = self->m_movementInfo.t_guid;
+ data->WriteBit(transGuid[5]);
+ data->WriteBit(0); // Has GO transport time 3
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[3]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(transGuid[1]);
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[2]);
+ data->WriteBit(0); // Has GO transport time 2
+ data->WriteBit(transGuid[7]);
+ }
- if (transport)
- data->append(transport->GetPackGUID());
- else
- *data << uint8(0);
+ if (flags & UPDATEFLAG_HAS_TARGET)
+ {
+ ObjectGuid victimGuid = self->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
+ data->WriteBit(victimGuid[2]);
+ data->WriteBit(victimGuid[7]);
+ data->WriteBit(victimGuid[0]);
+ data->WriteBit(victimGuid[4]);
+ data->WriteBit(victimGuid[5]);
+ data->WriteBit(victimGuid[6]);
+ data->WriteBit(victimGuid[1]);
+ data->WriteBit(victimGuid[3]);
+ }
- *data << object->GetPositionX();
- *data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
- *data << object->GetPositionZ();
+ if (flags & UPDATEFLAG_ANIMKITS)
+ {
+ data->WriteBit(1); // Missing AnimKit1
+ data->WriteBit(1); // Missing AnimKit2
+ data->WriteBit(1); // Missing AnimKit3
+ }
- if (transport)
- {
- *data << object->GetTransOffsetX();
- *data << object->GetTransOffsetY();
- *data << object->GetTransOffsetZ();
- }
- else
- {
- *data << object->GetPositionX();
- *data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
- *data << object->GetPositionZ();
- }
+ data->FlushBits();
- *data << object->GetOrientation();
+ // Data
+ for (uint32 i = 0; i < unkLoopCounter; ++i)
+ *data << uint32(0);
- if (GetTypeId() == TYPEID_CORPSE)
- *data << float(object->GetOrientation());
- else
- *data << float(0);
- }
- else
+ if (flags & UPDATEFLAG_LIVING)
+ {
+ data->WriteByteSeq(guid[4]);
+ *data << self->GetSpeed(MOVE_RUN_BACK);
+
+ if (hasFallData)
{
- // 0x40
- if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ if (hasFallDirection)
{
- *data << object->GetPositionX();
- *data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
- *data << object->GetPositionZ();
- *data << object->GetOrientation();
+ *data << float(self->m_movementInfo.j_cosAngle);
+ *data << float(self->m_movementInfo.j_xyspeed);
+ *data << float(self->m_movementInfo.j_sinAngle);
}
+
+ *data << uint32(self->m_movementInfo.fallTime);
+ *data << float(self->m_movementInfo.j_zspeed);
}
- }
- // 0x8
- if (flags & UPDATEFLAG_UNKNOWN)
- {
- *data << uint32(0);
- }
+ *data << self->GetSpeed(MOVE_SWIM_BACK);
+ if (hasSplineElevation)
+ *data << float(self->m_movementInfo.splineElevation);
- // 0x10
- if (flags & UPDATEFLAG_LOWGUID)
- {
- switch (GetTypeId())
+ if (hasSpline)
+ Movement::PacketBuilder::WriteCreateData(*self->movespline, *data);
+
+ *data << float(self->GetPositionZMinusOffset());
+ data->WriteByteSeq(guid[5]);
+
+ if (self->m_movementInfo.t_guid)
{
- case TYPEID_OBJECT:
- case TYPEID_ITEM:
- case TYPEID_CONTAINER:
- case TYPEID_GAMEOBJECT:
- case TYPEID_DYNAMICOBJECT:
- case TYPEID_CORPSE:
- *data << uint32(GetGUIDLow()); // GetGUIDLow()
- break;
- //! Unit, Player and default here are sending wrong values.
- /// @todo Research the proper formula
- case TYPEID_UNIT:
- *data << uint32(0x0000000B); // unk
- break;
- case TYPEID_PLAYER:
- if (flags & UPDATEFLAG_SELF)
- *data << uint32(0x0000002F); // unk
- else
- *data << uint32(0x00000008); // unk
- break;
- default:
- *data << uint32(0x00000000); // unk
- break;
+ ObjectGuid transGuid = self->m_movementInfo.t_guid;
+
+ data->WriteByteSeq(transGuid[5]);
+ data->WriteByteSeq(transGuid[7]);
+ *data << uint32(self->GetTransTime());
+ *data << float(self->GetTransOffsetO());
+ if (hasTransportTime2)
+ *data << uint32(self->m_movementInfo.t_time2);
+
+ *data << float(self->GetTransOffsetY());
+ *data << float(self->GetTransOffsetX());
+ data->WriteByteSeq(transGuid[3]);
+ *data << float(self->GetTransOffsetZ());
+ data->WriteByteSeq(transGuid[0]);
+ if (hasTransportTime3)
+ *data << uint32(self->m_movementInfo.t_time3);
+
+ *data << int8(self->GetTransSeat());
+ data->WriteByteSeq(transGuid[1]);
+ data->WriteByteSeq(transGuid[6]);
+ data->WriteByteSeq(transGuid[2]);
+ data->WriteByteSeq(transGuid[4]);
}
+
+ *data << float(self->GetPositionX());
+ *data << self->GetSpeed(MOVE_PITCH_RATE);
+ data->WriteByteSeq(guid[3]);
+ data->WriteByteSeq(guid[0]);
+ *data << self->GetSpeed(MOVE_SWIM);
+ *data << float(self->GetPositionY());
+ data->WriteByteSeq(guid[7]);
+ data->WriteByteSeq(guid[1]);
+ data->WriteByteSeq(guid[2]);
+ *data << self->GetSpeed(MOVE_WALK);
+
+ //if (true) // Has time, controlled by bit just after HasTransport
+ *data << uint32(getMSTime());
+
+ *data << self->GetSpeed(MOVE_FLIGHT_BACK);
+ data->WriteByteSeq(guid[6]);
+ *data << self->GetSpeed(MOVE_TURN_RATE);
+ if (!G3D::fuzzyEq(self->GetOrientation(), 0.0f))
+ *data << float(self->GetOrientation());
+
+ *data << self->GetSpeed(MOVE_RUN);
+ if (hasPitch)
+ *data << float(self->m_movementInfo.pitch);
+
+ *data << self->GetSpeed(MOVE_FLIGHT);
}
- // 0x4
- if (flags & UPDATEFLAG_HAS_TARGET)
+ if (flags & UPDATEFLAG_VEHICLE)
{
- if (Unit* victim = unit->getVictim())
- data->append(victim->GetPackGUID());
- else
- *data << uint8(0);
+ *data << float(self->GetOrientation());
+ *data << uint32(self->GetVehicleKit()->GetVehicleInfo()->m_ID);
}
- // 0x2
- if (flags & UPDATEFLAG_TRANSPORT)
+ if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION)
{
- *data << uint32(getMSTime()); // Unknown - getMSTime is wrong.
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ ObjectGuid transGuid = self->m_movementInfo.t_guid;
+
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[5]);
+ if (hasTransportTime3)
+ *data << uint32(self->m_movementInfo.t_time3);
+
+ data->WriteBit(transGuid[3]);
+ *data << float(self->GetTransOffsetX());
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(transGuid[1]);
+ *data << uint32(self->GetTransTime());
+ *data << float(self->GetTransOffsetY());
+ data->WriteBit(transGuid[2]);
+ data->WriteBit(transGuid[7]);
+ *data << float(self->GetTransOffsetZ());
+ *data << int8(self->GetTransSeat());
+ *data << float(self->GetTransOffsetO());
+ if (hasTransportTime2)
+ *data << uint32(self->m_movementInfo.t_time2);
}
- // 0x80
- if (flags & UPDATEFLAG_VEHICLE)
+ if (flags & UPDATEFLAG_ROTATION)
+ *data << uint64(ToGameObject()->GetRotation());
+
+ if (flags & UPDATEFLAG_UNK5)
+ {
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << uint8(0);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ }
+
+ if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
- /// @todo Allow players to aquire this updateflag.
- *data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->m_ID);
- *data << float(unit->GetOrientation());
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ *data << float(self->GetOrientation());
+ *data << float(self->GetPositionX());
+ *data << float(self->GetPositionY());
+ if (Unit const* unit = ToUnit())
+ *data << float(unit->GetPositionZMinusOffset());
+ else
+ *data << float(self->GetPositionZ());
}
- // 0x200
- if (flags & UPDATEFLAG_ROTATION)
- *data << int64(ToGameObject()->GetRotation());
+ if (flags & UPDATEFLAG_HAS_TARGET)
+ {
+ ObjectGuid victimGuid = self->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
+ data->WriteByteSeq(victimGuid[4]);
+ data->WriteByteSeq(victimGuid[0]);
+ data->WriteByteSeq(victimGuid[3]);
+ data->WriteByteSeq(victimGuid[5]);
+ data->WriteByteSeq(victimGuid[7]);
+ data->WriteByteSeq(victimGuid[6]);
+ data->WriteByteSeq(victimGuid[2]);
+ data->WriteByteSeq(victimGuid[1]);
+ }
+
+ //if (flags & UPDATEFLAG_ANIMKITS)
+ //{
+ // if (hasAnimKit1)
+ // *data << uint16(animKit1);
+ // if (hasAnimKit2)
+ // *data << uint16(animKit2);
+ // if (hasAnimKit3)
+ // *data << uint16(animKit3);
+ //}
+
+ if (flags & UPDATEFLAG_TRANSPORT)
+ *data << uint32(getMSTime()); // Unknown - getMSTime is wrong.
}
void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
@@ -557,7 +735,11 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask*
}
}
- ASSERT(updateMask && updateMask->GetCount() == m_valuesCount);
+ uint32 valCount = m_valuesCount;
+ if (GetTypeId() == TYPEID_PLAYER && target != this)
+ valCount = PLAYER_END_NOT_SELF;
+
+ ASSERT(updateMask && updateMask->GetCount() == valCount);
*data << uint8(updateMask->GetBlockCount());
updateMask->AppendToPacket(data);
@@ -566,7 +748,7 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask*
if (unit) // unit (creature/player) case
{
Creature const* creature = ToCreature();
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ for (uint16 index = 0; index < valCount; ++index)
{
if (updateMask->GetBit(index))
{
@@ -722,7 +904,7 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask*
}
else if (go) // gameobject case
{
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ for (uint16 index = 0; index < valCount; ++index)
{
if (updateMask->GetBit(index))
{
@@ -738,35 +920,28 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask*
*data << uint16(GO_DYNFLAG_LO_ACTIVATE);
else
*data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
break;
case GAMEOBJECT_TYPE_GENERIC:
if (target->isGameMaster())
*data << uint16(0);
else
*data << uint16(GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
break;
case GAMEOBJECT_TYPE_GOOBER:
if (target->isGameMaster())
*data << uint16(GO_DYNFLAG_LO_ACTIVATE);
else
*data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
break;
default:
- // unknown, not happen.
- *data << uint16(0);
- *data << uint16(-1);
+ *data << uint16(0); // unknown, not happen.
break;
}
}
else
- {
- // disable quest object
- *data << uint16(0);
- *data << uint16(-1);
- }
+ *data << uint16(0); // disable quest object
+
+ *data << uint16(-1);
}
else if (index == GAMEOBJECT_FLAGS)
{
@@ -784,7 +959,7 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask*
}
else // other objects case (no special index checks)
{
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ for (uint16 index = 0; index < valCount; ++index)
{
if (updateMask->GetBit(index))
{
@@ -813,7 +988,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons
if (iter == data_map.end())
{
- std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData()));
+ std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData(player->GetMapId())));
ASSERT(p.second);
iter = p.first;
}
@@ -867,6 +1042,9 @@ uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const
if (ToCorpse()->GetOwnerGUID() == target->GetGUID())
visibleFlag |= UF_FLAG_OWNER;
break;
+ case TYPEID_AREATRIGGER:
+ flags = AreaTriggerUpdateFieldFlags;
+ break;
case TYPEID_OBJECT:
break;
}
@@ -895,8 +1073,11 @@ void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const
{
uint32* flags = NULL;
uint32 visibleFlag = GetUpdateFieldData(target, flags);
+ uint32 valCount = m_valuesCount;
+ if (GetTypeId() == TYPEID_PLAYER && target != this)
+ valCount = PLAYER_END_NOT_SELF;
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ for (uint16 index = 0; index < valCount; ++index)
if (_fieldNotifyFlags & flags[index] || ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) || (_changesMask.GetBit(index) && (flags[index] & visibleFlag)))
updateMask->SetBit(index);
}
@@ -906,8 +1087,11 @@ void Object::_SetCreateBits(UpdateMask* updateMask, Player* target) const
uint32* value = m_uint32Values;
uint32* flags = NULL;
uint32 visibleFlag = GetUpdateFieldData(target, flags);
+ uint32 valCount = m_valuesCount;
+ if (GetTypeId() == TYPEID_PLAYER && target != this)
+ valCount = PLAYER_END_NOT_SELF;
- for (uint16 index = 0; index < m_valuesCount; ++index, ++value)
+ for (uint16 index = 0; index < valCount; ++index, ++value)
if (_fieldNotifyFlags & flags[index] || ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) || (*value && (flags[index] & visibleFlag)))
updateMask->SetBit(index);
}
@@ -1358,11 +1542,11 @@ void MovementInfo::OutDebug()
{
TC_LOG_INFO(LOG_FILTER_GENERAL, "MOVEMENT INFO");
TC_LOG_INFO(LOG_FILTER_GENERAL, "guid " UI64FMTD, guid);
- TC_LOG_INFO(LOG_FILTER_GENERAL, "flags %u", flags);
- TC_LOG_INFO(LOG_FILTER_GENERAL, "flags2 %u", flags2);
- TC_LOG_INFO(LOG_FILTER_GENERAL, "time %u current time " UI64FMTD "", flags2, uint64(::time(NULL)));
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "flags %s (%u)", Movement::MovementFlags_ToString(flags).c_str(), flags);
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "flags2 %s (%u)", Movement::MovementFlagsExtra_ToString(flags2).c_str(), flags2);
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "time %u current time %u", time, getMSTime());
TC_LOG_INFO(LOG_FILTER_GENERAL, "position: `%s`", pos.ToString().c_str());
- if (flags & MOVEMENTFLAG_ONTRANSPORT)
+ if (t_guid)
{
TC_LOG_INFO(LOG_FILTER_GENERAL, "TRANSPORT:");
TC_LOG_INFO(LOG_FILTER_GENERAL, "guid: " UI64FMTD, t_guid);
@@ -1371,14 +1555,19 @@ void MovementInfo::OutDebug()
TC_LOG_INFO(LOG_FILTER_GENERAL, "time: %u", t_time);
if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
TC_LOG_INFO(LOG_FILTER_GENERAL, "time2: %u", t_time2);
+ if (bits.hasTransportTime3)
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "time3: %u", t_time3);
}
if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
TC_LOG_INFO(LOG_FILTER_GENERAL, "pitch: %f", pitch);
- TC_LOG_INFO(LOG_FILTER_GENERAL, "fallTime: %u", fallTime);
- if (flags & MOVEMENTFLAG_FALLING)
- TC_LOG_INFO(LOG_FILTER_GENERAL, "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed);
+ if (flags & MOVEMENTFLAG_FALLING || bits.hasFallData)
+ {
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "fallTime: %u j_zspeed: %f", fallTime, j_zspeed);
+ if (flags & MOVEMENTFLAG_FALLING)
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", j_sinAngle, j_cosAngle, j_xyspeed);
+ }
if (flags & MOVEMENTFLAG_SPLINE_ELEVATION)
TC_LOG_INFO(LOG_FILTER_GENERAL, "splineElevation: %f", splineElevation);
@@ -2074,13 +2263,6 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
if (mask != obj->m_invisibility.GetFlags())
return false;
- // It isn't possible in invisibility to detect something that can't detect the invisible object
- // (it's at least true for spell: 66)
- // It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
- if (obj->ToUnit())
- if ((m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags()) != m_invisibility.GetFlags())
- return false;
-
for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
{
if (!(mask & (1 << i)))
@@ -2160,7 +2342,8 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
void WorldObject::SendPlaySound(uint32 Sound, bool OnlySelf)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
- data << Sound;
+ data << uint32(Sound);
+ data << uint64(GetGUID());
if (OnlySelf && GetTypeId() == TYPEID_PLAYER)
this->ToPlayer()->GetSession()->SendPacket(&data);
else
@@ -2356,13 +2539,11 @@ void WorldObject::BuildMonsterChat(WorldPacket* data, uint8 msgtype, char const*
*data << (uint32)(strlen(text)+1);
*data << text;
*data << (uint8)0; // ChatTag
-}
-
-void Unit::BuildHeartBeatMsg(WorldPacket* data) const
-{
- data->Initialize(MSG_MOVE_HEARTBEAT, 32);
- data->append(GetPackGUID());
- BuildMovementPacket(data);
+ if (msgtype == CHAT_MSG_RAID_BOSS_EMOTE || msgtype == CHAT_MSG_RAID_BOSS_WHISPER)
+ {
+ *data << float(0);
+ *data << uint8(0);
+ }
}
void WorldObject::SendMessageToSet(WorldPacket* data, bool self)
@@ -3108,6 +3289,7 @@ void WorldObject::PlayDirectSound(uint32 sound_id, Player* target /*= NULL*/)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound_id);
+ data << uint64(GetGUID());
if (target)
target->SendDirectMessage(&data);
else
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index ffbcd38049f..a72f4fcf3e4 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -54,6 +54,7 @@ enum TypeMask
TYPEMASK_GAMEOBJECT = 0x0020,
TYPEMASK_DYNAMICOBJECT = 0x0040,
TYPEMASK_CORPSE = 0x0080,
+ TYPEMASK_AREATRIGGER = 0x0100,
TYPEMASK_SEER = TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT
};
@@ -66,10 +67,11 @@ enum TypeID
TYPEID_PLAYER = 4,
TYPEID_GAMEOBJECT = 5,
TYPEID_DYNAMICOBJECT = 6,
- TYPEID_CORPSE = 7
+ TYPEID_CORPSE = 7,
+ TYPEID_AREATRIGGER = 8
};
-#define NUM_CLIENT_OBJECT_TYPES 8
+#define NUM_CLIENT_OBJECT_TYPES 9
uint32 GuidHigh2TypeId(uint32 guid_hi);
@@ -116,6 +118,62 @@ class ZoneScript;
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
+//! Structure to ease conversions from single 64 bit integer guid into individual bytes, for packet sending purposes
+//! Nuke this out when porting ObjectGuid from MaNGOS, but preserve the per-byte storage
+struct ObjectGuid
+{
+ public:
+ ObjectGuid() { _data.u64 = 0LL; }
+ ObjectGuid(uint64 guid) { _data.u64 = guid; }
+ ObjectGuid(ObjectGuid const& other) { _data.u64 = other._data.u64; }
+
+ uint8& operator[](uint32 index)
+ {
+ ASSERT(index < sizeof(uint64));
+
+#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
+ return _data.byte[index];
+#else
+ return _data.byte[7 - index];
+#endif
+ }
+
+ uint8 const& operator[](uint32 index) const
+ {
+ ASSERT(index < sizeof(uint64));
+
+#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
+ return _data.byte[index];
+#else
+ return _data.byte[7 - index];
+#endif
+ }
+
+ operator uint64()
+ {
+ return _data.u64;
+ }
+
+ ObjectGuid& operator=(uint64 guid)
+ {
+ _data.u64 = guid;
+ return *this;
+ }
+
+ ObjectGuid& operator=(ObjectGuid const& other)
+ {
+ _data.u64 = other._data.u64;
+ return *this;
+ }
+
+ private:
+ union
+ {
+ uint64 u64;
+ uint8 byte[8];
+ } _data;
+};
+
class Object
{
public:
@@ -144,7 +202,6 @@ class Object
void BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) const;
void BuildOutOfRangeUpdateBlock(UpdateData* data) const;
- void BuildMovementUpdateBlock(UpdateData* data, uint32 flags = 0) const;
virtual void DestroyForPlayer(Player* target, bool onDeath = false) const;
@@ -226,6 +283,9 @@ class Object
DynamicObject* ToDynObject() { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject*>(this); else return NULL; }
DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject const*>(this); else return NULL; }
+ AreaTrigger* ToAreaTrigger() { if (GetTypeId() == TYPEID_AREATRIGGER) return reinterpret_cast<AreaTrigger*>(this); else return NULL; }
+ AreaTrigger const* ToAreaTrigger() const { if (GetTypeId() == TYPEID_AREATRIGGER) return reinterpret_cast<AreaTrigger const*>(this); else return NULL; }
+
protected:
Object();
@@ -415,6 +475,7 @@ struct MovementInfo
int8 t_seat;
uint32 t_time;
uint32 t_time2;
+ uint32 t_time3;
// swimming/flying
float pitch;
// falling
@@ -424,11 +485,26 @@ struct MovementInfo
// spline
float splineElevation;
+ // bit markers
+ struct MovementElementMarkers
+ {
+ bool hasTransportTime2;
+ bool hasTransportTime3;
+ bool hasPitch;
+ bool hasFallData;
+ bool hasFallDirection;
+ bool hasSplineElevation;
+ } bits;
+
MovementInfo() :
- guid(), flags(), flags2(), pos(), time(), t_guid(), t_pos(),
- t_seat(-1), t_time(), t_time2(), pitch(), fallTime(),
- j_zspeed(), j_sinAngle(), j_cosAngle(), j_xyspeed()
- { }
+ guid(0), flags(0), flags2(0), time(0), t_guid(0),
+ t_seat(-1), t_time(0), t_time2(0), t_time3(0), pitch(0.0f), fallTime(0),
+ j_zspeed(0.0f), j_sinAngle(0.0f), j_cosAngle(0.0f), j_xyspeed(0.0f)
+ {
+ pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
+ t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
+ memset(&bits, 0, sizeof(bits));
+ }
uint32 GetMovementFlags() const { return flags; }
void SetMovementFlags(uint32 flag) { flags = flag; }
diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h
index d0b9819b0a3..5cbcde20bea 100644
--- a/src/server/game/Entities/Object/ObjectDefines.h
+++ b/src/server/game/Entities/Object/ObjectDefines.h
@@ -23,18 +23,21 @@
enum HighGuid
{
- HIGHGUID_ITEM = 0x4000, // blizz 4000
- HIGHGUID_CONTAINER = 0x4000, // blizz 4000
- HIGHGUID_PLAYER = 0x0000, // blizz 0000
- HIGHGUID_GAMEOBJECT = 0xF110, // blizz F110
- HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
- HIGHGUID_UNIT = 0xF130, // blizz F130
- HIGHGUID_PET = 0xF140, // blizz F140
- HIGHGUID_VEHICLE = 0xF150, // blizz F550
- HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100
+ HIGHGUID_ITEM = 0x400, // blizz 4000
+ HIGHGUID_CONTAINER = 0x400, // blizz 4000
+ HIGHGUID_PLAYER = 0x000, // blizz 0000
+ HIGHGUID_GAMEOBJECT = 0xF11, // blizz F110
+ HIGHGUID_TRANSPORT = 0xF12, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
+ HIGHGUID_UNIT = 0xF13, // blizz F130
+ HIGHGUID_PET = 0xF14, // blizz F140
+ HIGHGUID_VEHICLE = 0xF15, // blizz F550
+ HIGHGUID_DYNAMICOBJECT = 0xF10, // blizz F100
HIGHGUID_CORPSE = 0xF101, // blizz F100
- HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
- HIGHGUID_GROUP = 0x1F50
+ HIGHGUID_AREATRIGGER = 0xF102, // blizz F100
+ HIGHGUID_BATTLEGROUND = 0x1F1, // new 4.x
+ HIGHGUID_MO_TRANSPORT = 0x1FC, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
+ HIGHGUID_GROUP = 0x1F5,
+ HIGHGUID_GUILD = 0x1FF // new 4.x
};
// used for creating values for respawn for example
@@ -53,6 +56,7 @@ inline bool IS_VEHICLE_GUID(uint64 guid);
inline bool IS_CRE_OR_VEH_GUID(uint64 guid);
inline bool IS_CRE_OR_VEH_OR_PET_GUID(uint64 guid);
inline bool IS_PLAYER_GUID(uint64 guid);
+inline bool IS_GUILD_GUID(uint64 guid);
inline bool IS_UNIT_GUID(uint64 guid);
inline bool IS_ITEM_GUID(uint64 guid);
inline bool IS_GAMEOBJECT_GUID(uint64 guid);
@@ -61,6 +65,7 @@ inline bool IS_CORPSE_GUID(uint64 guid);
inline bool IS_TRANSPORT_GUID(uint64 guid);
inline bool IS_MO_TRANSPORT_GUID(uint64 guid);
inline bool IS_GROUP_GUID(uint64 guid);
+inline bool IS_AREATRIGGER_GUID(uint64 guid);
// l - OBJECT_FIELD_GUID
// e - OBJECT_FIELD_ENTRY for GO (except GAMEOBJECT_TYPE_MO_TRANSPORT) and creatures or UNIT_FIELD_PETNUMBER for pets
@@ -145,6 +150,11 @@ bool IS_PLAYER_GUID(uint64 guid)
return guid != 0 && GUID_HIPART(guid) == HIGHGUID_PLAYER;
}
+bool IS_GUILD_GUID(uint64 guid)
+{
+ return GUID_HIPART(guid) == HIGHGUID_GUILD;
+}
+
bool IS_UNIT_GUID(uint64 guid)
{
return IS_CRE_OR_VEH_OR_PET_GUID(guid) || IS_PLAYER_GUID(guid);
@@ -185,28 +195,33 @@ bool IS_GROUP_GUID(uint64 guid)
return GUID_HIPART(guid) == HIGHGUID_GROUP;
}
+bool IS_AREATRIGGER_GUID(uint64 guid)
+{
+ return GUID_HIPART(guid) == HIGHGUID_AREATRIGGER;
+}
+
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
{
- return uint64(uint64(l) | (uint64(e) << 24) | (uint64(h) << 48));
+ return uint64(uint64(l) | (uint64(e) << 32) | (uint64(h) << ((h == HIGHGUID_CORPSE || h == HIGHGUID_AREATRIGGER) ? 48 : 52)));
}
uint32 GUID_HIPART(uint64 guid)
{
- return (uint32)((uint64(guid) >> 48) & 0x0000FFFF);
+ uint32 t = ((uint64(guid) >> 48) & 0x0000FFFF);
+ return (t == HIGHGUID_CORPSE || t == HIGHGUID_AREATRIGGER) ? t : ((t >> 4) & 0x00000FFF);
}
uint32 GUID_ENPART(uint64 x)
{
return IsGuidHaveEnPart(x)
- ? (uint32)((x >> 24) & UI64LIT(0x0000000000FFFFFF))
+ ? ((uint32)((x >> 32) & UI64LIT(0x00000000000FFFFF)))
: 0;
}
uint32 GUID_LOPART(uint64 x)
{
- return IsGuidHaveEnPart(x)
- ? (uint32)(x & UI64LIT(0x0000000000FFFFFF))
- : (uint32)(x & UI64LIT(0x00000000FFFFFFFF));
+ // _GUID_LOPART_3 and _GUID_LOPART_2 were both equal to PAIR64_LOPART
+ return PAIR64_LOPART(x);
}
bool IsGuidHaveEnPart(uint64 guid)
@@ -218,6 +233,7 @@ bool IsGuidHaveEnPart(uint64 guid)
case HIGHGUID_DYNAMICOBJECT:
case HIGHGUID_CORPSE:
case HIGHGUID_GROUP:
+ case HIGHGUID_GUILD:
return false;
case HIGHGUID_GAMEOBJECT:
case HIGHGUID_TRANSPORT:
@@ -225,6 +241,7 @@ bool IsGuidHaveEnPart(uint64 guid)
case HIGHGUID_PET:
case HIGHGUID_VEHICLE:
case HIGHGUID_MO_TRANSPORT:
+ case HIGHGUID_AREATRIGGER:
default:
return true;
}
@@ -245,6 +262,8 @@ char const* GetLogNameForGuid(uint64 guid)
case HIGHGUID_CORPSE: return "corpse";
case HIGHGUID_MO_TRANSPORT: return "mo_transport";
case HIGHGUID_GROUP: return "group";
+ case HIGHGUID_GUILD: return "guild";
+ case HIGHGUID_AREATRIGGER: return "areatrigger";
default:
return "<unknown>";
}
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp
index ba4a4070e63..09a423350b7 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp
@@ -25,7 +25,7 @@
#include "World.h"
#include "zlib.h"
-UpdateData::UpdateData() : m_blockCount(0)
+UpdateData::UpdateData(uint16 map) : m_map(map), m_blockCount(0)
{
}
@@ -45,104 +45,24 @@ void UpdateData::AddUpdateBlock(const ByteBuffer &block)
++m_blockCount;
}
-void UpdateData::Compress(void* dst, uint32 *dst_size, void* src, int src_size)
-{
- z_stream c_stream;
-
- c_stream.zalloc = (alloc_func)0;
- c_stream.zfree = (free_func)0;
- c_stream.opaque = (voidpf)0;
-
- // default Z_BEST_SPEED (1)
- int z_res = deflateInit(&c_stream, sWorld->getIntConfig(CONFIG_COMPRESSION));
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Can't compress update packet (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- c_stream.next_out = (Bytef*)dst;
- c_stream.avail_out = *dst_size;
- c_stream.next_in = (Bytef*)src;
- c_stream.avail_in = (uInt)src_size;
-
- z_res = deflate(&c_stream, Z_NO_FLUSH);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Can't compress update packet (zlib: deflate) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- if (c_stream.avail_in != 0)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Can't compress update packet (zlib: deflate not greedy)");
- *dst_size = 0;
- return;
- }
-
- z_res = deflate(&c_stream, Z_FINISH);
- if (z_res != Z_STREAM_END)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- z_res = deflateEnd(&c_stream);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- *dst_size = c_stream.total_out;
-}
-
bool UpdateData::BuildPacket(WorldPacket* packet)
{
ASSERT(packet->empty()); // shouldn't happen
+ packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos());
- ByteBuffer buf(4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos());
-
- buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount);
+ *packet << uint16(m_map);
+ *packet << uint32(m_blockCount + (m_outOfRangeGUIDs.empty() ? 0 : 1));
if (!m_outOfRangeGUIDs.empty())
{
- buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS;
- buf << (uint32) m_outOfRangeGUIDs.size();
+ *packet << uint8(UPDATETYPE_OUT_OF_RANGE_OBJECTS);
+ *packet << uint32(m_outOfRangeGUIDs.size());
for (std::set<uint64>::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i)
- {
- buf.appendPackGUID(*i);
- }
- }
-
- buf.append(m_data);
-
- size_t pSize = buf.wpos(); // use real used data size
-
- if (pSize > 100) // compress large packets
- {
- uint32 destsize = compressBound(pSize);
- packet->resize(destsize + sizeof(uint32));
-
- packet->put<uint32>(0, pSize);
- Compress(const_cast<uint8*>(packet->contents()) + sizeof(uint32), &destsize, (void*)buf.contents(), pSize);
- if (destsize == 0)
- return false;
-
- packet->resize(destsize + sizeof(uint32));
- packet->SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT);
- }
- else // send small packets without compression
- {
- packet->append(buf);
- packet->SetOpcode(SMSG_UPDATE_OBJECT);
+ packet->appendPackGUID(*i);
}
+ packet->append(m_data);
return true;
}
@@ -151,5 +71,6 @@ void UpdateData::Clear()
m_data.clear();
m_outOfRangeGUIDs.clear();
m_blockCount = 0;
+ m_map = 0;
}
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.h b/src/server/game/Entities/Object/Updates/UpdateData.h
index 654db149ca0..c782ec99929 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.h
+++ b/src/server/game/Entities/Object/Updates/UpdateData.h
@@ -27,32 +27,34 @@ class WorldPacket;
enum OBJECT_UPDATE_TYPE
{
UPDATETYPE_VALUES = 0,
- UPDATETYPE_MOVEMENT = 1,
- UPDATETYPE_CREATE_OBJECT = 2,
- UPDATETYPE_CREATE_OBJECT2 = 3,
- UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4,
- UPDATETYPE_NEAR_OBJECTS = 5
+ UPDATETYPE_CREATE_OBJECT = 1,
+ UPDATETYPE_CREATE_OBJECT2 = 2,
+ UPDATETYPE_OUT_OF_RANGE_OBJECTS = 3,
};
enum OBJECT_UPDATE_FLAGS
{
- UPDATEFLAG_NONE = 0x0000,
- UPDATEFLAG_SELF = 0x0001,
- UPDATEFLAG_TRANSPORT = 0x0002,
- UPDATEFLAG_HAS_TARGET = 0x0004,
- UPDATEFLAG_UNKNOWN = 0x0008,
- UPDATEFLAG_LOWGUID = 0x0010,
- UPDATEFLAG_LIVING = 0x0020,
- UPDATEFLAG_STATIONARY_POSITION = 0x0040,
- UPDATEFLAG_VEHICLE = 0x0080,
- UPDATEFLAG_POSITION = 0x0100,
- UPDATEFLAG_ROTATION = 0x0200
+ UPDATEFLAG_NONE = 0x0000,
+ UPDATEFLAG_SELF = 0x0001,
+ UPDATEFLAG_TRANSPORT = 0x0002,
+ UPDATEFLAG_HAS_TARGET = 0x0004,
+ UPDATEFLAG_UNKNOWN = 0x0008,
+ UPDATEFLAG_LOWGUID = 0x0010,
+ UPDATEFLAG_LIVING = 0x0020,
+ UPDATEFLAG_STATIONARY_POSITION = 0x0040,
+ UPDATEFLAG_VEHICLE = 0x0080,
+ UPDATEFLAG_GO_TRANSPORT_POSITION = 0x0100,
+ UPDATEFLAG_ROTATION = 0x0200,
+ UPDATEFLAG_UNK3 = 0x0400,
+ UPDATEFLAG_ANIMKITS = 0x0800,
+ UPDATEFLAG_UNK5 = 0x1000,
+ UPDATEFLAG_UNK6 = 0x2000,
};
class UpdateData
{
public:
- UpdateData();
+ UpdateData(uint16 map);
void AddOutOfRangeGUID(std::set<uint64>& guids);
void AddOutOfRangeGUID(uint64 guid);
@@ -64,11 +66,10 @@ class UpdateData
std::set<uint64> const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; }
protected:
+ uint16 m_map;
uint32 m_blockCount;
std::set<uint64> m_outOfRangeGUIDs;
ByteBuffer m_data;
-
- void Compress(void* dst, uint32 *dst_size, void* src, int src_size);
};
#endif
diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
index 64b5037048b..4308094d81c 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
@@ -21,6 +21,8 @@ uint32 ItemUpdateFieldFlags[CONTAINER_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -77,12 +79,20 @@ uint32 ItemUpdateFieldFlags[CONTAINER_END] =
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_1
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_1+1
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_3
UF_FLAG_PUBLIC, // ITEM_FIELD_PROPERTY_SEED
UF_FLAG_PUBLIC, // ITEM_FIELD_RANDOM_PROPERTIES_ID
UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER, // ITEM_FIELD_DURABILITY
UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER, // ITEM_FIELD_MAXDURABILITY
UF_FLAG_PUBLIC, // ITEM_FIELD_CREATE_PLAYED_TIME
- UF_FLAG_NONE, // ITEM_FIELD_PAD
UF_FLAG_PUBLIC, // CONTAINER_FIELD_NUM_SLOTS
UF_FLAG_NONE, // CONTAINER_ALIGN_PAD
UF_FLAG_PUBLIC, // CONTAINER_FIELD_SLOT_1
@@ -163,6 +173,8 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -191,30 +203,22 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER3
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER4
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER5
- UF_FLAG_PUBLIC, // UNIT_FIELD_POWER6
- UF_FLAG_PUBLIC, // UNIT_FIELD_POWER7
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXHEALTH
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER1
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER2
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER3
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER4
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER5
- UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER6
- UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER7
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+1
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+2
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+3
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+4
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+5
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+6
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+1
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+2
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+3
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+4
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+5
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+6
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+1
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+2
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+3
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+4
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+1
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+2
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+3
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+4
UF_FLAG_PUBLIC, // UNIT_FIELD_LEVEL
UF_FLAG_PUBLIC, // UNIT_FIELD_FACTIONTEMPLATE
UF_FLAG_PUBLIC, // UNIT_VIRTUAL_ITEM_SLOT_ID
@@ -228,7 +232,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // UNIT_FIELD_RANGEDATTACKTIME
UF_FLAG_PUBLIC, // UNIT_FIELD_BOUNDINGRADIUS
UF_FLAG_PUBLIC, // UNIT_FIELD_COMBATREACH
- UF_FLAG_PUBLIC, // UNIT_FIELD_DISPLAYID
+ UF_FLAG_DYNAMIC, // UNIT_FIELD_DISPLAYID
UF_FLAG_PUBLIC, // UNIT_FIELD_NATIVEDISPLAYID
UF_FLAG_PUBLIC, // UNIT_FIELD_MOUNTDISPLAYID
UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_SPECIAL_INFO, // UNIT_FIELD_MINDAMAGE
@@ -242,6 +246,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_OWNER, // UNIT_FIELD_PETNEXTLEVELEXP
UF_FLAG_DYNAMIC, // UNIT_DYNAMIC_FLAGS
UF_FLAG_PUBLIC, // UNIT_MOD_CAST_SPEED
+ UF_FLAG_PUBLIC, // UNIT_MOD_CAST_HASTE
UF_FLAG_PUBLIC, // UNIT_CREATED_BY_SPELL
UF_FLAG_DYNAMIC, // UNIT_NPC_FLAGS
UF_FLAG_PUBLIC, // UNIT_NPC_EMOTESTATE
@@ -285,10 +290,12 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_BASE_HEALTH
UF_FLAG_PUBLIC, // UNIT_FIELD_BYTES_2
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MODS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MOD_POS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MOD_NEG
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MULTIPLIER
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MODS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MINRANGEDDAMAGE
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MAXRANGEDDAMAGE
@@ -308,142 +315,269 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_COST_MULTIPLIER+6
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MAXHEALTHMODIFIER
UF_FLAG_PUBLIC, // UNIT_FIELD_HOVERHEIGHT
+ UF_FLAG_PUBLIC, // UNIT_FIELD_MAXITEMLEVEL
UF_FLAG_NONE, // UNIT_FIELD_PADDING
UF_FLAG_PUBLIC, // PLAYER_DUEL_ARBITER
UF_FLAG_PUBLIC, // PLAYER_DUEL_ARBITER+1
UF_FLAG_PUBLIC, // PLAYER_FLAGS
- UF_FLAG_PUBLIC, // PLAYER_GUILDID
UF_FLAG_PUBLIC, // PLAYER_GUILDRANK
+ UF_FLAG_PUBLIC, // PLAYER_GUILDDELETE_DATE
+ UF_FLAG_PUBLIC, // PLAYER_GUILDLEVEL
UF_FLAG_PUBLIC, // PLAYER_BYTES
UF_FLAG_PUBLIC, // PLAYER_BYTES_2
UF_FLAG_PUBLIC, // PLAYER_BYTES_3
UF_FLAG_PUBLIC, // PLAYER_DUEL_TEAM
UF_FLAG_PUBLIC, // PLAYER_GUILD_TIMESTAMP
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_4
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_4
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_5
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_1_ENTRYID
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_1_ENCHANTMENT
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_2_ENTRYID
@@ -657,134 +791,6 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+21
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+22
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+2
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+3
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+4
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+5
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+6
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+7
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+8
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+9
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+10
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+11
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+12
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+13
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+14
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+15
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+16
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+17
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+18
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+19
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+21
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+22
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+24
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+25
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+26
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+27
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+28
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+29
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+30
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+31
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+32
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+33
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+34
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+35
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+36
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+37
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+38
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+39
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+40
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+41
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+42
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+43
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+44
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+45
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+46
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+47
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+48
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+49
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+50
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+51
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+52
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+53
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+54
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+55
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+56
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+57
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+58
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+59
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+60
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+61
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+62
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+63
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+2
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+3
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+4
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+5
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+6
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+7
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+8
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+9
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+10
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+11
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+12
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+13
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+14
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+15
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+16
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+17
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+18
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+19
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+21
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+22
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+24
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+25
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+26
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+27
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+28
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+29
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+30
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+31
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+32
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+33
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+34
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+35
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+36
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+37
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+38
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+39
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+40
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+41
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+42
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+43
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+44
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+45
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+46
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+47
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+48
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+49
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+50
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+51
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+52
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+53
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+54
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+55
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+56
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+57
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+58
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+59
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+60
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+61
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+62
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+63
UF_FLAG_PRIVATE, // PLAYER_FARSIGHT
UF_FLAG_PRIVATE, // PLAYER_FARSIGHT+1
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES
@@ -793,403 +799,402 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES1+1
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES2
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES2+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KNOWN_CURRENCIES
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KNOWN_CURRENCIES+1
+ UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES3
+ UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES3+1
UF_FLAG_PRIVATE, // PLAYER_XP
UF_FLAG_PRIVATE, // PLAYER_NEXT_LEVEL_XP
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+1
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+2
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+3
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+4
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+5
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+6
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+7
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+8
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+9
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+10
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+11
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+12
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+13
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+14
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+15
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+16
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+17
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+18
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+19
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+20
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+21
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+22
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+23
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+24
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+25
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+26
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+27
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+28
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+29
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+30
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+31
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+32
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+33
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+34
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+35
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+36
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+37
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+38
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+39
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+40
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+41
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+42
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+43
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+44
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+45
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+46
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+47
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+48
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+49
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+50
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+51
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+52
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+53
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+54
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+55
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+56
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+57
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+58
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+59
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+60
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+61
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+62
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+63
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+64
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+65
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+66
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+67
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+68
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+69
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+70
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+71
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+72
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+73
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+74
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+75
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+76
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+77
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+78
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+79
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+80
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+81
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+82
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+83
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+84
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+85
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+86
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+87
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+88
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+89
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+90
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+91
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+92
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+93
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+94
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+95
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+96
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+97
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+98
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+99
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+100
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+101
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+102
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+103
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+104
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+105
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+106
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+107
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+108
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+109
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+110
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+111
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+112
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+113
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+114
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+115
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+116
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+117
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+118
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+119
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+120
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+121
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+122
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+123
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+124
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+125
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+126
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+127
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+128
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+129
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+130
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+131
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+132
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+133
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+134
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+135
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+136
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+137
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+138
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+139
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+140
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+141
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+142
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+143
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+144
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+145
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+146
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+147
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+148
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+149
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+150
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+151
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+152
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+153
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+154
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+155
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+156
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+157
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+158
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+159
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+160
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+161
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+162
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+163
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+164
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+165
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+166
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+167
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+168
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+169
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+170
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+171
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+172
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+173
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+174
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+175
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+176
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+177
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+178
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+179
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+180
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+181
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+182
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+183
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+184
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+185
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+186
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+187
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+188
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+189
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+190
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+191
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+192
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+193
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+194
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+195
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+196
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+197
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+198
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+199
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+200
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+201
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+202
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+203
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+204
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+205
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+206
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+207
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+208
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+209
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+210
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+211
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+212
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+213
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+214
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+215
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+216
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+217
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+218
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+219
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+220
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+221
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+222
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+223
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+224
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+225
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+226
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+227
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+228
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+229
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+230
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+231
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+232
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+233
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+234
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+235
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+236
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+237
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+238
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+239
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+240
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+241
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+242
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+243
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+244
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+245
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+246
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+247
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+248
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+249
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+250
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+251
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+252
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+253
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+254
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+255
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+256
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+257
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+258
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+259
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+260
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+261
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+262
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+263
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+264
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+265
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+266
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+267
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+268
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+269
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+270
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+271
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+272
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+273
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+274
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+275
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+276
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+277
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+278
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+279
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+280
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+281
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+282
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+283
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+284
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+285
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+286
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+287
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+288
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+289
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+290
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+291
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+292
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+293
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+294
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+295
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+296
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+297
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+298
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+299
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+300
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+301
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+302
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+303
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+304
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+305
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+306
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+307
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+308
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+309
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+310
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+311
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+312
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+313
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+314
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+315
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+316
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+317
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+318
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+319
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+320
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+321
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+322
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+323
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+324
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+325
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+326
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+327
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+328
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+329
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+330
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+331
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+332
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+333
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+334
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+335
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+336
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+337
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+338
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+339
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+340
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+341
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+342
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+343
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+344
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+345
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+346
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+347
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+348
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+349
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+350
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+351
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+352
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+353
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+354
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+355
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+356
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+357
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+358
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+359
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+360
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+361
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+362
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+363
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+364
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+365
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+366
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+367
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+368
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+369
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+370
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+371
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+372
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+373
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+374
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+375
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+376
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+377
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+378
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+379
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+380
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+381
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+382
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+383
- UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS1
- UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+63
+ UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS
UF_FLAG_PRIVATE, // PLAYER_TRACK_CREATURES
UF_FLAG_PRIVATE, // PLAYER_TRACK_RESOURCES
+ UF_FLAG_PRIVATE, // PLAYER_EXPERTISE
+ UF_FLAG_PRIVATE, // PLAYER_OFFHAND_EXPERTISE
UF_FLAG_PRIVATE, // PLAYER_BLOCK_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_DODGE_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_PARRY_PERCENTAGE
- UF_FLAG_PRIVATE, // PLAYER_EXPERTISE
- UF_FLAG_PRIVATE, // PLAYER_OFFHAND_EXPERTISE
UF_FLAG_PRIVATE, // PLAYER_CRIT_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_RANGED_CRIT_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_OFFHAND_CRIT_PERCENTAGE
@@ -1202,6 +1207,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_SPELL_CRIT_PERCENTAGE1+6
UF_FLAG_PRIVATE, // PLAYER_SHIELD_BLOCK
UF_FLAG_PRIVATE, // PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE
+ UF_FLAG_PRIVATE, // PLAYER_MASTERY
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+1
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+2
@@ -1330,8 +1336,37 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+125
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+126
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+127
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+128
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+129
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+130
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+131
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+132
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+133
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+134
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+135
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+136
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+137
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+138
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+139
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+140
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+141
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+142
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+143
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+144
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+145
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+146
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+147
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+148
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+149
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+150
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+151
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+152
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+153
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+154
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+155
UF_FLAG_PRIVATE, // PLAYER_REST_STATE_EXPERIENCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_COINAGE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_COINAGE+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS+2
@@ -1356,10 +1391,14 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_DONE_POS
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_PCT
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_DONE_PCT
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_SPELL_POWER_PCT
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_TARGET_RESISTANCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_BYTES
- UF_FLAG_PRIVATE, // PLAYER_AMMO_ID
UF_FLAG_PRIVATE, // PLAYER_SELF_RES_SPELL
UF_FLAG_PRIVATE, // PLAYER_FIELD_PVP_MEDALS
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_PRICE_1
@@ -1387,8 +1426,6 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_TIMESTAMP_1+10
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_TIMESTAMP_1+11
UF_FLAG_PRIVATE, // PLAYER_FIELD_KILLS
- UF_FLAG_PRIVATE, // PLAYER_FIELD_TODAY_CONTRIBUTION
- UF_FLAG_PRIVATE, // PLAYER_FIELD_YESTERDAY_CONTRIBUTION
UF_FLAG_PRIVATE, // PLAYER_FIELD_LIFETIME_HONORBALE_KILLS
UF_FLAG_PRIVATE, // PLAYER_FIELD_BYTES2
UF_FLAG_PRIVATE, // PLAYER_FIELD_WATCHED_FACTION_INDEX
@@ -1417,6 +1454,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+22
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+23
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+24
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+25
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+2
@@ -1438,8 +1476,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+18
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+19
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_HONOR_CURRENCY
- UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_CURRENCY
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_BATTLEGROUND_RATING
UF_FLAG_PRIVATE, // PLAYER_FIELD_MAX_LEVEL
UF_FLAG_PRIVATE, // PLAYER_FIELD_DAILY_QUESTS_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_DAILY_QUESTS_1+1
@@ -1479,20 +1516,53 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+3
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+4
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+8
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+2
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+3
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+4
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+8
UF_FLAG_PRIVATE, // PLAYER_GLYPHS_ENABLED
UF_FLAG_PRIVATE, // PLAYER_PET_SPELL_POWER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+3
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+4
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+3
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+4
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+7
+ UF_FLAG_PRIVATE, // PLAYER_PROFESSION_SKILL_LINE_1
+ UF_FLAG_PRIVATE, // PLAYER_PROFESSION_SKILL_LINE_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_UI_HIT_MODIFIER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_UI_SPELL_HIT_MODIFIER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_HOME_REALM_TIME_OFFSET
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_RANGED_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_PET_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HASTE_REGEN
};
uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -1515,13 +1585,15 @@ uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
UF_FLAG_NONE, // OBJECT_FIELD_PADDING
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTER
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTER+1
- UF_FLAG_PUBLIC, // DYNAMICOBJECT_BYTES
+ UF_FLAG_DYNAMIC, // DYNAMICOBJECT_BYTES
UF_FLAG_PUBLIC, // DYNAMICOBJECT_SPELLID
UF_FLAG_PUBLIC, // DYNAMICOBJECT_RADIUS
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTTIME
@@ -1531,6 +1603,8 @@ uint32 CorpseUpdateFieldFlags[CORPSE_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -1561,8 +1635,24 @@ uint32 CorpseUpdateFieldFlags[CORPSE_END] =
UF_FLAG_PUBLIC, // CORPSE_FIELD_ITEM+18
UF_FLAG_PUBLIC, // CORPSE_FIELD_BYTES_1
UF_FLAG_PUBLIC, // CORPSE_FIELD_BYTES_2
- UF_FLAG_PUBLIC, // CORPSE_FIELD_GUILD
UF_FLAG_PUBLIC, // CORPSE_FIELD_FLAGS
UF_FLAG_DYNAMIC, // CORPSE_FIELD_DYNAMIC_FLAGS
- UF_FLAG_NONE, // CORPSE_FIELD_PAD
+};
+
+uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END] =
+{
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
+ UF_FLAG_NONE, // OBJECT_FIELD_PADDING
+ UF_FLAG_PUBLIC, // AREATRIGGER_SPELLID
+ UF_FLAG_PUBLIC, // AREATRIGGER_SPELLVISUALID
+ UF_FLAG_PUBLIC, // AREATRIGGER_DURATION
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS+1
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS+2
};
diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
index 6053b361905..80f7e71524b 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
@@ -40,5 +40,6 @@ extern uint32 UnitUpdateFieldFlags[PLAYER_END];
extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END];
extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END];
extern uint32 CorpseUpdateFieldFlags[CORPSE_END];
+extern uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END];
#endif // _UPDATEFIELDFLAGS_H
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h
index 9e659c0f581..15e9c67e8d0 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.h
@@ -16,418 +16,550 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _UPDATEFIELDS_AUTO_H
-#define _UPDATEFIELDS_AUTO_H
+#ifndef _UPDATEFIELDS_H
+#define _UPDATEFIELDS_H
-// Auto generated for version 3, 3, 5, 12340
+// Auto generated for version 4, 3, 4, 15595
enum EObjectFields
{
- OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- OBJECT_FIELD_TYPE = 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- OBJECT_FIELD_ENTRY = 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- OBJECT_FIELD_SCALE_X = 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
- OBJECT_FIELD_PADDING = 0x0005, // Size: 1, Type: INT, Flags: NONE
- OBJECT_END = 0x0006
+ OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ OBJECT_FIELD_DATA = 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ OBJECT_FIELD_TYPE = 0x0004, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ OBJECT_FIELD_ENTRY = 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ OBJECT_FIELD_SCALE_X = 0x0006, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ OBJECT_FIELD_PADDING = 0x0007, // Size: 1, Type: INT, Flags: NONE
+ OBJECT_END = 0x0008
};
enum EItemFields
{
- ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_DURABILITY = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE
- ITEM_END = OBJECT_END + 0x003A
+ ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_13_1 = OBJECT_END + 0x0034, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_13_3 = OBJECT_END + 0x0036, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_14_1 = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_14_3 = OBJECT_END + 0x0039, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_15_1 = OBJECT_END + 0x003A, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_15_3 = OBJECT_END + 0x003C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_DURABILITY = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0040, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0041, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_END = OBJECT_END + 0x0042,
};
enum EContainerFields
{
- CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
- CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE
- CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC
- CONTAINER_END = ITEM_END + 0x004A
+ CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
+ CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE
+ CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC
+ CONTAINER_END = ITEM_END + 0x004A
};
enum EUnitFields
{
- UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE
- UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER6 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER7 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0021, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0022, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0029, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_LEVEL = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0032, // Size: 3, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FLAGS = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_AURASTATE = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0038, // Size: 2, Type: INT, Flags: PUBLIC
- UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x003A, // Size: 1, Type: INT, Flags: PRIVATE
- UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003C, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0044, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER
- UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: OWNER
- UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER
- UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE
- UNIT_END = OBJECT_END + 0x008E,
+ UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE
+ UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x001E, // Size: 5, Type: FLOAT, Flags: PRIVATE, OWNER, UNUSED2
+ UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0023, // Size: 5, Type: FLOAT, Flags: PRIVATE, OWNER, UNUSED2
+ UNIT_FIELD_LEVEL = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x002A, // Size: 3, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS = OBJECT_END + 0x002D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x002E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_AURASTATE = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0030, // Size: 2, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PRIVATE
+ UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0033, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0034, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0038, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0039, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_BYTES_1 = OBJECT_END + 0x003C, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_PETNUMBER = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: OWNER
+ UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0040, // Size: 1, Type: INT, Flags: OWNER
+ UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0041, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_MOD_CAST_SPEED = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_MOD_CAST_HASTE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_CREATED_BY_SPELL = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_NPC_FLAGS = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_NPC_EMOTESTATE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_STAT0 = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT1 = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT2 = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT3 = OBJECT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT4 = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RESISTANCES = OBJECT_END + 0x0056, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_BASE_MANA = OBJECT_END + 0x006B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x006C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_BYTES_2 = OBJECT_END + 0x006D, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x006E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MOD_POS = OBJECT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x0070, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0071, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0075, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x0076, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x0078, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x007F, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x0086, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x0087, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_MAXITEMLEVEL = OBJECT_END + 0x0088, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PADDING = OBJECT_END + 0x0089, // Size: 1, Type: INT, Flags: NONE
+ UNIT_END = OBJECT_END + 0x008A
+};
+
+enum EPlayerFields
+{
+ PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDRANK = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDDELETE_DATE = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDLEVEL = UNIT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_BYTES = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_BYTES_2 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_BYTES_3 = UNIT_END + 0x0008, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_DUEL_TEAM = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000D, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0011, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0012, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0016, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0017, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001C, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x0020, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0021, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0025, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0026, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x002A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002B, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x0030, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0034, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0035, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0039, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x003A, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003F, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0043, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0044, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0048, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0049, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004E, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0052, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0053, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0057, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0058, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005D, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0061, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0062, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0066, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0067, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006C, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x0070, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0071, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0075, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0076, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x007A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007B, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x0080, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0084, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0085, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_1 = UNIT_END + 0x0088, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_2 = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_3 = UNIT_END + 0x008A, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_5 = UNIT_END + 0x008C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_1 = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_2 = UNIT_END + 0x008E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_3 = UNIT_END + 0x008F, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_5 = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_1 = UNIT_END + 0x0092, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_2 = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_3 = UNIT_END + 0x0094, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_5 = UNIT_END + 0x0096, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_1 = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_2 = UNIT_END + 0x0098, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_3 = UNIT_END + 0x0099, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_5 = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_1 = UNIT_END + 0x009C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_2 = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_3 = UNIT_END + 0x009E, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_5 = UNIT_END + 0x00A0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_1 = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_2 = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_3 = UNIT_END + 0x00A3, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_5 = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_1 = UNIT_END + 0x00A6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_2 = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_3 = UNIT_END + 0x00A8, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_5 = UNIT_END + 0x00AA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_1 = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_2 = UNIT_END + 0x00AC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_3 = UNIT_END + 0x00AD, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_5 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_1 = UNIT_END + 0x00B0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_2 = UNIT_END + 0x00B1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_3 = UNIT_END + 0x00B2, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_5 = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_1 = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_2 = UNIT_END + 0x00B6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_3 = UNIT_END + 0x00B7, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_5 = UNIT_END + 0x00B9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_1 = UNIT_END + 0x00BA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_2 = UNIT_END + 0x00BB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_3 = UNIT_END + 0x00BC, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_5 = UNIT_END + 0x00BE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_1 = UNIT_END + 0x00BF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_2 = UNIT_END + 0x00C0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_3 = UNIT_END + 0x00C1, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_5 = UNIT_END + 0x00C3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_1 = UNIT_END + 0x00C4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_2 = UNIT_END + 0x00C5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_3 = UNIT_END + 0x00C6, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_5 = UNIT_END + 0x00C8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_1 = UNIT_END + 0x00C9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_2 = UNIT_END + 0x00CA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_3 = UNIT_END + 0x00CB, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_5 = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_1 = UNIT_END + 0x00CE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_2 = UNIT_END + 0x00CF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_3 = UNIT_END + 0x00D0, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_5 = UNIT_END + 0x00D2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_1 = UNIT_END + 0x00D3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_2 = UNIT_END + 0x00D4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_3 = UNIT_END + 0x00D5, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_5 = UNIT_END + 0x00D7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_1 = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_2 = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_3 = UNIT_END + 0x00DA, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_5 = UNIT_END + 0x00DC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_1 = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_2 = UNIT_END + 0x00DE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_3 = UNIT_END + 0x00DF, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_5 = UNIT_END + 0x00E1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_1 = UNIT_END + 0x00E2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_2 = UNIT_END + 0x00E3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_3 = UNIT_END + 0x00E4, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_5 = UNIT_END + 0x00E6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_1 = UNIT_END + 0x00E7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_2 = UNIT_END + 0x00E8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_3 = UNIT_END + 0x00E9, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_5 = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_1 = UNIT_END + 0x00EC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_2 = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_3 = UNIT_END + 0x00EE, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_5 = UNIT_END + 0x00F0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_1 = UNIT_END + 0x00F1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_2 = UNIT_END + 0x00F2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_3 = UNIT_END + 0x00F3, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_5 = UNIT_END + 0x00F5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_1 = UNIT_END + 0x00F6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_2 = UNIT_END + 0x00F7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_3 = UNIT_END + 0x00F8, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_5 = UNIT_END + 0x00FA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_1 = UNIT_END + 0x00FB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_2 = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_3 = UNIT_END + 0x00FD, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_5 = UNIT_END + 0x00FF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_1 = UNIT_END + 0x0100, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_2 = UNIT_END + 0x0101, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_3 = UNIT_END + 0x0102, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_5 = UNIT_END + 0x0104, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0105, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0106, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0107, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x0108, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x0109, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x010A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x010B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x010E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0110, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0111, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0112, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0113, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0114, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0115, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0116, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0117, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x0118, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x0119, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x011A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x011B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x011E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x011F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x0120, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x0122, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x0123, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x0124, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x0125, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x0126, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x0127, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x0128, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x0129, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x012A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_CHOSEN_TITLE = UNIT_END + 0x012B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_FAKE_INEBRIATION = UNIT_END + 0x012C, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_FIELD_PAD_0 = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: NONE
+ PLAYER_END_NOT_SELF = UNIT_END + 0x012E,
- PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILDID = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILDRANK = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_BYTES = UNIT_END + 0x0005, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_BYTES_2 = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_BYTES_3 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_DUEL_TEAM = UNIT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0011, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0013, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0016, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0018, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0020, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0022, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0025, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0027, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x002F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0031, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0034, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0036, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x0039, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003E, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0040, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0043, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0045, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0048, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004D, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0052, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0057, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0061, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0063, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0066, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0068, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0070, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0075, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0077, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x007F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0081, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0084, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0086, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0088, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x008A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x008B, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x008E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x008F, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x0090, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0092, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0094, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0096, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0098, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0099, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x009A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x009E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x00A0, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x00A2, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x00A6, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x00A8, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x00A9, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x00AA, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_CHOSEN_TITLE = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FAKE_INEBRIATION = UNIT_END + 0x00AE, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FIELD_PAD_0 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: NONE
- PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x00B0, // Size: 46, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x00DE, // Size: 32, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x00FE, // Size: 56, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0136, // Size: 14, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0144, // Size: 24, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x015C, // Size: 64, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x019C, // Size: 64, Type: LONG, Flags: PRIVATE
- PLAYER_FARSIGHT = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x01E4, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER_XP = UNIT_END + 0x01E6, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E7, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x01E8, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_CREATURES = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_RESOURCES = UNIT_END + 0x036B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_EXPERTISE = UNIT_END + 0x036F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x0370, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x0371, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0372, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0373, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0374, // Size: 7, Type: FLOAT, Flags: PRIVATE
- PLAYER_SHIELD_BLOCK = UNIT_END + 0x037B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x037C, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037D, // Size: 128, Type: BYTES, Flags: PRIVATE
- PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x03FD, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COINAGE = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x03FF, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0406, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x040D, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x0414, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0415, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0416, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0418, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES = UNIT_END + 0x0419, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_AMMO_ID = UNIT_END + 0x041A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SELF_RES_SPELL = UNIT_END + 0x041B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x041D, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0429, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_KILLS = UNIT_END + 0x0435, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES2 = UNIT_END + 0x0439, // Size: 1, Type: 6, Flags: PRIVATE
- PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x043B, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0454, // Size: 21, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0469, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x046A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x046B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x046C, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_RUNE_REGEN_1 = UNIT_END + 0x0485, // Size: 4, Type: FLOAT, Flags: PRIVATE
- PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x0489, // Size: 3, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x048C, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0492, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_GLYPHS_ENABLED = UNIT_END + 0x0498, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_PET_SPELL_POWER = UNIT_END + 0x0499, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_END = UNIT_END + 0x049A
+ PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x012E, // Size: 46, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x015C, // Size: 32, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x017C, // Size: 56, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x01B4, // Size: 14, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x01C2, // Size: 24, Type: LONG, Flags: PRIVATE
+ PLAYER_FARSIGHT = UNIT_END + 0x01DA, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES3 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_XP = UNIT_END + 0x01E4, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E5, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SKILL_LINEID_0 = UNIT_END + 0x01E6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_STEP_0 = UNIT_END + 0x0226, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_RANK_0 = UNIT_END + 0x0266, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_MAX_RANK_0 = UNIT_END + 0x02A6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_MODIFIER_0 = UNIT_END + 0x02E6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_TALENT_0 = UNIT_END + 0x0326, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_CHARACTER_POINTS = UNIT_END + 0x0366, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_CREATURES = UNIT_END + 0x0367, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_RESOURCES = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_EXPERTISE = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036B, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x036F, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0370, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0371, // Size: 7, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK = UNIT_END + 0x0378, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x0379, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_MASTERY = UNIT_END + 0x037A, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037B, // Size: 156, Type: BYTES, Flags: PRIVATE
+ PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COINAGE = UNIT_END + 0x0418, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x041A, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0421, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0428, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x042F, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0430, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0431, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS = UNIT_END + 0x0432, // Size: 3, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_SPELL_POWER_PCT = UNIT_END + 0x0435, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT = UNIT_END + 0x0436, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES = UNIT_END + 0x0439, // Size: 1, Type: BYTES, Flags: PRIVATE
+ PLAYER_SELF_RES_SPELL = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x043B, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x043C, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0448, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_KILLS = UNIT_END + 0x0454, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0455, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES2 = UNIT_END + 0x0456, // Size: 1, Type: 6, Flags: PRIVATE
+ PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0457, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0458, // Size: 26, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0472, // Size: 21, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BATTLEGROUND_RATING = UNIT_END + 0x0487, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0488, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0489, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_RUNE_REGEN_1 = UNIT_END + 0x04A2, // Size: 4, Type: FLOAT, Flags: PRIVATE
+ PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x04A6, // Size: 3, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x04A9, // Size: 9, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x04B2, // Size: 9, Type: INT, Flags: PRIVATE
+ PLAYER_GLYPHS_ENABLED = UNIT_END + 0x04BB, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_PET_SPELL_POWER = UNIT_END + 0x04BC, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_RESEARCHING_1 = UNIT_END + 0x04BD, // Size: 8, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_RESERACH_SITE_1 = UNIT_END + 0x04C5, // Size: 8, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_PROFESSION_SKILL_LINE_1 = UNIT_END + 0x04CD, // Size: 2, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_UI_HIT_MODIFIER = UNIT_END + 0x04CF, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_UI_SPELL_HIT_MODIFIER = UNIT_END + 0x04D0, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_HOME_REALM_TIME_OFFSET = UNIT_END + 0x04D1, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HASTE = UNIT_END + 0x04D2, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_RANGED_HASTE = UNIT_END + 0x04D3, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_PET_HASTE = UNIT_END + 0x04D4, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HASTE_REGEN = UNIT_END + 0x04D5, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_END = UNIT_END + 0x04D6
};
enum EGameObjectFields
{
- OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
- GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC
- GAMEOBJECT_END = OBJECT_END + 0x000C
+ OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
+ GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC
+ GAMEOBJECT_END = OBJECT_END + 0x000C
};
enum EDynamicObjectFields
{
- DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC
- DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
- DYNAMICOBJECT_END = OBJECT_END + 0x0006
+ DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: DYNAMIC
+ DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
+ DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ DYNAMICOBJECT_END = OBJECT_END + 0x0006
};
enum ECorpseFields
{
- CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC
- CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC
- CORPSE_FIELD_GUILD = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: DYNAMIC
- CORPSE_FIELD_PAD = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: NONE
- CORPSE_END = OBJECT_END + 0x001E
+ CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC
+ CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC
+ CORPSE_FIELD_FLAGS = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: DYNAMIC
+ CORPSE_END = OBJECT_END + 0x001C
};
-#endif
+
+enum EAreaTriggerFields
+{
+ AREATRIGGER_SPELLID = OBJECT_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_SPELLVISUALID = OBJECT_END + 0x0001, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_DURATION = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_FINAL_POS = OBJECT_END + 0x0003, // Size: 3, Type: FLOAT, Flags: PUBLIC
+ AREATRIGGER_END = OBJECT_END + 0x0006
+};
+
+#endif // _UPDATEFIELDS_H
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index f6693ba2260..ce564bd9090 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -31,15 +31,16 @@
#include "Util.h"
#include "Group.h"
#include "Opcodes.h"
+#include "WorldSession.h"
#define PET_XP_FACTOR 0.05f
Pet::Pet(Player* owner, PetType type) :
Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
- m_happinessTimer(7500), m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
+ m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
m_declinedname(NULL)
{
- ASSERT(GetOwner()->GetTypeId() == TYPEID_PLAYER);
+ ASSERT(m_owner->GetTypeId() == TYPEID_PLAYER);
m_unitTypeMask |= UNIT_MASK_PET;
if (type == HUNTER_PET)
@@ -150,14 +151,14 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (!petEntry)
return false;
- uint32 summonSpellId = fields[15].GetUInt32();
+ uint32 summonSpellId = fields[14].GetUInt32();
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summonSpellId);
bool isTemporarySummon = spellInfo && spellInfo->GetDuration() > 0;
if (current && isTemporarySummon)
return false;
- PetType petType = PetType(fields[16].GetUInt8());
+ PetType petType = PetType(fields[15].GetUInt8());
if (petType == HUNTER_PET)
{
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
@@ -224,8 +225,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet abandon, cancel)
- SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- SetPower(POWER_HAPPINESS, fields[12].GetUInt32());
setPowerType(POWER_FOCUS);
break;
default:
@@ -256,7 +255,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
else
{
SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
- SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana);
+ SetPower(POWER_MANA, savedmana > uint32(GetMaxPower(POWER_MANA)) ? GetMaxPower(POWER_MANA) : savedmana);
}
}
@@ -304,13 +303,13 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
InitTalentForLevel(); // set original talents points before spell loading
- uint32 timediff = uint32(time(NULL) - fields[14].GetUInt32());
+ uint32 timediff = uint32(time(NULL) - fields[13].GetUInt32());
_LoadAuras(timediff);
// load action bar, if data broken will fill later by default spells.
if (!isTemporarySummon)
{
- m_charmInfo->LoadPetActionBar(fields[13].GetString());
+ m_charmInfo->LoadPetActionBar(fields[12].GetString());
_LoadSpells();
InitTalentForLevel(); // re-init to check talent count
@@ -438,7 +437,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
// save pet
std::ostringstream ss;
- ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType) "
+ ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ','
<< GetEntry() << ','
@@ -451,8 +450,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< name.c_str() << "', "
<< uint32(HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1) << ','
<< curhealth << ','
- << curmana << ','
- << GetPower(POWER_HAPPINESS) << ", '";
+ << curmana << ", '";
for (uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i)
{
@@ -513,12 +511,6 @@ void Pet::setDeathState(DeathState s) // overwrite virtual
// pet corpse non lootable and non skinnable
SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
-
- //lose happiness when died and not in BG/Arena
- MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId());
- if (!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND))
- ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE);
-
//SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
}
@@ -612,18 +604,6 @@ void Pet::Update(uint32 diff)
}
}
}
-
- if (getPetType() != HUNTER_PET)
- break;
-
- if (m_happinessTimer <= diff)
- {
- LoseHappiness();
- m_happinessTimer = 7500;
- }
- else
- m_happinessTimer -= diff;
-
break;
}
default:
@@ -671,27 +651,6 @@ void Creature::Regenerate(Powers power)
ModifyPower(power, int32(addvalue));
}
-void Pet::LoseHappiness()
-{
- uint32 curValue = GetPower(POWER_HAPPINESS);
- if (curValue <= 0)
- return;
- int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
- if (isInCombat()) //we know in combat happiness fades faster, multiplier guess
- addvalue = int32(addvalue * 1.5f);
- ModifyPower(POWER_HAPPINESS, -addvalue);
-}
-
-HappinessState Pet::GetHappinessState()
-{
- if (GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
- return UNHAPPY;
- else if (GetPower(POWER_HAPPINESS) >= HAPPINESS_LEVEL_SIZE * 2)
- return HAPPY;
- else
- return CONTENT;
-}
-
void Pet::Remove(PetSaveMode mode, bool returnreagent)
{
GetOwner()->RemovePet(this, mode, returnreagent);
@@ -776,7 +735,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
SetDisplayId(creature->GetDisplayId());
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
- SetName(cFamily->Name[sWorld->GetDefaultDbcLocale()]);
+ SetName(cFamily->Name);
else
SetName(creature->GetNameForLocaleIdx(sObjectMgr->GetDBCLocaleIndex()));
@@ -789,7 +748,7 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
return false;
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
- SetName(cFamily->Name[sWorld->GetDefaultDbcLocale()]);
+ SetName(cFamily->Name);
Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
@@ -804,8 +763,6 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phas
if (!Create(guid, map, phaseMask, cinfo->Entry, petId))
return false;
- SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- SetPower(POWER_HAPPINESS, 166500);
setPowerType(POWER_FOCUS);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
@@ -863,6 +820,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
//scale
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
@@ -1896,6 +1854,8 @@ bool Pet::IsPermanentPetFor(Player* owner) const
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
case CLASS_DEATH_KNIGHT:
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
+ case CLASS_MAGE:
+ return GetCreatureTemplate()->type == CREATURE_TYPE_ELEMENTAL;
default:
return false;
}
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index e0afef2b8e3..ac274e3035d 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -77,8 +77,6 @@ class Pet : public Guardian
return m_autospells[pos];
}
- void LoseHappiness();
- HappinessState GetHappinessState();
void GivePetXP(uint32 xp);
void GivePetLevel(uint8 level);
void SynchronizeLevelWithOwner();
@@ -149,7 +147,6 @@ class Pet : public Guardian
Player* GetOwner() const;
protected:
- uint32 m_happinessTimer;
PetType m_petType;
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
uint64 m_auraRaidUpdateMask;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a6ec2371837..642da3e8d95 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -37,6 +37,7 @@
#include "ConditionMgr.h"
#include "CreatureAI.h"
#include "DatabaseEnv.h"
+#include "DB2Stores.h"
#include "DisableMgr.h"
#include "Formulas.h"
#include "GameEventMgr.h"
@@ -78,21 +79,10 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "MovementStructures.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
-#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3))
-#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1)
-#define PLAYER_SKILL_BONUS_INDEX(x) (PLAYER_SKILL_INDEX(x)+2)
-
-#define SKILL_VALUE(x) PAIR32_LOPART(x)
-#define SKILL_MAX(x) PAIR32_HIPART(x)
-#define MAKE_SKILL_VALUE(v, m) MAKE_PAIR32(v, m)
-
-#define SKILL_TEMP_BONUS(x) int16(PAIR32_LOPART(x))
-#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x))
-#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p)
-
enum CharacterFlags
{
CHARACTER_FLAG_NONE = 0x00000000,
@@ -144,6 +134,22 @@ enum CharacterCustomizeFlags
static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };
+uint32 const MasterySpells[MAX_CLASSES] =
+{
+ 0,
+ 87500, // Warrior
+ 87494, // Paladin
+ 87493, // Hunter
+ 87496, // Rogue
+ 87495, // Priest
+ 87492, // Death Knight
+ 87497, // Shaman
+ 86467, // Mage
+ 87498, // Warlock
+ 0,
+ 87491, // Druid
+};
+
// == PlayerTaxi ================================================
PlayerTaxi::PlayerTaxi()
@@ -205,15 +211,16 @@ void PlayerTaxi::LoadTaxiMask(std::string const &data)
void PlayerTaxi::AppendTaximaskTo(ByteBuffer& data, bool all)
{
+ data << uint32(TaxiMaskSize);
if (all)
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint32(sTaxiNodesMask[i]); // all existed nodes
+ data << uint8(sTaxiNodesMask[i]); // all existed nodes
}
else
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint32(m_taximask[i]); // known nodes
+ data << uint8(m_taximask[i]); // known nodes
}
}
@@ -281,7 +288,7 @@ uint32 PlayerTaxi::GetCurrentTaxiPath() const
std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- ss << taxi.m_taximask[i] << ' ';
+ ss << uint32(taxi.m_taximask[i]) << ' ';
return ss;
}
@@ -359,7 +366,7 @@ void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/)
Update(false); // send spell info to caster self
}
-void TradeData::SetMoney(uint32 money)
+void TradeData::SetMoney(uint64 money)
{
if (m_money == money)
return;
@@ -433,6 +440,7 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
// 4.3. Give reputation (player must not be on BG).
// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
// 5. Credit instance encounter.
+// 6. Update guild achievements.
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
// 1. Initialize internal variables to default values.
_killer(killer), _victim(victim), _group(killer->GetGroup()),
@@ -521,10 +529,14 @@ inline void KillRewarder::_RewardXP(Player* player, float rate)
for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
AddPct(xp, (*i)->GetAmount());
- // 4.2.3. Give XP to player.
+ // 4.2.3. Calculate expansion penalty
+ if (_victim->GetTypeId() == TYPEID_UNIT && player->getLevel() >= GetMaxLevelForExpansion(_victim->ToCreature()->GetCreatureTemplate()->expansion))
+ xp = CalculatePct(xp, 10); // Players get only 10% xp for killing creatures of lower expansion levels than himself
+
+ // 4.2.4. Give XP to player.
player->GiveXP(xp, _victim, _groupRate);
if (Pet* pet = player->GetPet())
- // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
+ // 4.2.5. If player has pet, reward pet with XP (100% for single player, 50% for group case).
pet->GivePetXP(_group ? xp / 2 : xp);
}
}
@@ -603,7 +615,7 @@ void KillRewarder::_RewardGroup()
if (member->IsAtGroupRewardDistance(_victim))
{
_RewardPlayer(member, isDungeon);
- member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim);
+ member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, 0, _victim);
}
}
}
@@ -631,10 +643,18 @@ void KillRewarder::Reward()
}
// 5. Credit instance encounter.
+ // 6. Update guild achievements.
if (Creature* victim = _victim->ToCreature())
+ {
if (victim->IsDungeonBoss())
if (InstanceScript* instance = _victim->GetInstanceScript())
instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
+
+ if (uint32 guildId = victim->GetMap()->GetOwnerGuildId())
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, 0, victim, _killer);
+ }
+
}
// == Player ====================================================
@@ -644,7 +664,7 @@ void KillRewarder::Reward()
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
-Player::Player(WorldSession* session): Unit(true)
+Player::Player(WorldSession* session): Unit(true), phaseMgr(this)
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -677,11 +697,10 @@ Player::Player(WorldSession* session): Unit(true)
m_comboTarget = 0;
m_comboPoints = 0;
- m_usedTalentCount = 0;
- m_questRewardTalentCount = 0;
-
m_regenTimer = 0;
m_regenTimerCount = 0;
+ m_holyPowerRegenTimerCount = 0;
+ m_focusRegenTimerCount = 0;
m_weaponChangeTimer = 0;
m_zoneUpdateId = 0;
@@ -691,7 +710,7 @@ Player::Player(WorldSession* session): Unit(true)
m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE);
- clearResurrectRequestData();
+ _resurrectionData = NULL;
memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT);
@@ -755,7 +774,6 @@ Player::Player(WorldSession* session): Unit(true)
m_canBlock = false;
m_canDualWield = false;
m_canTitanGrip = false;
- m_ammoDPS = 0.0f;
m_temporaryUnsummonedPetNumber = 0;
//cache for UNIT_CREATED_BY_SPELL to allow
@@ -779,8 +797,6 @@ Player::Player(WorldSession* session): Unit(true)
unReadMails = 0;
m_nextMailDelivereTime = 0;
- m_resetTalentsCost = 0;
- m_resetTalentsTime = 0;
m_itemUpdateQueueBlocked = false;
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
@@ -796,17 +812,7 @@ Player::Player(WorldSession* session): Unit(true)
m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
m_lastPotionId = 0;
-
- m_activeSpec = 0;
- m_specsCount = 1;
-
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (uint8 g = 0; g < MAX_GLYPH_SLOT_INDEX; ++g)
- m_Glyphs[i][g] = 0;
-
- m_talents[i] = new PlayerTalentMap();
- }
+ _talentMgr = new PlayerTalentInfo();
for (uint8 i = 0; i < BASEMOD_END; ++i)
{
@@ -818,7 +824,6 @@ Player::Player(WorldSession* session): Unit(true)
m_baseRatingValue[i] = 0;
m_baseSpellPower = 0;
- m_baseFeralAP = 0;
m_baseManaRegen = 0;
m_baseHealthRegen = 0;
m_spellPenetrationItemMod = 0;
@@ -858,7 +863,7 @@ Player::Player(WorldSession* session): Unit(true)
m_ChampioningFaction = 0;
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i)
m_powerFraction[i] = 0;
isDebugAreaTriggers = false;
@@ -870,7 +875,12 @@ Player::Player(WorldSession* session): Unit(true)
SetPendingBind(0, 0);
_activeCheats = CHEAT_NONE;
- m_achievementMgr = new AchievementMgr(this);
+ _maxPersonalArenaRate = 0;
+
+ memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
+ memset(_CUFProfiles, 0, MAX_CUF_PROFILES * sizeof(CUFProfile*));
+
+ m_achievementMgr = new AchievementMgr<Player>(this);
m_reputationMgr = new ReputationMgr(this);
}
@@ -886,12 +896,7 @@ Player::~Player()
for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
delete itr->second;
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (PlayerTalentMap::const_iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end(); ++itr)
- delete itr->second;
- delete m_talents[i];
- }
+ delete _talentMgr;
//all mailed items should be deleted, also all mail should be deallocated
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -910,6 +915,14 @@ Player::~Player()
delete m_achievementMgr;
delete m_reputationMgr;
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ delete _voidStorageItems[i];
+
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ delete _CUFProfiles[i];
+
+ ClearResurrectRequestData();
+
sWorld->DecreasePlayerCount();
}
@@ -985,8 +998,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
}
+
SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);
- SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // default for players in 3.0.3
SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); // -1 is default value
@@ -999,8 +1012,9 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetByteValue(PLAYER_BYTES_3, 0, createInfo->Gender);
SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1)
- SetUInt32Value(PLAYER_GUILDID, 0);
+ SetUInt64Value(OBJECT_FIELD_DATA, 0);
SetUInt32Value(PLAYER_GUILDRANK, 0);
+ SetGuildLevel(0);
SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0);
for (int i = 0; i < KNOWN_TITLES_SIZE; ++i)
@@ -1009,8 +1023,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetUInt32Value(PLAYER_FIELD_KILLS, 0);
SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0);
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0);
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
// set starting level
uint32 start_level = getClass() != CLASS_DEATH_KNIGHT
@@ -1029,8 +1041,9 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
InitRunes();
SetUInt32Value(PLAYER_FIELD_COINAGE, sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY));
- SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
- SetArenaPoints(sWorld->getIntConfig(CONFIG_START_ARENA_POINTS));
+ SetCurrency(CURRENCY_TYPE_HONOR_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_HONOR_POINTS));
+ SetCurrency(CURRENCY_TYPE_JUSTICE_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_JUSTICE_POINTS));
+ SetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_CONQUEST_POINTS));
// start with every map explored
if (sWorld->getBoolConfig(CONFIG_START_ALL_EXPLORED))
@@ -1105,8 +1118,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
if (getPowerType() == POWER_RUNIC_POWER)
{
- SetPower(POWER_RUNE, 8);
- SetMaxPower(POWER_RUNE, 8);
+ SetPower(POWER_RUNES, 8);
+ SetMaxPower(POWER_RUNES, 8);
SetPower(POWER_RUNIC_POWER, 0);
SetMaxPower(POWER_RUNIC_POWER, 1000);
}
@@ -1137,7 +1150,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
uint32 count = iProto->BuyCount;
// special amount for food/drink
- if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD)
+ if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD_DRINK)
{
switch (iProto->Spells[0].SpellCategory)
{
@@ -1173,7 +1186,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
EquipItem(eDest, pItem, true);
}
- // move other items to more appropriate slots (ammo not equipped in special bag)
+ // move other items to more appropriate slots
else
{
ItemPosCountVec sDest;
@@ -1183,11 +1196,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
pItem = StoreItem(sDest, pItem, true);
}
-
- // if this is ammo then use it
- msg = CanUseAmmo(pItem->GetEntry());
- if (msg == EQUIP_ERR_OK)
- SetAmmo(pItem->GetEntry());
}
}
}
@@ -1297,8 +1305,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
TC_LOG_DEBUG(LOG_FILTER_PLAYER, "We are fall to death, loosing 10 percents durability");
DurabilityLossAll(0.10f, false);
// durability lost message
- WorldPacket data2(SMSG_DURABILITY_DAMAGE_DEATH, 0);
- GetSession()->SendPacket(&data2);
+ SendDurabilityLoss(this, 10);
}
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
@@ -1854,7 +1861,7 @@ void Player::setDeathState(DeathState s)
// lost combo points at any target (targeted combo points clear in Unit::setDeathState)
ClearComboPoints();
- clearResurrectRequestData();
+ ClearResurrectRequestData();
//FIXME: is pet dismissed at dying or releasing spirit? if second, add setDeathState(DEAD) to HandleRepopRequestOpcode and define pet unsummon here with (s == DEAD)
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
@@ -1893,100 +1900,70 @@ void Player::InnEnter(time_t time, uint32 mapid, float x, float y, float z)
time_inn_enter = time;
}
-bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
+bool Player::BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, ByteBuffer* bitBuffer)
{
// 0 1 2 3 4 5 6 7
// "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
// 8 9 10 11 12 13 14
// "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, "
- // 15 16 17 18 19 20 21
- // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, character_declinedname.genitive "
+ // 15 16 17 18 19 20 21 22
+ // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, characters.slot, character_declinedname.genitive"
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
+ std::string name = fields[1].GetString();
uint8 plrRace = fields[2].GetUInt8();
uint8 plrClass = fields[3].GetUInt8();
uint8 gender = fields[4].GetUInt8();
-
- PlayerInfo const* info = sObjectMgr->GetPlayerInfo(plrRace, plrClass);
- if (!info)
- {
- TC_LOG_ERROR(LOG_FILTER_PLAYER_LOADING, "Player %u has incorrect race/class pair. Don't build enum.", guid);
- return false;
- }
- else if (!IsValidGender(gender))
- {
- TC_LOG_ERROR(LOG_FILTER_PLAYER_LOADING, "Player (%u) has incorrect gender (%hu), don't build enum.", guid, gender);
- return false;
- }
-
- *data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
- *data << fields[1].GetString(); // name
- *data << uint8(plrRace); // race
- *data << uint8(plrClass); // class
- *data << uint8(gender); // gender
-
- uint32 playerBytes = fields[5].GetUInt32();
- *data << uint8(playerBytes); // skin
- *data << uint8(playerBytes >> 8); // face
- *data << uint8(playerBytes >> 16); // hair style
- *data << uint8(playerBytes >> 24); // hair color
-
- uint32 playerBytes2 = fields[6].GetUInt32();
- *data << uint8(playerBytes2 & 0xFF); // facial hair
-
- *data << uint8(fields[7].GetUInt8()); // level
- *data << uint32(fields[8].GetUInt16()); // zone
- *data << uint32(fields[9].GetUInt16()); // map
-
- *data << fields[10].GetFloat(); // x
- *data << fields[11].GetFloat(); // y
- *data << fields[12].GetFloat(); // z
-
- *data << uint32(fields[13].GetUInt32()); // guild id
+ uint8 skin = uint8(fields[5].GetUInt32() & 0xFF);
+ uint8 face = uint8((fields[5].GetUInt32() >> 8) & 0xFF);
+ uint8 hairStyle = uint8((fields[5].GetUInt32() >> 16) & 0xFF);
+ uint8 hairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF);
+ uint8 facialHair = uint8(fields[6].GetUInt32() & 0xFF);
+ uint8 level = fields[7].GetUInt8();
+ uint32 zone = fields[8].GetUInt16();
+ uint32 mapId = uint32(fields[9].GetUInt16());
+ float x = fields[10].GetFloat();
+ float y = fields[11].GetFloat();
+ float z = fields[12].GetFloat();
+ uint32 guildId = fields[13].GetUInt32();
+ ObjectGuid guildGuid = MAKE_NEW_GUID(guildId, 0, guildId ? uint32(HIGHGUID_GUILD) : 0);
+ uint32 playerFlags = fields[14].GetUInt32();
+ uint32 atLoginFlags = fields[15].GetUInt16();
+ Tokenizer equipment(fields[19].GetString(), ' ');
+ uint8 slot = fields[21].GetUInt8();
uint32 charFlags = 0;
- uint32 playerFlags = fields[14].GetUInt32();
- uint16 atLoginFlags = fields[15].GetUInt16();
if (playerFlags & PLAYER_FLAGS_HIDE_HELM)
charFlags |= CHARACTER_FLAG_HIDE_HELM;
+
if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK)
charFlags |= CHARACTER_FLAG_HIDE_CLOAK;
+
if (playerFlags & PLAYER_FLAGS_GHOST)
charFlags |= CHARACTER_FLAG_GHOST;
+
if (atLoginFlags & AT_LOGIN_RENAME)
charFlags |= CHARACTER_FLAG_RENAME;
+
if (fields[20].GetUInt32())
charFlags |= CHARACTER_FLAG_LOCKED_BY_BILLING;
- if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
- {
- if (!fields[21].GetString().empty())
- charFlags |= CHARACTER_FLAG_DECLINED;
- }
- else
- charFlags |= CHARACTER_FLAG_DECLINED;
- *data << uint32(charFlags); // character flags
+ if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[22].GetString().empty())
+ charFlags |= CHARACTER_FLAG_DECLINED;
- // character customize flags
+ uint32 customizationFlag = 0;
if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_CUSTOMIZE);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE;
else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_FACTION);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_FACTION;
else if (atLoginFlags & AT_LOGIN_CHANGE_RACE)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_RACE);
- else
- *data << uint32(CHAR_CUSTOMIZE_FLAG_NONE);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_RACE;
- // First login
- *data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0);
-
- // Pets info
uint32 petDisplayId = 0;
- uint32 petLevel = 0;
- uint32 petFamily = 0;
-
+ uint32 petLevel = 0;
+ uint32 petFamily = 0;
// show pet at selection character in character list only for non-ghost character
if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (plrClass == CLASS_WARLOCK || plrClass == CLASS_HUNTER || plrClass == CLASS_DEATH_KNIGHT))
{
@@ -1995,32 +1972,48 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
if (creatureInfo)
{
petDisplayId = fields[17].GetUInt32();
- petLevel = fields[18].GetUInt16();
- petFamily = creatureInfo->family;
- }
- }
-
- *data << uint32(petDisplayId);
- *data << uint32(petLevel);
- *data << uint32(petFamily);
-
- Tokenizer equipment(fields[19].GetString(), ' ');
+ petLevel = fields[18].GetUInt16();
+ petFamily = creatureInfo->family;
+ }
+ }
+
+ // Packet content flags
+ bitBuffer->WriteBit(guid[3]);
+ bitBuffer->WriteBit(guildGuid[1]);
+ bitBuffer->WriteBit(guildGuid[7]);
+ bitBuffer->WriteBit(guildGuid[2]);
+ bitBuffer->WriteBits(uint32(name.length()), 7);
+ bitBuffer->WriteBit(guid[4]);
+ bitBuffer->WriteBit(guid[7]);
+ bitBuffer->WriteBit(guildGuid[3]);
+ bitBuffer->WriteBit(guid[5]);
+ bitBuffer->WriteBit(guildGuid[6]);
+ bitBuffer->WriteBit(guid[1]);
+ bitBuffer->WriteBit(guildGuid[5]);
+ bitBuffer->WriteBit(guildGuid[4]);
+ bitBuffer->WriteBit(atLoginFlags & AT_LOGIN_FIRST);
+ bitBuffer->WriteBit(guid[0]);
+ bitBuffer->WriteBit(guid[2]);
+ bitBuffer->WriteBit(guid[6]);
+ bitBuffer->WriteBit(guildGuid[0]);
+
+ // Character data
+ *dataBuffer << uint8(plrClass); // Class
for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot)
{
- uint32 visualBase = slot * 2;
- uint32 itemId = GetUInt32ValueFromArray(equipment, visualBase);
+ uint32 visualbase = slot * 2;
+ uint32 itemId = GetUInt32ValueFromArray(equipment, visualbase);
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (!proto)
{
- *data << uint32(0);
- *data << uint8(0);
- *data << uint32(0);
+ *dataBuffer << uint8(0);
+ *dataBuffer << uint32(0);
+ *dataBuffer << uint32(0);
continue;
}
SpellItemEnchantmentEntry const* enchant = NULL;
-
- uint32 enchants = GetUInt32ValueFromArray(equipment, visualBase + 1);
+ uint32 enchants = GetUInt32ValueFromArray(equipment, visualbase + 1);
for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot)
{
// values stored in 2 uint16
@@ -2033,11 +2026,47 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
break;
}
- *data << uint32(proto->DisplayInfoID);
- *data << uint8(proto->InventoryType);
- *data << uint32(enchant ? enchant->aura_id : 0);
- }
-
+ *dataBuffer << uint8(proto->InventoryType);
+ *dataBuffer << uint32(proto->DisplayInfoID);
+ *dataBuffer << uint32(enchant ? enchant->aura_id : 0);
+ }
+
+ *dataBuffer << uint32(petFamily); // Pet family
+ dataBuffer->WriteByteSeq(guildGuid[2]);
+ *dataBuffer << uint8(slot); // List order
+ *dataBuffer << uint8(hairStyle); // Hair style
+ dataBuffer->WriteByteSeq(guildGuid[3]);
+ *dataBuffer << uint32(petDisplayId); // Pet DisplayID
+ *dataBuffer << uint32(charFlags); // Character flags
+ *dataBuffer << uint8(hairColor); // Hair color
+ dataBuffer->WriteByteSeq(guid[4]);
+ *dataBuffer << uint32(mapId); // Map Id
+ dataBuffer->WriteByteSeq(guildGuid[5]);
+ *dataBuffer << float(z); // Z
+ dataBuffer->WriteByteSeq(guildGuid[6]);
+ *dataBuffer << uint32(petLevel); // Pet level
+ dataBuffer->WriteByteSeq(guid[3]);
+ *dataBuffer << float(y); // Y
+ *dataBuffer << uint32(customizationFlag); // Character customization flags
+ *dataBuffer << uint8(facialHair); // Facial hair
+ dataBuffer->WriteByteSeq(guid[7]);
+ *dataBuffer << uint8(gender); // Gender
+ dataBuffer->append(name.c_str(), name.length()); // Name
+ *dataBuffer << uint8(face); // Face
+ dataBuffer->WriteByteSeq(guid[0]);
+ dataBuffer->WriteByteSeq(guid[2]);
+ dataBuffer->WriteByteSeq(guildGuid[1]);
+ dataBuffer->WriteByteSeq(guildGuid[7]);
+ *dataBuffer << float(x); // X
+ *dataBuffer << uint8(skin); // Skin
+ *dataBuffer << uint8(plrRace); // Race
+ *dataBuffer << uint8(level); // Level
+ dataBuffer->WriteByteSeq(guid[6]);
+ dataBuffer->WriteByteSeq(guildGuid[4]);
+ dataBuffer->WriteByteSeq(guildGuid[0]);
+ dataBuffer->WriteByteSeq(guid[5]);
+ dataBuffer->WriteByteSeq(guid[1]);
+ *dataBuffer << uint32(zone); // Zone id
return true;
}
@@ -2071,15 +2100,6 @@ uint8 Player::GetChatTag() const
return tag;
}
-void Player::SendTeleportAckPacket()
-{
- WorldPacket data(MSG_MOVE_TELEPORT_ACK, 41);
- data.append(GetPackGUID());
- data << uint32(0); // this value increments every time
- BuildMovementPacket(&data);
- GetSession()->SendPacket(&data);
-}
-
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options)
{
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
@@ -2135,9 +2155,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (m_transport)
{
- if (options & TELE_TO_NOT_LEAVE_TRANSPORT)
- AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
- else
+ if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT))
{
m_transport->RemovePassenger(this);
m_transport = NULL;
@@ -2183,15 +2201,14 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
SetFallInformation(0, z);
// code for finish transfer called in WorldSession::HandleMovementOpcodes()
- // at client packet MSG_MOVE_TELEPORT_ACK
+ // at client packet CMSG_MOVE_TELEPORT_ACK
SetSemaphoreTeleportNear(true);
- // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing
+ // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing
if (!GetSession()->PlayerLogout())
{
Position oldPos;
GetPosition(&oldPos);
Relocate(x, y, z, orientation);
- SendTeleportAckPacket();
SendTeleportPacket(oldPos); // this automatically relocates to oldPos in order to broadcast the packet in the right place
}
}
@@ -2275,10 +2292,16 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
{
// send transfer packets
WorldPacket data(SMSG_TRANSFER_PENDING, 4 + 4 + 4);
- data << uint32(mapid);
+ data.WriteBit(0); // unknown
if (m_transport)
- data << m_transport->GetEntry() << GetMapId();
+ {
+ data.WriteBit(1); // has transport
+ data << GetMapId() << m_transport->GetEntry();
+ }
+ else
+ data.WriteBit(0); // has transport
+ data << uint32(mapid);
GetSession()->SendPacket(&data);
}
@@ -2308,11 +2331,11 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!GetSession()->PlayerLogout())
{
WorldPacket data(SMSG_NEW_WORLD, 4 + 4 + 4 + 4 + 4);
+ data << float(m_teleport_dest.GetPositionX());
+ data << float(m_teleport_dest.GetOrientation());
+ data << float(m_teleport_dest.GetPositionZ());
data << uint32(mapid);
- if (m_transport)
- data << m_movementInfo.t_pos.PositionXYZOStream();
- else
- data << m_teleport_dest.PositionXYZOStream();
+ data << float(m_teleport_dest.GetPositionY());
GetSession()->SendPacket(&data);
SendSavedInstances();
@@ -2353,18 +2376,22 @@ void Player::ProcessDelayedOperations()
{
ResurrectPlayer(0.0f, false);
- if (GetMaxHealth() > m_resurrectHealth)
- SetHealth(m_resurrectHealth);
+ if (GetMaxHealth() > _resurrectionData->Health)
+ SetHealth(_resurrectionData->Health);
else
SetFullHealth();
- if (GetMaxPower(POWER_MANA) > m_resurrectMana)
- SetPower(POWER_MANA, m_resurrectMana);
+ if (uint32(GetMaxPower(POWER_MANA)) > _resurrectionData->Mana)
+ SetPower(POWER_MANA, _resurrectionData->Mana);
else
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
+ SetPower(POWER_ECLIPSE, 0);
+
+ if (uint32 aura = _resurrectionData->Aura)
+ CastSpell(this, aura, true, NULL, NULL, _resurrectionData->GUID);
SpawnCorpseBones();
}
@@ -2463,15 +2490,40 @@ void Player::RegenerateAll()
m_regenTimerCount += m_regenTimer;
- Regenerate(POWER_ENERGY);
+ if (getClass() == CLASS_PALADIN)
+ m_holyPowerRegenTimerCount += m_regenTimer;
+
+ if (getClass() == CLASS_HUNTER)
+ m_focusRegenTimerCount += m_regenTimer;
+ Regenerate(POWER_ENERGY);
Regenerate(POWER_MANA);
// Runes act as cooldowns, and they don't need to send any data
if (getClass() == CLASS_DEATH_KNIGHT)
- for (uint8 i = 0; i < MAX_RUNES; ++i)
- if (uint32 cd = GetRuneCooldown(i))
- SetRuneCooldown(i, (cd > m_regenTimer) ? cd - m_regenTimer : 0);
+ {
+ for (uint8 i = 0; i < MAX_RUNES; i += 2)
+ {
+ uint8 runeToRegen = i;
+ uint32 cd = GetRuneCooldown(i);
+ uint32 secondRuneCd = GetRuneCooldown(i + 1);
+ // Regenerate second rune of the same type only after first rune is off the cooldown
+ if (secondRuneCd && (cd > secondRuneCd || !cd))
+ {
+ runeToRegen = i + 1;
+ cd = secondRuneCd;
+ }
+
+ if (cd)
+ SetRuneCooldown(runeToRegen, (cd > m_regenTimer) ? cd - m_regenTimer : 0);
+ }
+ }
+
+ if (m_focusRegenTimerCount >= 1000 && getClass() == CLASS_HUNTER)
+ {
+ Regenerate(POWER_FOCUS);
+ m_focusRegenTimerCount -= 1000;
+ }
if (m_regenTimerCount >= 2000)
{
@@ -2490,6 +2542,12 @@ void Player::RegenerateAll()
m_regenTimerCount -= 2000;
}
+ if (m_holyPowerRegenTimerCount >= 10000 && getClass() == CLASS_PALADIN)
+ {
+ Regenerate(POWER_HOLY_POWER);
+ m_holyPowerRegenTimerCount -= 10000;
+ }
+
m_regenTimer = 0;
}
@@ -2505,33 +2563,44 @@ void Player::Regenerate(Powers power)
if (HasAuraTypeWithValue(SPELL_AURA_PREVENT_REGENERATE_POWER, power))
return;
+ // Skip regeneration for power type we cannot have
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return;
+
float addvalue = 0.0f;
+ // Powers now benefit from haste.
+ float rangedHaste = GetFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE);
+ float meleeHaste = GetFloatValue(PLAYER_FIELD_MOD_HASTE);
+ float spellHaste = GetFloatValue(UNIT_MOD_CAST_SPEED);
+
switch (power)
{
case POWER_MANA:
{
- bool recentCast = IsUnderLastManaUseEffect();
float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
- if (getLevel() < 15)
- ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA) * (2.066f - (getLevel() * 0.066f));
-
- if (recentCast) // Trinity Updates Mana in intervals of 2s, which is correct
- addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer;
+ if (isInCombat()) // Trinity Updates Mana in intervals of 2s, which is correct
+ addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste));
else
- addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer;
- } break;
- case POWER_RAGE: // Regenerate rage
+ addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste));
+ }
+ break;
+ case POWER_RAGE: // Regenerate rage
{
if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN))
{
float RageDecreaseRate = sWorld->getRate(RATE_POWER_RAGE_LOSS);
- addvalue += -20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec)
+ addvalue += -25 * RageDecreaseRate / meleeHaste; // 2.5 rage by tick (= 2 seconds => 1.25 rage/sec)
}
- } break;
- case POWER_ENERGY: // Regenerate energy (rogue)
- addvalue += 0.01f * m_regenTimer * sWorld->getRate(RATE_POWER_ENERGY);
+ }
+ break;
+ case POWER_FOCUS:
+ addvalue += (6.0f + CalculatePct(6.0f, rangedHaste)) * sWorld->getRate(RATE_POWER_FOCUS);
+ break;
+ case POWER_ENERGY: // Regenerate energy (rogue)
+ addvalue += ((0.01f * m_regenTimer) + CalculatePct(0.01f, meleeHaste)) * sWorld->getRate(RATE_POWER_ENERGY);
break;
case POWER_RUNIC_POWER:
{
@@ -2540,10 +2609,15 @@ void Player::Regenerate(Powers power)
float RunicPowerDecreaseRate = sWorld->getRate(RATE_POWER_RUNICPOWER_LOSS);
addvalue += -30 * RunicPowerDecreaseRate; // 3 RunicPower by tick
}
- } break;
- case POWER_RUNE:
- case POWER_FOCUS:
- case POWER_HAPPINESS:
+ }
+ break;
+ case POWER_HOLY_POWER: // Regenerate holy power
+ {
+ if (!isInCombat())
+ addvalue += -1.0f; // remove 1 each 10 sec
+ }
+ break;
+ case POWER_RUNES:
break;
case POWER_HEALTH:
return;
@@ -2577,7 +2651,7 @@ void Player::Regenerate(Powers power)
else
return;
- addvalue += m_powerFraction[power];
+ addvalue += m_powerFraction[powerIndex];
uint32 integerValue = uint32(fabs(addvalue));
if (addvalue < 0.0f)
@@ -2585,12 +2659,12 @@ void Player::Regenerate(Powers power)
if (curValue > integerValue)
{
curValue -= integerValue;
- m_powerFraction[power] = addvalue + integerValue;
+ m_powerFraction[powerIndex] = addvalue + integerValue;
}
else
{
curValue = 0;
- m_powerFraction[power] = 0;
+ m_powerFraction[powerIndex] = 0;
}
}
else
@@ -2600,15 +2674,16 @@ void Player::Regenerate(Powers power)
if (curValue > maxValue)
{
curValue = maxValue;
- m_powerFraction[power] = 0;
+ m_powerFraction[powerIndex] = 0;
}
else
- m_powerFraction[power] = addvalue - integerValue;
+ m_powerFraction[powerIndex] = addvalue - integerValue;
}
+
if (m_regenTimerCount >= 2000)
SetPower(power, curValue);
else
- UpdateUInt32Value(UNIT_FIELD_POWER1 + power, curValue);
+ UpdateUInt32Value(UNIT_FIELD_POWER1 + powerIndex, curValue);
}
void Player::RegenerateHealth()
@@ -2620,10 +2695,6 @@ void Player::RegenerateHealth()
return;
float HealthIncreaseRate = sWorld->getRate(RATE_HEALTH);
-
- if (getLevel() < 15)
- HealthIncreaseRate = sWorld->getRate(RATE_HEALTH) * (2.066f - (getLevel() * 0.066f));
-
float addvalue = 0.0f;
// polymorphed case
@@ -2632,9 +2703,14 @@ void Player::RegenerateHealth()
// normal regen case (maybe partly in combat case)
else if (!isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT))
{
- addvalue = OCTRegenHPPerSpirit() * HealthIncreaseRate;
+ addvalue = HealthIncreaseRate;
if (!isInCombat())
{
+ if (getLevel() < 15)
+ addvalue = (0.20f*((float)GetMaxHealth())/getLevel()*HealthIncreaseRate);
+ else
+ addvalue = 0.015f*((float)GetMaxHealth())*HealthIncreaseRate;
+
AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i)
AddPct(addvalue, (*i)->GetAmount());
@@ -2675,6 +2751,9 @@ void Player::ResetAllPowers()
case POWER_RUNIC_POWER:
SetPower(POWER_RUNIC_POWER, 0);
break;
+ case POWER_ECLIPSE:
+ SetPower(POWER_ECLIPSE, 0);
+ break;
default:
break;
}
@@ -2832,18 +2911,6 @@ void Player::SetGameMaster(bool on)
}
else
{
- // restore phase
- uint32 newPhase = 0;
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
-
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
-
- SetPhaseMask(newPhase, false);
-
m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON;
setFactionForRace(getRace());
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
@@ -2864,6 +2931,9 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(true);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
+
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ phaseMgr.Update();
}
UpdateObjectVisibility();
@@ -3034,23 +3104,21 @@ void Player::GiveLevel(uint8 level)
PlayerLevelInfo info;
sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), level, &info);
- PlayerClassLevelInfo classInfo;
- sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, &classInfo);
+ uint32 basehp = 0, basemana = 0;
+ sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, basehp, basemana);
// send levelup info to client
- WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS*4+MAX_STATS*4));
+ WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS_PER_CLASS*4+MAX_STATS*4));
data << uint32(level);
- data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth()));
- // for (int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-6)
- data << uint32(int32(classInfo.basemana) - int32(GetCreateMana()));
- data << uint32(0);
- data << uint32(0);
+ data << uint32(int32(basehp) - int32(GetCreateHealth()));
+ // for (int i = 0; i < MAX_STORED_POWERS; ++i) // Powers loop (0-10)
+ data << uint32(int32(basemana) - int32(GetCreateMana()));
data << uint32(0);
data << uint32(0);
data << uint32(0);
data << uint32(0);
// end for
- for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
+ for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i)));
GetSession()->SendPacket(&data);
@@ -3070,8 +3138,8 @@ void Player::GiveLevel(uint8 level)
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
SetCreateStat(Stats(i), info.stats[i]);
- SetCreateHealth(classInfo.basehealth);
- SetCreateMana(classInfo.basemana);
+ SetCreateHealth(basehp);
+ SetCreateMana(basemana);
InitTalentForLevel();
InitTaxiNodesForLevel();
@@ -3082,6 +3150,8 @@ void Player::GiveLevel(uint8 level)
if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL)) // Max weapon skill when leveling up
UpdateSkillsToMaxSkillsForLevel();
+ _ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms
+
// set current level health and mana/energy to maximum after applying all mods.
SetFullHealth();
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
@@ -3089,9 +3159,6 @@ void Player::GiveLevel(uint8 level)
if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE))
SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE));
SetPower(POWER_FOCUS, 0);
- SetPower(POWER_HAPPINESS, 0);
-
- _ApplyAllLevelScaleItemMods(true);
// update level to hunter/summon pet
if (Pet* pet = GetPet())
@@ -3107,6 +3174,11 @@ void Player::GiveLevel(uint8 level)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddConditionType(CONDITION_LEVEL);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
// Refer-A-Friend
if (GetSession()->GetRecruiterId())
if (level < sWorld->getIntConfig(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL))
@@ -3128,33 +3200,33 @@ void Player::InitTalentForLevel()
if (level < 10)
{
// Remove all talent points
- if (m_usedTalentCount > 0) // Free any used talents
+ if (GetUsedTalentCount() > 0) // Free any used talents
{
- resetTalents(true); /// @todo: Has to (collectively) be renamed to ResetTalents
+ ResetTalents(true);
SetFreeTalentPoints(0);
}
}
else
{
- if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || m_specsCount == 0)
+ if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetSpecsCount() == 0)
{
- m_specsCount = 1;
- m_activeSpec = 0;
+ SetSpecsCount(1);
+ SetActiveSpec(0);
}
uint32 talentPointsForLevel = CalculateTalentsPoints();
// if used more that have then reset
- if (m_usedTalentCount > talentPointsForLevel)
+ if (GetUsedTalentCount() > talentPointsForLevel)
{
if (!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED))
- resetTalents(true);
+ ResetTalents(true);
else
SetFreeTalentPoints(0);
}
// else update amount of free points
else
- SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
+ SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount());
}
if (!GetSession()->PlayerLoading())
@@ -3166,8 +3238,8 @@ void Player::InitStatsForLevel(bool reapplyMods)
if (reapplyMods) //reapply stats values only on .reset stats (level) command
_RemoveAllStatBonuses();
- PlayerClassLevelInfo classInfo;
- sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo);
+ uint32 basehp = 0, basemana = 0;
+ sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana);
PlayerLevelInfo info;
sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info);
@@ -3182,6 +3254,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
// set default cast time multiplier
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_HASTE, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, 1.0f);
// reset size before reapply auras
SetObjectScale(1.0f);
@@ -3193,10 +3268,10 @@ void Player::InitStatsForLevel(bool reapplyMods)
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
SetStat(Stats(i), info.stats[i]);
- SetCreateHealth(classInfo.basehealth);
+ SetCreateHealth(basehp);
//set create powers
- SetCreateMana(classInfo.basemana);
+ SetCreateMana(basemana);
SetArmor(int32(m_createStats[STAT_AGILITY]*2));
@@ -3207,13 +3282,17 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(index, 0);
SetUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, 0);
+ SetFloatValue(PLAYER_FIELD_MOD_HEALING_PCT, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_HEALING_DONE_PCT, 1.0f);
for (uint8 i = 0; i < 7; ++i)
{
SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, 0);
SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, 0);
- SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.00f);
+ SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.0f);
}
+ SetFloatValue(PLAYER_FIELD_MOD_SPELL_POWER_PCT, 1.0f);
+
//reset attack power, damage and attack speed fields
SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f);
SetFloatValue(UNIT_FIELD_BASEATTACKTIME + 1, 2000.0f); // offhand attack time
@@ -3225,12 +3304,11 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, 0.0f);
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f);
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f);
+ SetFloatValue(PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS, 1.0f);
SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0);
- SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0);
SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, 0.0f);
SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0);
- SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS, 0);
SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER, 0.0f);
// Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
@@ -3244,7 +3322,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetFloatValue(PLAYER_PARRY_PERCENTAGE, 0.0f);
SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 0.0f);
- SetUInt32Value(PLAYER_SHIELD_BLOCK, 0);
+
+ // Static 30% damage blocked
+ SetUInt32Value(PLAYER_SHIELD_BLOCK, 30);
// Dodge percentage
SetFloatValue(PLAYER_DODGE_PERCENTAGE, 0.0f);
@@ -3276,9 +3356,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
// save new stats
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
- SetMaxPower(Powers(i), uint32(GetCreatePowers(Powers(i))));
+ SetMaxPower(Powers(i), GetCreatePowers(Powers(i)));
- SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later
+ SetMaxHealth(basehp); // stamina bonus will applied later
// cleanup mounted state (it will set correctly at aura loading if player saved at mount.
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
@@ -3313,8 +3393,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE))
SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE));
- SetPower(POWER_FOCUS, 0);
- SetPower(POWER_HAPPINESS, 0);
+ SetPower(POWER_FOCUS, GetMaxPower(POWER_FOCUS));
SetPower(POWER_RUNIC_POWER, 0);
// update level to hunter/summon pet
@@ -3346,7 +3425,7 @@ void Player::SendInitialSpells()
data << uint32(itr->first);
data << uint16(0); // it's not slot id
- spellCount +=1;
+ ++spellCount;
}
data.put<uint16>(countPos, spellCount); // write real count value
@@ -3361,7 +3440,7 @@ void Player::SendInitialSpells()
data << uint32(itr->first);
- data << uint16(itr->second.itemid); // cast item id
+ data << uint32(itr->second.itemid); // cast item id
data << uint16(sEntry->Category); // spell category
// send infinity cooldown in special format
@@ -3407,15 +3486,15 @@ void Player::RemoveMail(uint32 id)
void Player::SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError, uint32 item_guid, uint32 item_count)
{
WorldPacket data(SMSG_SEND_MAIL_RESULT, (4+4+4+(mailError == MAIL_ERR_EQUIP_ERROR?4:(mailAction == MAIL_ITEM_TAKEN?4+4:0))));
- data << (uint32) mailId;
- data << (uint32) mailAction;
- data << (uint32) mailError;
+ data << uint32(mailId);
+ data << uint32(mailAction);
+ data << uint32(mailError);
if (mailError == MAIL_ERR_EQUIP_ERROR)
- data << (uint32) equipError;
+ data << uint32(equipError);
else if (mailAction == MAIL_ITEM_TAKEN)
{
- data << (uint32) item_guid; // item guid low?
- data << (uint32) item_count; // item count?
+ data << uint32(item_guid); // item guid low?
+ data << uint32(item_count); // item count?
}
GetSession()->SendPacket(&data);
}
@@ -3507,8 +3586,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
return false;
}
- PlayerTalentMap::iterator itr = m_talents[spec]->find(spellId);
- if (itr != m_talents[spec]->end())
+ PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_UNCHANGED;
else if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId))
{
@@ -3521,8 +3600,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
if (!rankSpellId || rankSpellId == spellId)
continue;
- itr = m_talents[spec]->find(rankSpellId);
- if (itr != m_talents[spec]->end())
+ itr = GetTalentMap(spec)->find(rankSpellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -3533,7 +3612,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
newtalent->state = state;
newtalent->spec = spec;
- (*m_talents[spec])[spellId] = newtalent;
+ (*GetTalentMap(spec))[spellId] = newtalent;
return true;
}
return false;
@@ -3802,7 +3881,7 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent
}
// update used talent points count
- m_usedTalentCount += talentCost;
+ SetUsedTalentCount(GetUsedTalentCount() + talentCost);
// update free primary prof.points (if any, can be none in case GM .learn prof. learning)
if (uint32 freeProfs = GetFreePrimaryProfessionPoints())
@@ -3842,12 +3921,6 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent
if (!pSkill)
continue;
- if (!Has310Flyer(false) && pSkill->id == SKILL_MOUNTS)
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- SetHas310Flyer(true);
-
if (HasSkill(pSkill->id))
continue;
@@ -3938,10 +4011,21 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (1 << (form - 1)))) ||
(!form && (spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
+ if (spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION)
+ need_cast &= IsCurrentSpecMasterySpell(spellInfo);
+
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
}
+bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const
+{
+ if (TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ return spellInfo->Id == talentTab->MasterySpellId[0] || spellInfo->Id == talentTab->MasterySpellId[1];
+
+ return false;
+}
+
void Player::learnSpell(uint32 spell_id, bool dependent)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
@@ -3954,9 +4038,9 @@ void Player::learnSpell(uint32 spell_id, bool dependent)
// prevent duplicated entires in spell book, also not send if not in world (loading)
if (learning && IsInWorld())
{
- WorldPacket data(SMSG_LEARNED_SPELL, 6);
+ WorldPacket data(SMSG_LEARNED_SPELL, 8);
data << uint32(spell_id);
- data << uint16(0);
+ data << uint32(0);
GetSession()->SendPacket(&data);
}
@@ -4038,10 +4122,10 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
uint32 talentCosts = GetTalentSpellCost(spell_id);
if (talentCosts > 0 && giveTalentPoints)
{
- if (talentCosts < m_usedTalentCount)
- m_usedTalentCount -= talentCosts;
+ if (talentCosts < GetUsedTalentCount())
+ SetUsedTalentCount(GetUsedTalentCount() - talentCosts);
else
- m_usedTalentCount = 0;
+ SetUsedTalentCount(0);
}
// update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning)
@@ -4112,16 +4196,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0);
}
-
- // most likely will never be used, haven't heard of cases where players unlearn a mount
- if (Has310Flyer(false) && _spell_idx->second->skillId == SKILL_MOUNTS)
- {
- if (spellInfo)
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- Has310Flyer(true, spell_id); // with true as first argument its also used to set/remove the flag
- }
}
}
@@ -4177,8 +4251,19 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
if (spell_id == 46917 && m_canTitanGrip)
SetCanTitanGrip(false);
- if (spell_id == 674 && m_canDualWield)
- SetCanDualWield(false);
+ if (m_canDualWield)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ if (spellInfo->IsPassive())
+ {
+ for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
+ if (spellInfo->Effects[i].Effect == SPELL_EFFECT_DUAL_WIELD)
+ {
+ SetCanDualWield(false);
+ break;
+ }
+ }
+ }
if (sWorld->getBoolConfig(CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN))
AutoUnequipOffhandIfNeed();
@@ -4192,40 +4277,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
}
}
-bool Player::Has310Flyer(bool checkAllSpells, uint32 excludeSpellId)
-{
- if (!checkAllSpells)
- return m_ExtraFlags & PLAYER_EXTRA_HAS_310_FLYER;
- else
- {
- SetHas310Flyer(false);
- SpellInfo const* spellInfo;
- for (PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
- {
- if (itr->first == excludeSpellId)
- continue;
-
- SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(itr->first);
- for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
- {
- if (_spell_idx->second->skillId != SKILL_MOUNTS)
- break; // We can break because mount spells belong only to one skillline (at least 310 flyers do)
-
- spellInfo = sSpellMgr->GetSpellInfo(itr->first);
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- {
- SetHas310Flyer(true);
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
void Player::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */)
{
m_spellCooldowns.erase(spell_id);
@@ -4296,9 +4347,7 @@ void Player::RemoveAllSpellCooldown()
{
if (!m_spellCooldowns.empty())
{
- for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr)
- SendClearCooldown(itr->first, this);
-
+ SendClearAllCooldowns(this);
m_spellCooldowns.clear();
}
}
@@ -4376,31 +4425,31 @@ void Player::_SaveSpellCooldowns(SQLTransaction& trans)
trans->Append(ss.str().c_str());
}
-uint32 Player::resetTalentsCost() const
+uint32 Player::GetNextResetTalentsCost() const
{
// The first time reset costs 1 gold
- if (m_resetTalentsCost < 1*GOLD)
+ if (GetTalentResetCost() < 1*GOLD)
return 1*GOLD;
// then 5 gold
- else if (m_resetTalentsCost < 5*GOLD)
+ else if (GetTalentResetCost() < 5*GOLD)
return 5*GOLD;
// After that it increases in increments of 5 gold
- else if (m_resetTalentsCost < 10*GOLD)
+ else if (GetTalentResetCost() < 10*GOLD)
return 10*GOLD;
else
{
- uint64 months = (sWorld->GetGameTime() - m_resetTalentsTime)/MONTH;
+ uint64 months = (sWorld->GetGameTime() - GetTalentResetTime())/MONTH;
if (months > 0)
{
// This cost will be reduced by a rate of 5 gold per month
- int32 new_cost = int32(m_resetTalentsCost - 5*GOLD*months);
+ int32 new_cost = int32(GetTalentResetCost() - 5*GOLD*months);
// to a minimum of 10 gold.
return (new_cost < 10*GOLD ? 10*GOLD : new_cost);
}
else
{
// After that it increases in increments of 5 gold
- int32 new_cost = m_resetTalentsCost + 5*GOLD;
+ int32 new_cost = GetTalentResetCost() + 5*GOLD;
// until it hits a cap of 50 gold.
if (new_cost > 50*GOLD)
new_cost = 50*GOLD;
@@ -4409,7 +4458,7 @@ uint32 Player::resetTalentsCost() const
}
}
-bool Player::resetTalents(bool no_cost)
+bool Player::ResetTalents(bool no_cost)
{
sScriptMgr->OnPlayerTalentsReset(this, no_cost);
@@ -4419,7 +4468,7 @@ bool Player::resetTalents(bool no_cost)
uint32 talentPointsForLevel = CalculateTalentsPoints();
- if (m_usedTalentCount == 0)
+ if (!GetUsedTalentCount())
{
SetFreeTalentPoints(talentPointsForLevel);
return false;
@@ -4429,9 +4478,9 @@ bool Player::resetTalents(bool no_cost)
if (!no_cost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST))
{
- cost = resetTalentsCost();
+ cost = GetNextResetTalentsCost();
- if (!HasEnoughMoney(cost))
+ if (!HasEnoughMoney(uint64(cost)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
return false;
@@ -4472,27 +4521,43 @@ bool Player::resetTalents(bool no_cost)
if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL)
removeSpell(_spellEntry->Effects[i].TriggerSpell, true);
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
- PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->RankID[rank]);
- if (plrTalent != m_talents[m_activeSpec]->end())
+ PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->RankID[rank]);
+ if (plrTalent != GetTalentMap(GetActiveSpec())->end())
plrTalent->second->state = PLAYERSPELL_REMOVED;
}
}
+ // Remove spec specific spells
+ uint32 const* talentTabs = GetTalentTabPages(getClass());
+ for (uint32 i = 0; i < MAX_TALENT_TABS; ++i)
+ {
+ if (std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i]))
+ for (size_t j = 0; j < specSpells->size(); ++j)
+ removeSpell(specSpells->at(j), true);
+
+ TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]);
+ for (uint32 j = 0; j < MAX_MASTERY_SPELLS; ++j)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[j])
+ RemoveAurasDueToSpell(mastery);
+ }
+
+
+ SetPrimaryTalentTree(GetActiveSpec(), 0);
+ SetFreeTalentPoints(talentPointsForLevel);
+
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_SaveTalents(trans);
_SaveSpells(trans);
CharacterDatabase.CommitTransaction(trans);
- SetFreeTalentPoints(talentPointsForLevel);
-
if (!no_cost)
{
- ModifyMoney(-(int32)cost);
+ ModifyMoney(-(int64)cost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1);
- m_resetTalentsCost = cost;
- m_resetTalentsTime = time(NULL);
+ SetTalentResetCost(cost);
+ SetTalentResetTime(time(NULL));
}
/* when prev line will dropped use next line
@@ -4506,12 +4571,6 @@ bool Player::resetTalents(bool no_cost)
return true;
}
-void Player::SetFreeTalentPoints(uint32 points)
-{
- sScriptMgr->OnPlayerFreeTalentPointsChanged(this, points);
- SetUInt32Value(PLAYER_CHARACTER_POINTS1, points);
-}
-
Mail* Player::GetMail(uint32 id)
{
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -4540,13 +4599,6 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (m_items[i] == NULL)
- continue;
-
- m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
- }
}
Unit::BuildCreateUpdateBlockForPlayer(data, target);
@@ -4573,13 +4625,6 @@ void Player::DestroyForPlayer(Player* target, bool onDeath) const
m_items[i]->DestroyForPlayer(target);
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (m_items[i] == NULL)
- continue;
-
- m_items[i]->DestroyForPlayer(target);
- }
}
}
@@ -4592,8 +4637,8 @@ bool Player::HasSpell(uint32 spell) const
bool Player::HasTalent(uint32 spell, uint8 spec) const
{
- PlayerTalentMap::const_iterator itr = m_talents[spec]->find(spell);
- return (itr != m_talents[spec]->end() && itr->second->state != PLAYERSPELL_REMOVED);
+ PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell);
+ return (itr != GetTalentMap(spec)->end() && itr->second->state != PLAYERSPELL_REMOVED);
}
bool Player::HasActiveSpell(uint32 spell) const
@@ -4752,7 +4797,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
uint32 sender = mailFields[3].GetUInt32();
std::string subject = mailFields[4].GetString();
std::string body = mailFields[5].GetString();
- uint32 money = mailFields[6].GetUInt32();
+ uint64 money = mailFields[6].GetUInt64();
bool has_items = mailFields[7].GetBool();
// We can return mail now
@@ -5054,24 +5099,6 @@ void Player::DeleteOldCharacters(uint32 keepDays)
}
}
-void Player::SetMovement(PlayerMovementType pType)
-{
- WorldPacket data;
- switch (pType)
- {
- case MOVE_ROOT: data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size()+4); break;
- case MOVE_UNROOT: data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size()+4); break;
- case MOVE_WATER_WALK: data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size()+4); break;
- case MOVE_LAND_WALK: data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size()+4); break;
- default:
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::SetMovement: Unsupported move type (%d), data not sent to client.", pType);
- return;
- }
- data.append(GetPackGUID());
- data << uint32(0);
- GetSession()->SendPacket(&data);
-}
-
/* Preconditions:
- a resurrectable corpse must not be loaded for the player (only bones)
- the player must be in world
@@ -5110,9 +5137,10 @@ void Player::BuildPlayerRepop()
// convert player body to ghost
SetHealth(1);
- SetMovement(MOVE_WATER_WALK);
+ AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ SendMovementWaterWalking();
if (!GetSession()->isLogingOut())
- SetMovement(MOVE_UNROOT);
+ SetRooted(false);
// BG - remove insignia related
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
@@ -5150,8 +5178,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
setDeathState(ALIVE);
- SetMovement(MOVE_LAND_WALK);
- SetMovement(MOVE_UNROOT);
+ RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ SendMovementWaterWalking();
+ SetRooted(false);
m_deathTimer = 0;
@@ -5162,6 +5191,8 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
SetPower(POWER_MANA, uint32(GetMaxPower(POWER_MANA)*restore_percent));
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent));
+ SetPower(POWER_FOCUS, uint32(GetMaxPower(POWER_FOCUS)*restore_percent));
+ SetPower(POWER_ECLIPSE, 0);
}
// trigger update zone for alive state zone updates
@@ -5211,7 +5242,7 @@ void Player::KillPlayer()
if (IsFlying() && !GetTransport())
i_motionMaster.MoveFall();
- SetMovement(MOVE_ROOT);
+ SetRooted(true);
StopMirrorTimers(); //disable timers(bars)
@@ -5273,12 +5304,10 @@ void Player::CreateCorpse()
flags |= CORPSE_FLAG_HIDE_CLOAK;
if (InBattleground() && !InArena())
flags |= CORPSE_FLAG_LOOTABLE; // to be able to remove insignia
- corpse->SetUInt32Value(CORPSE_FIELD_FLAGS, flags);
+ corpse->SetUInt32Value(CORPSE_FIELD_FLAGS, flags);
corpse->SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId());
- corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId());
-
uint32 iDisplayID;
uint32 iIventoryType;
uint32 _cfi;
@@ -5329,9 +5358,6 @@ void Player::DurabilityLossAll(double percent, bool inventory)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
DurabilityLoss(pItem, percent);
- // keys not have durability
- //for (int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -5350,6 +5376,8 @@ void Player::DurabilityLoss(Item* item, double percent)
if (!pMaxDurability)
return;
+ percent /= GetTotalAuraMultiplier(SPELL_AURA_MOD_DURABILITY_LOSS);
+
uint32 pDurabilityLoss = uint32(pMaxDurability*percent);
if (pDurabilityLoss < 1)
@@ -5373,9 +5401,6 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
DurabilityPointsLoss(pItem, points);
- // keys not have durability
- //for (int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -5494,13 +5519,13 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g
TotalCost = costs;
}
- else if (!HasEnoughMoney(costs))
+ else if (!HasEnoughMoney(uint64(costs)))
{
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "You do not have enough money");
return TotalCost;
}
else
- ModifyMoney(-int32(costs));
+ ModifyMoney(-int64(costs));
}
}
@@ -5521,7 +5546,7 @@ void Player::RepopAtGraveyard()
AreaTableEntry const* zone = GetAreaEntryByAreaID(GetAreaId());
// Such zones are considered unreachable as a ghost and the player must be automatically revived
- if ((!isAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < -500.0f)
+ if ((!isAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < (zone ? zone->MaxDepth : -500.0f))
{
ResurrectPlayer(0.5f);
SpawnCorpseBones();
@@ -5547,7 +5572,8 @@ void Player::RepopAtGraveyard()
// and don't show spirit healer location
if (ClosestGrave)
{
- TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, GetOrientation());
+ float const* orientation = sObjectMgr->GetGraveyardOrientation(ClosestGrave->ID);
+ TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, orientation ? *orientation : GetOrientation());
if (isDead()) // not send if alive, because it used in TeleportTo()
{
WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4*4); // show spirit healer position on minimap
@@ -5558,7 +5584,7 @@ void Player::RepopAtGraveyard()
GetSession()->SendPacket(&data);
}
}
- else if (GetPositionZ() < -500.0f)
+ else if (GetPositionZ() < zone->MaxDepth)
TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
}
@@ -5612,7 +5638,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
if (!cMgr)
return;
- std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()];
+ std::string current_zone_name = current_zone->area_name;
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
{
@@ -5648,7 +5674,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
else
currentNameExt = current_zone_name.c_str();
- snprintf(new_channel_name_buf, 100, channel->pattern[m_session->GetSessionDbcLocale()], currentNameExt);
+ snprintf(new_channel_name_buf, 100, channel->pattern, currentNameExt);
joinChannel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID);
if (usedChannel)
@@ -5663,7 +5689,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
}
}
else
- joinChannel = cMgr->GetJoinChannel(channel->pattern[m_session->GetSessionDbcLocale()], channel->ChannelID);
+ joinChannel = cMgr->GetJoinChannel(channel->pattern, channel->ChannelID);
}
else
removeChannel = usedChannel;
@@ -5694,12 +5720,6 @@ void Player::LeaveLFGChannel()
}
}
-void Player::UpdateDefense()
-{
- if (UpdateSkill(SKILL_DEFENSE, sWorld->getIntConfig(CONFIG_SKILL_GAIN_DEFENSE)))
- UpdateDefenseBonusesMod(); // update dependent from defense skill part
-}
-
void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
{
if (modGroup >= BASEMOD_END || modType >= MOD_END)
@@ -5726,7 +5746,6 @@ void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, floa
case CRIT_PERCENTAGE: UpdateCritPercentage(BASE_ATTACK); break;
case RANGED_CRIT_PERCENTAGE: UpdateCritPercentage(RANGED_ATTACK); break;
case OFFHAND_CRIT_PERCENTAGE: UpdateCritPercentage(OFF_ATTACK); break;
- case SHIELD_BLOCK_VALUE: UpdateShieldBlockValue(); break;
default: break;
}
}
@@ -5759,15 +5778,6 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD];
}
-uint32 Player::GetShieldBlockValue() const
-{
- float value = (m_auraBaseMod[SHIELD_BLOCK_VALUE][FLAT_MOD] + GetStat(STAT_STRENGTH) * 0.5f - 10)*m_auraBaseMod[SHIELD_BLOCK_VALUE][PCT_MOD];
-
- value = (value < 0) ? 0 : value;
-
- return uint32(value);
-}
-
float Player::GetMeleeCritFromAgility()
{
uint8 level = getLevel();
@@ -5790,17 +5800,17 @@ void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing)
// Table for base dodge values
const float dodge_base[MAX_CLASSES] =
{
- 0.036640f, // Warrior
- 0.034943f, // Paladin
- -0.040873f, // Hunter
- 0.020957f, // Rogue
- 0.034178f, // Priest
+ 0.037580f, // Warrior
+ 0.036520f, // Paladin
+ -0.054500f, // Hunter
+ -0.005900f, // Rogue
+ 0.031830f, // Priest
0.036640f, // DK
- 0.021080f, // Shaman
- 0.036587f, // Mage
- 0.024211f, // Warlock
+ 0.016750f, // Shaman
+ 0.034575f, // Mage
+ 0.020350f, // Warlock
0.0f, // ??
- 0.056097f // Druid
+ 0.049510f // Druid
};
// Crit/agility to dodge/agility coefficient multipliers; 3.2.0 increased required agility by 15%
const float crit_to_dodge[MAX_CLASSES] =
@@ -5846,13 +5856,13 @@ float Player::GetSpellCritFromIntellect()
if (level > GT_MAX_LEVEL)
level = GT_MAX_LEVEL;
- GtChanceToSpellCritBaseEntry const* critBase = sGtChanceToSpellCritBaseStore.LookupEntry(pclass-1);
- GtChanceToSpellCritEntry const* critRatio = sGtChanceToSpellCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
+ GtChanceToSpellCritBaseEntry const* critBase = sGtChanceToSpellCritBaseStore.LookupEntry(pclass - 1);
+ GtChanceToSpellCritEntry const* critRatio = sGtChanceToSpellCritStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1);
if (critBase == NULL || critRatio == NULL)
return 0.0f;
- float crit=critBase->base + GetStat(STAT_INTELLECT)*critRatio->ratio;
- return crit*100.0f;
+ float crit = critBase->base + GetStat(STAT_INTELLECT) * critRatio->ratio;
+ return crit * 100.0f;
}
float Player::GetRatingMultiplier(CombatRating cr) const
@@ -5873,7 +5883,10 @@ float Player::GetRatingMultiplier(CombatRating cr) const
float Player::GetRatingBonusValue(CombatRating cr) const
{
- return float(GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr)) * GetRatingMultiplier(cr);
+ float baseResult = float(GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr)) * GetRatingMultiplier(cr);
+ if (cr != CR_RESILIENCE_PLAYER_DAMAGE_TAKEN)
+ return baseResult;
+ return float(1.0f - pow(0.99f, baseResult)) * 100.0f;
}
float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
@@ -5890,29 +5903,6 @@ float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
return 0.0f;
}
-float Player::OCTRegenHPPerSpirit()
-{
- uint8 level = getLevel();
- uint32 pclass = getClass();
-
- if (level > GT_MAX_LEVEL)
- level = GT_MAX_LEVEL;
-
- GtOCTRegenHPEntry const* baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
- GtRegenHPPerSptEntry const* moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
- if (baseRatio == NULL || moreRatio == NULL)
- return 0.0f;
-
- // Formula from PaperDollFrame script
- float spirit = GetStat(STAT_SPIRIT);
- float baseSpirit = spirit;
- if (baseSpirit > 50)
- baseSpirit = 50;
- float moreSpirit = spirit - baseSpirit;
- float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio;
- return regen;
-}
-
float Player::OCTRegenMPPerSpirit()
{
uint8 level = getLevel();
@@ -5934,7 +5924,7 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
- m_baseRatingValue[cr]+=(apply ? value : -value);
+ m_baseRatingValue[cr] +=(apply ? value : -value);
// explicit affected values
switch (cr)
@@ -5944,18 +5934,18 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
float RatingChange = value * GetRatingMultiplier(cr);
ApplyAttackTimePercentMod(BASE_ATTACK, RatingChange, apply);
ApplyAttackTimePercentMod(OFF_ATTACK, RatingChange, apply);
+ if (getClass() == CLASS_DEATH_KNIGHT)
+ UpdateAllRunesRegen();
break;
}
case CR_HASTE_RANGED:
{
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyAttackTimePercentMod(RANGED_ATTACK, RatingChange, apply);
+ ApplyAttackTimePercentMod(RANGED_ATTACK, value * GetRatingMultiplier(cr), apply);
break;
}
case CR_HASTE_SPELL:
{
- float RatingChange = value * GetRatingMultiplier(cr);
- ApplyCastTimePercentMod(RatingChange, apply);
+ ApplyCastTimePercentMod(value * GetRatingMultiplier(cr), apply);
break;
}
default:
@@ -5982,9 +5972,8 @@ void Player::UpdateRating(CombatRating cr)
switch (cr)
{
- case CR_WEAPON_SKILL: // Implemented in Unit::RollMeleeOutcomeAgainst
+ case CR_WEAPON_SKILL:
case CR_DEFENSE_SKILL:
- UpdateDefenseBonusesMod();
break;
case CR_DODGE:
UpdateDodgePercentage();
@@ -6019,15 +6008,12 @@ void Player::UpdateRating(CombatRating cr)
if (affectStats)
UpdateAllSpellCritChances();
break;
- case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc
- case CR_HIT_TAKEN_RANGED:
- break;
- case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult
- break;
- case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit)
- case CR_CRIT_TAKEN_RANGED:
- break;
- case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit)
+ case CR_HIT_TAKEN_MELEE: // Deprecated since Cataclysm
+ case CR_HIT_TAKEN_RANGED: // Deprecated since Cataclysm
+ case CR_HIT_TAKEN_SPELL: // Deprecated since Cataclysm
+ case CR_RESILIENCE_PLAYER_DAMAGE_TAKEN:
+ case CR_RESILIENCE_CRIT_TAKEN:
+ case CR_CRIT_TAKEN_SPELL: // Deprecated since Cataclysm
break;
case CR_HASTE_MELEE: // Implemented in Player::ApplyRatingMod
case CR_HASTE_RANGED:
@@ -6048,6 +6034,9 @@ void Player::UpdateRating(CombatRating cr)
if (affectStats)
UpdateArmorPenetration(amount);
break;
+ case CR_MASTERY:
+ UpdateMastery();
+ break;
}
}
@@ -6086,23 +6075,25 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 value = SKILL_VALUE(data);
- uint32 max = SKILL_MAX(data);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
- if ((!max) || (!value) || (value >= max))
+ if (!max || !value || value >= max)
return false;
if (value < max)
{
- uint32 new_value = value+step;
+ uint16 new_value = value + step;
if (new_value > max)
new_value = max;
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value);
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
+
UpdateSkillEnchantments(skill_id, value, new_value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id);
return true;
@@ -6195,129 +6186,65 @@ bool Player::UpdateFishingSkill()
return UpdateSkillPro(SKILL_FISHING, chance*10, gathering_skill_gain);
}
-// levels sync. with spell requirement for skill levels to learn
-// bonus abilities in sSkillLineAbilityStore
-// Used only to avoid scan DBC at each skill grow
-static uint32 bonusSkillLevels[] = {75, 150, 225, 300, 375, 450};
-static const size_t bonusSkillLevelsSize = sizeof(bonusSkillLevels) / sizeof(uint32);
-
-bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
+bool Player::UpdateSkillPro(uint16 skillId, int32 chance, uint32 step)
{
- TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance / 10.0f);
- if (!SkillId)
+ // levels sync. with spell requirement for skill levels to learn
+ // bonus abilities in sSkillLineAbilityStore
+ // Used only to avoid scan DBC at each skill grow
+ static uint32 bonusSkillLevels[] = { 75, 150, 225, 300, 375, 450, 525 };
+ static const size_t bonusSkillLevelsSize = sizeof(bonusSkillLevels) / sizeof(uint32);
+
+ TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "UpdateSkillPro(SkillId %d, Chance %3.1f%%)", skillId, chance / 10.0f);
+ if (!skillId)
return false;
- if (Chance <= 0) // speedup in 0 chance case
+ if (chance <= 0) // speedup in 0 chance case
{
- TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% missed", Chance / 10.0f);
+ TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% missed", chance / 10.0f);
return false;
}
- SkillStatusMap::iterator itr = mSkillStatus.find(SkillId);
+ SkillStatusMap::iterator itr = mSkillStatus.find(skillId);
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
- uint32 data = GetUInt32Value(valueIndex);
- uint16 SkillValue = SKILL_VALUE(data);
- uint16 MaxValue = SKILL_MAX(data);
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
- if (!MaxValue || !SkillValue || SkillValue >= MaxValue)
+ if (!max || !value || value >= max)
return false;
- int32 Roll = irand(1, 1000);
-
- if (Roll <= Chance)
+ if (irand(1, 1000) > chance)
{
- uint32 new_value = SkillValue+step;
- if (new_value > MaxValue)
- new_value = MaxValue;
-
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- for (size_t i = 0; i < bonusSkillLevelsSize; ++i)
- {
- uint32 bsl = bonusSkillLevels[i];
- if (SkillValue < bsl && new_value >= bsl)
- {
- learnSkillRewardedSpells(SkillId, new_value);
- break;
- }
- }
- UpdateSkillEnchantments(SkillId, SkillValue, new_value);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, SkillId);
- TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% taken", Chance / 10.0f);
- return true;
+ TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% missed", chance / 10.0f);
+ return false;
}
- TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% missed", Chance / 10.0f);
- return false;
-}
-
-void Player::UpdateWeaponSkill(WeaponAttackType attType)
-{
- // no skill gain in pvp
- Unit* victim = getVictim();
- if (victim && victim->GetTypeId() == TYPEID_PLAYER)
- return;
-
- if (IsInFeralForm())
- return; // always maximized SKILL_FERAL_COMBAT in fact
-
- if (GetShapeshiftForm() == FORM_TREE)
- return; // use weapon but not skill up
-
- if (victim && victim->GetTypeId() == TYPEID_UNIT && (victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_SKILLGAIN))
- return;
-
- uint32 weapon_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_WEAPON);
-
- Item* tmpitem = GetWeaponForAttack(attType, true);
- if (!tmpitem && attType == BASE_ATTACK)
- UpdateSkill(SKILL_UNARMED, weapon_skill_gain);
- else if (tmpitem && tmpitem->GetTemplate()->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
- UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain);
-
- UpdateAllCritPercentages();
-}
-
-void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence)
-{
- uint8 plevel = getLevel(); // if defense than victim == attacker
- uint8 greylevel = Trinity::XP::GetGrayLevel(plevel);
- uint8 moblevel = victim->getLevelForTarget(this);
- if (moblevel < greylevel)
- return;
-
- if (moblevel > plevel + 5)
- moblevel = plevel + 5;
+ uint16 new_value = value + step;
+ if (new_value > max)
+ new_value = max;
- uint8 lvldif = moblevel - greylevel;
- if (lvldif < 3)
- lvldif = 3;
-
- uint32 skilldif = 5 * plevel - (defence ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType));
- if (skilldif <= 0)
- return;
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value);
+ if (itr->second.uState != SKILL_NEW)
+ itr->second.uState = SKILL_CHANGED;
- float chance = float(3 * lvldif * skilldif) / plevel;
- if (!defence)
- if (getClass() == CLASS_WARRIOR || getClass() == CLASS_ROGUE)
- chance += chance * 0.02f * GetStat(STAT_INTELLECT);
-
- chance = chance < 1.0f ? 1.0f : chance; //minimum chance to increase skill is 1%
-
- if (roll_chance_f(chance))
+ for (size_t i = 0; i < bonusSkillLevelsSize; ++i)
{
- if (defence)
- UpdateDefense();
- else
- UpdateWeaponSkill(attType);
+ uint32 bsl = bonusSkillLevels[i];
+ if (value < bsl && new_value >= bsl)
+ {
+ learnSkillRewardedSpells(skillId, new_value);
+ break;
+ }
}
- else
- return;
+
+ UpdateSkillEnchantments(skillId, value, new_value);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skillId);
+ TC_LOG_DEBUG(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% taken", chance / 10.0f);
+ return true;
}
void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent)
@@ -6326,25 +6253,18 @@ void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent)
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return;
- uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos);
+ uint16 field = itr->second.pos / 2 + (talent ? PLAYER_SKILL_TALENT_0 : PLAYER_SKILL_MODIFIER_0);
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
- uint32 bonus_val = GetUInt32Value(bonusIndex);
- int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val);
- int16 perm_bonus = SKILL_PERM_BONUS(bonus_val);
+ uint16 bonus = GetUInt16Value(field, offset);
- if (talent) // permanent bonus stored in high part
- SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus, perm_bonus+val));
- else // temporary/item bonus stored in low part
- SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus+val, perm_bonus));
+ SetUInt16Value(field, offset, bonus + val);
}
void Player::UpdateSkillsForLevel()
{
- uint16 maxconfskill = sWorld->GetConfigMaxSkillValue();
uint32 maxSkill = GetMaxSkillValueForLevel();
- bool alwaysMaxSkill = sWorld->getBoolConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL);
-
for (SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
{
if (itr->second.uState == SKILL_DELETED)
@@ -6358,27 +6278,22 @@ void Player::UpdateSkillsForLevel()
if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL)
continue;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 max = SKILL_MAX(data);
- uint32 val = SKILL_VALUE(data);
+ if (IsWeaponSkill(pSkill->id))
+ continue;
+
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ //uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
/// update only level dependent max skill values
if (max != 1)
{
- /// maximize skill always
- if (alwaysMaxSkill)
- {
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, maxSkill));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- }
- else if (max != maxconfskill) /// update max skill value if current max skill not maximized
- {
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- }
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, maxSkill);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill);
+ if (itr->second.uState != SKILL_NEW)
+ itr->second.uState = SKILL_CHANGED;
}
}
}
@@ -6393,18 +6308,22 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
uint32 pskill = itr->first;
if (IsProfessionOrRidingSkill(pskill))
continue;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 max = SKILL_MAX(data);
+
+ if (IsWeaponSkill(pskill))
+ continue;
+
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
if (max > 1)
{
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(max, max));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, max);
+
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
}
- if (pskill == SKILL_DEFENSE)
- UpdateDefenseBonusesMod();
}
}
@@ -6421,22 +6340,29 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
//has skill
if (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED)
{
- currVal = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+ currVal = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
if (newVal)
{
// if skill value is going down, update enchantments before setting the new value
if (newVal < currVal)
UpdateSkillEnchantments(id, currVal, newVal);
+
// update step
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_PAIR32(id, step));
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
// update value
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_SKILL_VALUE(newVal, maxVal));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, newVal);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal);
+
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
+
learnSkillRewardedSpells(id, newVal);
// if skill value is going up, update enchantments after setting the new value
if (newVal > currVal)
UpdateSkillEnchantments(id, currVal, newVal);
+
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
}
@@ -6445,9 +6371,12 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
//remove enchantments needing this skill
UpdateSkillEnchantments(id, currVal, 0);
// clear skill fields
- SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), 0);
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), 0);
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos), 0);
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
// mark as deleted or simply remove from map if not saved yet
if (itr->second.uState != SKILL_NEW)
@@ -6460,54 +6389,77 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
if (SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j))
if (pAbility->skillId == id)
removeSpell(sSpellMgr->GetFirstSpellInChain(pAbility->spellId));
+
+ // Clear profession lines
+ if (GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1) == id)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1, 0);
+ else if (GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1) == id)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1, 0);
}
}
else if (newVal) //add
{
currVal = 0;
- for (int i=0; i < PLAYER_MAX_SKILLS; ++i)
- if (!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
+ for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i)
{
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id);
- if (!pSkill)
+ uint16 field = i / 2;
+ uint8 offset = i & 1; // i % 2
+
+ if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset))
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER_SKILLS, "Skill not found in SkillLineStore: skill #%u", id);
- return;
- }
+ SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(id);
+ if (!skillEntry)
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Skill not found in SkillLineStore: skill #%u", id);
+ return;
+ }
- SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step));
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i), MAKE_SKILL_VALUE(newVal, maxVal));
- UpdateSkillEnchantments(id, currVal, newVal);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, id);
+ if (skillEntry->categoryId == SKILL_CATEGORY_PROFESSION)
+ {
+ if (!GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1))
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1, id);
+ else if (!GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1))
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1, id);
+ }
- // insert new entry or update if not deleted old entry yet
- if (itr != mSkillStatus.end())
- {
- itr->second.pos = i;
- itr->second.uState = SKILL_CHANGED;
- }
- else
- mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW)));
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, newVal);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal);
- // apply skill bonuses
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0);
+ UpdateSkillEnchantments(id, currVal, newVal);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
+
+ // insert new entry or update if not deleted old entry yet
+ if (itr != mSkillStatus.end())
+ {
+ itr->second.pos = i;
+ itr->second.uState = SKILL_CHANGED;
+ }
+ else
+ mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW)));
+
+ // apply skill bonuses
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
- // temporary bonuses
- AuraEffectList const& mModSkill = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL);
- for (AuraEffectList::const_iterator j = mModSkill.begin(); j != mModSkill.end(); ++j)
- if ((*j)->GetMiscValue() == int32(id))
+ // temporary bonuses
+ AuraEffectList const& mModSkill = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL);
+ for (AuraEffectList::const_iterator j = mModSkill.begin(); j != mModSkill.end(); ++j)
+ if ((*j)->GetMiscValue() == int32(id))
(*j)->HandleEffect(this, AURA_EFFECT_HANDLE_SKILL, true);
- // permanent bonuses
- AuraEffectList const& mModSkillTalent = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL_TALENT);
- for (AuraEffectList::const_iterator j = mModSkillTalent.begin(); j != mModSkillTalent.end(); ++j)
- if ((*j)->GetMiscValue() == int32(id))
+ // permanent bonuses
+ AuraEffectList const& mModSkillTalent = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL_TALENT);
+ for (AuraEffectList::const_iterator j = mModSkillTalent.begin(); j != mModSkillTalent.end(); ++j)
+ if ((*j)->GetMiscValue() == int32(id))
(*j)->HandleEffect(this, AURA_EFFECT_HANDLE_SKILL, true);
- // Learn all spells for skill
- learnSkillRewardedSpells(id, newVal);
- return;
+ // Learn all spells for skill
+ learnSkillRewardedSpells(id, newVal);
+ return;
+ }
}
}
}
@@ -6530,7 +6482,7 @@ uint16 Player::GetSkillStep(uint16 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return PAIR32_HIPART(GetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos)));
+ return GetUInt16Value(PLAYER_SKILL_STEP_0 + itr->second.pos / 2, itr->second.pos & 1);
}
uint16 Player::GetSkillValue(uint32 skill) const
@@ -6542,11 +6494,12 @@ uint16 Player::GetSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
- int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_TEMP_BONUS(bonus);
- result += SKILL_PERM_BONUS(bonus);
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6559,11 +6512,12 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
- int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_TEMP_BONUS(bonus);
- result += SKILL_PERM_BONUS(bonus);
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6576,7 +6530,10 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
}
uint16 Player::GetBaseSkillValue(uint32 skill) const
@@ -6588,8 +6545,11 @@ uint16 Player::GetBaseSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6602,7 +6562,10 @@ uint16 Player::GetPureSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
}
int16 Player::GetSkillPermBonusValue(uint32 skill) const
@@ -6614,7 +6577,10 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset);
}
int16 Player::GetSkillTempBonusValue(uint32 skill) const
@@ -6626,17 +6592,19 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset);
}
void Player::SendActionButtons(uint32 state) const
{
WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4));
- data << uint8(state);
/*
state can be 0, 1, 2
- 0 - Looks to be sent when initial action buttons get sent, however on Trinity we use 1 since 0 had some difficulties
- 1 - Used in any SMSG_ACTION_BUTTONS packet with button data on Trinity. Only used after spec swaps on retail.
+ 0 - Sends initial action buttons, client does not validate if we have the spell or not
+ 1 - Used used after spec swaps, client validates if a spell is known.
2 - Clears the action bars client sided. This is sent during spec swap before unlearning and before sending the new buttons
*/
if (state != 2)
@@ -6650,9 +6618,12 @@ void Player::SendActionButtons(uint32 state) const
data << uint32(0);
}
}
+ else
+ data.resize(MAX_ACTION_BUTTONS * 4); // insert crap, client doesnt even parse this for state == 2
+ data << uint8(state);
GetSession()->SendPacket(&data);
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec);
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Action Buttons for '%u' spec '%u' Sent", GetGUIDLow(), GetActiveSpec());
}
bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
@@ -7115,16 +7086,12 @@ void Player::UpdateHonorFields()
// update yesterday's contribution
if (m_lastHonorUpdateTime >= yesterday)
{
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
-
// this is the first update today, reset today's contribution
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0);
SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0, kills_today));
}
else
{
// no honor/kills yesterday or today, reset
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
SetUInt32Value(PLAYER_FIELD_KILLS, 0);
}
}
@@ -7216,7 +7183,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, victim->getClass());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, victim->getRace());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, victim);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, 0, victim);
}
else
{
@@ -7253,9 +7220,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
GetSession()->SendPacket(&data);
// add honor points
- ModifyHonorPoints(honor);
-
- ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, honor, true);
+ ModifyCurrency(CURRENCY_TYPE_HONOR_POINTS, int32(honor));
if (InBattleground() && honor > 0)
{
@@ -7290,82 +7255,441 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
return true;
}
-void Player::SetHonorPoints(uint32 value)
+
+void Player::_LoadCurrency(PreparedQueryResult result)
{
- if (value > sWorld->getIntConfig(CONFIG_MAX_HONOR_POINTS))
- value = sWorld->getIntConfig(CONFIG_MAX_HONOR_POINTS);
- SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value);
- if (value)
- AddKnownCurrency(ITEM_HONOR_POINTS_ID);
+ if (!result)
+ return;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint16 currencyID = fields[0].GetUInt16();
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyID);
+ if (!currency)
+ continue;
+
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_UNCHANGED;
+ cur.weekCount = fields[1].GetUInt32();
+ cur.totalCount = fields[2].GetUInt32();
+
+ _currencyStorage.insert(PlayerCurrenciesMap::value_type(currencyID, cur));
+
+ } while (result->NextRow());
}
-void Player::SetArenaPoints(uint32 value)
+void Player::_SaveCurrency(SQLTransaction& trans)
{
- if (value > sWorld->getIntConfig(CONFIG_MAX_ARENA_POINTS))
- value = sWorld->getIntConfig(CONFIG_MAX_ARENA_POINTS);
- SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value);
- if (value)
- AddKnownCurrency(ITEM_ARENA_POINTS_ID);
+ PreparedStatement* stmt = NULL;
+ for (PlayerCurrenciesMap::iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
+ {
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(itr->first);
+ if (!entry) // should never happen
+ continue;
+
+ switch (itr->second.state)
+ {
+ case PLAYERCURRENCY_NEW:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_PLAYER_CURRENCY);
+ stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt32(2, itr->second.weekCount);
+ stmt->setUInt32(3, itr->second.totalCount);
+ trans->Append(stmt);
+ break;
+ case PLAYERCURRENCY_CHANGED:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_CURRENCY);
+ stmt->setUInt32(0, itr->second.weekCount);
+ stmt->setUInt32(1, itr->second.totalCount);
+ stmt->setUInt32(2, GetGUIDLow());
+ stmt->setUInt16(3, itr->first);
+ trans->Append(stmt);
+ break;
+ default:
+ break;
+ }
+
+ itr->second.state = PLAYERCURRENCY_UNCHANGED;
+ }
}
-void Player::ModifyHonorPoints(int32 value, SQLTransaction* trans /*=NULL*/)
+void Player::SendNewCurrency(uint32 id) const
{
- int32 newValue = int32(GetHonorPoints()) + value;
- if (newValue < 0)
- newValue = 0;
- SetHonorPoints(uint32(newValue));
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return;
+
+ ByteBuffer currencyData;
+ WorldPacket packet(SMSG_INIT_CURRENCY, 4 + (5*4 + 1));
+ packet.WriteBits(1, 23);
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(id);
+ if (!entry) // should never happen
+ return;
+
+ uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+ uint32 weekCount = itr->second.weekCount / precision;
+ uint32 weekCap = GetCurrencyWeekCap(entry) / precision;
- if (trans && !trans->null())
+ packet.WriteBit(weekCount);
+ packet.WriteBits(0, 4); // some flags
+ packet.WriteBit(weekCap);
+ packet.WriteBit(0); // season total earned
+
+ currencyData << uint32(itr->second.totalCount / precision);
+ if (weekCap)
+ currencyData << uint32(weekCap);
+
+ //if (seasonTotal)
+ // currencyData << uint32(seasonTotal / precision);
+
+ currencyData << uint32(entry->ID);
+ if (weekCount)
+ currencyData << uint32(weekCount);
+
+ packet.FlushBits();
+ packet.append(currencyData);
+ GetSession()->SendPacket(&packet);
+}
+
+void Player::SendCurrencies() const
+{
+ ByteBuffer currencyData;
+ WorldPacket packet(SMSG_INIT_CURRENCY, 4 + _currencyStorage.size()*(5*4 + 1));
+ size_t count_pos = packet.bitwpos();
+ packet.WriteBits(_currencyStorage.size(), 23);
+
+ size_t count = 0;
+ for (PlayerCurrenciesMap::const_iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_HONOR_POINTS);
- stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
- (*trans)->Append(stmt);
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(itr->first);
+
+ // not send init meta currencies.
+ if (!entry || entry->Category == CURRENCY_CATEGORY_META_CONQUEST)
+ continue;
+
+ uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+ uint32 weekCount = itr->second.weekCount / precision;
+ uint32 weekCap = GetCurrencyWeekCap(entry) / precision;
+
+ packet.WriteBit(weekCount);
+ packet.WriteBits(0, 4); // some flags
+ packet.WriteBit(weekCap);
+ packet.WriteBit(0); // season total earned
+
+ currencyData << uint32(itr->second.totalCount / precision);
+ if (weekCap)
+ currencyData << uint32(weekCap);
+
+ //if (seasonTotal)
+ // currencyData << uint32(seasonTotal / precision);
+
+ currencyData << uint32(entry->ID);
+ if (weekCount)
+ currencyData << uint32(weekCount);
+
+ ++count;
+ }
+
+ packet.FlushBits();
+ packet.append(currencyData);
+ packet.PutBits(count_pos, count, 23);
+ GetSession()->SendPacket(&packet);
+}
+
+void Player::SendPvpRewards() const
+{
+ WorldPacket packet(SMSG_REQUEST_PVP_REWARDS_RESPONSE, 24);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_ARENA, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_META_ARENA, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ GetSession()->SendPacket(&packet);
+}
+
+uint32 Player::GetCurrency(uint32 id, bool usePrecision) const
+{
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return 0;
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ uint32 precision = (usePrecision && currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return itr->second.totalCount / precision;
+}
+
+uint32 Player::GetCurrencyOnWeek(uint32 id, bool usePrecision) const
+{
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return 0;
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ uint32 precision = (usePrecision && currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return itr->second.weekCount / precision;
+}
+
+bool Player::HasCurrency(uint32 id, uint32 count) const
+{
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ return itr != _currencyStorage.end() && itr->second.totalCount >= count;
+}
+
+void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bool ignoreMultipliers/* = false*/)
+{
+ if (!count)
+ return;
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ ASSERT(currency);
+
+ if (!ignoreMultipliers)
+ count *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_CURRENCY_GAIN, id);
+
+ int32 precision = currency->Flags & CURRENCY_FLAG_HIGH_PRECISION ? CURRENCY_PRECISION : 1;
+ uint32 oldTotalCount = 0;
+ uint32 oldWeekCount = 0;
+ PlayerCurrenciesMap::iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ {
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_NEW;
+ cur.totalCount = 0;
+ cur.weekCount = 0;
+ _currencyStorage[id] = cur;
+ itr = _currencyStorage.find(id);
+ }
+ else
+ {
+ oldTotalCount = itr->second.totalCount;
+ oldWeekCount = itr->second.weekCount;
+ }
+
+ // count can't be more then weekCap if used (weekCap > 0)
+ uint32 weekCap = GetCurrencyWeekCap(currency);
+ if (weekCap && count > int32(weekCap))
+ count = weekCap;
+
+ // count can't be more then totalCap if used (totalCap > 0)
+ uint32 totalCap = GetCurrencyTotalCap(currency);
+ if (totalCap && count > int32(totalCap))
+ count = totalCap;
+
+ int32 newTotalCount = int32(oldTotalCount) + count;
+ if (newTotalCount < 0)
+ newTotalCount = 0;
+
+ int32 newWeekCount = int32(oldWeekCount) + (count > 0 ? count : 0);
+ if (newWeekCount < 0)
+ newWeekCount = 0;
+
+ // if we get more then weekCap just set to limit
+ if (weekCap && int32(weekCap) < newWeekCount)
+ {
+ newWeekCount = int32(weekCap);
+ // weekCap - oldWeekCount always >= 0 as we set limit before!
+ newTotalCount = oldTotalCount + (weekCap - oldWeekCount);
+ }
+
+ // if we get more then totalCap set to maximum;
+ if (totalCap && int32(totalCap) < newTotalCount)
+ {
+ newTotalCount = int32(totalCap);
+ newWeekCount = weekCap;
+ }
+
+ if (uint32(newTotalCount) != oldTotalCount)
+ {
+ if (itr->second.state != PLAYERCURRENCY_NEW)
+ itr->second.state = PLAYERCURRENCY_CHANGED;
+
+ itr->second.totalCount = newTotalCount;
+ itr->second.weekCount = newWeekCount;
+
+ if (count > 0)
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CURRENCY, id, count);
+
+ if (currency->Category == CURRENCY_CATEGORY_META_CONQUEST)
+ {
+ // count was changed to week limit, now we can modify original points.
+ ModifyCurrency(CURRENCY_TYPE_CONQUEST_POINTS, count, printLog);
+ return;
+ }
+
+ WorldPacket packet(SMSG_UPDATE_CURRENCY, 12);
+
+ packet.WriteBit(weekCap != 0);
+ packet.WriteBit(0); // hasSeasonCount
+ packet.WriteBit(!printLog); // print in log
+
+ // if hasSeasonCount packet << uint32(seasontotalearned); TODO: save this in character DB and use it
+
+ packet << uint32(newTotalCount / precision);
+ packet << uint32(id);
+ if (weekCap)
+ packet << uint32(newWeekCount / precision);
+
+ GetSession()->SendPacket(&packet);
}
}
-void Player::ModifyArenaPoints(int32 value, SQLTransaction* trans /*=NULL*/)
+void Player::SetCurrency(uint32 id, uint32 count, bool /*printLog*/ /*= true*/)
{
- int32 newValue = int32(GetArenaPoints()) + value;
- if (newValue < 0)
- newValue = 0;
- SetArenaPoints(uint32(newValue));
+ PlayerCurrenciesMap::iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ {
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_NEW;
+ cur.totalCount = count;
+ cur.weekCount = 0;
+ _currencyStorage[id] = cur;
+ }
+}
- if (trans && !trans->null())
+uint32 Player::GetCurrencyWeekCap(uint32 id, bool usePrecision) const
+{
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(id);
+ if (!entry)
+ return 0;
+
+ uint32 precision = (usePrecision && entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return GetCurrencyWeekCap(entry) / precision;
+}
+
+void Player::ResetCurrencyWeekCap()
+{
+ for (uint32 arenaSlot = 0; arenaSlot < MAX_ARENA_SLOT; arenaSlot++)
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_ARENA_POINTS);
- stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
- (*trans)->Append(stmt);
+ if (uint32 arenaTeamId = GetArenaTeamId(arenaSlot))
+ {
+ ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId);
+ arenaTeam->FinishWeek(); // set played this week etc values to 0 in memory, too
+ arenaTeam->SaveToDB(); // save changes
+ arenaTeam->NotifyStatsChanged(); // notify the players of the changes
+ }
+ }
+
+ for (PlayerCurrenciesMap::iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
+ {
+ itr->second.weekCount = 0;
+ itr->second.state = PLAYERCURRENCY_CHANGED;
+ }
+
+ WorldPacket data(SMSG_WEEKLY_RESET_CURRENCY, 0);
+ SendDirectMessage(&data);
+}
+
+uint32 Player::GetCurrencyWeekCap(CurrencyTypesEntry const* currency) const
+{
+ switch (currency->ID)
+ {
+ //original conquest not have week cap
+ case CURRENCY_TYPE_CONQUEST_POINTS:
+ return std::max(GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_ARENA, false), GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, false));
+ case CURRENCY_TYPE_CONQUEST_META_ARENA:
+ // should add precision mod = 100
+ return Trinity::Currency::ConquestRatingCalculator(_maxPersonalArenaRate) * CURRENCY_PRECISION;
+ case CURRENCY_TYPE_CONQUEST_META_RBG:
+ // should add precision mod = 100
+ return Trinity::Currency::BgConquestRatingCalculator(GetRBGPersonalRating()) * CURRENCY_PRECISION;
}
+
+ return currency->WeekCap;
+}
+
+uint32 Player::GetCurrencyTotalCap(CurrencyTypesEntry const* currency) const
+{
+ uint32 cap = currency->TotalCap;
+
+ switch (currency->ID)
+ {
+ case CURRENCY_TYPE_HONOR_POINTS:
+ {
+ uint32 honorcap = sWorld->getIntConfig(CONFIG_CURRENCY_MAX_HONOR_POINTS);
+ if (honorcap > 0)
+ cap = honorcap;
+ break;
+ }
+ case CURRENCY_TYPE_JUSTICE_POINTS:
+ {
+ uint32 justicecap = sWorld->getIntConfig(CONFIG_CURRENCY_MAX_JUSTICE_POINTS);
+ if (justicecap > 0)
+ cap = justicecap;
+ break;
+ }
+ }
+
+ return cap;
+}
+
+void Player::UpdateConquestCurrencyCap(uint32 currency)
+{
+ uint32 currenciesToUpdate[2] = { currency, CURRENCY_TYPE_CONQUEST_POINTS };
+
+ for (uint32 i = 0; i < 2; ++i)
+ {
+ CurrencyTypesEntry const* currencyEntry = sCurrencyTypesStore.LookupEntry(currenciesToUpdate[i]);
+ if (!currencyEntry)
+ continue;
+
+ uint32 precision = (currencyEntry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1;
+ uint32 cap = GetCurrencyWeekCap(currencyEntry);
+
+ WorldPacket packet(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, 8);
+ packet << uint32(cap / precision);
+ packet << uint32(currenciesToUpdate[i]);
+ GetSession()->SendPacket(&packet);
+ }
+}
+
+void Player::SetInGuild(uint32 guildId)
+{
+ if (guildId)
+ SetUInt64Value(OBJECT_FIELD_DATA, MAKE_NEW_GUID(guildId, 0, HIGHGUID_GUILD));
+ else
+ SetUInt64Value(OBJECT_FIELD_DATA, 0);
+
+ ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_GUILD_LEVEL_ENABLED, guildId != 0 && sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED));
+ SetUInt16Value(OBJECT_FIELD_TYPE, 1, guildId != 0);
}
uint32 Player::GetGuildIdFromDB(uint64 guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
stmt->setUInt32(0, GUID_LOPART(guid));
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
-
- if (!result)
- return 0;
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ return result->Fetch()[0].GetUInt32();
- uint32 id = result->Fetch()[0].GetUInt32();
- return id;
+ return 0;
}
uint8 Player::GetRankFromDB(uint64 guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
stmt->setUInt32(0, GUID_LOPART(guid));
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ return result->Fetch()[1].GetUInt8();
- if (result)
+ return 0;
+}
+
+void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
+{
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
+ if (type == ARENA_TEAM_PERSONAL_RATING && value > _maxPersonalArenaRate)
{
- uint32 v = result->Fetch()[1].GetUInt8();
- return v;
+ _maxPersonalArenaRate = value;
+ UpdateConquestCurrencyCap(CURRENCY_TYPE_CONQUEST_META_ARENA);
}
- else
- return 0;
}
void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type)
@@ -7373,10 +7697,6 @@ void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type)
SetArenaTeamInfoField(slot, ARENA_TEAM_ID, ArenaTeamId);
SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type);
}
-void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
-{
- SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
-}
uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type)
{
@@ -7459,6 +7779,8 @@ void Player::UpdateArea(uint32 newArea)
// so apply them accordingly
m_areaUpdateId = newArea;
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE);
+
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
UpdatePvPState(true);
@@ -7475,10 +7797,14 @@ void Player::UpdateArea(uint32 newArea)
}
else
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
+
+ phaseMgr.RemoveUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE);
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
+
if (m_zoneUpdateId != newZone)
{
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
@@ -7504,7 +7830,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (!zone)
return;
- if (sWorld->getBoolConfig(CONFIG_WEATHER))
+ if (sWorld->getBoolConfig(CONFIG_WEATHER) && !HasAuraType(SPELL_AURA_FORCE_WEATHER))
{
if (Weather* weather = WeatherMgr::FindWeather(zone->ID))
weather->SendWeatherUpdateToPlayer(this);
@@ -7587,6 +7913,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateLocalChannels(newZone);
UpdateZoneDependentAuras(newZone);
+
+ phaseMgr.RemoveUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
}
//If players are too far away from the duel flag... they lose the duel
@@ -7648,8 +7976,8 @@ void Player::DuelComplete(DuelCompleteType type)
{
data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size
data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled
- data << duel->opponent->GetName();
data << GetName();
+ data << duel->opponent->GetName();
SendMessageToSet(&data, true);
}
@@ -7770,10 +8098,6 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), apply);
_ApplyItemBonuses(proto, slot, apply);
-
- if (slot == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
-
ApplyItemEquipSpell(item, apply);
ApplyEnchantment(item, apply);
@@ -7794,7 +8118,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (ssd && ssd_level > ssd->MaxLevel)
ssd_level = ssd->MaxLevel;
- ScalingStatValuesEntry const* ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
+ ScalingStatValuesEntry const* ssv = ssd ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
if (only_level_scale && !ssv)
return;
@@ -7808,12 +8132,10 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (ssd->StatMod[i] < 0)
continue;
statType = ssd->StatMod[i];
- val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
+ val = (ssv->GetStatMultiplier(proto->InventoryType) * ssd->Modifier[i]) / 10000;
}
else
{
- if (i >= proto->StatsCount)
- continue;
statType = proto->ItemStat[i].ItemStatType;
val = proto->ItemStat[i].ItemStatValue;
}
@@ -7879,24 +8201,24 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
case ITEM_MOD_CRIT_SPELL_RATING:
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
break;
- case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
- break;
- case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
- break;
- case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- break;
+ // case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
+ // break;
case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(val), apply);
break;
+ // case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ // break;
case ITEM_MOD_HASTE_MELEE_RATING:
ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply);
break;
@@ -7916,20 +8238,18 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply);
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
break;
- case ITEM_MOD_HIT_TAKEN_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
- break;
+ // case ITEM_MOD_HIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ // break;
case ITEM_MOD_RESILIENCE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(val), apply);
break;
case ITEM_MOD_HASTE_RATING:
ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply);
@@ -7946,9 +8266,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
case ITEM_MOD_RANGED_ATTACK_POWER:
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
break;
-// case ITEM_MOD_FERAL_ATTACK_POWER:
-// ApplyFeralAPBonus(int32(val), apply);
-// break;
case ITEM_MOD_MANA_REGENERATION:
ApplyManaRegenBonus(int32(val), apply);
break;
@@ -7965,28 +8282,39 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -val, apply);
m_spellPenetrationItemMod += apply ? val : -val;
break;
- case ITEM_MOD_BLOCK_VALUE:
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply);
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, int32(val), apply);
+ break;
+ case ITEM_MOD_FIRE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
break;
- // deprecated item mods
- case ITEM_MOD_SPELL_HEALING_DONE:
- case ITEM_MOD_SPELL_DAMAGE_DONE:
+ case ITEM_MOD_FROST_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_HOLY_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_SHADOW_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_NATURE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_ARCANE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
}
}
// Apply Spell Power from ScalingStatValue if set
- if (ssv)
- if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue))
+ if (ssv && proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ if (int32 spellbonus = int32(ssv->Spellpower))
ApplySpellPowerBonus(spellbonus, apply);
// If set ScalingStatValue armor get it or use item armor
uint32 armor = proto->Armor;
- if (ssv)
- {
- if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue))
- armor = ssvarmor;
- }
+ if (ssv && proto->Class == ITEM_CLASS_ARMOR)
+ armor = ssv->GetArmor(proto->InventoryType, proto->SubClass - 1);
else if (armor && proto->ArmorDamageModifier)
armor -= uint32(proto->ArmorDamageModifier);
@@ -8013,27 +8341,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (proto->ArmorDamageModifier > 0)
HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
- if (proto->Block)
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
-
- if (proto->HolyRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
-
- if (proto->FireRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
-
- if (proto->NatureRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
-
- if (proto->FrostRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
-
- if (proto->ShadowRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
-
- if (proto->ArcaneRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
-
WeaponAttackType attType = BASE_ATTACK;
if (slot == EQUIPMENT_SLOT_RANGED && (
@@ -8049,23 +8356,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (CanUseAttackType(attType))
_ApplyWeaponDamage(slot, proto, ssv, apply);
-
-
- // Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
- if (getClass() == CLASS_DRUID)
- {
- int32 dpsMod = 0;
- int32 feral_bonus = 0;
- if (ssv)
- {
- dpsMod = ssv->getDPSMod(proto->ScalingStatValue);
- feral_bonus += ssv->getFeralBonus(proto->ScalingStatValue);
- }
-
- feral_bonus += proto->getFeralBonus(dpsMod);
- if (feral_bonus)
- ApplyFeralAPBonus(feral_bonus, apply);
- }
}
void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply)
@@ -8084,18 +8374,20 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
attType = OFF_ATTACK;
}
- float minDamage = proto->Damage[0].DamageMin;
- float maxDamage = proto->Damage[0].DamageMax;
+ float minDamage = proto->DamageMin;
+ float maxDamage = proto->DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
+ int32 extraDPS = 0;
if (ssv)
{
- int32 extraDPS = ssv->getDPSMod(proto->ScalingStatValue);
+ float damageMultiplier = 0.0f;
+ extraDPS = ssv->GetDPSAndDamageMultiplier(proto->SubClass, proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON, &damageMultiplier);
if (extraDPS)
{
float average = extraDPS * proto->Delay / 1000.0f;
- minDamage = 0.7f * average;
- maxDamage = 1.3f * average;
+ minDamage = (1.0f - damageMultiplier) * average;
+ maxDamage = (1.0f + damageMultiplier) * average;
}
}
@@ -8121,10 +8413,6 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME);
}
- // No need to modify any physical damage for ferals as it is calculated from stats only
- if (IsInFeralForm())
- return;
-
if (CanModifyStats() && (damage || proto->Delay))
UpdateDamagePhysical(attType);
}
@@ -8368,10 +8656,10 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
float chance = (float)spellInfo->ProcChance;
- if (spellData.SpellPPMRate)
+ if (proto->SpellPPMRate)
{
uint32 WeaponSpeed = GetAttackTime(attType);
- chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo);
+ chance = GetPPMProcChance(WeaponSpeed, proto->SpellPPMRate, spellInfo);
}
else if (chance > 100.0f)
chance = GetWeaponProcChance();
@@ -8384,6 +8672,9 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
// item combat enchantments
for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
{
+ if (e_slot > PRISMATIC_ENCHANTMENT_SLOT || e_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
@@ -8459,7 +8750,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
if (!spellInfo)
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ", proto->ItemId, learn_spell_id);
- SendEquipError(EQUIP_ERR_NONE, item, NULL);
+ SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, item, NULL);
return;
}
@@ -8506,6 +8797,9 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
// Item enchantments spells casted at use
for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
{
+ if (e_slot > PRISMATIC_ENCHANTMENT_SLOT || e_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
@@ -8572,9 +8866,6 @@ void Player::_RemoveAllItemMods()
_ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false);
_ApplyItemBonuses(proto, i, false);
-
- if (i == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
}
}
@@ -8601,9 +8892,6 @@ void Player::_ApplyAllItemMods()
_ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true);
_ApplyItemBonuses(proto, i, true);
-
- if (i == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
}
}
@@ -8648,63 +8936,6 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply)
}
}
-void Player::_ApplyAmmoBonuses()
-{
- // check ammo
- uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID);
- if (!ammo_id)
- return;
-
- float currentAmmoDPS;
-
- ItemTemplate const* ammo_proto = sObjectMgr->GetItemTemplate(ammo_id);
- if (!ammo_proto || ammo_proto->Class != ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto))
- currentAmmoDPS = 0.0f;
- else
- currentAmmoDPS = (ammo_proto->Damage[0].DamageMin + ammo_proto->Damage[0].DamageMax) / 2;
-
- if (currentAmmoDPS == GetAmmoDPS())
- return;
-
- m_ammoDPS = currentAmmoDPS;
-
- if (CanModifyStats())
- UpdateDamagePhysical(RANGED_ATTACK);
-}
-
-bool Player::CheckAmmoCompatibility(const ItemTemplate* ammo_proto) const
-{
- if (!ammo_proto)
- return false;
-
- // check ranged weapon
- Item* weapon = GetWeaponForAttack(RANGED_ATTACK);
- if (!weapon || weapon->IsBroken())
- return false;
-
- ItemTemplate const* weapon_proto = weapon->GetTemplate();
- if (!weapon_proto || weapon_proto->Class != ITEM_CLASS_WEAPON)
- return false;
-
- // check ammo ws. weapon compatibility
- switch (weapon_proto->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- if (ammo_proto->SubClass != ITEM_SUBCLASS_ARROW)
- return false;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- if (ammo_proto->SubClass != ITEM_SUBCLASS_BULLET)
- return false;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
/* If in a battleground a player dies, and an enemy removes the insignia, the player's bones is lootable
Called by remove insignia spell effect */
void Player::RemovedInsignia(Player* looterPlr)
@@ -9049,7 +9280,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
// need know merged fishing/corpse loot type for achievements
loot->loot_type = loot_type;
- WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
+ WorldPacket data(SMSG_LOOT_RESPONSE, 8 + 1 + 50 + 1 + 1); // we guess size
data << uint64(guid);
data << uint8(loot_type);
data << LootView(*loot, this, permission);
@@ -9079,9 +9310,10 @@ void Player::SendNotifyLootItemRemoved(uint8 lootSlot)
void Player::SendUpdateWorldState(uint32 Field, uint32 Value)
{
- WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8);
+ WorldPacket data(SMSG_UPDATE_WORLD_STATE, 4+4+1);
data << Field;
data << Value;
+ data << uint8(0);
GetSession()->SendPacket(&data);
}
@@ -9134,46 +9366,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
case 2257: // Deeprun Tram
case 3703: // Shattrath City
break;
- case 139: // Eastern Plaguelands
- if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_EP)
- pvp->FillInitialWorldStates(data);
- else
- {
- data << uint32(0x97a) << uint32(0x0); // 10 2426
- data << uint32(0x917) << uint32(0x0); // 11 2327
- data << uint32(0x918) << uint32(0x0); // 12 2328
- data << uint32(0x97b) << uint32(0x32); // 13 2427
- data << uint32(0x97c) << uint32(0x32); // 14 2428
- data << uint32(0x933) << uint32(0x1); // 15 2355
- data << uint32(0x946) << uint32(0x0); // 16 2374
- data << uint32(0x947) << uint32(0x0); // 17 2375
- data << uint32(0x948) << uint32(0x0); // 18 2376
- data << uint32(0x949) << uint32(0x0); // 19 2377
- data << uint32(0x94a) << uint32(0x0); // 20 2378
- data << uint32(0x94b) << uint32(0x0); // 21 2379
- data << uint32(0x932) << uint32(0x0); // 22 2354
- data << uint32(0x934) << uint32(0x0); // 23 2356
- data << uint32(0x935) << uint32(0x0); // 24 2357
- data << uint32(0x936) << uint32(0x0); // 25 2358
- data << uint32(0x937) << uint32(0x0); // 26 2359
- data << uint32(0x938) << uint32(0x0); // 27 2360
- data << uint32(0x939) << uint32(0x1); // 28 2361
- data << uint32(0x930) << uint32(0x1); // 29 2352
- data << uint32(0x93a) << uint32(0x0); // 30 2362
- data << uint32(0x93b) << uint32(0x0); // 31 2363
- data << uint32(0x93c) << uint32(0x0); // 32 2364
- data << uint32(0x93d) << uint32(0x0); // 33 2365
- data << uint32(0x944) << uint32(0x0); // 34 2372
- data << uint32(0x945) << uint32(0x0); // 35 2373
- data << uint32(0x931) << uint32(0x1); // 36 2353
- data << uint32(0x93e) << uint32(0x0); // 37 2366
- data << uint32(0x931) << uint32(0x1); // 38 2367 ?? grey horde not in dbc! send for consistency's sake, and to match field count
- data << uint32(0x940) << uint32(0x0); // 39 2368
- data << uint32(0x941) << uint32(0x0); // 7 2369
- data << uint32(0x942) << uint32(0x0); // 8 2370
- data << uint32(0x943) << uint32(0x0); // 9 2371
- }
- break;
case 1377: // Silithus
if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_SI)
pvp->FillInitialWorldStates(data);
@@ -9657,6 +9849,27 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER
}
break;
+ // Twin Peaks
+ case 5031:
+ if (bg && bg->GetTypeID(true) == BATTLEGROUND_TP)
+ bg->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(0x62d) << uint32(0x0); // 7 1581 alliance flag captures
+ data << uint32(0x62e) << uint32(0x0); // 8 1582 horde flag captures
+ data << uint32(0x609) << uint32(0x0); // 9 1545 unk
+ data << uint32(0x60a) << uint32(0x0); // 10 1546 unk
+ data << uint32(0x60b) << uint32(0x2); // 11 1547 unk
+ data << uint32(0x641) << uint32(0x3); // 12 1601 unk
+ data << uint32(0x922) << uint32(0x1); // 13 2338 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
+ data << uint32(0x923) << uint32(0x1); // 14 2339 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
+ }
+ break;
+ // Battle for Gilneas
+ case 5449:
+ if (bg && bg->GetTypeID(true) == BATTLEGROUND_BFG)
+ bg->FillInitialWorldStates(data);
+ break;
// Wintergrasp
case 4197:
if (bf && bf->GetTypeId() == BATTLEFIELD_WG)
@@ -9748,7 +9961,7 @@ void Player::SendTalentWipeConfirm(uint64 guid)
{
WorldPacket data(MSG_TALENT_WIPE_CONFIRM, (8+4));
data << uint64(guid);
- uint32 cost = sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST) ? 0 : resetTalentsCost();
+ uint32 cost = sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST) ? 0 : GetNextResetTalentsCost();
data << cost;
GetSession()->SendPacket(&data);
}
@@ -9946,30 +10159,10 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
break;
case INVTYPE_RELIC:
{
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_ARMOR_LIBRAM:
- if (playerClass == CLASS_PALADIN)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_IDOL:
- if (playerClass == CLASS_DRUID)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_TOTEM:
- if (playerClass == CLASS_SHAMAN)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_MISC:
- if (playerClass == CLASS_WARLOCK)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_SIGIL:
- if (playerClass == CLASS_DEATH_KNIGHT)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- }
- break;
+ if (playerClass == CLASS_PALADIN || playerClass == CLASS_DRUID ||
+ playerClass == CLASS_SHAMAN || playerClass == CLASS_DEATH_KNIGHT)
+ slots[0] = EQUIPMENT_SLOT_RANGED;
+ break;
}
default:
return NULL_SLOT;
@@ -10031,14 +10224,6 @@ InventoryResult Player::CanUnequipItems(uint32 item, uint32 count) const
return EQUIP_ERR_OK;
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetEntry() == item)
- {
- tempcount += pItem->GetCount();
- if (tempcount >= count)
- return EQUIP_ERR_OK;
- }
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
@@ -10063,11 +10248,6 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
if (pItem != skipItem && pItem->GetEntry() == item)
count += pItem->GetCount();
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem != skipItem && pItem->GetEntry() == item)
- count += pItem->GetCount();
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
count += pBag->GetItemCount(item, skipItem);
@@ -10110,13 +10290,6 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte
if (pProto->ItemLimitCategory == limitCategory)
count += pItem->GetCount();
- for (int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem != skipItem)
- if (ItemTemplate const* pProto = pItem->GetTemplate())
- if (pProto->ItemLimitCategory == limitCategory)
- count += pItem->GetCount();
-
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem);
@@ -10142,11 +10315,6 @@ Item* Player::GetItemByGuid(uint64 guid) const
if (pItem->GetGUID() == guid)
return pItem;
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetGUID() == guid)
- return pItem;
-
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pItem->GetGUID() == guid)
@@ -10178,7 +10346,7 @@ Item* Player::GetItemByPos(uint16 pos) const
Item* Player::GetItemByPos(uint8 bag, uint8 slot) const
{
- if (bag == INVENTORY_SLOT_BAG_0 && (slot < BANK_SLOT_BAG_END || (slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END)))
+ if (bag == INVENTORY_SLOT_BAG_0 && slot < BANK_SLOT_BAG_END)
return m_items[slot];
else if (Bag* pBag = GetBagByPos(bag))
return pBag->GetItemByPos(slot);
@@ -10268,8 +10436,6 @@ bool Player::IsInventoryPos(uint8 bag, uint8 slot)
return true;
if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && (slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END))
- return true;
return false;
}
@@ -10328,10 +10494,6 @@ bool Player::IsValidPos(uint8 bag, uint8 slot, bool explicit_pos)
if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END)
return true;
- // keyring slots
- if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END)
- return true;
-
// bank main slots
if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END)
return true;
@@ -10371,16 +10533,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
return true;
}
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
- {
- tempcount += pItem->GetCount();
- if (tempcount >= count)
- return true;
- }
- }
+
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
if (Bag* pBag = GetBagByPos(i))
@@ -10510,11 +10663,11 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
if (pItem && pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// no maximum
if ((pProto->MaxCount <= 0 && pProto->ItemLimitCategory == 0) || pProto->MaxCount == 2147483647)
@@ -10527,7 +10680,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count + curcount - pProto->MaxCount;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
@@ -10539,7 +10692,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
}
if (limitEntry->mode == ITEM_LIMIT_CATEGORY_MODE_HAVE)
@@ -10549,7 +10702,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count + curcount - limitEntry->maxCount;
- return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED;
+ return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS;
}
}
}
@@ -10570,36 +10723,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& des
return CanStoreItem(bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL);
}
-bool Player::HasItemTotemCategory(uint32 TotemCategory) const
-{
- Item* pItem;
- for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
- {
- pItem = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- pItem = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
- {
- if (Bag* pBag = GetBagByPos(i))
- {
- for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
- {
- pItem = GetUseableItemByPos(i, j);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- }
- }
- return false;
-}
-
InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec &dest, ItemTemplate const* pProto, uint32& count, bool swap, Item* pSrcItem) const
{
Item* pItem2 = GetItemByPos(bag, slot);
@@ -10611,40 +10734,32 @@ InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemP
uint32 need_space;
if (pSrcItem && pSrcItem->IsNotEmptyBag() && !IsBagPos(uint16(bag) << 8 | slot))
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
// empty specific slot - check item fit to slot
if (!pItem2 || swap)
{
if (bag == INVENTORY_SLOT_BAG_0)
{
- // keyring case
- if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
-
- // currencytoken case
- if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(pProto->IsCurrencyToken()))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
-
// prevent cheating
if ((slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END) || slot >= PLAYER_SLOT_END)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
}
else
{
Bag* pBag = GetBagByPos(bag);
if (!pBag)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
ItemTemplate const* pBagProto = pBag->GetTemplate();
if (!pBagProto)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (slot >= pBagProto->ContainerSlots)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (!ItemCanGoIntoBag(pProto, pBagProto))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
}
// non empty stack with space
@@ -10678,26 +10793,26 @@ InventoryResult Player::CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, Ite
{
// skip specific bag already processed in first called CanStoreItem_InBag
if (bag == skip_bag)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// skip not existed bag or self targeted bag
Bag* pBag = GetBagByPos(bag);
if (!pBag || pBag == pSrcItem)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (pSrcItem && pSrcItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
ItemTemplate const* pBagProto = pBag->GetTemplate();
if (!pBagProto)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// specialized bag mode or non-specilized
if (non_specialized != (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (!ItemCanGoIntoBag(pProto, pBagProto))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
@@ -10748,7 +10863,7 @@ InventoryResult Player::CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 sl
{
//this is never called for non-bag slots so we can do this
if (pSrcItem && pSrcItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
for (uint32 j = slot_begin; j < slot_end; j++)
{
@@ -10804,7 +10919,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (no_space_count)
*no_space_count = count;
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
}
if (pItem)
@@ -10814,14 +10929,14 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
}
if (pItem->IsBindedNotWith(this))
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
}
}
@@ -10857,7 +10972,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
@@ -10871,24 +10986,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (bag == INVENTORY_SLOT_BAG_0) // inventory
{
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
-
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, true, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -10904,7 +11001,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
else // equipped bag
@@ -10928,7 +11025,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -10936,67 +11033,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search free slot in bag for place to
if (bag == INVENTORY_SLOT_BAG_0) // inventory
{
- // search free slot - keyring case
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, KEYRING_SLOT_START+keyringSize, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
-
- res = CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
- }
- else if (pProto->IsCurrencyToken())
- {
- res = CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
- }
-
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, false, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -11012,7 +11048,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
else // equipped bag
@@ -11035,7 +11071,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11045,24 +11081,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search stack for merge to
if (pProto->Stackable != 1)
{
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
-
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, true, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -11078,7 +11096,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
if (pProto->BagFamily)
@@ -11096,7 +11114,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11114,7 +11132,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11122,48 +11140,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search free slot - special bag case
if (pProto->BagFamily)
{
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, KEYRING_SLOT_START+keyringSize, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
- }
- else if (pProto->IsCurrencyToken())
- {
- res = CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- {
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return res;
- }
-
- if (count == 0)
- {
- if (no_similar_count == 0)
- return EQUIP_ERR_OK;
-
- if (no_space_count)
- *no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
- }
- }
-
for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, count, false, false, pItem, bag, slot);
@@ -11177,13 +11153,13 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
if (pItem && pItem->IsNotEmptyBag())
- return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG;
+ return EQUIP_ERR_BAG_IN_BAG;
// search free slot
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, false, pItem, bag, slot);
@@ -11201,7 +11177,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
@@ -11217,14 +11193,14 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_INVENTORY_FULL;
+ return EQUIP_ERR_INV_FULL;
}
//////////////////////////////////////////////////////////////////////////
@@ -11235,13 +11211,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// fill space table
int inv_slot_items[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START];
int inv_bags[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE];
- int inv_keys[KEYRING_SLOT_END - KEYRING_SLOT_START];
- int inv_tokens[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START];
memset(inv_slot_items, 0, sizeof(int) * (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
memset(inv_bags, 0, sizeof(int) * (INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START) * MAX_BAG_SIZE);
- memset(inv_keys, 0, sizeof(int) * (KEYRING_SLOT_END - KEYRING_SLOT_START));
- memset(inv_tokens, 0, sizeof(int) * (CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START));
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
@@ -11250,20 +11222,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
inv_slot_items[i - INVENTORY_SLOT_ITEM_START] = pItem2->GetCount();
}
- for (uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_keys[i - KEYRING_SLOT_START] = pItem2->GetCount();
- }
-
- for (uint8 i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_tokens[i - CURRENCYTOKEN_SLOT_START] = pItem2->GetCount();
- }
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -11291,11 +11249,11 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// item it 'bind'
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
ItemTemplate const* pBagProto;
@@ -11309,32 +11267,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
{
bool b_found = false;
- for (uint8 t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; ++t)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
- {
- inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount();
- b_found = true;
- break;
- }
- }
- if (b_found)
- continue;
-
- for (int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
- {
- inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount();
- b_found = true;
- break;
- }
- }
- if (b_found)
- continue;
-
for (int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++t)
{
pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
@@ -11375,38 +11307,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
if (pProto->BagFamily)
{
bool b_found = false;
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- for (uint32 t = KEYRING_SLOT_START; t < KEYRING_SLOT_START+keyringSize; ++t)
- {
- if (inv_keys[t-KEYRING_SLOT_START] == 0)
- {
- inv_keys[t-KEYRING_SLOT_START] = 1;
- b_found = true;
- break;
- }
- }
- }
-
- if (b_found)
- continue;
-
- if (pProto->IsCurrencyToken())
- {
- for (uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
- {
- if (inv_tokens[t-CURRENCYTOKEN_SLOT_START] == 0)
- {
- inv_tokens[t-CURRENCYTOKEN_SLOT_START] = 1;
- b_found = true;
- break;
- }
- }
- }
-
- if (b_found)
- continue;
for (int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; ++t)
{
@@ -11473,7 +11373,7 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// no free slot found?
if (!b_found)
- return EQUIP_ERR_INVENTORY_FULL;
+ return EQUIP_ERR_INV_FULL;
}
return EQUIP_ERR_OK;
@@ -11505,10 +11405,10 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
{
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
// check count of items (skip for auto move for same player from bank)
InventoryResult res = CanTakeMoreSimilarItems(pItem);
@@ -11521,7 +11421,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
// May be here should be more stronger checks; STUNNED checked
// ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked.
if (HasUnitState(UNIT_STATE_STUNNED))
- return EQUIP_ERR_YOU_ARE_STUNNED;
+ return EQUIP_ERR_GENERIC_STUNNED;
// do not allow equipping gear except weapons, offhands, projectiles, relics in
// - combat
@@ -11537,27 +11437,27 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
}
if (isInCombat()&& (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer != 0)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err
+ return EQUIP_ERR_CLIENT_LOCKED_OUT; // maybe exist better err
if (IsNonMeleeSpellCasted(false))
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
ScalingStatDistributionEntry const* ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0;
// check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items)
if (ssd && ssd->MaxLevel < DEFAULT_MAX_LEVEL && ssd->MaxLevel < getLevel())
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
uint8 eslot = FindEquipSlot(pProto, slot, swap);
if (eslot == NULL_SLOT)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
res = CanUseItem(pItem, not_loading);
if (res != EQUIP_ERR_OK)
return res;
if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot))
- return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE;
+ return EQUIP_ERR_NO_SLOT_AVAILABLE;
// if we are swapping 2 equiped items, CanEquipUniqueItem check
// should ignore the item we are trying to swap, and not the
@@ -11601,8 +11501,8 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (ItemTemplate const* pBagProto = pBag->GetTemplate())
if (pBagProto->Class == pProto->Class && (!swap || pBag->GetSlot() != eslot))
return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
- ? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH
- : EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
+ ? EQUIP_ERR_ONLY_ONE_AMMO
+ : EQUIP_ERR_ONLY_ONE_QUIVER;
uint32 type = pProto->InventoryType;
@@ -11610,21 +11510,20 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
{
// Do not allow polearm to be equipped in the offhand (rare case for the only 1h polearm 41750)
if (type == INVTYPE_WEAPON && pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM)
- return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
-
+ return EQUIP_ERR_2HSKILLNOTFOUND;
else if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
if (!CanDualWield())
- return EQUIP_ERR_CANT_DUAL_WIELD;
+ return EQUIP_ERR_2HSKILLNOTFOUND;
}
else if (type == INVTYPE_2HWEAPON)
{
if (!CanDualWield() || !CanTitanGrip())
- return EQUIP_ERR_CANT_DUAL_WIELD;
+ return EQUIP_ERR_2HSKILLNOTFOUND;
}
if (IsTwoHandUsed())
- return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
+ return EQUIP_ERR_2HANDED_EQUIPPED;
}
// equip two-hand weapon case (with possible unequip 2 items)
@@ -11633,10 +11532,10 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (eslot == EQUIPMENT_SLOT_OFFHAND)
{
if (!CanTitanGrip())
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
}
else if (eslot != EQUIPMENT_SLOT_MAINHAND)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
if (!CanTitanGrip())
{
@@ -11646,7 +11545,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (offItem && (!not_loading ||
CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND, false) != EQUIP_ERR_OK ||
CanStoreItem(NULL_BAG, NULL_SLOT, off_dest, offItem, false) != EQUIP_ERR_OK))
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_INV_FULL;
}
}
dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot);
@@ -11654,7 +11553,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
}
}
- return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
+ return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_CANT_SWAP;
}
InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
@@ -11677,7 +11576,7 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// do not allow unequipping gear except weapons, offhands, projectiles, relics in
// - combat
@@ -11693,7 +11592,7 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
}
if (!swap && pItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
return EQUIP_ERR_OK;
}
@@ -11701,29 +11600,28 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item* pItem, bool swap, bool not_loading) const
{
if (!pItem)
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
uint32 count = pItem->GetCount();
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount());
ItemTemplate const* pProto = pItem->GetTemplate();
if (!pProto)
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
- // Currency tokens are not supposed to be swapped out of their hidden bag
- uint8 pItemslot = pItem->GetSlot();
- if (pItemslot >= CURRENCYTOKEN_SLOT_START && pItemslot < CURRENCYTOKEN_SLOT_END)
+ // Currency Tokenizer are not supposed to be swapped out of their hidden bag
+ if (pItem->IsCurrencyToken())
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Possible hacking attempt: Player %s [guid: %u] tried to move token [guid: %u, entry: %u] out of the currency bag!",
GetName().c_str(), GetGUIDLow(), pItem->GetGUIDLow(), pProto->ItemId);
- return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
+ return EQUIP_ERR_CANT_SWAP;
}
// check count of items (skip for auto move for same player from bank)
@@ -11737,10 +11635,10 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest
if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END)
{
if (!pItem->IsBag())
- return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
+ return EQUIP_ERR_WRONG_SLOT;
if (slot - BANK_SLOT_BAG_START >= GetBankBagSlotCount())
- return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
+ return EQUIP_ERR_NO_BANK_SLOT;
res = CanUseItem(pItem, not_loading);
if (res != EQUIP_ERR_OK)
@@ -11761,7 +11659,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest
if (bag != NULL_BAG)
{
if (pItem->IsNotEmptyBag())
- return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG;
+ return EQUIP_ERR_BAG_IN_BAG;
// search stack in bag for merge to
if (pProto->Stackable != 1)
@@ -11892,16 +11790,16 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "STORAGE: CanUseItem item = %u", pItem->GetEntry());
if (!isAlive() && not_loading)
- return EQUIP_ERR_YOU_ARE_DEAD;
+ return EQUIP_ERR_PLAYER_DEAD;
//if (isStunned())
- // return EQUIP_ERR_YOU_ARE_STUNNED;
+ // return EQUIP_ERR_GENERIC_STUNNED;
ItemTemplate const* pProto = pItem->GetTemplate();
if (pProto)
{
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
InventoryResult res = CanUseItem(pProto);
if (res != EQUIP_ERR_OK)
@@ -11914,8 +11812,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
// Armor that is binded to account can "morph" from plate to mail, etc. if skill is not learned yet.
if (pProto->Quality == ITEM_QUALITY_HEIRLOOM && pProto->Class == ITEM_CLASS_ARMOR && !HasSkill(itemSkill))
{
- /// @todo when you right-click already equipped item it throws EQUIP_ERR_NO_REQUIRED_PROFICIENCY.
-
+ /// @todo when you right-click already equipped item it throws EQUIP_ERR_PROFICIENCY_NEEDED.
// In fact it's a visual bug, everything works properly... I need sniffs of operations with
// binded to account items from off server.
@@ -11932,7 +11829,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
}
}
if (!allowEquip && GetSkillValue(itemSkill) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
}
if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
@@ -11951,31 +11848,31 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
if (proto)
{
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if (proto->RequiredSkill != 0)
{
if (GetSkillValue(proto->RequiredSkill) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank)
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
if (getLevel() < proto->RequiredLevel)
return EQUIP_ERR_CANT_EQUIP_LEVEL_I;
// If World Event is not active, prevent using event dependant items
if (proto->HolidayId && !IsHolidayActive((HolidayIds)proto->HolidayId))
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
return EQUIP_ERR_OK;
}
@@ -12007,15 +11904,15 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
}; //Copy from function Item::GetSkill()
if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
if (proto->RequiredSkill != 0)
{
if (!GetSkillValue(proto->RequiredSkill))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank)
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
@@ -12023,108 +11920,43 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
uint8 _class = getClass();
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
- if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISC && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
+ if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
{
if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
if (_class == CLASS_ROGUE || _class == CLASS_DRUID)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
return EQUIP_ERR_OK;
}
-InventoryResult Player::CanUseAmmo(uint32 item) const
-{
- TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "STORAGE: CanUseAmmo item = %u", item);
- if (!isAlive())
- return EQUIP_ERR_YOU_ARE_DEAD;
- //if (isStunned())
- // return EQUIP_ERR_YOU_ARE_STUNNED;
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
- if (pProto)
- {
- if (pProto->InventoryType!= INVTYPE_AMMO)
- return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE;
-
- InventoryResult res = CanUseItem(pProto);
- if (res != EQUIP_ERR_OK)
- return res;
-
- /*if (GetReputationMgr().GetReputation() < pProto->RequiredReputation)
- return EQUIP_ERR_CANT_EQUIP_REPUTATION;
- */
-
- // Requires No Ammo
- if (HasAura(46699))
- return EQUIP_ERR_BAG_FULL6;
-
- return EQUIP_ERR_OK;
- }
- return EQUIP_ERR_ITEM_NOT_FOUND;
-}
-
-void Player::SetAmmo(uint32 item)
-{
- if (!item)
- return;
-
- // already set
- if (GetUInt32Value(PLAYER_AMMO_ID) == item)
- return;
-
- // check ammo
- if (item)
- {
- InventoryResult msg = CanUseAmmo(item);
- if (msg != EQUIP_ERR_OK)
- {
- SendEquipError(msg, NULL, NULL, item);
- return;
- }
- }
-
- SetUInt32Value(PLAYER_AMMO_ID, item);
-
- _ApplyAmmoBonuses();
-}
-
-void Player::RemoveAmmo()
-{
- SetUInt32Value(PLAYER_AMMO_ID, 0);
-
- m_ammoDPS = 0.0f;
-
- if (CanModifyStats())
- UpdateDamagePhysical(RANGED_ATTACK);
-}
-
// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update, int32 randomPropertyId, AllowedLooterSet const& allowedLooters)
{
@@ -12226,10 +12058,6 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
pItem->SetSlot(slot);
pItem->SetContainer(NULL);
-
- // need update known currency
- if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END)
- AddKnownCurrency(pItem->GetEntry());
}
else
pBag->StoreItem(slot, pItem, update);
@@ -12447,7 +12275,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem)
{
if (pItem)
{
- SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetEntry());
+ SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetVisibleEntry());
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0, pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 1, pItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT));
}
@@ -12745,34 +12573,6 @@ void Player::DestroyItemCount(uint32 itemEntry, uint32 count, bool update, bool
}
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- {
- if (item->GetEntry() == itemEntry && !item->IsInTrade())
- {
- if (item->GetCount() + remcount <= count)
- {
- // all keys can be unequipped
- remcount += item->GetCount();
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
-
- if (remcount >= count)
- return;
- }
- else
- {
- ItemRemovedQuestCheck(item->GetEntry(), count - remcount);
- item->SetCount(item->GetCount() - count + remcount);
- if (IsInWorld() && update)
- item->SendUpdateToPlayer(this);
- item->SetState(ITEM_CHANGED, this);
- return;
- }
- }
- }
- }
-
// in inventory bags
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
@@ -12912,11 +12712,6 @@ void Player::DestroyZoneLimitedItem(bool update, uint32 new_zone)
if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone))
DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone))
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
-
// in inventory bags
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
@@ -12967,11 +12762,6 @@ Item* Player::GetItemByEntry(uint32 entry) const
if (pItem->GetEntry() == entry)
return pItem;
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetEntry() == entry)
- return pItem;
-
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
@@ -13029,21 +12819,21 @@ void Player::SplitItem(uint16 src, uint16 dst, uint32 count)
if (pSrcItem->m_lootGenerated) // prevent split looting item (item
{
//best error message found for attempting to split while looting
- SendEquipError(EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_SPLIT_FAILED, pSrcItem, NULL);
return;
}
// not let split all items (can be only at cheating)
if (pSrcItem->GetCount() == count)
{
- SendEquipError(EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_SPLIT_FAILED, pSrcItem, NULL);
return;
}
// not let split more existed items (can be only at cheating)
if (pSrcItem->GetCount() < count)
{
- SendEquipError(EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_TOO_FEW_TO_SPLIT, pSrcItem, NULL);
return;
}
@@ -13144,7 +12934,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (!isAlive())
{
- SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_PLAYER_DEAD, pSrcItem, pDstItem);
return;
}
@@ -13153,7 +12943,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (pSrcItem->m_lootGenerated) // prevent swap looting item
{
//best error message found for attempting to swap while looting
- SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, pSrcItem, NULL);
return;
}
@@ -13172,14 +12962,14 @@ void Player::SwapItem(uint16 src, uint16 dst)
// prevent put equipped/bank bag in self
if (IsBagPos(src) && srcslot == dstbag)
{
- SendEquipError(EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_BAG_IN_BAG, pSrcItem, pDstItem);
return;
}
// prevent equipping bag in the same slot from its inside
if (IsBagPos(dst) && srcbag == dstslot)
{
- SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_CANT_SWAP, pSrcItem, pDstItem);
return;
}
@@ -13190,7 +12980,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (pDstItem->m_lootGenerated) // prevent swap looting item
{
//best error message found for attempting to swap while looting
- SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL);
+ SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, pDstItem, NULL);
return;
}
@@ -13387,7 +13177,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (!bagItemProto || !ItemCanGoIntoBag(bagItemProto, emptyProto))
{
// one from items not go to empty target bag
- SendEquipError(EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_BAG_IN_BAG, pSrcItem, pDstItem);
return;
}
@@ -13397,7 +13187,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (count > emptyBag->GetBagSize())
{
// too small targeted bag
- SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_CANT_SWAP, pSrcItem, pDstItem);
return;
}
@@ -13591,16 +13381,16 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint
data << uint32(proto ? proto->RequiredLevel : 0);
break;
}
- case EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM: // no idea about this one...
+ case EQUIP_ERR_NO_OUTPUT: // no idea about this one...
{
data << uint64(0); // item guid
data << uint32(0); // slot
data << uint64(0); // container
break;
}
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED:
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED:
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED_IS:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS:
{
ItemTemplate const* proto = pItem ? pItem->GetTemplate() : sObjectMgr->GetItemTemplate(itemid);
data << uint32(proto ? proto->ItemLimitCategory : 0);
@@ -13613,26 +13403,22 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint
GetSession()->SendPacket(&data);
}
-void Player::SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 param)
+void Player::SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 /*param*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_BUY_FAILED");
WorldPacket data(SMSG_BUY_FAILED, (8+4+4+1));
data << uint64(creature ? creature->GetGUID() : 0);
data << uint32(item);
- if (param > 0)
- data << uint32(param);
data << uint8(msg);
GetSession()->SendPacket(&data);
}
-void Player::SendSellError(SellResult msg, Creature* creature, uint64 guid, uint32 param)
+void Player::SendSellError(SellResult msg, Creature* creature, uint64 guid)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_SELL_ITEM");
- WorldPacket data(SMSG_SELL_ITEM, (8+8+(param?4:0)+1)); // last check 2.0.10
+ WorldPacket data(SMSG_SELL_ITEM, (8+8+1)); // last check 4.3.4
data << uint64(creature ? creature->GetGUID() : 0);
data << uint64(guid);
- if (param > 0)
- data << uint32(param);
data << uint8(msg);
GetSession()->SendPacket(&data);
}
@@ -13748,6 +13534,9 @@ void Player::AddEnchantmentDurations(Item* item)
{
for (int x = 0; x < MAX_ENCHANTMENT_SLOT; ++x)
{
+ if (x > PRISMATIC_ENCHANTMENT_SLOT || x < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (!item->GetEnchantmentId(EnchantmentSlot(x)))
continue;
@@ -13842,10 +13631,257 @@ void Player::AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 dur
}
}
+void Player::ApplyReforgeEnchantment(Item* item, bool apply)
+{
+ if (!item)
+ return;
+
+ ItemReforgeEntry const* reforge = sItemReforgeStore.LookupEntry(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT));
+ if (!reforge)
+ return;
+
+ float removeValue = item->GetReforgableStat(ItemModType(reforge->SourceStat)) * reforge->SourceMultiplier;
+ float addValue = removeValue * reforge->FinalMultiplier;
+
+ switch (reforge->SourceStat)
+ {
+ case ITEM_MOD_MANA:
+ HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_HEALTH:
+ HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_AGILITY:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_AGILITY, -removeValue, apply);
+ break;
+ case ITEM_MOD_STRENGTH:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_STRENGTH, -removeValue, apply);
+ break;
+ case ITEM_MOD_INTELLECT:
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_INTELLECT, -removeValue, apply);
+ break;
+ case ITEM_MOD_SPIRIT:
+ HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_SPIRIT, -removeValue, apply);
+ break;
+ case ITEM_MOD_STAMINA:
+ HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_STAMINA, -removeValue, apply);
+ break;
+ case ITEM_MOD_DEFENSE_SKILL_RATING:
+ ApplyRatingMod(CR_DEFENSE_SKILL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_DODGE_RATING:
+ ApplyRatingMod(CR_DODGE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_PARRY_RATING:
+ ApplyRatingMod(CR_PARRY, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_BLOCK_RATING:
+ ApplyRatingMod(CR_BLOCK, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_MELEE_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_RANGED_RATING:
+ ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_SPELL_RATING:
+ ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_MELEE_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RANGED_RATING:
+ ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_SPELL_RATING:
+ ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HASTE_SPELL_RATING:
+ ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_RESILIENCE_RATING:
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HASTE_RATING:
+ ApplyRatingMod(CR_HASTE_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HASTE_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_EXPERTISE_RATING:
+ ApplyRatingMod(CR_EXPERTISE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, -removeValue, apply);
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ApplyRatingMod(CR_ARMOR_PENETRATION, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellPowerBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ApplyHealthRegenBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_SPELL_PENETRATION:
+ ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(removeValue), apply);
+ m_spellPenetrationItemMod += apply ? -int32(removeValue) : int32(removeValue);
+ break;
+ case ITEM_MOD_BLOCK_VALUE:
+ HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, -removeValue, apply);
+ break;
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, -int32(removeValue), apply);
+ break;
+ }
+
+ switch (reforge->FinalStat)
+ {
+ case ITEM_MOD_MANA:
+ HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_HEALTH:
+ HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_AGILITY:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_AGILITY, addValue, apply);
+ break;
+ case ITEM_MOD_STRENGTH:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_STRENGTH, addValue, apply);
+ break;
+ case ITEM_MOD_INTELLECT:
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_INTELLECT, addValue, apply);
+ break;
+ case ITEM_MOD_SPIRIT:
+ HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_SPIRIT, addValue, apply);
+ break;
+ case ITEM_MOD_STAMINA:
+ HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_STAMINA, addValue, apply);
+ break;
+ case ITEM_MOD_DEFENSE_SKILL_RATING:
+ ApplyRatingMod(CR_DEFENSE_SKILL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_DODGE_RATING:
+ ApplyRatingMod(CR_DODGE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_PARRY_RATING:
+ ApplyRatingMod(CR_PARRY, int32(addValue), apply);
+ break;
+ case ITEM_MOD_BLOCK_RATING:
+ ApplyRatingMod(CR_BLOCK, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_MELEE_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_RANGED_RATING:
+ ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_SPELL_RATING:
+ ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_MELEE_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RANGED_RATING:
+ ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_SPELL_RATING:
+ ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HASTE_SPELL_RATING:
+ ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_RESILIENCE_RATING:
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HASTE_RATING:
+ ApplyRatingMod(CR_HASTE_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_HASTE_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_EXPERTISE_RATING:
+ ApplyRatingMod(CR_EXPERTISE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, addValue, apply);
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ApplyRatingMod(CR_ARMOR_PENETRATION, int32(addValue), apply);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellPowerBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ApplyHealthRegenBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_SPELL_PENETRATION:
+ ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, int32(addValue), apply);
+ m_spellPenetrationItemMod += apply ? int32(addValue) : -int32(addValue);
+ break;
+ case ITEM_MOD_BLOCK_VALUE:
+ HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, addValue, apply);
+ break;
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, int32(addValue), apply);
+ break;
+ }
+}
+
void Player::ApplyEnchantment(Item* item, bool apply)
{
for (uint32 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
+ {
+ // Apply reforge as last enchant
+ if (slot == REFORGE_ENCHANTMENT_SLOT)
+ continue;
+
ApplyEnchantment(item, EnchantmentSlot(slot), apply);
+ }
+
+ ApplyEnchantment(item, REFORGE_ENCHANTMENT_SLOT, apply);
}
void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition)
@@ -13856,6 +13892,15 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (slot >= MAX_ENCHANTMENT_SLOT)
return;
+ if (slot == TRANSMOGRIFY_ENCHANTMENT_SLOT)
+ return;
+
+ if (slot == REFORGE_ENCHANTMENT_SLOT)
+ {
+ ApplyReforgeEnchantment(item, apply);
+ return;
+ }
+
uint32 enchant_id = item->GetEnchantmentId(slot);
if (!enchant_id)
return;
@@ -13873,6 +13918,11 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (pEnchant->requiredSkill > 0 && pEnchant->requiredSkillValue > GetSkillValue(pEnchant->requiredSkill))
return;
+ // Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2
+ if (ItemTemplate const* gem = sObjectMgr->GetItemTemplate(pEnchant->GemID))
+ if (gem->RequiredSkill && GetSkillValue(gem->RequiredSkill) < gem->RequiredSkillRank)
+ return;
+
// If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements
// rather than the gem requirements itself. If the socket has no color it is a prismatic socket.
if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3)
@@ -13914,13 +13964,13 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
{
int32 basepoints = 0;
// Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor)
- if (item->GetItemRandomPropertyId())
+ if (item->GetItemRandomPropertyId() < 0)
{
ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId()));
if (item_rand)
{
// Search enchant_amount
- for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ for (int k = 0; k < 5; ++k)
{
if (item_rand->enchant_id[k] == enchant_id)
{
@@ -13966,7 +14016,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ItemRandomSuffixEntry const* item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId()));
if (item_rand_suffix)
{
- for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ for (int k = 0; k < 5; ++k)
{
if (item_rand_suffix->enchant_id[k] == enchant_id)
{
@@ -14053,32 +14103,32 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u SPELL_CRIT", enchant_amount);
break;
-// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used
-// in Enchantments
-// case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HASTE_MELEE_RATING:
-// ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HASTE_RANGED_RATING:
-// ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply);
-// break;
+ // Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used
+ // in Enchantments
+ // case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HASTE_MELEE_RATING:
+ // ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HASTE_RANGED_RATING:
+ // ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply);
+ // break;
case ITEM_MOD_HASTE_SPELL_RATING:
ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply);
break;
@@ -14094,21 +14144,18 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u CRITICAL", enchant_amount);
break;
-// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment
-// case ITEM_MOD_HIT_TAKEN_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
-// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
-// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
-// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
-// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
+ // case ITEM_MOD_HIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
case ITEM_MOD_RESILIENCE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, enchant_amount, apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u RESILIENCE", enchant_amount);
break;
case ITEM_MOD_HASTE_RATING:
@@ -14130,10 +14177,6 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u RANGED_ATTACK_POWER", enchant_amount);
break;
-// case ITEM_MOD_FERAL_ATTACK_POWER:
-// ApplyFeralAPBonus(enchant_amount, apply);
-// TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u FERAL_ATTACK_POWER", enchant_amount);
-// break;
case ITEM_MOD_MANA_REGENERATION:
ApplyManaRegenBonus(enchant_amount, apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u MANA_REGENERATION", enchant_amount);
@@ -14159,8 +14202,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u BLOCK_VALUE", enchant_amount);
break;
- case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
- case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, enchant_amount, apply);
+ TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u MASTERY", enchant_amount);
+ break;
default:
break;
}
@@ -14229,6 +14274,9 @@ void Player::UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16
{
for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
{
+ if (slot > PRISMATIC_ENCHANTMENT_SLOT || slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 ench_id = m_items[i]->GetEnchantmentId(EnchantmentSlot(slot));
if (!ench_id)
continue;
@@ -14269,17 +14317,13 @@ void Player::UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16
void Player::SendEnchantmentDurations()
{
for (EnchantDurationList::const_iterator itr = m_enchantDuration.begin(); itr != m_enchantDuration.end(); ++itr)
- {
GetSession()->SendItemEnchantTimeUpdate(GetGUID(), itr->item->GetGUID(), itr->slot, uint32(itr->leftduration) / 1000);
- }
}
void Player::SendItemDurations()
{
for (ItemDurationList::const_iterator itr = m_itemDuration.begin(); itr != m_itemDuration.end(); ++itr)
- {
(*itr)->SendTimeUpdate(this);
- }
}
void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast)
@@ -14513,7 +14557,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
return;
int32 cost = int32(item->BoxMoney);
- if (!HasEnoughMoney(cost))
+ if (!HasEnoughMoney(int64(cost)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
PlayerTalkClass->SendCloseGossip();
@@ -14682,11 +14726,11 @@ void Player::PrepareQuestMenu(uint64 guid)
//only for quests which cast teleport spells on player
Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
ASSERT(_map);
- GameObject* pGameObject = _map->GetGameObject(guid);
- if (pGameObject)
+ GameObject* gameObject = _map->GetGameObject(guid);
+ if (gameObject)
{
- objectQR = sObjectMgr->GetGOQuestRelationBounds(pGameObject->GetEntry());
- objectQIR = sObjectMgr->GetGOQuestInvolvedRelationBounds(pGameObject->GetEntry());
+ objectQR = sObjectMgr->GetGOQuestRelationBounds(gameObject->GetEntry());
+ objectQIR = sObjectMgr->GetGOQuestInvolvedRelationBounds(gameObject->GetEntry());
}
else
return;
@@ -14822,24 +14866,40 @@ bool Player::IsActiveQuest(uint32 quest_id) const
Quest const* Player::GetNextQuest(uint64 guid, Quest const* quest)
{
QuestRelationBounds objectQR;
+ uint32 nextQuestID = quest->GetNextQuestInChain();
- Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid);
- if (creature)
- objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry());
- else
+ switch (GUID_HIPART(guid))
{
- //we should obtain map pointer from GetMap() in 99% of cases. Special case
- //only for quests which cast teleport spells on player
- Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
- ASSERT(_map);
- GameObject* pGameObject = _map->GetGameObject(guid);
- if (pGameObject)
- objectQR = sObjectMgr->GetGOQuestRelationBounds(pGameObject->GetEntry());
- else
+ case HIGHGUID_PLAYER:
+ ASSERT(quest->HasFlag(QUEST_FLAGS_AUTO_SUBMIT));
+ return sObjectMgr->GetQuestTemplate(nextQuestID);
+ case HIGHGUID_UNIT:
+ case HIGHGUID_PET:
+ case HIGHGUID_VEHICLE:
+ {
+ if (Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid))
+ objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry());
+ else
+ return NULL;
+ break;
+ }
+ case HIGHGUID_GAMEOBJECT:
+ {
+ //we should obtain map pointer from GetMap() in 99% of cases. Special case
+ //only for quests which cast teleport spells on player
+ Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
+ ASSERT(_map);
+ if (GameObject* gameObject = _map->GetGameObject(guid))
+ objectQR = sObjectMgr->GetGOQuestRelationBounds(gameObject->GetEntry());
+ else
+ return NULL;
+ break;
+ }
+ default:
return NULL;
}
- uint32 nextQuestID = quest->GetNextQuestInChain();
+ // for unit and go state
for (QuestRelations::const_iterator itr = objectQR.first; itr != objectQR.second; ++itr)
{
if (itr->second == nextQuestID)
@@ -14889,7 +14949,7 @@ bool Player::CanAddQuest(Quest const* quest, bool msg)
InventoryResult msg2 = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, srcitem, count);
// player already have max number (in most case 1) source item, no additional item needed and quest can be added.
- if (msg2 == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ if (msg2 == EQUIP_ERR_ITEM_MAX_COUNT)
return true;
else if (msg2 != EQUIP_ERR_OK)
{
@@ -14923,7 +14983,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
{
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
{
@@ -14932,7 +14992,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
}
}
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
{
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
{
@@ -14944,19 +15004,19 @@ bool Player::CanCompleteQuest(uint32 quest_id)
}
}
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
if (qInfo->GetPlayersSlain() != 0 && q_status.PlayerCount < qInfo->GetPlayersSlain())
return false;
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored)
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored)
return false;
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && q_status.Timer == 0)
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && q_status.Timer == 0)
return false;
if (qInfo->GetRewOrReqMoney() < 0)
{
- if (!HasEnoughMoney(-qInfo->GetRewOrReqMoney()))
+ if (!HasEnoughMoney(-int64(qInfo->GetRewOrReqMoney())))
return false;
}
@@ -14978,7 +15038,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest)
if (!CanTakeQuest(quest, false))
return false;
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
if (quest->RequiredItemId[i] && quest->RequiredItemCount[i] && !HasItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i]))
return false;
@@ -15004,7 +15064,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg)
return false;
// prevent receive reward with quest items in bank
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
{
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
{
@@ -15018,8 +15078,12 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg)
}
}
+ for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; i++)
+ if (quest->RequiredCurrencyId[i] && !HasCurrency(quest->RequiredCurrencyId[i], quest->RequiredCurrencyCount[i]))
+ return false;
+
// prevent receive reward with low money and GetRewOrReqMoney() < 0
- if (quest->GetRewOrReqMoney() < 0 && !HasEnoughMoney(-quest->GetRewOrReqMoney()))
+ if (quest->GetRewOrReqMoney() < 0 && !HasEnoughMoney(-int64(quest->GetRewOrReqMoney())))
return false;
return true;
@@ -15081,19 +15145,19 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
questStatusData.Status = QUEST_STATUS_INCOMPLETE;
questStatusData.Explored = false;
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
{
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
questStatusData.ItemCount[i] = 0;
}
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
{
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
questStatusData.CreatureOrGOCount[i] = 0;
}
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
questStatusData.PlayerCount = 0;
GiveQuestSourceItem(quest);
@@ -15108,7 +15172,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
GetReputationMgr().SetVisible(factionEntry);
uint32 qtime = 0;
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
{
uint32 limittime = quest->GetLimitTime();
@@ -15153,7 +15217,7 @@ void Player::CompleteQuest(uint32 quest_id)
if (qInfo->HasFlag(QUEST_FLAGS_TRACKING))
RewardQuest(qInfo, 0, this, false);
else
- SendQuestComplete(quest_id);
+ SendQuestComplete(qInfo);
}
}
}
@@ -15182,6 +15246,10 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (quest->RequiredItemId[i])
DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true);
+ for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ if (quest->RequiredCurrencyId[i])
+ ModifyCurrency(quest->RequiredCurrencyId[i], -int32(quest->RequiredCurrencyCount[i]));
+
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
if (quest->RequiredSourceItemId[i])
@@ -15222,6 +15290,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
}
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ if (quest->RewardCurrencyId[i])
+ ModifyCurrency(quest->RewardCurrencyId[i], quest->RewardCurrencyCount[i]);
+
+ if (uint32 skill = quest->GetRewardSkillId())
+ UpdateSkillPro(skill, 1000, quest->GetRewardSkillPoints());
+
RewardReputation(quest);
uint16 log_slot = FindQuestSlot(quest_id);
@@ -15231,7 +15306,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
bool rewarded = (m_RewardedQuests.find(quest_id) != m_RewardedQuests.end());
// Not give XP in case already completed once repeatable quest
- uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST));
+ uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST));
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
@@ -15244,6 +15319,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
else
moneyRew = int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY));
+ if (Guild* guild = sGuildMgr->GetGuildById(GetGuildId()))
+ guild->GiveXP(uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST) * sWorld->getRate(RATE_XP_GUILD_MODIFIER)), this);
+
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
if (quest->GetRewOrReqMoney())
moneyRew += quest->GetRewOrReqMoney();
@@ -15267,15 +15345,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
+ if (uint32 talents = quest->GetBonusTalents())
{
- m_questRewardTalentCount+=quest->GetBonusTalents();
+ AddQuestRewardedTalentCount(talents);
InitTalentForLevel();
}
- if (quest->GetRewArenaPoints())
- ModifyArenaPoints(quest->GetRewArenaPoints());
-
// Send reward mail
if (uint32 mail_template_id = quest->GetRewMailTemplateId())
{
@@ -15349,7 +15424,7 @@ void Player::FailQuest(uint32 questId)
SetQuestSlotState(log_slot, QUEST_STATE_FAIL);
}
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
{
QuestStatusData& q_status = m_QuestStatus[questId];
@@ -15604,7 +15679,7 @@ bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg)
bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg)
{
- if (!m_timedquests.empty() && qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED))
+ if (!m_timedquests.empty() && qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
{
if (msg)
SendCanTakeQuestResponse(INVALIDREASON_QUEST_ONLY_ONE_TIMED);
@@ -15784,7 +15859,7 @@ bool Player::GiveQuestSourceItem(Quest const* quest)
return true;
}
// player already have max amount required item, just report success
- else if (msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ else if (msg == EQUIP_ERR_ITEM_MAX_COUNT)
return true;
else
SendEquipError(msg, NULL, NULL, srcitem);
@@ -15882,6 +15957,11 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
m_QuestStatusSave[quest_id] = true;
}
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
uint32 zone = 0, area = 0;
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id);
@@ -15916,6 +15996,11 @@ void Player::RemoveActiveQuest(uint32 quest_id)
{
m_QuestStatus.erase(itr);
m_QuestStatusSave[quest_id] = false;
+
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
return;
}
}
@@ -15927,6 +16012,11 @@ void Player::RemoveRewardedQuest(uint32 quest_id)
{
m_RewardedQuests.erase(rewItr);
m_RewardedQuestsSave[quest_id] = false;
+
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
}
}
@@ -15946,7 +16036,7 @@ uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry)
void Player::AdjustQuestReqItemCount(Quest const* quest, QuestStatusData& questStatusData)
{
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
{
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
@@ -16087,7 +16177,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
continue;
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid);
- if (!qInfo || !qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (!qInfo || !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
continue;
for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
@@ -16104,7 +16194,8 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
m_QuestStatusSave[questid] = true;
- SendQuestUpdateAddItem(qInfo, j, additemcount);
+ //SendQuestUpdateAddItem(qInfo, j, additemcount);
+ // FIXME: verify if there's any packet sent updating item
}
if (CanCompleteQuest(questid))
CompleteQuest(questid);
@@ -16125,7 +16216,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid);
if (!qInfo)
continue;
- if (!qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
+ if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
continue;
for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
@@ -16182,7 +16273,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid)
}
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, killed);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, 0, killed);
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
@@ -16197,7 +16288,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid)
QuestStatusData& q_status = m_QuestStatus[questid];
if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty())))
{
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST))
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
@@ -16252,7 +16343,7 @@ void Player::KilledPlayerCredit()
QuestStatusData& q_status = m_QuestStatus[questid];
if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty())))
{
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
{
uint32 reqkill = qInfo->GetPlayersSlain();
uint16 curkill = q_status.PlayerCount;
@@ -16294,7 +16385,7 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id)
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST))
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
@@ -16377,7 +16468,7 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid)
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
- if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO))
+ if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
{
@@ -16561,39 +16652,50 @@ bool Player::HasQuestForItem(uint32 itemid) const
return false;
}
-void Player::SendQuestComplete(uint32 quest_id)
+void Player::SendQuestComplete(Quest const* quest)
{
- if (quest_id)
+ if (quest)
{
WorldPacket data(SMSG_QUESTUPDATE_COMPLETE, 4);
- data << uint32(quest_id);
+ data << uint32(quest->GetQuestId());
GetSession()->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest->GetQuestId());
}
}
void Player::SendQuestReward(Quest const* quest, uint32 XP)
{
- uint32 questid = quest->GetQuestId();
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid);
- sGameEventMgr->HandleQuestComplete(questid);
- WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4));
- data << uint32(questid);
+ uint32 questId = quest->GetQuestId();
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questId);
+ sGameEventMgr->HandleQuestComplete(questId);
+
+ uint32 xp;
+ uint32 moneyReward;
if (getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
- data << uint32(XP);
- data << uint32(quest->GetRewOrReqMoney());
+ xp = XP;
+ moneyReward = quest->GetRewOrReqMoney();
}
- else
+ else // At max level, increase gold reward
{
- data << uint32(0);
- data << uint32(quest->GetRewOrReqMoney() + int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY)));
+ xp = 0;
+ moneyReward = uint32(quest->GetRewOrReqMoney() + int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY)));
}
- data << uint32(10 * quest->CalculateHonorGain(GetQuestLevel(quest)));
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints());
+ WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4));
+
+ data << uint32(quest->GetBonusTalents()); // bonus talents (not verified for 4.x)
+ data << uint32(quest->GetRewardSkillPoints()); // 4.x bonus skill points
+ data << uint32(moneyReward);
+ data << uint32(xp);
+ data << uint32(questId);
+ data << uint32(quest->GetRewardSkillId()); // 4.x bonus skill id
+
+ data.WriteBit(0); // FIXME: unknown bits, common values sent
+ data.WriteBit(1);
+ data.FlushBits();
+
GetSession()->SendPacket(&data);
}
@@ -16661,15 +16763,6 @@ void Player::SendPushToPartyResponse(Player* player, uint32 msg)
}
}
-void Player::SendQuestUpdateAddItem(Quest const* /*quest*/, uint32 /*item_idx*/, uint16 /*count*/)
-{
- WorldPacket data(SMSG_QUESTUPDATE_ADD_ITEM, 0);
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM");
- //data << quest->RequiredItemId[item_idx];
- //data << count;
- GetSession()->SendPacket(&data);
-}
-
void Player::SendQuestUpdateAddCreatureOrGo(Quest const* quest, uint64 guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count)
{
ASSERT(old_count + add_count < 65536 && "mob/GO count store in 16 bits 2^16 = 65536 (0..65536)");
@@ -16910,12 +17003,14 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
//QueryResult* result = CharacterDatabase.PQuery("SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
// 12 13 14 15 16 17 18 19 20 21 22 23 24
//"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
- // 25 26 27 28 29 30 31 32 33 34 35 36 37 38
- //"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
- // 39 40 41 42 43 44 45 46 47 48 49
- //"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, "
- // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
- //"health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
+ // 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
+ //"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
+ // 40 41 42 43 44 45
+ //"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
+ // 46 47 48 49 50 51 52 53 54 55 56
+ //"health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, "
+ // 57 58 59
+ //"knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM);
if (!result)
{
@@ -16979,8 +17074,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
SetUInt32Value(PLAYER_XP, fields[7].GetUInt32());
- _LoadIntoDataField(fields[61].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
- _LoadIntoDataField(fields[64].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
+ _LoadIntoDataField(fields[55].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
+ _LoadIntoDataField(fields[57].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
SetObjectScale(1.0f);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
@@ -16988,7 +17083,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateAchievementCriteria)
m_achievementMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS));
- uint32 money = fields[8].GetUInt32();
+ uint64 money = fields[8].GetUInt64();
if (money > MAX_MONEY_AMOUNT)
money = MAX_MONEY_AMOUNT;
SetMoney(money);
@@ -16996,16 +17091,12 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetUInt32Value(PLAYER_BYTES, fields[9].GetUInt32());
SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32());
SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8());
- SetByteValue(PLAYER_BYTES_3, 1, fields[49].GetUInt8());
+ SetByteValue(PLAYER_BYTES_3, 1, fields[45].GetUInt8());
SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32());
- SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetUInt32());
-
- SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64());
-
- SetUInt32Value(PLAYER_AMMO_ID, fields[63].GetUInt32());
+ SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[44].GetUInt32());
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
- SetByteValue(PLAYER_FIELD_BYTES, 2, fields[65].GetUInt8());
+ SetByteValue(PLAYER_FIELD_BYTES, 2, fields[58].GetUInt8());
InitDisplayIds();
@@ -17033,21 +17124,23 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
InitPrimaryProfessions(); // to max set before any spell loaded
// init saved position, and fix it later if problematic
- uint32 transGUID = fields[30].GetUInt32();
+ uint32 transGUID = uint32(fields[31].GetUInt32());
+
Relocate(fields[12].GetFloat(), fields[13].GetFloat(), fields[14].GetFloat(), fields[16].GetFloat());
+
uint32 mapId = fields[15].GetUInt16();
- uint32 instanceId = fields[58].GetUInt32();
+ uint32 instanceId = fields[52].GetUInt32();
- uint32 dungeonDiff = fields[38].GetUInt8() & 0x0F;
+ uint32 dungeonDiff = fields[39].GetUInt8() & 0x0F;
if (dungeonDiff >= MAX_DUNGEON_DIFFICULTY)
dungeonDiff = DUNGEON_DIFFICULTY_NORMAL;
- uint32 raidDiff = (fields[38].GetUInt8() >> 4) & 0x0F;
+ uint32 raidDiff = (fields[39].GetUInt8() >> 4) & 0x0F;
if (raidDiff >= MAX_RAID_DIFFICULTY)
raidDiff = RAID_DIFFICULTY_10MAN_NORMAL;
SetDungeonDifficulty(Difficulty(dungeonDiff)); // may be changed in _LoadGroup
SetRaidDifficulty(Difficulty(raidDiff)); // may be changed in _LoadGroup
- std::string taxi_nodes = fields[37].GetString();
+ std::string taxi_nodes = fields[38].GetString();
#define RelocateToHomebind(){ mapId = m_homebindMapId; instanceId = 0; Relocate(m_homebindX, m_homebindY, m_homebindZ); }
@@ -17055,8 +17148,6 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadArenaTeamInfo(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ARENA_INFO));
- SetArenaPoints(fields[39].GetUInt32());
-
// check arena teams integrity
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
@@ -17073,12 +17164,10 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetArenaTeamInfoField(arena_slot, ArenaTeamInfoType(j), 0);
}
- SetHonorPoints(fields[40].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[43].GetUInt32());
- SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[44].GetUInt16());
- SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[45].GetUInt16());
+ _LoadCurrency(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CURRENCY));
+ SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[40].GetUInt32());
+ SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[41].GetUInt16());
+ SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[42].GetUInt16());
_LoadBoundInstances(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES));
_LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES));
@@ -17142,17 +17231,17 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
else if (transGUID)
{
m_movementInfo.t_guid = MAKE_NEW_GUID(transGUID, 0, HIGHGUID_MO_TRANSPORT);
- m_movementInfo.t_pos.Relocate(fields[26].GetFloat(), fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat());
+ m_movementInfo.t_pos.Relocate(fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), fields[30].GetFloat());
if (!Trinity::IsValidMapCoord(
GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY,
- GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.m_orientation) ||
+ GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation()) ||
// transport size limited
m_movementInfo.t_pos.m_positionX > 250 || m_movementInfo.t_pos.m_positionY > 250 || m_movementInfo.t_pos.m_positionZ > 250)
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.",
guid, GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY,
- GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.m_orientation);
+ GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation());
RelocateToHomebind();
}
@@ -17249,7 +17338,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
if (!map)
{
instanceId = 0;
- AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(mapId);
+ AreaTriggerStruct const* at = sObjectMgr->GetGoBackTrigger(mapId);
if (at)
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (guidlow %d) is teleported to gobacktrigger (Map: %u X: %f Y: %f Z: %f O: %f).", guid, mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
@@ -17281,7 +17370,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// if the player is in an instance and it has been reset in the meantime teleport him to the entrance
if (instanceId && !sInstanceSaveMgr->GetInstanceSave(instanceId) && !map->IsBattlegroundOrArena())
{
- AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(mapId);
+ AreaTriggerStruct const* at = sObjectMgr->GetMapEntranceTrigger(mapId);
if (at)
Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation);
else
@@ -17318,28 +17407,28 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
m_Played_time[PLAYED_TIME_TOTAL]= fields[19].GetUInt32();
m_Played_time[PLAYED_TIME_LEVEL]= fields[20].GetUInt32();
- m_resetTalentsCost = fields[24].GetUInt32();
- m_resetTalentsTime = time_t(fields[25].GetUInt32());
+ SetTalentResetCost(fields[24].GetUInt32());
+ SetTalentResetTime(time_t(fields[25].GetUInt32()));
m_taxi.LoadTaxiMask(fields[17].GetString()); // must be before InitTaxiNodesForLevel
- uint32 extraflags = fields[31].GetUInt16();
+ uint32 extraflags = fields[32].GetUInt16();
- m_stableSlots = fields[32].GetUInt8();
+ m_stableSlots = fields[33].GetUInt8();
if (m_stableSlots > MAX_PET_STABLES)
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player can have not more %u stable slots, but have in DB %u", MAX_PET_STABLES, uint32(m_stableSlots));
m_stableSlots = MAX_PET_STABLES;
}
- m_atLoginFlags = fields[33].GetUInt16();
+ m_atLoginFlags = fields[34].GetUInt16();
// Honor system
// Update Honor kills data
m_lastHonorUpdateTime = logoutTime;
UpdateHonorFields();
- m_deathExpireTime = time_t(fields[36].GetUInt32());
+ m_deathExpireTime = time_t(fields[37].GetUInt32());
if (m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP)
m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1;
@@ -17399,14 +17488,26 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
//mails are loaded only when needed ;-) - when player in game click on mailbox.
//_LoadMail();
- m_specsCount = fields[59].GetUInt8();
- m_activeSpec = fields[60].GetUInt8();
+ SetSpecsCount(fields[53].GetUInt8());
+ SetActiveSpec(fields[54].GetUInt8());
// sanity check
- if (m_specsCount > MAX_TALENT_SPECS || m_activeSpec > MAX_TALENT_SPEC || m_specsCount < MIN_TALENT_SPECS)
+ if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS)
{
- m_activeSpec = 0;
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUIDLow(), m_specsCount, m_activeSpec);
+ SetActiveSpec(0);
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUIDLow(), GetSpecsCount(), GetActiveSpec());
+ }
+
+ // Only load selected specializations, learning mastery spells requires this
+ Tokenizer talentTrees(fields[26].GetString(), ' ', MAX_TALENT_SPECS);
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ if (i >= talentTrees.size())
+ break;
+
+ uint32 talentTree = atol(talentTrees[i]);
+ if (sTalentTabStore.LookupEntry(talentTree))
+ SetPrimaryTalentTree(i, talentTree);
}
_LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
@@ -17437,6 +17538,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadInventory(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INVENTORY), time_diff);
+ if (IsVoidStorageUnlocked())
+ _LoadVoidStorage(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE));
+
// update items with duration and realtime
UpdateItemDuration(time_diff, true);
@@ -17449,7 +17553,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
- uint32 curTitle = fields[46].GetUInt32();
+ uint32 curTitle = fields[43].GetUInt32();
if (curTitle && !HasTitle(curTitle))
curTitle = 0;
@@ -17472,12 +17576,35 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
UpdateAllStats();
// restore remembered power/health values (but not more max values)
- uint32 savedHealth = fields[50].GetUInt32();
+ uint32 savedHealth = fields[46].GetUInt32();
SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth);
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ uint32 loadedPowers = 0;
+ for (uint32 i = 0; i < MAX_POWERS; ++i)
{
- uint32 savedPower = fields[51+i].GetUInt32();
- SetPower(Powers(i), savedPower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedPower);
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ uint32 savedPower = fields[47+loadedPowers].GetUInt32();
+ uint32 maxPower = GetUInt32Value(UNIT_FIELD_MAXPOWER1 + loadedPowers);
+ SetPower(Powers(i), (savedPower > maxPower) ? maxPower : savedPower);
+ if (++loadedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; loadedPowers < MAX_POWERS_PER_CLASS; ++loadedPowers)
+ SetUInt32Value(UNIT_FIELD_POWER1 + loadedPowers, 0);
+
+ SetPower(POWER_ECLIPSE, 0);
+
+ // Verify loaded talent specializations
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ if (i >= talentTrees.size())
+ break;
+
+ uint32 talentTree = atol(talentTrees[i]);
+ if (talentTree != 0 && !sTalentTabStore.LookupEntry(talentTree) && i == GetActiveSpec())
+ SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); // invalid tree, reset talents
}
TC_LOG_DEBUG(LOG_FILTER_PLAYER_LOADING, "The value of player %s after load item and aura is: ", m_name.c_str());
@@ -17532,7 +17659,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
}
// RaF stuff.
- m_grantableLevels = fields[66].GetUInt8();
+ m_grantableLevels = fields[59].GetUInt8();
if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0))
SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND);
@@ -17541,13 +17668,50 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
- m_achievementMgr->CheckAllAchievementCriteria();
+ m_achievementMgr->CheckAllAchievementCriteria(this);
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
+ _LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
+
return true;
}
+void Player::_LoadCUFProfiles(PreparedQueryResult result)
+{
+ if (!result)
+ return;
+
+ do
+ {
+ // SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?
+ Field* fields = result->Fetch();
+
+ uint8 id = fields[0].GetUInt8();
+ std::string name = fields[1].GetString();
+ uint16 frameHeight = fields[2].GetUInt16();
+ uint16 frameWidth = fields[3].GetUInt16();
+ uint8 sortBy = fields[4].GetUInt8();
+ uint8 healthText = fields[5].GetUInt8();
+ uint32 boolOptions = fields[6].GetUInt32();
+ uint8 unk146 = fields[7].GetUInt8();
+ uint8 unk147 = fields[8].GetUInt8();
+ uint8 unk148 = fields[9].GetUInt8();
+ uint16 unk150 = fields[10].GetUInt16();
+ uint16 unk152 = fields[11].GetUInt16();
+ uint16 unk154 = fields[12].GetUInt16();
+
+ if (id > MAX_CUF_PROFILES)
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::_LoadCUFProfiles - Player (GUID: %u, name: %s) has an CUF profile with invalid id (id: %u), max is %i.", GetGUIDLow(), GetName().c_str(), id, MAX_CUF_PROFILES);
+ continue;
+ }
+
+ _CUFProfiles[id] = new CUFProfile(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154);
+ }
+ while (result->NextRow());
+}
+
bool Player::isAllowedToLoot(const Creature* creature)
{
if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward())
@@ -17701,7 +17865,7 @@ void Player::_LoadGlyphAuras()
{
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyph = GetGlyph(i))
+ if (uint32 glyph = GetGlyph(GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -17825,7 +17989,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
std::map<uint32, Item*>::iterator itr = invalidBagMap.find(bagGuid);
if (std::find(problematicItems.begin(), problematicItems.end(), itr->second) != problematicItems.end())
- err = EQUIP_ERR_INT_BAG_ERROR;
+ err = EQUIP_ERR_INTERNAL_BAG_ERROR;
}
else
{
@@ -17872,6 +18036,53 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
_ApplyAllItemMods();
}
+void Player::_LoadVoidStorage(PreparedQueryResult result)
+{
+ if (!result)
+ return;
+
+ do
+ {
+ // SELECT itemid, itemEntry, slot, creatorGuid FROM character_void_storage WHERE playerGuid = ?
+ Field* fields = result->Fetch();
+
+ uint64 itemId = fields[0].GetUInt64();
+ uint32 itemEntry = fields[1].GetUInt32();
+ uint8 slot = fields[2].GetUInt8();
+ uint32 creatorGuid = fields[3].GetUInt32();
+ uint32 randomProperty = fields[4].GetUInt32();
+ uint32 suffixFactor = fields[5].GetUInt32();
+
+ if (!itemId)
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid id (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry);
+ continue;
+ }
+
+ if (!sObjectMgr->GetItemTemplate(itemEntry))
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid entry (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry);
+ continue;
+ }
+
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid slot (item id: " UI64FMTD ", entry: %u, slot: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry, slot);
+ continue;
+ }
+
+ std::string name;
+ if (creatorGuid && !sObjectMgr->GetPlayerNameByGUID(creatorGuid, name))
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid creator guid, set to 0 (item id: " UI64FMTD ", entry: %u, creatorGuid: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry, creatorGuid);
+ creatorGuid = 0;
+ }
+
+ _voidStorageItems[slot] = new VoidStorageItem(itemId, itemEntry, creatorGuid, randomProperty, suffixFactor);
+ }
+ while (result->NextRow());
+}
+
Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, Field* fields)
{
Item* item = NULL;
@@ -18093,8 +18304,8 @@ void Player::_LoadMail()
bool has_items = fields[6].GetBool();
m->expire_time = time_t(fields[7].GetUInt32());
m->deliver_time = time_t(fields[8].GetUInt32());
- m->money = fields[9].GetUInt32();
- m->COD = fields[10].GetUInt32();
+ m->money = fields[9].GetUInt64();
+ m->COD = fields[10].GetUInt64();
m->checked = fields[11].GetUInt8();
m->stationery = fields[12].GetUInt8();
m->mailTemplateId = fields[13].GetInt16();
@@ -18166,7 +18377,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
time_t quest_time = time_t(fields[3].GetUInt32());
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id))
{
AddTimedQuest(quest_id);
@@ -18244,8 +18455,8 @@ void Player::_LoadQuestStatusRewarded(PreparedQueryResult result)
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
- m_questRewardTalentCount += quest->GetBonusTalents();
+ if (uint32 talents = quest->GetBonusTalents())
+ AddQuestRewardedTalentCount(talents);
}
m_RewardedQuests.insert(quest_id);
@@ -18434,7 +18645,7 @@ void Player::_LoadBoundInstances(PreparedQueryResult result)
bool deleteInstance = false;
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
- std::string mapname = mapEntry ? mapEntry->name[sWorld->GetDefaultDbcLocale()] : "Unknown";
+ std::string mapname = mapEntry ? mapEntry->name : "Unknown";
if (!mapEntry || !mapEntry->IsDungeon())
{
@@ -18628,16 +18839,25 @@ void Player::SendRaidInfo()
if (itr->second.perm)
{
InstanceSave* save = itr->second.save;
+ bool isHeroic = save->GetDifficulty() == RAID_DIFFICULTY_10MAN_HEROIC || save->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC;
+ uint32 completedEncounters = 0;
+ if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
+ if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
+ completedEncounters = instanceScript->GetCompletedEncounterMask();
+
data << uint32(save->GetMapId()); // map id
data << uint32(save->GetDifficulty()); // difficulty
+ data << uint32(isHeroic); // heroic
data << uint64(save->GetInstanceId()); // instance id
data << uint8(1); // expired = 0
data << uint8(0); // extended = 1
data << uint32(save->GetResetTime() - now); // reset time
+ data << uint32(completedEncounters); // completed encounters mask
++counter;
}
}
}
+
data.put<uint32>(p_counter, counter);
GetSession()->SendPacket(&data);
}
@@ -18662,8 +18882,8 @@ void Player::SendSavedInstances()
}
}
- //Send opcode 811. true or false means, whether you have current raid/heroic instances
- data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP);
+ //Send opcode SMSG_UPDATE_INSTANCE_OWNERSHIP. true or false means, whether you have current raid/heroic instances
+ data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4);
data << uint32(hasBeenSaved);
GetSession()->SendPacket(&data);
@@ -18676,7 +18896,7 @@ void Player::SendSavedInstances()
{
if (itr->second.perm)
{
- data.Initialize(SMSG_UPDATE_LAST_INSTANCE);
+ data.Initialize(SMSG_UPDATE_LAST_INSTANCE, 4);
data << uint32(itr->second.save->GetMapId());
GetSession()->SendPacket(&data);
}
@@ -18824,7 +19044,8 @@ bool Player::_LoadHomeBind(PreparedQueryResult result)
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
if (!info)
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (Name %s) has incorrect race/class pair. Can't be loaded.", GetName().c_str());
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (Name %s) has incorrect race/class (%u/%u) pair. Can't be loaded.",
+ GetName().c_str(), uint32(getRace()), uint32(getClass()));
return false;
}
@@ -18916,7 +19137,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getGender());
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
- stmt->setUInt32(index++, GetMoney());
+ stmt->setUInt64(index++, GetMoney());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
@@ -18939,8 +19160,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, GetTalentResetTime());
+
+ ss.str("");
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ ss << GetPrimaryTalentTree(i) << " ";
+ stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_stableSlots);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -18951,26 +19177,32 @@ void Player::SaveToDB(bool create /*=false*/)
ss << m_taxi.SaveTaxiDestinationsToString();
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetArenaPoints());
- stmt->setUInt32(index++, GetHonorPoints());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE));
- stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX));
stmt->setUInt8(index++, GetDrunkValue());
stmt->setUInt32(index++, GetHealth());
+ uint32 storedPowers = 0;
for (uint32 i = 0; i < MAX_POWERS; ++i)
- stmt->setUInt32(index++, GetPower(Powers(i)));
+ {
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers));
+ if (++storedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; storedPowers < MAX_POWERS_PER_CLASS; ++storedPowers)
+ stmt->setUInt32(index++, 0);
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -18991,15 +19223,13 @@ void Player::SaveToDB(bool create /*=false*/)
ss << '0';
ss << " 0 ";
}
-
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID));
ss.str("");
for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i)
ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' ';
-
stmt->setString(index++, ss.str());
+
stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2));
stmt->setUInt32(index++, m_grantableLevels);
}
@@ -19013,7 +19243,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getGender());
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
- stmt->setUInt32(index++, GetMoney());
+ stmt->setUInt64(index++, GetMoney());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
@@ -19050,8 +19280,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, GetTalentResetTime());
+
+ ss.str("");
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ ss << GetPrimaryTalentTree(i) << " ";
+ stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_stableSlots);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -19062,26 +19297,32 @@ void Player::SaveToDB(bool create /*=false*/)
ss << m_taxi.SaveTaxiDestinationsToString();
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetArenaPoints());
- stmt->setUInt32(index++, GetHonorPoints());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE));
- stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX));
stmt->setUInt8(index++, GetDrunkValue());
stmt->setUInt32(index++, GetHealth());
+ uint32 storedPowers = 0;
for (uint32 i = 0; i < MAX_POWERS; ++i)
- stmt->setUInt32(index++, GetPower(Powers(i)));
+ {
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers));
+ if (++storedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; storedPowers < MAX_POWERS_PER_CLASS; ++storedPowers)
+ stmt->setUInt32(index++, 0);
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19104,7 +19345,6 @@ void Player::SaveToDB(bool create /*=false*/)
}
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID));
ss.str("");
for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i)
@@ -19128,6 +19368,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveBGData(trans);
_SaveInventory(trans);
+ _SaveVoidStorage(trans);
_SaveQuestStatus(trans);
_SaveDailyQuestStatus(trans);
_SaveWeeklyQuestStatus(trans);
@@ -19145,6 +19386,8 @@ void Player::SaveToDB(bool create /*=false*/)
GetSession()->SaveTutorialsData(trans); // changed only while character in game
_SaveGlyphs(trans);
_SaveInstanceTimeRestrictions(trans);
+ _SaveCurrency(trans);
+ _SaveCUFProfiles(trans);
// check if stats should only be saved on logout
// save stats can be out of transaction
@@ -19162,13 +19405,14 @@ void Player::SaveToDB(bool create /*=false*/)
void Player::SaveInventoryAndGoldToDB(SQLTransaction& trans)
{
_SaveInventory(trans);
+ _SaveCurrency(trans);
SaveGoldToDB(trans);
}
void Player::SaveGoldToDB(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_MONEY);
- stmt->setUInt32(0, GetMoney());
+ stmt->setUInt64(0, GetMoney());
stmt->setUInt32(1, GetGUIDLow());
trans->Append(stmt);
}
@@ -19184,7 +19428,7 @@ void Player::_SaveActions(SQLTransaction& trans)
case ACTIONBUTTON_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
stmt->setUInt32(0, GetGUIDLow());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
stmt->setUInt8(4, uint8(itr->second.GetType()));
@@ -19199,7 +19443,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt->setUInt8(1, uint8(itr->second.GetType()));
stmt->setUInt32(2, GetGUIDLow());
stmt->setUInt8(3, itr->first);
- stmt->setUInt8(4, m_activeSpec);
+ stmt->setUInt8(4, GetActiveSpec());
trans->Append(stmt);
itr->second.uState = ACTIONBUTTON_UNCHANGED;
@@ -19209,7 +19453,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt8(1, itr->first);
- stmt->setUInt8(2, m_activeSpec);
+ stmt->setUInt8(2, GetActiveSpec());
trans->Append(stmt);
m_actionButtons.erase(itr++);
@@ -19368,7 +19612,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
// save all changes to the item...
if (item->GetState() != ITEM_NEW) // only for existing items, no dupes
item->SaveToDB(trans);
- // ...but do not save position in invntory
+ // ...but do not save position in inventory
continue;
}
}
@@ -19397,6 +19641,76 @@ void Player::_SaveInventory(SQLTransaction& trans)
m_itemUpdateQueue.clear();
}
+void Player::_SaveVoidStorage(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = NULL;
+ uint32 lowGuid = GetGUIDLow();
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ if (!_voidStorageItems[i]) // unused item
+ {
+ // DELETE FROM void_storage WHERE slot = ? AND playerGuid = ?
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT);
+ stmt->setUInt8(0, i);
+ stmt->setUInt32(1, lowGuid);
+ }
+ else
+ {
+ // REPLACE INTO character_inventory (itemId, playerGuid, itemEntry, slot, creatorGuid) VALUES (?, ?, ?, ?, ?)
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM);
+ stmt->setUInt64(0, _voidStorageItems[i]->ItemId);
+ stmt->setUInt32(1, lowGuid);
+ stmt->setUInt32(2, _voidStorageItems[i]->ItemEntry);
+ stmt->setUInt8(3, i);
+ stmt->setUInt32(4, _voidStorageItems[i]->CreatorGuid);
+ stmt->setUInt32(5, _voidStorageItems[i]->ItemRandomPropertyId);
+ stmt->setUInt32(6, _voidStorageItems[i]->ItemSuffixFactor);
+ }
+
+ trans->Append(stmt);
+ }
+}
+
+
+void Player::_SaveCUFProfiles(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = NULL;
+ uint32 lowGuid = GetGUIDLow();
+
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ if (!_CUFProfiles[i]) // unused profile
+ {
+ // DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ }
+ else
+ {
+ // REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ stmt->setString(2, _CUFProfiles[i]->ProfileName);
+ stmt->setUInt16(3, _CUFProfiles[i]->FrameHeight);
+ stmt->setUInt16(4, _CUFProfiles[i]->FrameWidth);
+ stmt->setUInt8(5, _CUFProfiles[i]->SortBy);
+ stmt->setUInt8(6, _CUFProfiles[i]->HealthText);
+ stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 27 of 32 fields used, fits in an int
+ stmt->setUInt8(8, _CUFProfiles[i]->Unk146);
+ stmt->setUInt8(9, _CUFProfiles[i]->Unk147);
+ stmt->setUInt8(10, _CUFProfiles[i]->Unk148);
+ stmt->setUInt16(11, _CUFProfiles[i]->Unk150);
+ stmt->setUInt16(12, _CUFProfiles[i]->Unk152);
+ stmt->setUInt16(13, _CUFProfiles[i]->Unk154);
+ }
+
+ trans->Append(stmt);
+ }
+}
+
void Player::_SaveMail(SQLTransaction& trans)
{
if (!m_mailsLoaded)
@@ -19678,9 +19992,11 @@ void Player::_SaveSkills(SQLTransaction& trans)
continue;
}
- uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos));
- uint16 value = SKILL_VALUE(valueData);
- uint16 max = SKILL_MAX(valueData);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
switch (itr->second.uState)
{
@@ -19691,7 +20007,6 @@ void Player::_SaveSkills(SQLTransaction& trans)
stmt->setUInt16(2, value);
stmt->setUInt16(3, max);
trans->Append(stmt);
-
break;
case SKILL_CHANGED:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_SKILLS);
@@ -19700,13 +20015,12 @@ void Player::_SaveSkills(SQLTransaction& trans)
stmt->setUInt32(2, GetGUIDLow());
stmt->setUInt16(3, uint16(itr->first));
trans->Append(stmt);
-
break;
default:
break;
}
- itr->second.uState = SKILL_UNCHANGED;
+ itr->second.uState = SKILL_UNCHANGED;
++itr;
}
}
@@ -19769,7 +20083,7 @@ void Player::_SaveStats(SQLTransaction& trans)
stmt->setUInt32(index++, GetGUIDLow());
stmt->setUInt32(index++, GetMaxHealth());
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i)
stmt->setUInt32(index++, GetMaxPower(Powers(i)));
for (uint8 i = 0; i < MAX_STATS; ++i)
@@ -19787,7 +20101,7 @@ void Player::_SaveStats(SQLTransaction& trans)
stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_ATTACK_POWER));
stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER));
stmt->setUInt32(index++, GetBaseSpellPowerBonus());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_CRIT_TAKEN_SPELL));
+ stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_RESILIENCE_PLAYER_DAMAGE_TAKEN));
trans->Append(stmt);
}
@@ -19875,15 +20189,15 @@ void Player::SavePositionInDB(uint32 mapid, float x, float y, float z, float o,
CharacterDatabase.Execute(stmt);
}
-void Player::SetUInt32ValueInArray(Tokenizer& tokens, uint16 index, uint32 value)
+void Player::SetUInt32ValueInArray(Tokenizer& Tokenizer, uint16 index, uint32 value)
{
char buf[11];
snprintf(buf, 11, "%u", value);
- if (index >= tokens.size())
+ if (index >= Tokenizer.size())
return;
- tokens[index] = buf;
+ Tokenizer[index] = buf;
}
void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair)
@@ -20040,7 +20354,7 @@ void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId)
// 1: There are players offline in your party.
// 2>: There are players in your party attempting to zone into an instance.
*/
- WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 4);
+ WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 8);
data << uint32(reason);
data << uint32(MapId);
GetSession()->SendPacket(&data);
@@ -20235,13 +20549,16 @@ void Player::StopCastingCharm()
}
}
-inline void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const
+inline void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix /*= NULL*/) const
{
*data << uint8(msgtype);
*data << uint32(language);
*data << uint64(GetGUID());
*data << uint32(0); // constant unknown time
- *data << uint64(GetGUID());
+ if (addonPrefix)
+ *data << addonPrefix;
+ else
+ *data << uint64(GetGUID());
*data << uint32(text.length() + 1);
*data << text;
*data << uint8(GetChatTag());
@@ -20277,12 +20594,25 @@ void Player::TextEmote(const std::string& text)
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHAT));
}
+void Player::WhisperAddon(const std::string& text, const std::string& prefix, Player* receiver)
+{
+ std::string _text(text);
+ sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, LANG_UNIVERSAL, _text, receiver);
+
+ if (!receiver->GetSession()->IsAddonRegistered(prefix))
+ return;
+
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str());
+ receiver->GetSession()->SendPacket(&data);
+}
+
void Player::Whisper(const std::string& text, uint32 language, uint64 receiver)
{
bool isAddonMessage = language == LANG_ADDON;
- if (!isAddonMessage) // if not addon data
- language = LANG_UNIVERSAL; // whispers should always be readable
+ if (!isAddonMessage) // if not addon data
+ language = LANG_UNIVERSAL; // whispers should always be readable
Player* rPlayer = ObjectAccessor::FindPlayer(receiver);
@@ -20613,33 +20943,37 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
void Player::AddSpellMod(SpellModifier* mod, bool apply)
{
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "Player::AddSpellMod %d", mod->spellId);
- uint16 Opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
+ Opcodes opcode = Opcodes((mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER);
int i = 0;
flag96 _mask = 0;
+ uint32 modTypeCount = 0; // count of mods per one mod->op
+ WorldPacket data(opcode);
+ data << uint32(1); // count of different mod->op's in packet
+ size_t writePos = data.wpos();
+ data << uint32(modTypeCount);
+ data << uint8(mod->op);
for (int eff = 0; eff < 96; ++eff)
{
- if (eff != 0 && eff%32 == 0)
+ if (eff != 0 && (eff % 32) == 0)
_mask[i++] = 0;
- _mask[i] = uint32(1) << (eff-(32*i));
+ _mask[i] = uint32(1) << (eff - (32 * i));
if (mod->mask & _mask)
{
int32 val = 0;
for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
- {
if ((*itr)->type == mod->type && (*itr)->mask & _mask)
val += (*itr)->value;
- }
val += apply ? mod->value : -(mod->value);
- WorldPacket data(Opcode, (1+1+4));
+
data << uint8(eff);
- data << uint8(mod->op);
- data << int32(val);
- SendDirectMessage(&data);
+ data << float(val);
+ ++modTypeCount;
}
}
-
+ data.put<uint32>(writePos, modTypeCount);
+ SendDirectMessage(&data);
if (apply)
m_spellMods[mod->op].push_back(mod);
else
@@ -21054,7 +21388,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
return false;
}
- uint32 money = GetMoney();
+ uint64 money = GetMoney();
if (npc)
totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc));
@@ -21067,7 +21401,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
}
//Checks and preparations done, DO FLIGHT
- ModifyMoney(-(int32)totalcost);
+ ModifyMoney(-int64(totalcost));
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
@@ -21208,7 +21542,7 @@ void Player::InitDataForForm(bool reapplyMods)
{
ShapeshiftForm form = GetShapeshiftForm();
- SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->attackSpeed)
{
SetAttackTime(BASE_ATTACK, ssEntry->attackSpeed);
@@ -21228,7 +21562,6 @@ void Player::InitDataForForm(bool reapplyMods)
break;
}
case FORM_BEAR:
- case FORM_DIREBEAR:
{
if (getPowerType() != POWER_RAGE)
setPowerType(POWER_RAGE);
@@ -21279,10 +21612,11 @@ void Player::InitDisplayIds()
inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore)
{
+ uint32 stacks = count / pProto->BuyCount;
ItemPosCountVec vDest;
uint16 uiDest = 0;
InventoryResult msg = bStore ?
- CanStoreNewItem(bag, slot, vDest, item, pProto->BuyCount * count) :
+ CanStoreNewItem(bag, slot, vDest, item, count) :
CanEquipNewItem(slot, uiDest, item, false);
if (msg != EQUIP_ERR_OK)
{
@@ -21292,19 +21626,19 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
ModifyMoney(-price);
- if (crItem->ExtendedCost) // case for new honor system
+ if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if (iece->reqhonorpoints)
- ModifyHonorPoints(- int32(iece->reqhonorpoints * count));
-
- if (iece->reqarenapoints)
- ModifyArenaPoints(- int32(iece->reqarenapoints * count));
+ for (int i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (iece->RequiredItem[i])
+ DestroyItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks, true);
+ }
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (int i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
{
- if (iece->reqitem[i])
- DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
+ if (iece->RequiredCurrency[i])
+ ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i] * stacks), true, true);
}
}
@@ -21313,7 +21647,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
EquipNewItem(uiDest, item, true);
if (it)
{
- uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, pProto->BuyCount * count);
+ uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
data << uint64(pVendor->GetGUID());
@@ -21321,7 +21655,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
data << int32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
data << uint32(count);
GetSession()->SendPacket(&data);
- SendNewItem(it, pProto->BuyCount * count, true, false, false);
+ SendNewItem(it, count, true, false, false);
if (!bStore)
AutoUnequipOffhandIfNeed();
@@ -21339,6 +21673,132 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
return true;
}
+bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count)
+{
+ // cheating attempt
+ if (count < 1) count = 1;
+
+ if (!isAlive())
+ return false;
+
+ CurrencyTypesEntry const* proto = sCurrencyTypesStore.LookupEntry(currency);
+ if (!proto)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, currency, 0);
+ return false;
+ }
+
+ Creature* creature = GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
+ if (!creature)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: BuyCurrencyFromVendorSlot - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid));
+ SendBuyError(BUY_ERR_DISTANCE_TOO_FAR, NULL, currency, 0);
+ return false;
+ }
+
+ VendorItemData const* vItems = creature->GetVendorItems();
+ if (!vItems || vItems->Empty())
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ if (vendorSlot >= vItems->GetItemCount())
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ VendorItem const* crItem = vItems->GetItem(vendorSlot);
+ // store diff item (cheating)
+ if (!crItem || crItem->item != currency || crItem->Type != ITEM_VENDOR_TYPE_CURRENCY)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ if (count % crItem->maxcount)
+ {
+ SendEquipError(EQUIP_ERR_CANT_BUY_QUANTITY, NULL, NULL);
+ return false;
+ }
+
+ uint32 stacks = count / crItem->maxcount;
+ ItemExtendedCostEntry const* iece = NULL;
+ if (crItem->ExtendedCost)
+ {
+ iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
+ if (!iece)
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Currency %u have wrong ExtendedCost field value %u", currency, crItem->ExtendedCost);
+ return false;
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
+ {
+ if (iece->RequiredItem[i] && !HasItemCount(iece->RequiredItem[i], (iece->RequiredItemCount[i] * stacks)))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
+ return false;
+ }
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ if (!entry)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0); // Find correct error
+ return false;
+ }
+
+ if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * stacks)))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+ }
+
+ // check for personal arena rating requirement
+ if (GetMaxPersonalArenaRatingRequirement(iece->RequiredArenaSlot) < iece->RequiredPersonalArenaRating)
+ {
+ // probably not the proper equip err
+ SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL);
+ return false;
+ }
+ }
+ else // currencies have no price defined, can only be bought with ExtendedCost
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, currency, 0);
+ return false;
+ }
+
+ ModifyCurrency(currency, count, true, true);
+ if (iece)
+ {
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
+ {
+ if (!iece->RequiredItem[i])
+ continue;
+
+ DestroyItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks, true);
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i]) * stacks, false, true);
+ }
+ }
+
+ return true;
+}
+
// Return true is the bought item has a max count to force refresh of window by caller
bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot)
{
@@ -21406,31 +21866,43 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
if (crItem->ExtendedCost)
{
- ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if (!iece)
+ // Can only buy full stacks for extended cost
+ if (count % pProto->BuyCount)
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
+ SendEquipError(EQUIP_ERR_CANT_BUY_QUANTITY, NULL, NULL);
return false;
}
- // honor points price
- if (GetHonorPoints() < (iece->reqhonorpoints * count))
+ uint32 stacks = count / pProto->BuyCount;
+ ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
+ if (!iece)
{
- SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL);
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
return false;
}
- // arena points price
- if (GetArenaPoints() < (iece->reqarenapoints * count))
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL);
- return false;
+ if (iece->RequiredItem[i] && !HasItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
+ return false;
+ }
}
- // item base price
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
{
- if (iece->reqitem[i] && !HasItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count)))
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ if (!entry)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, item, 0);
+ return false;
+ }
+
+ if (!HasCurrency(iece->RequiredCurrency[i], iece->RequiredCurrencyCount[i] * stacks))
{
SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
return false;
@@ -21438,7 +21910,7 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
// check for personal arena rating requirement
- if (GetMaxPersonalArenaRatingRequirement(iece->reqarenaslot) < iece->reqpersonalarenarating)
+ if (GetMaxPersonalArenaRatingRequirement(iece->RequiredArenaSlot) < iece->RequiredPersonalArenaRating)
{
// probably not the proper equip err
SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL);
@@ -21460,7 +21932,10 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
// reputation discount
price = uint32(floor(price * GetReputationPriceDiscount(creature)));
- if (!HasEnoughMoney(price))
+ if (int32 priceMod = GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
+ price -= CalculatePct(price, priceMod);
+
+ if (!HasEnoughMoney(uint64(price)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, item, 0);
return false;
@@ -21474,9 +21949,9 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
else if (IsEquipmentPos(bag, slot))
{
- if (pProto->BuyCount * count != 1)
+ if (count != 1)
{
- SendEquipError(EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL);
+ SendEquipError(EQUIP_ERR_NOT_EQUIPPABLE, NULL, NULL);
return false;
}
if (!_StoreOrEquipNewItem(vendorslot, item, count, bag, slot, price, pProto, creature, crItem, false))
@@ -21484,11 +21959,19 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
else
{
- SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return false;
}
- return crItem->maxcount != 0;
+ if (crItem->maxcount != 0) // bought
+ {
+ if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_PURCHASED, GetGUID(), 0, item);
+ return true;
+ }
+
+ return false;
}
uint32 Player::GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const
@@ -21683,9 +22166,26 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
if (catrec > 0 && !(spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell);
+ // Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers
+ // Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only
+ if (cat)
+ {
+ if (int32 categoryModifier = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN, cat))
+ {
+ if (rec > 0)
+ rec += categoryModifier;
+
+ if (catrec > 0)
+ catrec += categoryModifier;
+ }
+ }
+
// replace negative cooldowns by 0
- if (rec < 0) rec = 0;
- if (catrec < 0) catrec = 0;
+ if (rec < 0)
+ rec = 0;
+
+ if (catrec < 0)
+ catrec = 0;
// no cooldown after applying spell mods
if (rec == 0 && catrec == 0)
@@ -21760,15 +22260,15 @@ void Player::UpdatePotionCooldown(Spell* spell)
m_lastPotionId = 0;
}
-void Player::setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana)
+void Player::SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura)
{
- m_resurrectGUID = guid;
- m_resurrectMap = mapId;
- m_resurrectX = X;
- m_resurrectY = Y;
- m_resurrectZ = Z;
- m_resurrectHealth = health;
- m_resurrectMana = mana;
+ ASSERT(!IsRessurectRequested());
+ _resurrectionData = new ResurrectionData();
+ _resurrectionData->GUID = caster->GetGUID();
+ _resurrectionData->Location.WorldRelocate(*caster);
+ _resurrectionData->Health = health;
+ _resurrectionData->Mana = mana;
+ _resurrectionData->Aura = appliedAura;
}
//slot to be excluded while counting
bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
@@ -22219,7 +22719,7 @@ void Player::UpdateTriggerVisibility()
if (!IsInWorld())
return;
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
for (ClientGUIDs::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
@@ -22311,7 +22811,7 @@ void Player::InitPrimaryProfessions()
SetFreePrimaryProfessions(sWorld->getIntConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL));
}
-bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
+bool Player::ModifyMoney(int64 amount, bool sendError /*= true*/)
{
if (!amount)
return true;
@@ -22319,10 +22819,10 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
sScriptMgr->OnPlayerMoneyChanged(this, amount);
if (amount < 0)
- SetMoney (GetMoney() > uint32(-amount) ? GetMoney() + amount : 0);
+ SetMoney(GetMoney() > uint64(-amount) ? GetMoney() + amount : 0);
else
{
- if (GetMoney() < uint32(MAX_MONEY_AMOUNT - amount))
+ if (GetMoney() < uint64(MAX_MONEY_AMOUNT - amount))
SetMoney(GetMoney() + amount);
else
{
@@ -22335,16 +22835,16 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
return true;
}
-bool Player::HasEnoughMoney(int32 amount) const
+bool Player::HasEnoughMoney(int64 amount) const
{
if (amount > 0)
- return (GetMoney() >= (uint32) amount);
+ return (GetMoney() >= (uint64) amount);
return true;
}
-void Player::SetMoney(uint32 value)
+void Player::SetMoney(uint64 value)
{
- SetUInt32Value(PLAYER_FIELD_COINAGE, value);
+ SetUInt64Value(PLAYER_FIELD_COINAGE, value);
MoneyChanged(value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
}
@@ -22490,12 +22990,6 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendTalentsInfoData(false);
- // SMSG_INSTANCE_DIFFICULTY
- data.Initialize(SMSG_INSTANCE_DIFFICULTY, 4+4);
- data << uint32(GetMap()->GetDifficulty());
- data << uint32(0);
- GetSession()->SendPacket(&data);
-
SendInitialSpells();
data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4);
@@ -22504,7 +22998,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendInitialActionButtons();
m_reputationMgr->SendInitialReputations();
- m_achievementMgr->SendAllAchievementData();
+ m_achievementMgr->SendAllAchievementData(this);
SendEquipmentSetList();
@@ -22521,6 +23015,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
// SMSG_UPDATE_WORLD_STATE
// SMSG_POWER_UPDATE
+ SendCurrencies();
SetMover(this);
}
@@ -22536,6 +23031,8 @@ void Player::SendInitialPacketsAfterAddToMap()
ResetTimeSync();
SendTimeSync();
+ GetSession()->SendLoadCUFProfiles();
+
CastSpell(this, 836, true); // LOGINEFFECT
// set some aura effects that send packet to player client after add player to map
@@ -22555,16 +23052,11 @@ void Player::SendInitialPacketsAfterAddToMap()
}
if (HasAuraType(SPELL_AURA_MOD_STUN))
- SetMovement(MOVE_ROOT);
+ SetRooted(true);
// manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that must not be re-applied.
if (HasAuraType(SPELL_AURA_MOD_ROOT))
- {
- WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10);
- data2.append(GetPackGUID());
- data2 << (uint32)2;
- SendMessageToSet(&data2, true);
- }
+ SendMoveRoot(2);
SendAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map
@@ -22600,18 +23092,8 @@ void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8
{
WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2);
data << uint32(mapid);
- data << uint8(reason); // transfer abort reason
- switch (reason)
- {
- case TRANSFER_ABORT_INSUF_EXPAN_LVL:
- case TRANSFER_ABORT_DIFFICULTY:
- case TRANSFER_ABORT_UNIQUE_MESSAGE:
- // these are the ONLY cases that have an extra argument in the packet!!!
- data << uint8(arg);
- break;
- default:
- break;
- }
+ data << uint8(reason); // transfer abort reason
+ data << uint8(arg);
GetSession()->SendPacket(&data);
}
@@ -22958,6 +23440,7 @@ void Player::ResetWeeklyQuestStatus()
m_weeklyquests.clear();
// DB data deleted in caller
m_WeeklyQuestChanged = false;
+
}
void Player::ResetSeasonalQuestStatus(uint16 event_id)
@@ -23184,7 +23667,7 @@ void Player::UpdateForQuestWorldObjects()
if (m_clientGUIDs.empty())
return;
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
for (ClientGUIDs::iterator itr=m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
@@ -23465,7 +23948,7 @@ uint32 Player::GetResurrectionSpellId()
}
// Used in triggers for check "Only to targets that grant experience or honor" req
-bool Player::isHonorOrXPTarget(Unit* victim)
+bool Player::isHonorOrXPTarget(Unit const* victim)
{
uint8 v_level = victim->getLevel();
uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel());
@@ -23474,11 +23957,11 @@ bool Player::isHonorOrXPTarget(Unit* victim)
if (v_level <= k_grey)
return false;
- if (victim->GetTypeId() == TYPEID_UNIT)
+ if (Creature const* const creature = victim->ToCreature())
{
- if (victim->ToCreature()->isTotem() ||
- victim->ToCreature()->isPet() ||
- victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
+ if (creature->isTotem() ||
+ creature->isPet() ||
+ creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
return false;
}
return true;
@@ -23585,23 +24068,12 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const
return pOther->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE);
}
-uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const
-{
- Item* item = GetWeaponForAttack(attType, true);
-
- // unarmed only with base attack
- if (attType != BASE_ATTACK && !item)
- return 0;
-
- // weapon skill or (unarmed for base attack and for fist weapons)
- uint32 skill = (item && item->GetSkill() != SKILL_FIST_WEAPONS) ? item->GetSkill() : uint32(SKILL_UNARMED);
- return GetBaseSkillValue(skill);
-}
-
void Player::ResurectUsingRequestData()
{
/// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse
- TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
+ float x, y, z, o;
+ _resurrectionData->Location.GetPosition(x, y, z, o);
+ TeleportTo(_resurrectionData->Location.GetMapId(), x, y, z, o);
if (IsBeingTeleported())
{
@@ -23611,19 +24083,23 @@ void Player::ResurectUsingRequestData()
ResurrectPlayer(0.0f, false);
- if (GetMaxHealth() > m_resurrectHealth)
- SetHealth(m_resurrectHealth);
+ if (GetMaxHealth() > _resurrectionData->Health)
+ SetHealth(_resurrectionData->Health);
else
SetFullHealth();
- if (GetMaxPower(POWER_MANA) > m_resurrectMana)
- SetPower(POWER_MANA, m_resurrectMana);
+ if (uint32(GetMaxPower(POWER_MANA)) > _resurrectionData->Mana)
+ SetPower(POWER_MANA, _resurrectionData->Mana);
else
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
SetPower(POWER_RAGE, 0);
-
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
+ SetPower(POWER_FOCUS, GetMaxPower(POWER_FOCUS));
+ SetPower(POWER_ECLIPSE, 0);
+
+ if (uint32 aura = _resurrectionData->Aura)
+ CastSpell(this, aura, true, NULL, NULL, _resurrectionData->GUID);
SpawnCorpseBones();
}
@@ -23643,6 +24119,29 @@ void Player::SetMover(Unit* target)
m_mover->m_movedPlayer = NULL;
m_mover = target;
m_mover->m_movedPlayer = this;
+
+ ObjectGuid guid = target->GetGUID();
+
+ WorldPacket data(SMSG_MOVE_SET_ACTIVE_MOVER, 9);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[4]);
+
+ SendDirectMessage(&data);
}
void Player::UpdateZoneDependentAuras(uint32 newZone)
@@ -24122,32 +24621,27 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n
void Player::InitGlyphsForLevel()
{
- for (uint32 i = 0; i < sGlyphSlotStore.GetNumRows(); ++i)
+ uint32 slot = 0;
+ for (uint32 i = 0; i < sGlyphSlotStore.GetNumRows() && slot < MAX_GLYPH_SLOT_INDEX; ++i)
if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(i))
- if (gs->Order)
- SetGlyphSlot(gs->Order - 1, gs->Id);
+ SetGlyphSlot(slot++, gs->Id);
uint8 level = getLevel();
- uint32 value = 0;
+ uint32 slotMask = 0;
- // 0x3F = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 for 80 level
- if (level >= 15)
- value |= (0x01 | 0x02);
- if (level >= 30)
- value |= 0x08;
+ if (level >= 25)
+ slotMask |= 0x01 | 0x02 | 0x40;
if (level >= 50)
- value |= 0x04;
- if (level >= 70)
- value |= 0x10;
- if (level >= 80)
- value |= 0x20;
+ slotMask |= 0x04 | 0x08 | 0x80;
+ if (level >= 75)
+ slotMask |= 0x10 | 0x20 | 0x100;
- SetUInt32Value(PLAYER_GLYPHS_ENABLED, value);
+ SetUInt32Value(PLAYER_GLYPHS_ENABLED, slotMask);
}
void Player::SetGlyph(uint8 slot, uint32 glyph)
{
- m_Glyphs[m_activeSpec][slot] = glyph;
+ _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph;
SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph);
}
@@ -24257,17 +24751,25 @@ void Player::UpdateCharmedAI()
}
}
-uint32 Player::GetRuneBaseCooldown(uint8 index)
+uint32 Player::GetRuneTypeBaseCooldown(RuneType runeType) const
{
- uint8 rune = GetBaseRune(index);
- uint32 cooldown = RUNE_BASE_COOLDOWN;
+ float cooldown = RUNE_BASE_COOLDOWN;
+ float hastePct = 0.0f;
AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for (AuraEffectList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i)
- {
- if ((*i)->GetMiscValue() == POWER_RUNE && (*i)->GetMiscValueB() == rune)
- cooldown = cooldown*(100-(*i)->GetAmount())/100;
- }
+ if ((*i)->GetMiscValue() == POWER_RUNES && (*i)->GetMiscValueB() == runeType)
+ cooldown *= 1.0f - (*i)->GetAmount() / 100.0f;
+
+ // Runes cooldown are now affected by player's haste from equipment ...
+ hastePct = GetRatingBonusValue(CR_HASTE_MELEE);
+
+ // ... and some auras.
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE);
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_2);
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_3);
+
+ cooldown *= 1.0f - (hastePct / 100.0f);
return cooldown;
}
@@ -24378,7 +24880,7 @@ void Player::InitRunes()
}
for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
- SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f);
+ SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); // set a base regen timer equal to 10 sec
}
bool Player::IsBaseRuneSlotsOnCooldown(RuneType runeType) const
@@ -24427,7 +24929,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
if (!item)
{
- SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL);
+ SendEquipError(EQUIP_ERR_LOOT_GONE, NULL, NULL);
return;
}
@@ -24477,9 +24979,14 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
--loot->unlootedCount;
+ if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid))
+ if (proto->Quality > ITEM_QUALITY_EPIC || (proto->Quality == ITEM_QUALITY_EPIC && proto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid);
+
SendNewItem(newitem, uint32(item->count), false, false, true);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item->itemid, item->count, loot->loot_type);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count);
// LootItem is being removed (looted) from the container, delete it from the DB.
@@ -24493,16 +25000,30 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
uint32 Player::CalculateTalentsPoints() const
{
- uint32 base_talent = getLevel() < 10 ? 0 : getLevel()-9;
+ // this dbc file has entries only up to level 100
+ NumTalentsAtLevelEntry const* count = sNumTalentsAtLevelStore.LookupEntry(std::min<uint32>(getLevel(), 100));
+ if (!count)
+ return 0;
+
+ float baseForLevel = count->Talents;
if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
- return uint32(base_talent * sWorld->getRate(RATE_TALENT));
+ return uint32(baseForLevel * sWorld->getRate(RATE_TALENT));
+
+ // Death Knight starting level
+ // hardcoded here - number of quest awarded talents is equal to number of talents any other class would have at level 55
+ if (getLevel() < 55)
+ return 0;
- uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55;
- talentPointsForLevel += m_questRewardTalentCount;
+ NumTalentsAtLevelEntry const* dkBase = sNumTalentsAtLevelStore.LookupEntry(55);
+ if (!dkBase)
+ return 0;
+
+ float talentPointsForLevel = count->Talents - dkBase->Talents;
+ talentPointsForLevel += float(GetQuestRewardedTalentCount());
- if (talentPointsForLevel > base_talent)
- talentPointsForLevel = base_talent;
+ if (talentPointsForLevel > baseForLevel)
+ talentPointsForLevel = baseForLevel;
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
}
@@ -24528,6 +25049,7 @@ void Player::_LoadSkills(PreparedQueryResult result)
// SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
uint32 count = 0;
+ uint8 professionCount = 0;
if (result)
{
do
@@ -24570,14 +25092,28 @@ void Player::_LoadSkills(PreparedQueryResult result)
continue;
}
- // enable unlearn button for primary professions only
+ uint16 field = count / 2;
+ uint8 offset = count & 1;
+
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill);
+ uint16 step = 0;
+
+ if (pSkill->categoryId == SKILL_CATEGORY_SECONDARY)
+ step = max / 75;
+
if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
- SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 1));
- else
- SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0));
+ {
+ step = max / 75;
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max));
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
+ if (professionCount < 2)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill);
+ }
+
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, value);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, max);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED)));
@@ -24596,9 +25132,15 @@ void Player::_LoadSkills(PreparedQueryResult result)
for (; count < PLAYER_MAX_SKILLS; ++count)
{
- SetUInt32Value(PLAYER_SKILL_INDEX(count), 0);
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0);
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
+ uint16 field = count / 2;
+ uint8 offset = count & 1;
+
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
}
// special settings
@@ -24630,25 +25172,6 @@ void Player::_LoadSkills(PreparedQueryResult result)
}
}
-uint32 Player::GetPhaseMaskForSpawn() const
-{
- uint32 phase = PHASEMASK_NORMAL;
- if (!isGameMaster())
- phase = GetPhaseMask();
- else
- {
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- phase = phases.front()->GetMiscValue();
- }
-
- // some aura phases include 1 normal map in addition to phase itself
- if (uint32 n_phase = phase & ~PHASEMASK_NORMAL)
- return n_phase;
-
- return PHASEMASK_NORMAL;
-}
-
InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const
{
ItemTemplate const* pProto = pItem->GetTemplate();
@@ -24689,7 +25212,7 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
{
// there is an equip limit on this item
if (HasItemOrGemWithIdEquipped(itemProto->ItemId, 1, except_slot))
- return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE;
+ return EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE;
}
// check unique-equipped limit
@@ -24697,12 +25220,12 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
{
ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(itemProto->ItemLimitCategory);
if (!limitEntry)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
// NOTE: limitEntry->mode not checked because if item have have-limit then it applied and to equip case
if (limit_count > limitEntry->maxCount)
- return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED;
+ return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS;
// there is an equip limit on this item
if (HasItemOrGemWithLimitCategoryEquipped(itemProto->ItemLimitCategory, limitEntry->maxCount - limit_count + 1, except_slot))
@@ -24722,7 +25245,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
{
// calculate total z distance of the fall
float z_diff = m_lastFallZ - movementInfo.pos.GetPositionZ();
- //TC_LOG_DEBUG("zDiff = %f", z_diff);
+ //TC_LOG_DEBUG(LOG_FILTER_GENERAL, "zDiff = %f", z_diff);
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
// 14.57 can be calculated by resolving damageperc formula below to 0
@@ -24774,7 +25297,12 @@ void Player::ResetAchievements()
void Player::SendRespondInspectAchievements(Player* player) const
{
- m_achievementMgr->SendRespondInspectAchievements(player);
+ m_achievementMgr->SendAchievementInfo(player);
+}
+
+uint32 Player::GetAchievementPoints() const
+{
+ return m_achievementMgr->GetAchievementPoints();
}
bool Player::HasAchieved(uint32 achievementId) const
@@ -24792,44 +25320,54 @@ void Player::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 e
m_achievementMgr->RemoveTimedAchievement(type, entry);
}
-void Player::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
+void Player::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
{
m_achievementMgr->ResetAchievementCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
}
-void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
+void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
{
- m_achievementMgr->UpdateAchievementCriteria(type, miscValue1, miscValue2, unit);
+ m_achievementMgr->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ Guild* guild = sGuildMgr->GetGuildById(GetGuildId());
+ if (!guild)
+ return;
+
+ // Update only individual achievement criteria here, otherwise we may get multiple updates
+ // from a single boss kill
+ if (sAchievementMgr->IsGroupCriteriaType(type))
+ return;
+
+ guild->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
}
void Player::CompletedAchievement(AchievementEntry const* entry)
{
- m_achievementMgr->CompletedAchievement(entry);
+ m_achievementMgr->CompletedAchievement(entry, this);
}
-void Player::LearnTalent(uint32 talentId, uint32 talentRank)
+bool Player::LearnTalent(uint32 talentId, uint32 talentRank)
{
uint32 CurTalentPoints = GetFreeTalentPoints();
if (CurTalentPoints == 0)
- return;
+ return false;
if (talentRank >= MAX_TALENT_RANK)
- return;
+ return false;
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
if (!talentInfo)
- return;
+ return false;
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
if (!talentTabInfo)
- return;
+ return false;
// prevent learn talent for different class (cheating)
if ((getClassMask() & talentTabInfo->ClassMask) == 0)
- return;
+ return false;
// find current max talent rank (0~5)
uint8 curtalent_maxrank = 0; // 0 = not learned any rank
@@ -24844,11 +25382,11 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// we already have same or higher talent rank learned
if (curtalent_maxrank >= (talentRank + 1))
- return;
+ return false;
// check if we have enough talent points
if (CurTalentPoints < (talentRank - curtalent_maxrank + 1))
- return;
+ return false;
// Check if it requires another talent
if (talentInfo->DependsOn > 0)
@@ -24863,33 +25401,32 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
hasEnoughRank = true;
}
if (!hasEnoughRank)
- return;
+ return false;
}
}
// Find out how many points we have in this field
uint32 spentPoints = 0;
-
+ uint32 primaryTreeTalents = 0;
uint32 tTab = talentInfo->TalentTab;
- if (talentInfo->Row > 0)
+ bool isMainTree = GetPrimaryTalentTree(GetActiveSpec()) == tTab || !GetPrimaryTalentTree(GetActiveSpec());
+
+ if (talentInfo->Row > 0 || !isMainTree)
{
- uint32 numRows = sTalentStore.GetNumRows();
- for (uint32 i = 0; i < numRows; i++) // Loop through all talents.
+ for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents.
{
- // Someday, someone needs to revamp
- const TalentEntry* tmpTalent = sTalentStore.LookupEntry(i);
- if (tmpTalent) // the way talents are tracked
+ if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // Someday, someone needs to revamp the way talents are tracked
{
- if (tmpTalent->TalentTab == tTab)
+ for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
{
- for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
+ if (tmpTalent->RankID[rank] != 0)
{
- if (tmpTalent->RankID[rank] != 0)
+ if (HasSpell(tmpTalent->RankID[rank]))
{
- if (HasSpell(tmpTalent->RankID[rank]))
- {
+ if (tmpTalent->TalentTab == tTab)
spentPoints += (rank + 1);
- }
+ if (tmpTalent->TalentTab == GetPrimaryTalentTree(GetActiveSpec()))
+ primaryTreeTalents += (rank + 1);
}
}
}
@@ -24899,28 +25436,49 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// not have required min points spent in talent tree
if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
- return;
+ return false;
+
+ // player has not spent 31 talents in main tree before attempting to learn other tree's talents
+ if (!isMainTree && primaryTreeTalents < REQ_PRIMARY_TREE_TALENTS)
+ return false;
// spell not set in talent.dbc
uint32 spellid = talentInfo->RankID[talentRank];
if (spellid == 0)
{
TC_LOG_ERROR(LOG_FILTER_PLAYER, "Talent.dbc have for talent: %u Rank: %u spell id = 0", talentId, talentRank);
- return;
+ return false;
}
// already known
if (HasSpell(spellid))
- return;
+ return false;
// learn! (other talent ranks will unlearned at learning)
learnSpell(spellid, false);
- AddTalent(spellid, m_activeSpec, true);
+ AddTalent(spellid, GetActiveSpec(), true);
- TC_LOG_INFO(LOG_FILTER_PLAYER, "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, m_activeSpec);
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, GetActiveSpec());
+
+ // set talent tree for player
+ if (!GetPrimaryTalentTree(GetActiveSpec()))
+ {
+ SetPrimaryTalentTree(GetActiveSpec(), talentInfo->TalentTab);
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentInfo->TalentTab);
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ learnSpell(specSpells->at(i), false);
+
+ if (CanUseMastery())
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(talentTabInfo->MasterySpellId[i]))
+ if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell))
+ CastSpell(this, masterySpell->Id, true);
+ }
// update free talent points
SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1));
+ return true;
}
void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank)
@@ -25061,7 +25619,7 @@ void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank)
void Player::AddKnownCurrency(uint32 itemId)
{
if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId))
- SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (1LL << (ctEntry->BitIndex-1)));
+ SetFlag64(0, (1LL << (ctEntry->ID-1)));
}
void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode)
@@ -25135,17 +25693,18 @@ bool Player::canSeeSpellClickOn(Creature const* c) const
void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
{
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
- *data << uint8(m_specsCount); // talent group count (0, 1 or 2)
- *data << uint8(m_activeSpec); // talent group index (0 or 1)
+ *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2)
+ *data << uint8(GetActiveSpec()); // talent group index (0 or 1)
- if (m_specsCount)
+ if (GetSpecsCount())
{
- if (m_specsCount > MAX_TALENT_SPECS)
- m_specsCount = MAX_TALENT_SPECS;
+ if (GetSpecsCount() > MAX_TALENT_SPECS)
+ SetSpecsCount(MAX_TALENT_SPECS);
// loop through all specs (only 1 for now)
- for (uint32 specIdx = 0; specIdx < m_specsCount; ++specIdx)
+ for (uint8 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx)
{
+ *data << uint32(GetPrimaryTalentTree(specIdx));
uint8 talentIdCount = 0;
size_t pos = data->wpos();
*data << uint8(talentIdCount); // [PH], talentIdCount
@@ -25194,7 +25753,7 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
*data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- *data << uint16(m_Glyphs[specIdx][i]); // GlyphProperties.dbc
+ *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc
}
}
}
@@ -25505,6 +26064,39 @@ void Player::SendClearCooldown(uint32 spell_id, Unit* target)
SendDirectMessage(&data);
}
+void Player::SendClearAllCooldowns(Unit* target)
+{
+ uint32 spellCount = m_spellCooldowns.size();
+ ObjectGuid guid = target ? target->GetGUID() : 0;
+
+ WorldPacket data(SMSG_CLEAR_COOLDOWNS, 4+8);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBits(spellCount, 24); // Spell Count
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr)
+ data << uint32(itr->first); // Spell ID
+
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ SendDirectMessage(&data);
+}
+
void Player::ResetMap()
{
// this may be called during Map::Update
@@ -25525,7 +26117,7 @@ void Player::SetMap(Map* map)
void Player::_LoadGlyphs(PreparedQueryResult result)
{
- // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 from character_glyphs WHERE guid = '%u'
+ // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u'
if (!result)
return;
@@ -25534,15 +26126,11 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
Field* fields = result->Fetch();
uint8 spec = fields[0].GetUInt8();
- if (spec >= m_specsCount)
+ if (spec >= GetSpecsCount())
continue;
- m_Glyphs[spec][0] = fields[1].GetUInt16();
- m_Glyphs[spec][1] = fields[2].GetUInt16();
- m_Glyphs[spec][2] = fields[3].GetUInt16();
- m_Glyphs[spec][3] = fields[4].GetUInt16();
- m_Glyphs[spec][4] = fields[5].GetUInt16();
- m_Glyphs[spec][5] = fields[6].GetUInt16();
+ for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16();
}
while (result->NextRow());
}
@@ -25554,7 +26142,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
trans->Append(stmt);
- for (uint8 spec = 0; spec < m_specsCount; ++spec)
+ for (uint8 spec = 0; spec < GetSpecsCount(); ++spec)
{
uint8 index = 0;
@@ -25564,7 +26152,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
stmt->setUInt8(index++, spec);
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- stmt->setUInt16(index++, uint16(m_Glyphs[spec][i]));
+ stmt->setUInt16(index++, uint16(GetGlyph(spec, i)));
trans->Append(stmt);
}
@@ -25587,7 +26175,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
{
- for (PlayerTalentMap::iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end();)
+ for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
{
@@ -25610,7 +26198,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
if (itr->second->state == PLAYERSPELL_REMOVED)
{
delete itr->second;
- m_talents[i]->erase(itr++);
+ GetTalentMap(i)->erase(itr++);
}
else
{
@@ -25627,7 +26215,7 @@ void Player::UpdateSpecCount(uint8 count)
if (curCount == count)
return;
- if (m_activeSpec >= count)
+ if (GetActiveSpec() >= count)
ActivateSpec(0);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -25654,11 +26242,10 @@ void Player::UpdateSpecCount(uint8 count)
_SaveActions(trans);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC);
- stmt->setUInt8(0, m_activeSpec);
+ stmt->setUInt8(0, GetActiveSpec());
stmt->setUInt32(1, GetGUIDLow());
trans->Append(stmt);
- m_activeSpec = 0;
}
CharacterDatabase.CommitTransaction(trans);
@@ -25737,10 +26324,25 @@ void Player::ActivateSpec(uint8 spec)
}
}
+ // Remove spec specific spells
+ for (uint32 i = 0; i < MAX_TALENT_TABS; ++i)
+ {
+ uint32 const* talentTabs = GetTalentTabPages(getClass());
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i]);
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ removeSpell(specSpells->at(i), true);
+
+ TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]);
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[i])
+ removeSpell(mastery, true);
+ }
+
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
// remove secondary glyph
- if (uint32 oldglyph = m_Glyphs[m_activeSpec][slot])
+ if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot))
if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
RemoveAurasDueToSpell(old_gp->SpellId);
@@ -25770,7 +26372,7 @@ void Player::ActivateSpec(uint8 spec)
if (talentInfo->RankID[rank] == 0)
continue;
// if the talent can be found in the newly activated PlayerTalentMap
- if (HasTalent(talentInfo->RankID[rank], m_activeSpec))
+ if (HasTalent(talentInfo->RankID[rank], GetActiveSpec()))
{
learnSpell(talentInfo->RankID[rank], false); // add the talent to the PlayerSpellMap
spentTalents += (rank + 1); // increment the spentTalents count
@@ -25778,10 +26380,21 @@ void Player::ActivateSpec(uint8 spec)
}
}
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetPrimaryTalentTree(GetActiveSpec()));
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ learnSpell(specSpells->at(i), false);
+
+ if (CanUseMastery())
+ if (TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[i])
+ learnSpell(mastery, false);
+
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
{
- uint32 glyph = m_Glyphs[m_activeSpec][slot];
+ uint32 glyph = GetGlyph(GetActiveSpec(), slot);
// apply primary glyph
if (glyph)
@@ -25791,13 +26404,13 @@ void Player::ActivateSpec(uint8 spec)
SetGlyph(slot, glyph);
}
- m_usedTalentCount = spentTalents;
+ SetUsedTalentCount(spentTalents);
InitTalentForLevel();
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC);
stmt->setUInt32(0, GetGUIDLow());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
_LoadActions(result);
}
@@ -25809,6 +26422,9 @@ void Player::ActivateSpec(uint8 spec)
SetPower(POWER_MANA, 0); // Mana must be 0 even if it isn't the active power type.
SetPower(pw, 0);
+
+ if (!sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ ResetTalents(true);
}
void Player::ResetTimeSync()
@@ -25821,8 +26437,10 @@ void Player::ResetTimeSync()
void Player::SendTimeSync()
{
+ m_timeSyncCounter = m_movementCounter;
+
WorldPacket data(SMSG_TIME_SYNC_REQ, 4);
- data << uint32(m_timeSyncCounter++);
+ data << uint32(m_movementCounter++);
GetSession()->SendPacket(&data);
// Schedule next sync in 10 sec
@@ -25839,9 +26457,9 @@ uint32 Player::GetReputation(uint32 factionentry) const
return GetReputationMgr().GetReputation(sFactionStore.LookupEntry(factionentry));
}
-std::string const& Player::GetGuildName()
+std::string Player::GetGuildName()
{
- return sGuildMgr->GetGuildById(GetGuildId())->GetName();
+ return GetGuildId() ? sGuildMgr->GetGuildById(GetGuildId())->GetName() : "";
}
void Player::SendDuelCountdown(uint32 counter)
@@ -25890,18 +26508,44 @@ void Player::SendRefundInfo(Item* item)
return;
}
+ ObjectGuid guid = item->GetGUID();
WorldPacket data(SMSG_ITEM_REFUND_INFO_RESPONSE, 8+4+4+4+4*4+4*4+4+4);
- data << uint64(item->GetGUID()); // item guid
- data << uint32(item->GetPaidMoney()); // money cost
- data << uint32(iece->reqhonorpoints); // honor point cost
- data << uint32(iece->reqarenapoints); // arena point cost
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i) // item cost data
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[7]);
+ data << uint32(GetTotalPlayedTime() - item->GetPlayedTime());
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i) // item cost data
{
- data << uint32(iece->reqitem[i]);
- data << uint32(iece->reqitemcount[i]);
+ data << uint32(iece->RequiredItemCount[i]);
+ data << uint32(iece->RequiredItem[i]);
}
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[2]);
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) // currency cost data
+ {
+ CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ data << uint32(iece->RequiredCurrencyCount[i] / precision);
+ data << uint32(iece->RequiredCurrency[i]);
+ }
+
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[5]);
data << uint32(0);
- data << uint32(GetTotalPlayedTime() - item->GetPlayedTime());
+ data.WriteByteSeq(guid[0]);
+ data << uint32(item->GetPaidMoney()); // money cost
GetSession()->SendPacket(&data);
}
@@ -25928,6 +26572,54 @@ bool Player::AddItem(uint32 itemId, uint32 count)
return true;
}
+void Player::SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, uint8 error)
+{
+ ObjectGuid guid = item->GetGUID();
+ WorldPacket data(SMSG_ITEM_REFUND_RESULT, 1 + 1 + 8 + 4*8 + 4 + 4*8 + 1);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(!error);
+ data.WriteBit(item->GetPaidMoney() > 0);
+ data.FlushBits();
+ if (!error)
+ {
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ data << uint32(iece->RequiredCurrencyCount[i] / precision);
+ data << uint32(iece->RequiredCurrency[i]);
+ }
+
+ data << uint32(item->GetPaidMoney()); // money cost
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i) // item cost data
+ {
+ data << uint32(iece->RequiredItemCount[i]);
+ data << uint32(iece->RequiredItem[i]);
+ }
+ }
+
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[5]);
+
+ data << uint8(error); // error code
+ GetSession()->SendPacket(&data);
+}
+
void Player::RefundItem(Item* item)
{
if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
@@ -25939,10 +26631,7 @@ void Player::RefundItem(Item* item)
if (item->IsRefundExpired()) // item refund has expired
{
item->SetNotRefundable(this);
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4);
- data << uint64(item->GetGUID()); // Guid
- data << uint32(10); // Error!
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, NULL, 10);
return;
}
@@ -25961,10 +26650,10 @@ void Player::RefundItem(Item* item)
}
bool store_error = false;
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- uint32 count = iece->reqitemcount[i];
- uint32 itemid = iece->reqitem[i];
+ uint32 count = iece->RequiredItemCount[i];
+ uint32 itemid = iece->RequiredItem[i];
if (count && itemid)
{
@@ -25980,25 +26669,11 @@ void Player::RefundItem(Item* item)
if (store_error)
{
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4);
- data << uint64(item->GetGUID()); // Guid
- data << uint32(10); // Error!
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, iece, 10);
return;
}
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4+4+4+4+4*4+4*4);
- data << uint64(item->GetGUID()); // item guid
- data << uint32(0); // 0, or error code
- data << uint32(item->GetPaidMoney()); // money cost
- data << uint32(iece->reqhonorpoints); // honor point cost
- data << uint32(iece->reqarenapoints); // arena point cost
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i) // item cost data
- {
- data << uint32(iece->reqitem[i]);
- data << uint32(iece->reqitemcount[i]);
- }
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, iece, 0);
uint32 moneyRefund = item->GetPaidMoney(); // item-> will be invalidated in DestroyItem
@@ -26012,10 +26687,10 @@ void Player::RefundItem(Item* item)
DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
// Grant back extendedcost items
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- uint32 count = iece->reqitemcount[i];
- uint32 itemid = iece->reqitem[i];
+ uint32 count = iece->RequiredItemCount[i];
+ uint32 itemid = iece->RequiredItem[i];
if (count && itemid)
{
ItemPosCountVec dest;
@@ -26026,18 +26701,19 @@ void Player::RefundItem(Item* item)
}
}
+ // Grant back currencies
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ uint32 count = iece->RequiredCurrencyCount[i];
+ uint32 currencyid = iece->RequiredCurrency[i];
+ if (count && currencyid)
+ ModifyCurrency(currencyid, count);
+ }
+
// Grant back money
if (moneyRefund)
ModifyMoney(moneyRefund); // Saved in SaveInventoryAndGoldToDB
- // Grant back Honor points
- if (uint32 honorRefund = iece->reqhonorpoints)
- ModifyHonorPoints(honorRefund, &trans);
-
- // Grant back Arena points
- if (uint32 arenaRefund = iece->reqarenapoints)
- ModifyArenaPoints(arenaRefund, &trans);
-
SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
@@ -26125,46 +26801,119 @@ bool Player::IsInWhisperWhiteList(uint64 guid)
return false;
}
-void Player::SendMovementSetCanFly(bool apply)
+uint8 Player::GetNextVoidStorageFreeSlot() const
{
- WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (!_voidStorageItems[i]) // unused item
+ return i;
+
+ return VOID_STORAGE_MAX_SLOT;
}
-void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply)
+uint8 Player::GetNumOfVoidStorageFreeSlots() const
{
- WorldPacket data(apply ?
- SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY :
- SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ uint8 count = 0;
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (!_voidStorageItems[i])
+ count++;
+
+ return count;
}
-void Player::SendMovementSetHover(bool apply)
+uint8 Player::AddVoidStorageItem(const VoidStorageItem& item)
{
- WorldPacket data(apply ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ int8 slot = GetNextVoidStorageFreeSlot();
+
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return 255;
+ }
+
+ _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemEntry,
+ item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor);
+ return slot;
}
-void Player::SendMovementSetWaterWalking(bool apply)
+void Player::AddVoidStorageItemAtSlot(uint8 slot, const VoidStorageItem& item)
{
- WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return;
+ }
+
+ if (_voidStorageItems[slot])
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Player::AddVoidStorageItemAtSlot - Player (GUID: %u, name: %s) tried to add an item to an used slot (item id: " UI64FMTD ", entry: %u, slot: %u).", GetGUIDLow(), GetName().c_str(), _voidStorageItems[slot]->ItemId, _voidStorageItems[slot]->ItemEntry, slot);
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
+
+ _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemId,
+ item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor);
}
-void Player::SendMovementSetFeatherFall(bool apply)
+void Player::DeleteVoidStorageItem(uint8 slot)
{
- WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
+
+ delete _voidStorageItems[slot];
+ _voidStorageItems[slot] = NULL;
+}
+
+bool Player::SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot)
+{
+ if (oldSlot >= VOID_STORAGE_MAX_SLOT || newSlot >= VOID_STORAGE_MAX_SLOT || oldSlot == newSlot)
+ return false;
+
+ std::swap(_voidStorageItems[newSlot], _voidStorageItems[oldSlot]);
+ return true;
+}
+
+VoidStorageItem* Player::GetVoidStorageItem(uint8 slot) const
+{
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return NULL;
+ }
+
+ return _voidStorageItems[slot];
+}
+
+VoidStorageItem* Player::GetVoidStorageItem(uint64 id, uint8& slot) const
+{
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ if (_voidStorageItems[i] && _voidStorageItems[i]->ItemId == id)
+ {
+ slot = i;
+ return _voidStorageItems[i];
+ }
+ }
+
+ return NULL;
+}
+
+void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply)
+{
+ Movement::PacketSender(this, NULL_OPCODE, apply ?
+ SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY :
+ SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY).Send();
+}
+
+void Player::SendMovementSetCollisionHeight(float height)
+{
+ static MovementStatusElements const heightElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&heightElement);
+ extra.Data.floatData = height;
+ Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_SET_COLLISION_HEIGHT, SMSG_MOVE_UPDATE_COLLISION_HEIGHT, &extra).Send();
}
float Player::GetCollisionHeight(bool mounted) const
@@ -26318,3 +27067,293 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
return pet;
}
+
+bool Player::CanUseMastery() const
+{
+ return HasSpell(MasterySpells[getClass()]);
+}
+
+void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::ExtraMovementStatusElement* extras /*= NULL*/)
+{
+ MovementStatusElements const* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
+ if (!sequence)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player::ReadMovementInfo: No movement sequence found for opcode %s", GetOpcodeNameForLogging(data.GetOpcode()).c_str());
+ return;
+ }
+
+ bool hasMovementFlags = false;
+ bool hasMovementFlags2 = false;
+ bool hasTimestamp = false;
+ bool hasOrientation = false;
+ bool hasTransportData = false;
+
+ ObjectGuid guid;
+ ObjectGuid tguid;
+
+ for (; *sequence != MSEEnd; ++sequence)
+ {
+ MovementStatusElements const& element = *sequence;
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ guid[element - MSEHasGuidByte0] = data.ReadBit();
+ break;
+ case MSEHasTransportGuidByte0:
+ case MSEHasTransportGuidByte1:
+ case MSEHasTransportGuidByte2:
+ case MSEHasTransportGuidByte3:
+ case MSEHasTransportGuidByte4:
+ case MSEHasTransportGuidByte5:
+ case MSEHasTransportGuidByte6:
+ case MSEHasTransportGuidByte7:
+ if (hasTransportData)
+ tguid[element - MSEHasTransportGuidByte0] = data.ReadBit();
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ data.ReadByteSeq(guid[element - MSEGuidByte0]);
+ break;
+ case MSETransportGuidByte0:
+ case MSETransportGuidByte1:
+ case MSETransportGuidByte2:
+ case MSETransportGuidByte3:
+ case MSETransportGuidByte4:
+ case MSETransportGuidByte5:
+ case MSETransportGuidByte6:
+ case MSETransportGuidByte7:
+ if (hasTransportData)
+ data.ReadByteSeq(tguid[element - MSETransportGuidByte0]);
+ break;
+ case MSEHasMovementFlags:
+ hasMovementFlags = !data.ReadBit();
+ break;
+ case MSEHasMovementFlags2:
+ hasMovementFlags2 = !data.ReadBit();
+ break;
+ case MSEHasTimestamp:
+ hasTimestamp = !data.ReadBit();
+ break;
+ case MSEHasOrientation:
+ hasOrientation = !data.ReadBit();
+ break;
+ case MSEHasTransportData:
+ hasTransportData = data.ReadBit();
+ break;
+ case MSEHasTransportTime2:
+ if (hasTransportData)
+ mi->bits.hasTransportTime2 = data.ReadBit();
+ break;
+ case MSEHasTransportTime3:
+ if (hasTransportData)
+ mi->bits.hasTransportTime3 = data.ReadBit();
+ break;
+ case MSEHasPitch:
+ mi->bits.hasPitch = !data.ReadBit();
+ break;
+ case MSEHasFallData:
+ mi->bits.hasFallData = data.ReadBit();
+ break;
+ case MSEHasFallDirection:
+ if (mi->bits.hasFallData)
+ mi->bits.hasFallDirection = data.ReadBit();
+ break;
+ case MSEHasSplineElevation:
+ mi->bits.hasSplineElevation = !data.ReadBit();
+ break;
+ case MSEHasSpline:
+ data.ReadBit();
+ break;
+ case MSEMovementFlags:
+ if (hasMovementFlags)
+ mi->flags = data.ReadBits(30);
+ break;
+ case MSEMovementFlags2:
+ if (hasMovementFlags2)
+ mi->flags2 = data.ReadBits(12);
+ break;
+ case MSETimestamp:
+ if (hasTimestamp)
+ data >> mi->time;
+ break;
+ case MSEPositionX:
+ data >> mi->pos.m_positionX;
+ break;
+ case MSEPositionY:
+ data >> mi->pos.m_positionY;
+ break;
+ case MSEPositionZ:
+ data >> mi->pos.m_positionZ;
+ break;
+ case MSEOrientation:
+ if (hasOrientation)
+ mi->pos.SetOrientation(data.read<float>());
+ break;
+ case MSETransportPositionX:
+ if (hasTransportData)
+ data >> mi->t_pos.m_positionX;
+ break;
+ case MSETransportPositionY:
+ if (hasTransportData)
+ data >> mi->t_pos.m_positionY;
+ break;
+ case MSETransportPositionZ:
+ if (hasTransportData)
+ data >> mi->t_pos.m_positionZ;
+ break;
+ case MSETransportOrientation:
+ if (hasTransportData)
+ mi->t_pos.SetOrientation(data.read<float>());
+ break;
+ case MSETransportSeat:
+ if (hasTransportData)
+ data >> mi->t_seat;
+ break;
+ case MSETransportTime:
+ if (hasTransportData)
+ data >> mi->t_time;
+ break;
+ case MSETransportTime2:
+ if (hasTransportData && mi->bits.hasTransportTime2)
+ data >> mi->t_time2;
+ break;
+ case MSETransportTime3:
+ if (hasTransportData && mi->bits.hasTransportTime3)
+ data >> mi->t_time3;
+ break;
+ case MSEPitch:
+ if (mi->bits.hasPitch)
+ data >> mi->pitch;
+ break;
+ case MSEFallTime:
+ if (mi->bits.hasFallData)
+ data >> mi->fallTime;
+ break;
+ case MSEFallVerticalSpeed:
+ if (mi->bits.hasFallData)
+ data >> mi->j_zspeed;
+ break;
+ case MSEFallCosAngle:
+ if (mi->bits.hasFallData && mi->bits.hasFallDirection)
+ data >> mi->j_cosAngle;
+ break;
+ case MSEFallSinAngle:
+ if (mi->bits.hasFallData && mi->bits.hasFallDirection)
+ data >> mi->j_sinAngle;
+ break;
+ case MSEFallHorizontalSpeed:
+ if (mi->bits.hasFallData && mi->bits.hasFallDirection)
+ data >> mi->j_xyspeed;
+ break;
+ case MSESplineElevation:
+ if (mi->bits.hasSplineElevation)
+ data >> mi->splineElevation;
+ break;
+ case MSECounter:
+ data.read_skip<uint32>(); /// @TODO: Maybe compare it with m_movementCounter to verify that packets are sent & received in order?
+ break;
+ case MSEZeroBit:
+ case MSEOneBit:
+ data.ReadBit();
+ break;
+ case MSEExtraElement:
+ extras->ReadNextElement(data);
+ break;
+ default:
+ ASSERT(Movement::PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+ }
+
+ mi->guid = guid;
+ mi->t_guid = tguid;
+
+ if (hasTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX)
+ if (GetTransport())
+ GetTransport()->UpdatePosition(mi);
+
+ //! Anti-cheat checks. Please keep them in seperate if () blocks to maintain a clear overview.
+ //! Might be subject to latency, so just remove improper flags.
+ #ifdef TRINITY_DEBUG
+ #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
+ { \
+ if (check) \
+ { \
+ TC_LOG_DEBUG(LOG_FILTER_UNITS, "Player::ReadMovementInfo: Violation of MovementFlags found (%s). " \
+ "MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
+ STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetGUIDLow(), maskToRemove); \
+ mi->RemoveMovementFlag((maskToRemove)); \
+ } \
+ }
+ #else
+ #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
+ if (check) \
+ mi->RemoveMovementFlag((maskToRemove));
+ #endif
+
+ /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
+ in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
+ It will freeze clients that receive this player's movement info.
+ */
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
+ MOVEMENTFLAG_ROOT);
+
+ //! Cannot hover without SPELL_AURA_HOVER
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !HasAuraType(SPELL_AURA_HOVER),
+ MOVEMENTFLAG_HOVER);
+
+ //! Cannot ascend and descend at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
+ MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
+
+ //! Cannot move left and right at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
+ MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
+
+ //! Cannot strafe left and right at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
+ MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
+
+ //! Cannot pitch up and down at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
+ MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
+
+ //! Cannot move forwards and backwards at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
+ MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
+
+ //! Cannot walk on water without SPELL_AURA_WATER_WALK
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !HasAuraType(SPELL_AURA_WATER_WALK),
+ MOVEMENTFLAG_WATERWALKING);
+
+ //! Cannot feather fall without SPELL_AURA_FEATHER_FALL
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !HasAuraType(SPELL_AURA_FEATHER_FALL),
+ MOVEMENTFLAG_FALLING_SLOW);
+
+ /*! Cannot fly if no fly auras present. Exception is being a GM.
+ Note that we check for account level instead of Player::IsGameMaster() because in some
+ situations it may be feasable to use .gm fly on as a GM without having .gm on,
+ e.g. aerial combat.
+ */
+
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && ToPlayer()->GetSession()->GetSecurity() == SEC_PLAYER &&
+ !ToPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
+ !ToPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
+ MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
+
+ #undef REMOVE_VIOLATING_FLAGS
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index b05a08446c0..bbda2a75fba 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -25,19 +25,23 @@
#include "Item.h"
#include "PetDefines.h"
+#include "PhaseMgr.h"
#include "QuestDef.h"
#include "SpellMgr.h"
#include "Unit.h"
+#include "Opcodes.h"
+#include "WorldSession.h"
#include <string>
#include <vector>
struct CreatureTemplate;
struct Mail;
+struct ItemExtendedCostEntry;
struct TrainerSpell;
struct VendorItem;
-class AchievementMgr;
+template<class T> class AchievementMgr;
class ReputationMgr;
class Channel;
class CharacterCreateInfo;
@@ -51,12 +55,13 @@ class PlayerMenu;
class PlayerSocial;
class SpellCastTargets;
class UpdateMask;
+class PhaseMgr;
typedef std::deque<Mail*> PlayerMails;
-#define PLAYER_MAX_SKILLS 127
+#define PLAYER_MAX_SKILLS 128
#define PLAYER_MAX_DAILY_QUESTS 25
-#define PLAYER_EXPLORED_ZONES_SIZE 128
+#define PLAYER_EXPLORED_ZONES_SIZE 156
// Note: SPELLMOD_* values is aura types in fact
enum SpellModType
@@ -108,6 +113,42 @@ struct PlayerTalent
uint8 spec : 8;
};
+extern uint32 const MasterySpells[MAX_CLASSES];
+
+enum TalentTree // talent tabs
+{
+ TALENT_TREE_WARRIOR_ARMS = 746,
+ TALENT_TREE_WARRIOR_FURY = 815,
+ TALENT_TREE_WARRIOR_PROTECTION = 845,
+ TALENT_TREE_PALADIN_HOLY = 831,
+ TALENT_TREE_PALADIN_PROTECTION = 839,
+ TALENT_TREE_PALADIN_RETRIBUTION = 855,
+ TALENT_TREE_HUNTER_BEAST_MASTERY = 811,
+ TALENT_TREE_HUNTER_MARKSMANSHIP = 807,
+ TALENT_TREE_HUNTER_SURVIVAL = 809,
+ TALENT_TREE_ROGUE_ASSASSINATION = 182,
+ TALENT_TREE_ROGUE_COMBAT = 181,
+ TALENT_TREE_ROGUE_SUBTLETY = 183,
+ TALENT_TREE_PRIEST_DISCIPLINE = 760,
+ TALENT_TREE_PRIEST_HOLY = 813,
+ TALENT_TREE_PRIEST_SHADOW = 795,
+ TALENT_TREE_DEATH_KNIGHT_BLOOD = 398,
+ TALENT_TREE_DEATH_KNIGHT_FROST = 399,
+ TALENT_TREE_DEATH_KNIGHT_UNHOLY = 400,
+ TALENT_TREE_SHAMAN_ELEMENTAL = 261,
+ TALENT_TREE_SHAMAN_ENHANCEMENT = 263,
+ TALENT_TREE_SHAMAN_RESTORATION = 262,
+ TALENT_TREE_MAGE_ARCANE = 799,
+ TALENT_TREE_MAGE_FIRE = 851,
+ TALENT_TREE_MAGE_FROST = 823,
+ TALENT_TREE_WARLOCK_AFFLICTION = 871,
+ TALENT_TREE_WARLOCK_DEMONOLOGY = 867,
+ TALENT_TREE_WARLOCK_DESTRUCTION = 865,
+ TALENT_TREE_DRUID_BALANCE = 752,
+ TALENT_TREE_DRUID_FERAL_COMBAT = 750,
+ TALENT_TREE_DRUID_RESTORATION = 748
+};
+
// Spell modifier (used for modify other spells)
struct SpellModifier
{
@@ -121,12 +162,121 @@ struct SpellModifier
Aura* const ownerAura;
};
+enum PlayerCurrencyState
+{
+ PLAYERCURRENCY_UNCHANGED = 0,
+ PLAYERCURRENCY_CHANGED = 1,
+ PLAYERCURRENCY_NEW = 2,
+ PLAYERCURRENCY_REMOVED = 3 //not removed just set count == 0
+};
+
+struct PlayerCurrency
+{
+ PlayerCurrencyState state;
+ uint32 totalCount;
+ uint32 weekCount;
+};
+
typedef UNORDERED_MAP<uint32, PlayerTalent*> PlayerTalentMap;
typedef UNORDERED_MAP<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
+typedef UNORDERED_MAP<uint32, PlayerCurrency> PlayerCurrenciesMap;
typedef std::list<uint64> WhisperListContainer;
+/// Maximum number of CompactUnitFrames profiles
+#define MAX_CUF_PROFILES 5
+
+/// Bit index used in the many bool options of CompactUnitFrames
+enum CUFBoolOptions
+{
+ CUF_KEEP_GROUPS_TOGETHER,
+ CUF_DISPLAY_PETS,
+ CUF_DISPLAY_MAIN_TANK_AND_ASSIST,
+ CUF_DISPLAY_HEAL_PREDICTION,
+ CUF_DISPLAY_AGGRO_HIGHLIGHT,
+ CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS,
+ CUF_DISPLAY_POWER_BAR,
+ CUF_DISPLAY_BORDER,
+ CUF_USE_CLASS_COLORS,
+ CUF_DISPLAY_NON_BOSS_DEBUFFS,
+ CUF_DISPLAY_HORIZONTAL_GROUPS,
+ CUF_LOCKED,
+ CUF_SHOWN,
+ CUF_AUTO_ACTIVATE_2_PLAYERS,
+ CUF_AUTO_ACTIVATE_3_PLAYERS,
+ CUF_AUTO_ACTIVATE_5_PLAYERS,
+ CUF_AUTO_ACTIVATE_10_PLAYERS,
+ CUF_AUTO_ACTIVATE_15_PLAYERS,
+ CUF_AUTO_ACTIVATE_25_PLAYERS,
+ CUF_AUTO_ACTIVATE_40_PLAYERS,
+ CUF_AUTO_ACTIVATE_SPEC_1,
+ CUF_AUTO_ACTIVATE_SPEC_2,
+ CUF_AUTO_ACTIVATE_PVP,
+ CUF_AUTO_ACTIVATE_PVE,
+ CUF_UNK_145,
+ CUF_UNK_156,
+ CUF_UNK_157,
+
+ // The unks is _LOCKED and _SHOWN and _DYNAMIC, unknown order
+
+ CUF_BOOL_OPTIONS_COUNT,
+};
+
+/// Represents a CompactUnitFrame profile
+struct CUFProfile
+{
+ CUFProfile() : ProfileName(), BoolOptions() // might want to change default value for options
+ {
+ FrameHeight = 0;
+ FrameWidth = 0;
+ SortBy = 0;
+ HealthText = 0;
+ Unk146 = 0;
+ Unk147 = 0;
+ Unk148 = 0;
+ Unk150 = 0;
+ Unk152 = 0;
+ Unk154 = 0;
+ }
+
+ CUFProfile(const std::string& name, uint16 frameHeight, uint16 frameWidth, uint8 sortBy, uint8 healthText, uint32 boolOptions,
+ uint8 unk146, uint8 unk147, uint8 unk148, uint16 unk150, uint16 unk152, uint16 unk154)
+ : ProfileName(name), BoolOptions((int)boolOptions)
+ {
+ FrameHeight = frameHeight;
+ FrameWidth = frameWidth;
+ SortBy = sortBy;
+ HealthText = healthText;
+ Unk146 = unk146;
+ Unk147 = unk147;
+ Unk148 = unk148;
+ Unk150 = unk150;
+ Unk152 = unk152;
+ Unk154 = unk154;
+ }
+
+ std::string ProfileName;
+ uint16 FrameHeight;
+ uint16 FrameWidth;
+ uint8 SortBy;
+ uint8 HealthText;
+
+ // LeftAlign, TopAlight, BottomAllign (unk order)
+ uint8 Unk146;
+ uint8 Unk147;
+ uint8 Unk148;
+
+ // LeftOffset, TopOffset and BottomOffset (unk order)
+ uint16 Unk150;
+ uint16 Unk152;
+ uint16 Unk154;
+
+ std::bitset<CUF_BOOL_OPTIONS_COUNT> BoolOptions;
+
+ // More fields can be added to BoolOptions without changing DB schema (up to 32, currently 27)
+};
+
struct SpellCooldown
{
time_t end;
@@ -138,9 +288,9 @@ typedef UNORDERED_MAP<uint32 /*instanceId*/, time_t/*releaseTime*/> InstanceTime
enum TrainerSpellState
{
- TRAINER_SPELL_GREEN = 0,
- TRAINER_SPELL_RED = 1,
- TRAINER_SPELL_GRAY = 2,
+ TRAINER_SPELL_GRAY = 0,
+ TRAINER_SPELL_GREEN = 1,
+ TRAINER_SPELL_RED = 2,
TRAINER_SPELL_GREEN_DISABLED = 10 // custom value, not send to client: formally green but learn not allowed
};
@@ -212,20 +362,6 @@ struct PlayerCreateInfoItem
typedef std::list<PlayerCreateInfoItem> PlayerCreateInfoItems;
-struct PlayerClassLevelInfo
-{
- PlayerClassLevelInfo() : basehealth(0), basemana(0) {}
- uint16 basehealth;
- uint16 basemana;
-};
-
-struct PlayerClassInfo
-{
- PlayerClassInfo() : levelInfo(NULL) { }
-
- PlayerClassLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
-};
-
struct PlayerLevelInfo
{
PlayerLevelInfo() { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; }
@@ -354,14 +490,6 @@ struct EnchantDuration
typedef std::list<EnchantDuration> EnchantDurationList;
typedef std::list<Item*> ItemDurationList;
-enum PlayerMovementType
-{
- MOVE_ROOT = 1,
- MOVE_UNROOT = 2,
- MOVE_WATER_WALK = 3,
- MOVE_LAND_WALK = 4
-};
-
enum DrunkenState
{
DRUNKEN_SOBER = 0,
@@ -374,87 +502,42 @@ enum DrunkenState
enum PlayerFlags
{
- PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
- PLAYER_FLAGS_AFK = 0x00000002,
- PLAYER_FLAGS_DND = 0x00000004,
- PLAYER_FLAGS_GM = 0x00000008,
- PLAYER_FLAGS_GHOST = 0x00000010,
- PLAYER_FLAGS_RESTING = 0x00000020,
- PLAYER_FLAGS_UNK6 = 0x00000040,
- PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
- PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
- PLAYER_FLAGS_IN_PVP = 0x00000200,
- PLAYER_FLAGS_HIDE_HELM = 0x00000400,
- PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
- PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
- PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
- PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
- PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
- PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
- PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
- PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
- PLAYER_FLAGS_UBER = 0x00080000,
- PLAYER_FLAGS_UNK20 = 0x00100000,
- PLAYER_FLAGS_UNK21 = 0x00200000,
- PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
- PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
- PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
- PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
- PLAYER_FLAGS_UNK26 = 0x04000000,
- PLAYER_FLAGS_UNK27 = 0x08000000,
- PLAYER_FLAGS_UNK28 = 0x10000000,
- PLAYER_FLAGS_UNK29 = 0x20000000,
- PLAYER_FLAGS_UNK30 = 0x40000000,
- PLAYER_FLAGS_UNK31 = 0x80000000
-};
-
-// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
-// can't use enum for uint64 values
-#define PLAYER_TITLE_DISABLED UI64LIT(0x0000000000000000)
-#define PLAYER_TITLE_NONE UI64LIT(0x0000000000000001)
-#define PLAYER_TITLE_PRIVATE UI64LIT(0x0000000000000002) // 1
-#define PLAYER_TITLE_CORPORAL UI64LIT(0x0000000000000004) // 2
-#define PLAYER_TITLE_SERGEANT_A UI64LIT(0x0000000000000008) // 3
-#define PLAYER_TITLE_MASTER_SERGEANT UI64LIT(0x0000000000000010) // 4
-#define PLAYER_TITLE_SERGEANT_MAJOR UI64LIT(0x0000000000000020) // 5
-#define PLAYER_TITLE_KNIGHT UI64LIT(0x0000000000000040) // 6
-#define PLAYER_TITLE_KNIGHT_LIEUTENANT UI64LIT(0x0000000000000080) // 7
-#define PLAYER_TITLE_KNIGHT_CAPTAIN UI64LIT(0x0000000000000100) // 8
-#define PLAYER_TITLE_KNIGHT_CHAMPION UI64LIT(0x0000000000000200) // 9
-#define PLAYER_TITLE_LIEUTENANT_COMMANDER UI64LIT(0x0000000000000400) // 10
-#define PLAYER_TITLE_COMMANDER UI64LIT(0x0000000000000800) // 11
-#define PLAYER_TITLE_MARSHAL UI64LIT(0x0000000000001000) // 12
-#define PLAYER_TITLE_FIELD_MARSHAL UI64LIT(0x0000000000002000) // 13
-#define PLAYER_TITLE_GRAND_MARSHAL UI64LIT(0x0000000000004000) // 14
-#define PLAYER_TITLE_SCOUT UI64LIT(0x0000000000008000) // 15
-#define PLAYER_TITLE_GRUNT UI64LIT(0x0000000000010000) // 16
-#define PLAYER_TITLE_SERGEANT_H UI64LIT(0x0000000000020000) // 17
-#define PLAYER_TITLE_SENIOR_SERGEANT UI64LIT(0x0000000000040000) // 18
-#define PLAYER_TITLE_FIRST_SERGEANT UI64LIT(0x0000000000080000) // 19
-#define PLAYER_TITLE_STONE_GUARD UI64LIT(0x0000000000100000) // 20
-#define PLAYER_TITLE_BLOOD_GUARD UI64LIT(0x0000000000200000) // 21
-#define PLAYER_TITLE_LEGIONNAIRE UI64LIT(0x0000000000400000) // 22
-#define PLAYER_TITLE_CENTURION UI64LIT(0x0000000000800000) // 23
-#define PLAYER_TITLE_CHAMPION UI64LIT(0x0000000001000000) // 24
-#define PLAYER_TITLE_LIEUTENANT_GENERAL UI64LIT(0x0000000002000000) // 25
-#define PLAYER_TITLE_GENERAL UI64LIT(0x0000000004000000) // 26
-#define PLAYER_TITLE_WARLORD UI64LIT(0x0000000008000000) // 27
-#define PLAYER_TITLE_HIGH_WARLORD UI64LIT(0x0000000010000000) // 28
-#define PLAYER_TITLE_GLADIATOR UI64LIT(0x0000000020000000) // 29
-#define PLAYER_TITLE_DUELIST UI64LIT(0x0000000040000000) // 30
-#define PLAYER_TITLE_RIVAL UI64LIT(0x0000000080000000) // 31
-#define PLAYER_TITLE_CHALLENGER UI64LIT(0x0000000100000000) // 32
-#define PLAYER_TITLE_SCARAB_LORD UI64LIT(0x0000000200000000) // 33
-#define PLAYER_TITLE_CONQUEROR UI64LIT(0x0000000400000000) // 34
-#define PLAYER_TITLE_JUSTICAR UI64LIT(0x0000000800000000) // 35
-#define PLAYER_TITLE_CHAMPION_OF_THE_NAARU UI64LIT(0x0000001000000000) // 36
-#define PLAYER_TITLE_MERCILESS_GLADIATOR UI64LIT(0x0000002000000000) // 37
-#define PLAYER_TITLE_OF_THE_SHATTERED_SUN UI64LIT(0x0000004000000000) // 38
-#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39
-#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40
-
-#define KNOWN_TITLES_SIZE 3
-#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE*64) // 3 uint64 fields
+ PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
+ PLAYER_FLAGS_AFK = 0x00000002,
+ PLAYER_FLAGS_DND = 0x00000004,
+ PLAYER_FLAGS_GM = 0x00000008,
+ PLAYER_FLAGS_GHOST = 0x00000010,
+ PLAYER_FLAGS_RESTING = 0x00000020,
+ PLAYER_FLAGS_UNK6 = 0x00000040,
+ PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
+ PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
+ PLAYER_FLAGS_IN_PVP = 0x00000200,
+ PLAYER_FLAGS_HIDE_HELM = 0x00000400,
+ PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
+ PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
+ PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
+ PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
+ PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
+ PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
+ PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
+ PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
+ PLAYER_FLAGS_UBER = 0x00080000,
+ PLAYER_FLAGS_UNK20 = 0x00100000,
+ PLAYER_FLAGS_UNK21 = 0x00200000,
+ PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
+ PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
+ PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
+ PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
+ PLAYER_FLAGS_UNK26 = 0x04000000,
+ PLAYER_FLAGS_AUTO_DECLINE_GUILD = 0x08000000, // Automatically declines guild invites
+ PLAYER_FLAGS_GUILD_LEVEL_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI
+ PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage
+ PLAYER_FLAGS_UNK30 = 0x40000000,
+ PLAYER_FLAGS_UNK31 = 0x80000000
+};
+
+#define KNOWN_TITLES_SIZE 4
+#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE * 64) // 4 uint64 fields
// used in PLAYER_FIELD_BYTES values
enum PlayerFieldByteFlags
@@ -476,7 +559,7 @@ enum MirrorTimerType
{
FATIGUE_TIMER = 0,
BREATH_TIMER = 1,
- FIRE_TIMER = 2
+ FIRE_TIMER = 2 // feign death
};
#define MAX_TIMERS 3
#define DISABLED_MIRROR_TIMER -1
@@ -490,7 +573,6 @@ enum PlayerExtraFlags
PLAYER_EXTRA_TAXICHEAT = 0x0008,
PLAYER_EXTRA_GM_INVISIBLE = 0x0010,
PLAYER_EXTRA_GM_CHAT = 0x0020, // Show GM badge in chat messages
- PLAYER_EXTRA_HAS_310_FLYER = 0x0040, // Marks if player already has 310% speed flying mount
// other states
PLAYER_EXTRA_PVP_DEATH = 0x0100 // store PvP death status until corpse creating.
@@ -562,7 +644,7 @@ enum PlayerSlots
// first slot for item stored (in any way in player m_items data)
PLAYER_SLOT_START = 0,
// last+1 slot for item stored (in any way in player m_items data)
- PLAYER_SLOT_END = 150,
+ PLAYER_SLOT_END = 86,
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
};
@@ -624,18 +706,6 @@ enum BuyBackSlots // 12 slots
BUYBACK_SLOT_END = 86
};
-enum KeyRingSlots // 32 slots
-{
- KEYRING_SLOT_START = 86,
- KEYRING_SLOT_END = 118
-};
-
-enum CurrencyTokenSlots // 32 slots
-{
- CURRENCYTOKEN_SLOT_START = 118,
- CURRENCYTOKEN_SLOT_END = 150
-};
-
enum EquipmentSetUpdateState
{
EQUIPMENT_SET_UNCHANGED = 0,
@@ -683,22 +753,24 @@ enum TradeSlots
enum TransferAbortReason
{
- TRANSFER_ABORT_NONE = 0x00,
- TRANSFER_ABORT_ERROR = 0x01,
- TRANSFER_ABORT_MAX_PLAYERS = 0x02, // Transfer Aborted: instance is full
- TRANSFER_ABORT_NOT_FOUND = 0x03, // Transfer Aborted: instance not found
- TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x04, // You have entered too many instances recently.
- TRANSFER_ABORT_ZONE_IN_COMBAT = 0x06, // Unable to zone in while an encounter is in progress.
- TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x07, // You must have <TBC, WotLK> expansion installed to access this area.
- TRANSFER_ABORT_DIFFICULTY = 0x08, // <Normal, Heroic, Epic> difficulty mode is not available for %s.
- TRANSFER_ABORT_UNIQUE_MESSAGE = 0x09, // Until you've escaped TLK's grasp, you cannot leave this place!
- TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A, // Additional instances cannot be launched, please try again later.
- TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
- TRANSFER_ABORT_NOT_FOUND1 = 0x0C, // 3.1
- TRANSFER_ABORT_NOT_FOUND2 = 0x0D, // 3.1
- TRANSFER_ABORT_NOT_FOUND3 = 0x0E, // 3.2
- TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
- TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10 // Map can't be entered at this time.
+ TRANSFER_ABORT_NONE = 0x00,
+ TRANSFER_ABORT_ERROR = 0x01,
+ TRANSFER_ABORT_MAX_PLAYERS = 0x02, // Transfer Aborted: instance is full
+ TRANSFER_ABORT_NOT_FOUND = 0x03, // Transfer Aborted: instance not found
+ TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x04, // You have entered too many instances recently.
+ TRANSFER_ABORT_ZONE_IN_COMBAT = 0x06, // Unable to zone in while an encounter is in progress.
+ TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x07, // You must have <TBC, WotLK> expansion installed to access this area.
+ TRANSFER_ABORT_DIFFICULTY = 0x08, // <Normal, Heroic, Epic> difficulty mode is not available for %s.
+ TRANSFER_ABORT_UNIQUE_MESSAGE = 0x09, // Until you've escaped TLK's grasp, you cannot leave this place!
+ TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A, // Additional instances cannot be launched, please try again later.
+ TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
+ TRANSFER_ABORT_NOT_FOUND1 = 0x0C, // 3.1
+ TRANSFER_ABORT_NOT_FOUND2 = 0x0D, // 3.1
+ TRANSFER_ABORT_NOT_FOUND3 = 0x0E, // 3.2
+ TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
+ TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10, // Map can't be entered at this time.
+ TRANSFER_ABORT_LOCKED_TO_DIFFERENT_INSTANCE = 0x12, // 4.2.2
+ TRANSFER_ABORT_ALREADY_COMPLETED_ENCOUNTER = 0x13 // 4.2.2
};
enum InstanceResetWarningType
@@ -807,6 +879,9 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES = 30,
PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS = 31,
PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS = 32,
+ PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE = 33,
+ PLAYER_LOGIN_QUERY_LOAD_CURRENCY = 34,
+ PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES = 35,
MAX_PLAYER_LOGIN_QUERY
};
@@ -823,7 +898,7 @@ enum PlayerDelayedOperations
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
-#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
+#define MAX_MONEY_AMOUNT (UI64LIT(9999999999)) // TODO: Move this restriction to worldserver.conf, default to this value, hardcap at uint64.max
struct InstancePlayerBind
{
@@ -854,12 +929,6 @@ enum CharDeleteMethod
// the name gets freed up and appears as deleted ingame
};
-enum CurrencyItems
-{
- ITEM_HONOR_POINTS_ID = 43308,
- ITEM_ARENA_POINTS_ID = 43307
-};
-
enum ReferAFriendError
{
ERR_REFER_A_FRIEND_NONE = 0x00,
@@ -906,14 +975,14 @@ class PlayerTaxi
bool IsTaximaskNodeKnown(uint32 nodeidx) const
{
- uint8 field = uint8((nodeidx - 1) / 32);
- uint32 submask = 1 << ((nodeidx-1) % 32);
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx-1) % 8);
return (m_taximask[field] & submask) == submask;
}
bool SetTaximaskNode(uint32 nodeidx)
{
- uint8 field = uint8((nodeidx - 1) / 32);
- uint32 submask = 1 << ((nodeidx-1) % 32);
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx-1) % 8);
if ((m_taximask[field] & submask) != submask)
{
m_taximask[field] |= submask;
@@ -954,12 +1023,14 @@ class Player;
struct BGData
{
BGData() : bgInstanceID(0), bgTypeID(BATTLEGROUND_TYPE_NONE), bgAfkReportedCount(0), bgAfkReportedTimer(0),
- bgTeam(0), mountSpell(0) { ClearTaxiPath(); }
+ bgTeam(0), mountSpell(0) { bgQueuesJoinedTime.clear(); ClearTaxiPath(); }
uint32 bgInstanceID; ///< This variable is set to bg->m_InstanceID,
/// when player is teleported to BG - (it is battleground's GUID)
BattlegroundTypeId bgTypeID;
+ std::map<uint32, uint32> bgQueuesJoinedTime;
+
std::set<uint32> bgAfkReporter;
uint8 bgAfkReportedCount;
time_t bgAfkReportedTimer;
@@ -975,6 +1046,33 @@ struct BGData
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
};
+struct VoidStorageItem
+{
+ VoidStorageItem()
+ {
+ ItemId = 0;
+ ItemEntry = 0;
+ CreatorGuid = 0;
+ ItemRandomPropertyId = 0;
+ ItemSuffixFactor = 0;
+ }
+
+ VoidStorageItem(uint64 id, uint32 entry, uint32 creator, uint32 randomPropertyId, uint32 suffixFactor)
+ {
+ ItemId = id;
+ ItemEntry = entry;
+ CreatorGuid = creator;
+ ItemRandomPropertyId = randomPropertyId;
+ ItemSuffixFactor = suffixFactor;
+ }
+
+ uint64 ItemId;
+ uint32 ItemEntry;
+ uint32 CreatorGuid;
+ uint32 ItemRandomPropertyId;
+ uint32 ItemSuffixFactor;
+};
+
class TradeData
{
public: // constructors
@@ -996,8 +1094,8 @@ class TradeData
Item* GetSpellCastItem() const;
bool HasSpellCastItem() const { return m_spellCastItem != 0; }
- uint32 GetMoney() const { return m_money; }
- void SetMoney(uint32 money);
+ uint64 GetMoney() const { return m_money; }
+ void SetMoney(uint64 money);
bool IsAccepted() const { return m_accepted; }
void SetAccepted(bool state, bool crosssend = false);
@@ -1017,7 +1115,7 @@ class TradeData
bool m_accepted; // m_player press accept for trade list
bool m_acceptProccess; // one from player/trader press accept and this processed
- uint32 m_money; // m_player place money to trade
+ uint64 m_money; // m_player place money to trade
uint32 m_spell; // m_player apply spell to non-traded slot item
uint64 m_spellCastItem; // applied spell casted by item use
@@ -1025,6 +1123,15 @@ class TradeData
uint64 m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot
};
+struct ResurrectionData
+{
+ uint64 GUID;
+ WorldLocation Location;
+ uint32 Health;
+ uint32 Mana;
+ uint32 Aura;
+};
+
class KillRewarder
{
public:
@@ -1057,6 +1164,50 @@ private:
bool _isPvP;
};
+struct PlayerTalentInfo
+{
+ PlayerTalentInfo() :
+ FreeTalentPoints(0), UsedTalentCount(0), QuestRewardedTalentCount(0),
+ ResetTalentsCost(0), ResetTalentsTime(0),
+ ActiveSpec(0), SpecsCount(1)
+ {
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ SpecInfo[i].Talents = new PlayerTalentMap();
+ memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
+ SpecInfo[i].TalentTree = 0;
+ }
+ }
+
+ ~PlayerTalentInfo()
+ {
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ for (PlayerTalentMap::const_iterator itr = SpecInfo[i].Talents->begin(); itr != SpecInfo[i].Talents->end(); ++itr)
+ delete itr->second;
+ delete SpecInfo[i].Talents;
+ }
+ }
+
+ struct TalentSpecInfo
+ {
+ PlayerTalentMap* Talents;
+ uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
+ uint32 TalentTree;
+ } SpecInfo[MAX_TALENT_SPECS];
+
+ uint32 FreeTalentPoints;
+ uint32 UsedTalentCount;
+ uint32 QuestRewardedTalentCount;
+ uint32 ResetTalentsCost;
+ time_t ResetTalentsTime;
+ uint8 ActiveSpec;
+ uint8 SpecsCount;
+
+private:
+ PlayerTalentInfo(PlayerTalentInfo const&);
+};
+
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1089,7 +1240,7 @@ class Player : public Unit, public GridObject<Player>
void Update(uint32 time);
- static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
+ static bool BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, ByteBuffer* bitBuffer);
void SetInWater(bool apply);
@@ -1134,8 +1285,6 @@ class Player : public Unit, public GridObject<Player>
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
void SetGMVisible(bool on);
- bool Has310Flyer(bool checkAllSpells, uint32 excludeSpellId = 0);
- void SetHas310Flyer(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_HAS_310_FLYER; else m_ExtraFlags &= ~PLAYER_EXTRA_HAS_310_FLYER; }
void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
void GiveXP(uint32 xp, Unit* victim, float group_rate=1.0f);
@@ -1176,7 +1325,8 @@ class Player : public Unit, public GridObject<Player>
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
- uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
+
+ PhaseMgr& GetPhaseMgr() { return phaseMgr; }
/// Handles said message in regular chat based on declared language and in config pre-defined Range.
void Say(std::string const& text, const uint32 language);
@@ -1186,8 +1336,9 @@ class Player : public Unit, public GridObject<Player>
void TextEmote(std::string const& text);
/// Handles whispers from Addons and players based on sender, receiver's guid and language.
void Whisper(std::string const& text, const uint32 language, uint64 receiver);
+ void WhisperAddon(std::string const& text, std::string const& prefix, Player* receiver);
/// Constructs the player Chat data for the specific functions to use
- void BuildPlayerChat(WorldPacket* data, uint8 msgtype, std::string const& text, uint32 language) const;
+ void BuildPlayerChat(WorldPacket* data, uint8 msgtype, std::string const& text, uint32 language, const char* addonPrefix = NULL) const;
/*********************************************************/
/*** STORAGE SYSTEM ***/
@@ -1258,11 +1409,36 @@ class Player : public Unit, public GridObject<Player>
void AddRefundReference(uint32 it);
void DeleteRefundReference(uint32 it);
+ /// send initialization of new currency for client
+ void SendNewCurrency(uint32 id) const;
+ /// send full data about all currencies to client
+ void SendCurrencies() const;
+ /// send conquest currency points and their cap week/arena
+ void SendPvpRewards() const;
+ /// return count of currency witch has plr
+ uint32 GetCurrency(uint32 id, bool usePrecision) const;
+ /// return count of currency gaind on current week
+ uint32 GetCurrencyOnWeek(uint32 id, bool usePrecision) const;
+ /// return week cap by currency id
+ uint32 GetCurrencyWeekCap(uint32 id, bool usePrecision) const;
+ /// return presence related currency
+ bool HasCurrency(uint32 id, uint32 count) const;
+ /// initialize currency count for custom initialization at create character
+ void SetCurrency(uint32 id, uint32 count, bool printLog = true);
+ void ResetCurrencyWeekCap();
+
+ /**
+ * @name ModifyCurrency
+ * @brief Change specific currency and send result to client
+
+ * @param id currency entry from CurrencyTypes.dbc
+ * @param count integer value for adding/removing curent currency
+ * @param printLog used on SMSG_UPDATE_CURRENCY
+ * @param ignore gain multipliers
+ */
+ void ModifyCurrency(uint32 id, int32 count, bool printLog = true, bool ignoreMultipliers = false);
+
void ApplyEquipCooldown(Item* pItem);
- void SetAmmo(uint32 item);
- void RemoveAmmo();
- float GetAmmoDPS() const { return m_ammoDPS; }
- bool CheckAmmoCompatibility(const ItemTemplate* ammo_proto) const;
void QuickEquipItem(uint16 pos, Item* pItem);
void VisualizeItem(uint8 slot, Item* pItem);
void SetVisibleItemSlot(uint8 slot, Item* pItem);
@@ -1283,10 +1459,9 @@ class Player : public Unit, public GridObject<Player>
void AddItemToBuyBackSlot(Item* pItem);
Item* GetItemFromBuyBackSlot(uint32 slot);
void RemoveItemFromBuyBackSlot(uint32 slot, bool del);
- uint32 GetMaxKeyringSize() const { return KEYRING_SLOT_END-KEYRING_SLOT_START; }
void SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2 = NULL, uint32 itemid = 0);
void SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 param);
- void SendSellError(SellResult msg, Creature* creature, uint64 guid, uint32 param);
+ void SendSellError(SellResult msg, Creature* creature, uint64 guid);
void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag; }
void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; }
uint32 GetWeaponProficiency() const { return m_WeaponProficiency; }
@@ -1295,6 +1470,7 @@ class Player : public Unit, public GridObject<Player>
bool IsTwoHandUsed() const;
void SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast = false);
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
+ bool BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count);
bool _StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
float GetReputationPriceDiscount(Creature const* creature) const;
@@ -1314,6 +1490,7 @@ class Player : public Unit, public GridObject<Player>
void AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 duration);
void ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur = true, bool ignore_condition = false);
void ApplyEnchantment(Item* item, bool apply);
+ void ApplyReforgeEnchantment(Item* item, bool apply);
void UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16 new_value);
void SendEnchantmentDurations();
void BuildEnchantmentsInfoData(WorldPacket* data);
@@ -1413,7 +1590,7 @@ class Player : public Unit, public GridObject<Player>
void ItemAddedQuestCheck(uint32 entry, uint32 count);
void ItemRemovedQuestCheck(uint32 entry, uint32 count);
void KilledMonster(CreatureTemplate const* cInfo, uint64 guid);
- void KilledMonsterCredit(uint32 entry, uint64 guid);
+ void KilledMonsterCredit(uint32 entry, uint64 guid = 0);
void KilledPlayerCredit();
void CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id);
void TalkedToCreature(uint32 entry, uint64 guid);
@@ -1425,14 +1602,13 @@ class Player : public Unit, public GridObject<Player>
void UpdateForQuestWorldObjects();
bool CanShareQuest(uint32 quest_id) const;
- void SendQuestComplete(uint32 quest_id);
+ void SendQuestComplete(Quest const* quest);
void SendQuestReward(Quest const* quest, uint32 XP);
void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK);
void SendQuestTimerFailed(uint32 quest_id);
void SendCanTakeQuestResponse(uint32 msg) const;
void SendQuestConfirmAccept(Quest const* quest, Player* pReceiver);
void SendPushToPartyResponse(Player* player, uint32 msg);
- void SendQuestUpdateAddItem(Quest const* quest, uint32 item_idx, uint16 count);
void SendQuestUpdateAddCreatureOrGo(Quest const* quest, uint64 guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count);
void SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint16 add_count);
@@ -1446,6 +1622,17 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 quest_id) { m_timedquests.insert(quest_id); }
void RemoveTimedQuest(uint32 quest_id) { m_timedquests.erase(quest_id); }
+ void SaveCUFProfile(uint8 id, CUFProfile* profile) { delete _CUFProfiles[id]; _CUFProfiles[id] = profile; } ///> Replaces a CUF profile at position 0-4
+ CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id]; } ///> Retrieves a CUF profile at position 0-4
+ uint8 GetCUFProfilesCount() const
+ {
+ uint8 count = 0;
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ if (_CUFProfiles[i])
+ ++count;
+ return count;
+ }
+
bool HasPvPForcingQuest() const;
/*********************************************************/
@@ -1463,6 +1650,8 @@ class Player : public Unit, public GridObject<Player>
static bool LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, uint64 guid);
static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; }
+ static bool IsValidClass(uint8 Class) { return (1 << (Class - 1)) & CLASSMASK_ALL_PLAYABLE; }
+ static bool IsValidRace(uint8 Race) { return (1 << (Race - 1)) & RACEMASK_ALL_PLAYABLE; }
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -1494,11 +1683,11 @@ class Player : public Unit, public GridObject<Player>
void setRegenTimerCount(uint32 time) {m_regenTimerCount = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
- uint32 GetMoney() const { return GetUInt32Value(PLAYER_FIELD_COINAGE); }
- bool ModifyMoney(int32 amount, bool sendError = true);
- bool HasEnoughMoney(uint32 amount) const { return (GetMoney() >= amount); }
- bool HasEnoughMoney(int32 amount) const;
- void SetMoney(uint32 value);
+ uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); }
+ bool ModifyMoney(int64 amount, bool sendError = true);
+ bool HasEnoughMoney(uint64 amount) const { return (GetMoney() >= amount); }
+ bool HasEnoughMoney(int64 amount) const;
+ void SetMoney(uint64 value);
RewardedQuestSet const& getRewardedQuests() const { return m_RewardedQuests; }
QuestStatusMap& getQuestStatusMap() { return m_QuestStatus; }
@@ -1560,6 +1749,7 @@ class Player : public Unit, public GridObject<Player>
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
bool IsSpellFitByClassAndRace(uint32 spell_id) const;
bool IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const;
+ bool IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const;
void SendProficiency(ItemClass itemClass, uint32 itemSubclassMask);
void SendInitialSpells();
@@ -1575,39 +1765,55 @@ class Player : public Unit, public GridObject<Player>
void RemoveTemporarySpell(uint32 spellId);
void SetReputation(uint32 factionentry, uint32 value);
uint32 GetReputation(uint32 factionentry) const;
- std::string const& GetGuildName();
- uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
- void SetFreeTalentPoints(uint32 points);
- bool resetTalents(bool no_cost = false);
- uint32 resetTalentsCost() const;
+ std::string GetGuildName();
+
+ // Talents
+ uint32 GetFreeTalentPoints() const { return _talentMgr->FreeTalentPoints; }
+ void SetFreeTalentPoints(uint32 points) { _talentMgr->FreeTalentPoints = points; }
+ uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; }
+ void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; }
+ uint32 GetQuestRewardedTalentCount() const { return _talentMgr->QuestRewardedTalentCount; }
+ void AddQuestRewardedTalentCount(uint32 points) { _talentMgr->QuestRewardedTalentCount += points; }
+ uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; }
+ void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; }
+ uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; }
+ void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; }
+ uint32 GetPrimaryTalentTree(uint8 spec) const { return _talentMgr->SpecInfo[spec].TalentTree; }
+ void SetPrimaryTalentTree(uint8 spec, uint32 tree) { _talentMgr->SpecInfo[spec].TalentTree = tree; }
+ uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; }
+ void SetActiveSpec(uint8 spec){ _talentMgr->ActiveSpec = spec; }
+ uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; }
+ void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; }
+
+ bool ResetTalents(bool no_cost = false);
+ uint32 GetNextResetTalentsCost() const;
void InitTalentForLevel();
void BuildPlayerTalentsInfoData(WorldPacket* data);
void BuildPetTalentsInfoData(WorldPacket* data);
void SendTalentsInfoData(bool pet);
- void LearnTalent(uint32 talentId, uint32 talentRank);
+ bool LearnTalent(uint32 talentId, uint32 talentRank);
void LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank);
-
bool AddTalent(uint32 spellId, uint8 spec, bool learning);
bool HasTalent(uint32 spell_id, uint8 spec) const;
-
uint32 CalculateTalentsPoints() const;
// Dual Spec
void UpdateSpecCount(uint8 count);
- uint32 GetActiveSpec() { return m_activeSpec; }
- void SetActiveSpec(uint8 spec){ m_activeSpec = spec; }
- uint8 GetSpecsCount() { return m_specsCount; }
- void SetSpecsCount(uint8 count) { m_specsCount = count; }
void ActivateSpec(uint8 spec);
void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
- uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
+
+ uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph);
- uint32 GetGlyph(uint8 slot) { return m_Glyphs[m_activeSpec][slot]; }
+ uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; }
+
+ PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->SpecInfo[spec].Talents; }
+ PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->SpecInfo[spec].Talents; }
+ ActionButtonList const& GetActionButtons() const { return m_actionButtons; }
- uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
- void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); }
+ uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); }
+ void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS, profs); }
void InitPrimaryProfessions();
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
@@ -1635,6 +1841,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
+ void SendClearAllCooldowns(Unit* target);
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
@@ -1646,10 +1853,22 @@ class Player : public Unit, public GridObject<Player>
void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; }
void UpdatePotionCooldown(Spell* spell = NULL);
- void setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana);
- void clearResurrectRequestData() { setResurrectRequestData(0, 0, 0.0f, 0.0f, 0.0f, 0, 0); }
- bool isRessurectRequestedBy(uint64 guid) const { return m_resurrectGUID == guid; }
- bool isRessurectRequested() const { return m_resurrectGUID != 0; }
+ void SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura);
+ void ClearResurrectRequestData()
+ {
+ delete _resurrectionData;
+ _resurrectionData = NULL;
+ }
+
+ bool IsRessurectRequestedBy(uint64 guid) const
+ {
+ if (!IsRessurectRequested())
+ return false;
+
+ return _resurrectionData->GUID == guid;
+ }
+
+ bool IsRessurectRequested() const { return _resurrectionData != NULL; }
void ResurectUsingRequestData();
uint8 getCinematic() { return m_cinematic; }
@@ -1658,7 +1877,7 @@ class Player : public Unit, public GridObject<Player>
ActionButton* addActionButton(uint8 button, uint32 action, uint8 type);
void removeActionButton(uint8 button);
ActionButton const* GetActionButton(uint8 button);
- void SendInitialActionButtons() const { SendActionButtons(1); }
+ void SendInitialActionButtons() const { SendActionButtons(0); }
void SendActionButtons(uint32 state) const;
bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type);
@@ -1693,11 +1912,13 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromGroup(RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT) { RemoveFromGroup(GetGroup(), GetGUID(), method); }
void SendUpdateToOutOfRangeGroupMembers();
- void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); }
+ void SetInGuild(uint32 guildId);
void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
uint8 GetRank() const { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); }
+ void SetGuildLevel(uint32 level) { SetUInt32Value(PLAYER_GUILDLEVEL, level); }
+ uint32 GetGuildLevel() { return GetUInt32Value(PLAYER_GUILDLEVEL); }
void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; }
- uint32 GetGuildId() const { return GetUInt32Value(PLAYER_GUILDID); }
+ uint32 GetGuildId() const { return GetUInt32Value(OBJECT_FIELD_DATA); /* return only lower part */ }
Guild* GetGuild();
static uint32 GetGuildIdFromDB(uint64 guid);
static uint8 GetRankFromDB(uint64 guid);
@@ -1713,6 +1934,7 @@ class Player : public Unit, public GridObject<Player>
uint32 GetArenaPersonalRating(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); }
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
+ uint32 GetRBGPersonalRating() const { return 0; }
Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
@@ -1723,15 +1945,12 @@ class Player : public Unit, public GridObject<Player>
void StoreRaidMapDifficulty() { m_raidMapDifficulty = GetMap()->GetDifficulty(); }
bool UpdateSkill(uint32 skill_id, uint32 step);
- bool UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step);
+ bool UpdateSkillPro(uint16 skillId, int32 chance, uint32 step);
bool UpdateCraftSkill(uint32 spellid);
bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1);
bool UpdateFishingSkill();
- uint32 GetBaseDefenseSkillValue() const { return GetBaseSkillValue(SKILL_DEFENSE); }
- uint32 GetBaseWeaponSkillValue(WeaponAttackType attType) const;
-
uint32 GetSpellByProto(ItemTemplate* proto);
float GetHealthBonusFromStamina();
@@ -1743,28 +1962,27 @@ class Player : public Unit, public GridObject<Player>
void UpdateArmor();
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
- void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false);
- void UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType);
void ApplySpellPowerBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
+ void UpdateMastery();
+ bool CanUseMastery() const;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage);
- void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
float GetMeleeCritFromAgility();
void GetDodgeFromAgility(float &diminishing, float &nondiminishing);
- float GetMissPercentageFromDefence() const;
float GetSpellCritFromIntellect();
- float OCTRegenHPPerSpirit();
float OCTRegenMPPerSpirit();
float GetRatingMultiplier(CombatRating cr) const;
float GetRatingBonusValue(CombatRating cr) const;
+
+ /// Returns base spellpower bonus from spellpower stat on items, without spellpower from intellect stat
uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; }
int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
@@ -1786,6 +2004,7 @@ class Player : public Unit, public GridObject<Player>
void ApplyHealthRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
void UpdateRuneRegen(RuneType rune);
+ void UpdateAllRunesRegen();
uint64 GetLootGUID() const { return m_lootGuid; }
void SetLootGUID(uint64 guid) { m_lootGuid = guid; }
@@ -1823,8 +2042,6 @@ class Player : public Unit, public GridObject<Player>
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr);
- void SendTeleportAckPacket();
-
Corpse* GetCorpse() const;
void SpawnCorpseBones();
void CreateCorpse();
@@ -1846,8 +2063,6 @@ class Player : public Unit, public GridObject<Player>
void StopMirrorTimers();
bool IsMirrorTimerActive(MirrorTimerType type);
- void SetMovement(PlayerMovementType pType);
-
bool CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone);
void JoinedChannel(Channel* c);
@@ -1856,10 +2071,6 @@ class Player : public Unit, public GridObject<Player>
void UpdateLocalChannels(uint32 newZone);
void LeaveLFGChannel();
- void UpdateDefense();
- void UpdateWeaponSkill (WeaponAttackType attType);
- void UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence);
-
void SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal);
uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus
uint16 GetPureMaxSkillValue(uint32 skill) const; // max
@@ -1893,7 +2104,7 @@ class Player : public Unit, public GridObject<Player>
bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const;
void RewardPlayerAndGroupAtKill(Unit* victim, bool isBattleGround);
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource);
- bool isHonorOrXPTarget(Unit* victim);
+ bool isHonorOrXPTarget(Unit const* victim);
bool GetsRecruitAFriendBonus(bool forXP);
uint8 GetGrantableLevels() { return m_grantableLevels; }
@@ -1914,15 +2125,10 @@ class Player : public Unit, public GridObject<Player>
/*********************************************************/
/*** PVP SYSTEM ***/
/*********************************************************/
+ // TODO: Properly implement correncies as of Cataclysm
void UpdateHonorFields();
bool RewardHonor(Unit* victim, uint32 groupsize, int32 honor = -1, bool pvptoken = false);
- uint32 GetHonorPoints() const { return GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY); }
- uint32 GetArenaPoints() const { return GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY); }
- void ModifyHonorPoints(int32 value, SQLTransaction* trans = NULL); //! If trans is specified, honor save query will be added to trans
- void ModifyArenaPoints(int32 value, SQLTransaction* trans = NULL); //! If trans is specified, arena point save query will be added to trans
uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const;
- void SetHonorPoints(uint32 value);
- void SetArenaPoints(uint32 value);
//End of PvP System
@@ -1937,7 +2143,7 @@ class Player : public Unit, public GridObject<Player>
void UpdateCorpseReclaimDelay();
void SendCorpseReclaimDelay(bool load = false);
- uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual)
+ uint32 GetBlockPercent() const { return GetUInt32Value(PLAYER_SHIELD_BLOCK); }
bool CanParry() const { return m_canParry; }
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
@@ -1967,7 +2173,6 @@ class Player : public Unit, public GridObject<Player>
void _ApplyAllLevelScaleItemMods(bool apply);
void _ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply, bool only_level_scale = false);
void _ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply);
- void _ApplyAmmoBonuses();
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot);
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
void CorrectMetaGemEnchants(uint8 slot, bool apply);
@@ -2010,6 +2215,16 @@ class Player : public Unit, public GridObject<Player>
BattlegroundTypeId GetBattlegroundTypeId() const { return m_bgData.bgTypeID; }
Battleground* GetBattleground() const;
+ uint32 GetBattlegroundQueueJoinTime(uint32 bgTypeId) const { return m_bgData.bgQueuesJoinedTime.find(bgTypeId)->second; }
+ void AddBattlegroundQueueJoinTime(uint32 bgTypeId, uint32 joinTime)
+ {
+ m_bgData.bgQueuesJoinedTime[bgTypeId] = joinTime;
+ }
+ void RemoveBattlegroundQueueJoinTime(uint32 bgTypeId)
+ {
+ m_bgData.bgQueuesJoinedTime.erase(m_bgData.bgQueuesJoinedTime.find(bgTypeId)->second);
+ }
+
bool InBattlegroundQueue() const;
BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const;
@@ -2235,7 +2450,8 @@ class Player : public Unit, public GridObject<Player>
RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
uint32 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
- uint32 GetRuneBaseCooldown(uint8 index);
+ uint32 GetRuneBaseCooldown(uint8 index) const { return GetRuneTypeBaseCooldown(GetBaseRune(index)); }
+ uint32 GetRuneTypeBaseCooldown(RuneType runeType) const;
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
RuneType GetLastUsedRune() { return m_runes->lastUsedRune; }
void SetLastUsedRune(RuneType type) { m_runes->lastUsedRune = type; }
@@ -2252,11 +2468,12 @@ class Player : public Unit, public GridObject<Player>
void InitRunes();
void SendRespondInspectAchievements(Player* player) const;
+ uint32 GetAchievementPoints() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
void CheckAllAchievementCriteria();
- void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, bool evenIfCriteriaComplete = false);
- void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
+ void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit* unit = NULL);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
void CompletedAchievement(AchievementEntry const* entry);
@@ -2280,25 +2497,39 @@ class Player : public Unit, public GridObject<Player>
bool IsInWhisperWhiteList(uint64 guid);
void RemoveFromWhisperWhiteList(uint64 guid) { WhisperList.remove(guid); }
+ void ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::ExtraMovementStatusElement* extras = NULL);
+
/*! These methods send different packets to the client in apply and unapply case.
These methods are only sent to the current unit.
*/
- void SendMovementSetCanFly(bool apply);
void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply);
- void SendMovementSetHover(bool apply);
- void SendMovementSetWaterWalking(bool apply);
- void SendMovementSetFeatherFall(bool apply);
+ void SendMovementSetCollisionHeight(float height);
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
//! Return collision height sent to client
float GetCollisionHeight(bool mounted) const;
+ // Void Storage
+ bool IsVoidStorageUnlocked() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ void UnlockVoidStorage() { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ void LockVoidStorage() { RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ uint8 GetNextVoidStorageFreeSlot() const;
+ uint8 GetNumOfVoidStorageFreeSlots() const;
+ uint8 AddVoidStorageItem(const VoidStorageItem& item);
+ void AddVoidStorageItemAtSlot(uint8 slot, const VoidStorageItem& item);
+ void DeleteVoidStorageItem(uint8 slot);
+ bool SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot);
+ VoidStorageItem* GetVoidStorageItem(uint8 slot) const;
+ VoidStorageItem* GetVoidStorageItem(uint64 id, uint8& slot) const;
+
protected:
// Gamemaster whisper whitelist
WhisperListContainer WhisperList;
uint32 m_regenTimerCount;
- float m_powerFraction[MAX_POWERS];
+ uint32 m_holyPowerRegenTimerCount;
+ uint32 m_focusRegenTimerCount;
+ float m_powerFraction[MAX_POWERS_PER_CLASS];
uint32 m_contestedPvPTimer;
/*********************************************************/
@@ -2344,6 +2575,7 @@ class Player : public Unit, public GridObject<Player>
void _LoadGlyphAuras();
void _LoadBoundInstances(PreparedQueryResult result);
void _LoadInventory(PreparedQueryResult result, uint32 timeDiff);
+ void _LoadVoidStorage(PreparedQueryResult result);
void _LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery);
void _LoadMail();
void _LoadMailedItems(Mail* mail);
@@ -2366,6 +2598,8 @@ class Player : public Unit, public GridObject<Player>
void _LoadGlyphs(PreparedQueryResult result);
void _LoadTalents(PreparedQueryResult result);
void _LoadInstanceTimeRestrictions(PreparedQueryResult result);
+ void _LoadCurrency(PreparedQueryResult result);
+ void _LoadCUFProfiles(PreparedQueryResult result);
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -2374,6 +2608,7 @@ class Player : public Unit, public GridObject<Player>
void _SaveActions(SQLTransaction& trans);
void _SaveAuras(SQLTransaction& trans);
void _SaveInventory(SQLTransaction& trans);
+ void _SaveVoidStorage(SQLTransaction& trans);
void _SaveMail(SQLTransaction& trans);
void _SaveQuestStatus(SQLTransaction& trans);
void _SaveDailyQuestStatus(SQLTransaction& trans);
@@ -2388,6 +2623,8 @@ class Player : public Unit, public GridObject<Player>
void _SaveTalents(SQLTransaction& trans);
void _SaveStats(SQLTransaction& trans);
void _SaveInstanceTimeRestrictions(SQLTransaction& trans);
+ void _SaveCurrency(SQLTransaction& trans);
+ void _SaveCUFProfiles(SQLTransaction& trans);
/*********************************************************/
/*** ENVIRONMENTAL SYSTEM ***/
@@ -2419,6 +2656,29 @@ class Player : public Unit, public GridObject<Player>
Item* m_items[PLAYER_SLOTS_COUNT];
uint32 m_currentBuybackSlot;
+ PlayerCurrenciesMap _currencyStorage;
+
+ /**
+ * @name GetCurrencyWeekCap
+ * @brief return week cap for selected currency
+
+ * @param CurrencyTypesEntry for which to retrieve weekly cap
+ */
+ uint32 GetCurrencyWeekCap(CurrencyTypesEntry const* currency) const;
+
+ /*
+ * @name GetCurrencyTotalCap
+ * @brief return total cap for selected currency
+
+ * @param CurrencyTypesEntry for which to retrieve total cap
+ */
+ uint32 GetCurrencyTotalCap(CurrencyTypesEntry const* currency) const;
+
+ /// Updates weekly conquest point cap (dynamic cap)
+ void UpdateConquestCurrencyCap(uint32 currency);
+
+ VoidStorageItem* _voidStorageItems[VOID_STORAGE_MAX_SLOT];
+
std::vector<Item*> m_itemUpdateQueue;
bool m_itemUpdateQueueBlocked;
@@ -2441,22 +2701,17 @@ class Player : public Unit, public GridObject<Player>
PlayerMails m_mail;
PlayerSpellMap m_spells;
- PlayerTalentMap* m_talents[MAX_TALENT_SPECS];
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
GlobalCooldownMgr m_GlobalCooldownMgr;
- uint8 m_activeSpec;
- uint8 m_specsCount;
-
- uint32 m_Glyphs[MAX_TALENT_SPECS][MAX_GLYPH_SLOT_INDEX];
+ PlayerTalentInfo* _talentMgr;
ActionButtonList m_actionButtons;
float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint32 m_baseSpellPower;
- uint32 m_baseFeralAP;
uint32 m_baseManaRegen;
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
@@ -2470,10 +2725,7 @@ class Player : public Unit, public GridObject<Player>
void ResetTimeSync();
void SendTimeSync();
- uint64 m_resurrectGUID;
- uint32 m_resurrectMap;
- float m_resurrectX, m_resurrectY, m_resurrectZ;
- uint32 m_resurrectHealth, m_resurrectMana;
+ ResurrectionData* _resurrectionData;
WorldSession* m_session;
@@ -2508,7 +2760,6 @@ class Player : public Unit, public GridObject<Player>
bool m_canBlock;
bool m_canTitanGrip;
uint8 m_swingErrorMsg;
- float m_ammoDPS;
////////////////////Rest System/////////////////////
time_t time_inn_enter;
@@ -2519,10 +2770,6 @@ class Player : public Unit, public GridObject<Player>
float m_rest_bonus;
RestType rest_type;
////////////////////Rest System/////////////////////
- uint32 m_resetTalentsCost;
- time_t m_resetTalentsTime;
- uint32 m_usedTalentCount;
- uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;
@@ -2555,6 +2802,8 @@ class Player : public Unit, public GridObject<Player>
uint8 m_grantableLevels;
+ CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
+
private:
// internal common parts for CanStore/StoreItem functions
InventoryResult CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemTemplate const* pProto, uint32& count, bool swap, Item* pSrcItem) const;
@@ -2566,6 +2815,7 @@ class Player : public Unit, public GridObject<Player>
std::set<uint32> m_refundableItems;
void SendRefundInfo(Item* item);
void RefundItem(Item* item);
+ void SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, uint8 error);
// know currencies are not removed at any point (0 displayed)
void AddKnownCurrency(uint32 itemId);
@@ -2604,7 +2854,7 @@ class Player : public Unit, public GridObject<Player>
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
- AchievementMgr* m_achievementMgr;
+ AchievementMgr<Player>* m_achievementMgr;
ReputationMgr* m_reputationMgr;
SpellCooldowns m_spellCooldowns;
@@ -2621,6 +2871,9 @@ class Player : public Unit, public GridObject<Player>
uint32 _pendingBindTimer;
uint32 _activeCheats;
+ uint32 _maxPersonalArenaRate;
+
+ PhaseMgr phaseMgr;
};
void AddItemsSetItem(Player*player, Item* item);
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index 5df6a99f1bf..f4ab052aa1d 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -26,6 +26,7 @@
#include "World.h"
#include "Util.h"
#include "AccountMgr.h"
+#include "WorldSession.h"
PlayerSocial::PlayerSocial(): m_playerGUID()
{ }
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index f41b5c2f001..3ed41781982 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -170,7 +170,7 @@ void MapManager::LoadTransportNPCs()
Transport::Transport(uint32 period, uint32 script) : GameObject(), m_pathTime(0), m_timer(0),
currenttguid(0), m_period(period), ScriptId(script), m_nextNodeTime(0)
{
- m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);
+ m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);
}
Transport::~Transport()
@@ -576,7 +576,7 @@ void Transport::UpdateForMap(Map const* targetMap)
{
if (this != itr->getSource()->GetTransport())
{
- UpdateData transData;
+ UpdateData transData(GetMapId());
BuildCreateUpdateBlockForPlayer(&transData, itr->getSource());
WorldPacket packet;
transData.BuildPacket(&packet);
@@ -586,7 +586,7 @@ void Transport::UpdateForMap(Map const* targetMap)
}
else
{
- UpdateData transData;
+ UpdateData transData(targetMap->GetId());
BuildOutOfRangeUpdateBlock(&transData);
WorldPacket out_packet;
transData.BuildPacket(&out_packet);
@@ -634,8 +634,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y,
}
creature->SetTransport(this);
- creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
- creature->m_movementInfo.guid = GetGUID();
+ creature->m_movementInfo.t_guid = GetGUID();
creature->m_movementInfo.t_pos.Relocate(x, y, z, o);
if (anim)
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 3538188a234..ac771004096 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -71,9 +71,6 @@ bool Player::UpdateStats(Stats stat)
switch (stat)
{
- case STAT_STRENGTH:
- UpdateShieldBlockValue();
- break;
case STAT_AGILITY:
UpdateArmor();
UpdateAllCritPercentages();
@@ -94,24 +91,12 @@ bool Player::UpdateStats(Stats stat)
}
if (stat == STAT_STRENGTH)
- {
UpdateAttackPowerAndDamage(false);
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(true);
- }
else if (stat == STAT_AGILITY)
{
UpdateAttackPowerAndDamage(false);
UpdateAttackPowerAndDamage(true);
}
- else
- {
- // Need update (exist AP from stat auras)
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(false);
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(true);
- }
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
@@ -171,8 +156,9 @@ bool Player::UpdateAllStats()
UpdateAllRatings();
UpdateAllCritPercentages();
UpdateAllSpellCritChances();
- UpdateDefenseBonusesMod();
- UpdateShieldBlockValue();
+ UpdateBlockPercentage();
+ UpdateParryPercentage();
+ UpdateDodgePercentage();
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
UpdateExpertise(BASE_ATTACK);
@@ -205,7 +191,6 @@ void Player::UpdateArmor()
float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
value += GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
@@ -229,15 +214,21 @@ void Player::UpdateArmor()
float Player::GetHealthBonusFromStamina()
{
+ // Taken from PaperDollFrame.lua - 4.3.4.15595
+ float ratio = 10.0f;
+ if (gtOCTHpPerStaminaEntry const* hpBase = sGtOCTHpPerStaminaStore.LookupEntry((getClass() - 1) * GT_MAX_LEVEL + getLevel() - 1))
+ ratio = hpBase->ratio;
+
float stamina = GetStat(STAT_STAMINA);
float baseStam = std::min(20.0f, stamina);
float moreStam = stamina - baseStam;
- return baseStam + (moreStam*10.0f);
+ return baseStam + moreStam * ratio;
}
float Player::GetManaBonusFromIntellect()
{
+ // Taken from PaperDollFrame.lua - 4.3.4.15595
float intellect = GetStat(STAT_INTELLECT);
float baseInt = std::min(20.0f, intellect);
@@ -272,140 +263,32 @@ void Player::UpdateMaxPower(Powers power)
SetMaxPower(power, uint32(value));
}
-void Player::ApplyFeralAPBonus(int32 amount, bool apply)
-{
- _ModifyUInt32(apply, m_baseFeralAP, amount);
- UpdateAttackPowerAndDamage();
-}
-
void Player::UpdateAttackPowerAndDamage(bool ranged)
{
float val2 = 0.0f;
float level = float(getLevel());
+ ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass());
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
- uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
- uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
- index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
- index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
-
- switch (getClass())
- {
- case CLASS_HUNTER:
- val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_ROGUE:
- val2 = level + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_WARRIOR:
- val2 = level + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_DRUID:
- switch (GetShapeshiftForm())
- {
- case FORM_CAT:
- case FORM_BEAR:
- case FORM_DIREBEAR:
- val2 = 0.0f; break;
- default:
- val2 = GetStat(STAT_AGILITY) - 10.0f; break;
- }
- break;
- default: val2 = GetStat(STAT_AGILITY) - 10.0f; break;
- }
+ val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility;
}
else
{
- switch (getClass())
- {
- case CLASS_WARRIOR:
- val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
- break;
- case CLASS_PALADIN:
- val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
- break;
- case CLASS_DEATH_KNIGHT:
- val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
- break;
- case CLASS_ROGUE:
- val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
- break;
- case CLASS_HUNTER:
- val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
- break;
- case CLASS_SHAMAN:
- val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
- break;
- case CLASS_DRUID:
- {
- // Check if Predatory Strikes is skilled
- float mLevelMult = 0.0f;
- float weapon_bonus = 0.0f;
- if (IsInFeralForm())
- {
- Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
- {
- AuraEffect* aurEff = *itr;
- if (aurEff->GetSpellInfo()->SpellIconID == 1563)
- {
- switch (aurEff->GetEffIndex())
- {
- case 0: // Predatory Strikes (effect 0)
- mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
- break;
- case 1: // Predatory Strikes (effect 1)
- if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
- {
- // also gains % attack power from equipped weapon
- ItemTemplate const* proto = mainHand->GetTemplate();
- if (!proto)
- continue;
-
- weapon_bonus = CalculatePct(float(proto->getFeralBonus()), aurEff->GetAmount());
- }
- break;
- default:
- break;
- }
- }
- }
- }
-
- switch (GetShapeshiftForm())
- {
- case FORM_CAT:
- val2 = getLevel() * (mLevelMult + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
- break;
- case FORM_BEAR:
- case FORM_DIREBEAR:
- val2 = getLevel() * (mLevelMult + 3.0f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
- break;
- case FORM_MOONKIN:
- val2 = getLevel() * (mLevelMult + 1.5f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
- break;
- default:
- val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
- break;
- }
- break;
- }
- case CLASS_MAGE:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- case CLASS_PRIEST:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- case CLASS_WARLOCK:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- }
+ float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f);
+ float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f);
+
+ SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm());
+ // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ?
+ if (form && form->flags1 & 0x20)
+ agilityValue += std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerStrenth, 0.0f);
+
+ val2 = strengthValue + agilityValue;
}
SetModifierValue(unitMod, BASE_VALUE, val2);
@@ -414,32 +297,15 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
- if (ranged)
- {
- if ((getClassMask() & CLASSMASK_WAND_USERS) == 0)
- {
- AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT);
- for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i)
- attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount());
- }
- }
- else
+ if (!ranged)
{
- AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT);
- for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i)
- attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount());
-
AuraEffectList const& mAPbyArmor = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR);
for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter)
// always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL)
attPowerMod += int32(GetArmor() / (*iter)->GetAmount());
}
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
-
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
- SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
- SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
Pet* pet = GetPet(); //update pet's AP
Guardian* guardian = GetGuardianPet();
@@ -466,11 +332,6 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Player::UpdateShieldBlockValue()
-{
- SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
-}
-
void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage)
{
UnitMods unitMod;
@@ -491,7 +352,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
float att_speed = GetAPMultiplier(attType, normalized);
- float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed;
+ float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed;
float base_pct = GetModifierValue(unitMod, BASE_PCT);
float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
float total_pct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
@@ -501,12 +362,20 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
if (IsInFeralForm()) //check if player is druid and in cat or bear forms
{
- uint8 lvl = getLevel();
- if (lvl > 60)
- lvl = 60;
+ float weaponSpeed = BASE_ATTACK_TIME / 1000.f;
+ if (Item* weapon = GetWeaponForAttack(BASE_ATTACK, true))
+ weaponSpeed = weapon->GetTemplate()->Delay / 1000;
- weapon_mindamage = lvl*0.85f*att_speed;
- weapon_maxdamage = lvl*1.25f*att_speed;
+ if (GetShapeshiftForm() == FORM_CAT)
+ {
+ weapon_mindamage = weapon_mindamage / weaponSpeed;
+ weapon_maxdamage = weapon_maxdamage / weaponSpeed;
+ }
+ else if (GetShapeshiftForm() == FORM_BEAR)
+ {
+ weapon_mindamage = weapon_mindamage / weaponSpeed + weapon_mindamage / 2.5;
+ weapon_maxdamage = weapon_mindamage / weaponSpeed + weapon_maxdamage / 2.5;
+ }
}
else if (!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case)
{
@@ -520,11 +389,13 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
weapon_mindamage = BASE_MINDAMAGE;
weapon_maxdamage = BASE_MAXDAMAGE;
}
+ /*
+ TODO: Is this still needed after ammo has been removed?
else if (attType == RANGED_ATTACK) //add ammo DPS to ranged damage
{
- weapon_mindamage += GetAmmoDPS() * att_speed;
- weapon_maxdamage += GetAmmoDPS() * att_speed;
- }
+ weapon_mindamage += ammo * att_speed;
+ weapon_maxdamage += ammo * att_speed;
+ }*/
min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
@@ -555,13 +426,6 @@ void Player::UpdateDamagePhysical(WeaponAttackType attType)
}
}
-void Player::UpdateDefenseBonusesMod()
-{
- UpdateBlockPercentage();
- UpdateParryPercentage();
- UpdateDodgePercentage();
-}
-
void Player::UpdateBlockPercentage()
{
// No block
@@ -570,8 +434,6 @@ void Player::UpdateBlockPercentage()
{
// Base value
value = 5.0f;
- // Modify value from defense skill
- value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
// Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura
value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
// Increase from rating
@@ -613,7 +475,7 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr);
// Modify crit from weapon skill and maximized defense skill of same level victim difference
- value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f;
+ value += (int32(GetMaxSkillValueForLevel()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) : value;
@@ -635,6 +497,44 @@ void Player::UpdateAllCritPercentages()
UpdateCritPercentage(RANGED_ATTACK);
}
+void Player::UpdateMastery()
+{
+ if (!CanUseMastery())
+ {
+ SetFloatValue(PLAYER_MASTERY, 0.0f);
+ return;
+ }
+
+ float value = GetTotalAuraModifier(SPELL_AURA_MASTERY);
+ value += GetRatingBonusValue(CR_MASTERY);
+ SetFloatValue(PLAYER_MASTERY, value);
+
+ TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec()));
+ if (!talentTab)
+ return;
+
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ {
+ if (!talentTab->MasterySpellId[i])
+ continue;
+
+ if (Aura* aura = GetAura(talentTab->MasterySpellId[i]))
+ {
+ for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
+ {
+ if (!aura->HasEffect(j))
+ continue;
+
+ float mult = aura->GetSpellInfo()->Effects[j].BonusMultiplier;
+ if (G3D::fuzzyEq(mult, 0.0f))
+ continue;
+
+ aura->GetEffect(j)->ChangeAmount(int32(value * aura->GetSpellInfo()->Effects[j].BonusMultiplier));
+ }
+ }
+ }
+}
+
const float m_diminishing_k[MAX_CLASSES] =
{
0.9560f, // Warrior
@@ -650,43 +550,16 @@ const float m_diminishing_k[MAX_CLASSES] =
0.9720f // Druid
};
-float Player::GetMissPercentageFromDefence() const
-{
- float const miss_cap[MAX_CLASSES] =
- {
- 16.00f, // Warrior //correct
- 16.00f, // Paladin //correct
- 16.00f, // Hunter //?
- 16.00f, // Rogue //?
- 16.00f, // Priest //?
- 16.00f, // DK //correct
- 16.00f, // Shaman //?
- 16.00f, // Mage //?
- 16.00f, // Warlock //?
- 0.0f, // ??
- 16.00f // Druid //?
- };
-
- float diminishing = 0.0f, nondiminishing = 0.0f;
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
-
- // apply diminishing formula to diminishing miss chance
- uint32 pclass = getClass()-1;
- return nondiminishing + (diminishing * miss_cap[pclass] / (diminishing + miss_cap[pclass] * m_diminishing_k[pclass]));
-}
-
void Player::UpdateParryPercentage()
{
const float parry_cap[MAX_CLASSES] =
{
- 47.003525f, // Warrior
- 47.003525f, // Paladin
+ 65.631440f, // Warrior
+ 65.631440f, // Paladin
145.560408f, // Hunter
145.560408f, // Rogue
0.0f, // Priest
- 47.003525f, // DK
+ 65.631440f, // DK
145.560408f, // Shaman
0.0f, // Mage
0.0f, // Warlock
@@ -702,9 +575,6 @@ void Player::UpdateParryPercentage()
float nondiminishing = 5.0f;
// Parry from rating
float diminishing = GetRatingBonusValue(CR_PARRY);
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
// apply diminishing formula to diminishing parry chance
@@ -722,12 +592,12 @@ void Player::UpdateDodgePercentage()
{
const float dodge_cap[MAX_CLASSES] =
{
- 88.129021f, // Warrior
- 88.129021f, // Paladin
+ 65.631440f, // Warrior
+ 65.631440f, // Paladin
145.560408f, // Hunter
145.560408f, // Rogue
150.375940f, // Priest
- 88.129021f, // DK
+ 65.631440f, // DK
145.560408f, // Shaman
150.375940f, // Mage
150.375940f, // Warlock
@@ -737,9 +607,6 @@ void Player::UpdateDodgePercentage()
float diminishing = 0.0f, nondiminishing = 0.0f;
GetDodgeFromAgility(diminishing, nondiminishing);
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
// Dodge from rating
@@ -854,29 +721,23 @@ void Player::ApplyHealthRegenBonus(int32 amount, bool apply)
void Player::UpdateManaRegen()
{
- float Intellect = GetStat(STAT_INTELLECT);
- // Mana regen from spirit and intellect
- float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit();
+ // Mana regen from spirit
+ float spirit_regen = OCTRegenMPPerSpirit();
// Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen
- power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
+ spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
- // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura
- float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f;
+ // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5
+ if (GetStat(STAT_INTELLECT) > 0.0f)
+ spirit_regen *= sqrt(GetStat(STAT_INTELLECT));
- // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura
- AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT);
- for (AuraEffectList::const_iterator i = regenAura.begin(); i != regenAura.end(); ++i)
- {
- power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f;
- }
+ // CombatRegen = 5% of Base Mana
+ float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
// Set regen rate in cast state apply only on spirit based regen
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
- if (modManaRegenInterrupt > 100)
- modManaRegenInterrupt = 100;
- SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + CalculatePct(power_regen, modManaRegenInterrupt));
- SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen);
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt));
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, 0.001f + spirit_regen + base_regen);
}
void Player::UpdateRuneRegen(RuneType rune)
@@ -900,6 +761,13 @@ void Player::UpdateRuneRegen(RuneType rune)
SetFloatValue(PLAYER_RUNE_REGEN_1 + uint8(rune), regen);
}
+void Player::UpdateAllRunesRegen()
+{
+ for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
+ if (uint32 cooldown = GetRuneTypeBaseCooldown(RuneType(i)))
+ SetFloatValue(PLAYER_RUNE_REGEN_1 + i, float(1 * IN_MILLISECONDS) / float(cooldown));
+}
+
void Player::_ApplyAllStatBonuses()
{
SetCanModifyStats(false);
@@ -986,22 +854,18 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
- uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
- index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
}
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
- SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
//automatically update weapon damage after attack power modification
@@ -1115,7 +979,7 @@ bool Guardian::UpdateStats(Stats stat)
if (aurEff)
{
SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value
- AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale
+ AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue(owner)); // Ravenous Dead edits the original scale
}
// Glyph of the Ghoul
aurEff = owner->GetAuraEffect(58686, 0);
@@ -1126,29 +990,8 @@ bool Guardian::UpdateStats(Stats stat)
}
else if (stat == STAT_STAMINA)
{
- if (owner->getClass() == CLASS_WARLOCK && isPet())
- {
- ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA), 75);
- value += ownersBonus;
- }
- else
- {
- mod = 0.45f;
- if (isPet())
- {
- PetSpellMap::const_iterator itr = (ToPet()->m_spells.find(62758)); // Wild Hunt rank 1
- if (itr == ToPet()->m_spells.end())
- itr = ToPet()->m_spells.find(62762); // Wild Hunt rank 2
-
- if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
- AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue());
- }
- }
- ownersBonus = float(owner->GetStat(stat)) * mod;
- value += ownersBonus;
- }
+ ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA), 30);
+ value += ownersBonus;
}
//warlock's and mage's pets gain 30% of owner's intellect
else if (stat == STAT_INTELLECT)
@@ -1221,13 +1064,14 @@ void Guardian::UpdateArmor()
float bonus_armor = 0.0f;
UnitMods unitMod = UNIT_MOD_ARMOR;
- // hunter and warlock pets gain 35% of owner's armor value
- if (isPet())
- bonus_armor = float(CalculatePct(m_owner->GetArmor(), 35));
+ // hunter pets gain 35% of owner's armor value, warlock pets gain 100% of owner's armor
+ if (isHunterPet())
+ bonus_armor = float(CalculatePct(m_owner->GetArmor(), 70));
+ else if (isPet())
+ bonus_armor = m_owner->GetArmor();
value = GetModifierValue(unitMod, BASE_VALUE);
value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetStat(STAT_AGILITY) * 2.0f;
value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
value *= GetModifierValue(unitMod, TOTAL_PCT);
@@ -1304,19 +1148,6 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
if (isHunterPet()) //hunter pets benefit from owner's attack power
{
float mod = 1.0f; //Hunter contribution modifier
- if (isPet())
- {
- PetSpellMap::const_iterator itr = ToPet()->m_spells.find(62758); //Wild Hunt rank 1
- if (itr == ToPet()->m_spells.end())
- itr = ToPet()->m_spells.find(62762); //Wild Hunt rank 2
-
- if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
- {
- SpellInfo const* sProto = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
- mod += CalculatePct(1.0f, sProto->Effects[1].CalcValue());
- }
- }
-
bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod;
SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod));
}
@@ -1336,8 +1167,8 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//demons benefit from warlocks shadow or fire damage
else if (isPet())
{
- int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
- int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
+ int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
int32 maximum = (fire > shadow) ? fire : shadow;
if (maximum < 0)
maximum = 0;
@@ -1347,7 +1178,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//water elementals benefit from mage's frost damage
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
{
- int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
+ int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
if (frost < 0)
frost = 0;
SetBonusDamage(int32(frost * 0.4f));
@@ -1358,13 +1189,10 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
//UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower);
- //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
- SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod);
//UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier);
@@ -1383,14 +1211,14 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
//force of nature
if (GetEntry() == ENTRY_TREANT)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
@@ -1411,27 +1239,6 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
- // Pet's base damage changes depending on happiness
- if (isHunterPet() && attType == BASE_ATTACK)
- {
- switch (ToPet()->GetHappinessState())
- {
- case HAPPY:
- // 125% of normal damage
- mindamage = mindamage * 1.25f;
- maxdamage = maxdamage * 1.25f;
- break;
- case CONTENT:
- // 100% of normal damage, nothing to modify
- break;
- case UNHAPPY:
- // 75% of normal damage
- mindamage = mindamage * 0.75f;
- maxdamage = maxdamage * 0.75f;
- break;
- }
- }
-
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 3995c9ed661..bda77af54ed 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -35,7 +35,6 @@
#include "Log.h"
#include "MapManager.h"
#include "MoveSpline.h"
-#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@@ -59,6 +58,7 @@
#include "Vehicle.h"
#include "World.h"
#include "WorldPacket.h"
+#include "MovementStructures.h"
#include "WorldSession.h"
#include <math.h>
@@ -175,7 +175,7 @@ Unit::Unit(bool isWorldObject) :
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
- m_updateFlag = (UPDATEFLAG_LIVING | UPDATEFLAG_STATIONARY_POSITION);
+ m_updateFlag = UPDATEFLAG_LIVING;
m_attackTimer[BASE_ATTACK] = 0;
m_attackTimer[OFF_ATTACK] = 0;
@@ -187,7 +187,7 @@ Unit::Unit(bool isWorldObject) :
m_extraAttacks = 0;
m_canDualWield = false;
- m_rootTimes = 0;
+ m_movementCounter = 0;
m_state = 0;
m_deathState = ALIVE;
@@ -238,7 +238,6 @@ Unit::Unit(bool isWorldObject) :
m_baseSpellCritChance = 5;
m_CombatTimer = 0;
- m_lastManaUse = 0;
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
m_threatModifier[i] = 1.0f;
@@ -388,8 +387,6 @@ void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool gen
void Unit::UpdateSplineMovement(uint32 t_diff)
{
- uint32 const positionUpdateDelay = 400;
-
if (movespline->Finalized())
return;
@@ -401,32 +398,36 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
m_movesplineTimer.Update(t_diff);
if (m_movesplineTimer.Passed() || arrived)
- {
- m_movesplineTimer.Reset(positionUpdateDelay);
- Movement::Location loc = movespline->ComputePosition();
-
- if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- {
- Position& pos = m_movementInfo.t_pos;
- pos.m_positionX = loc.x;
- pos.m_positionY = loc.y;
- pos.m_positionZ = loc.z;
- pos.m_orientation = loc.orientation;
+ UpdateSplinePosition();
+}
- if (TransportBase* transport = GetDirectTransport())
- transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
- }
+void Unit::UpdateSplinePosition()
+{
+ uint32 const positionUpdateDelay = 400;
- if (HasUnitState(UNIT_STATE_CANNOT_TURN))
- loc.orientation = GetOrientation();
+ m_movesplineTimer.Reset(positionUpdateDelay);
+ Movement::Location loc = movespline->ComputePosition();
+ if (GetTransGUID())
+ {
+ Position& pos = m_movementInfo.t_pos;
+ pos.m_positionX = loc.x;
+ pos.m_positionY = loc.y;
+ pos.m_positionZ = loc.z;
+ pos.SetOrientation(loc.orientation);
- UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
+ if (TransportBase* transport = GetDirectTransport())
+ transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
}
+
+ if (HasUnitState(UNIT_STATE_CANNOT_TURN))
+ loc.orientation = GetOrientation();
+
+ UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
}
void Unit::DisableSpline()
{
- m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD));
+ m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD);
movespline->_Interrupt();
}
@@ -626,32 +627,13 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
// Rage from Damage made (only from direct weapon damage)
if (cleanDamage && damagetype == DIRECT_DAMAGE && this != victim && getPowerType() == POWER_RAGE)
{
- uint32 weaponSpeedHitFactor;
- uint32 rage_damage = damage + cleanDamage->absorbed_damage;
-
+ uint32 rage = uint32(GetAttackTime(cleanDamage->attackType) / 1000 * 8.125f);
switch (cleanDamage->attackType)
{
- case BASE_ATTACK:
- {
- weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 3.5f);
- if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
- weaponSpeedHitFactor *= 2;
-
- RewardRage(rage_damage, weaponSpeedHitFactor, true);
-
- break;
- }
case OFF_ATTACK:
- {
- weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 1.75f);
- if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
- weaponSpeedHitFactor *= 2;
-
- RewardRage(rage_damage, weaponSpeedHitFactor, true);
-
- break;
- }
- case RANGED_ATTACK:
+ rage /= 2;
+ case BASE_ATTACK:
+ RewardRage(rage, true);
break;
default:
break;
@@ -662,7 +644,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
{
// Rage from absorbed damage
if (cleanDamage && cleanDamage->absorbed_damage && victim->getPowerType() == POWER_RAGE)
- victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
+ victim->RewardRage(cleanDamage->absorbed_damage, false);
return 0;
}
@@ -707,7 +689,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (Battleground* bg = killer->GetBattleground())
bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, victim);
+ killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, 0, victim);
killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
}
@@ -759,7 +741,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (this != victim && victim->getPowerType() == POWER_RAGE)
{
uint32 rage_damage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
- victim->RewardRage(rage_damage, 0, false);
+ victim->RewardRage(rage_damage, false);
}
if (GetTypeId() == TYPEID_PLAYER)
@@ -973,7 +955,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
return;
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
- uint32 crTypeMask = victim->GetCreatureTypeMask();
if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType);
@@ -1014,9 +995,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100;
- // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
- critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
-
if (critPctDamageMod != 0)
AddPct(damage, critPctDamageMod);
}
@@ -1024,19 +1002,15 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// Spell weapon based damage CAN BE crit & blocked at same time
if (blocked)
{
- damageInfo->blocked = victim->GetShieldBlockValue();
// double blocked amount if block is critical
+ uint32 value = victim->GetBlockPercent();
if (victim->isBlockCritical())
- damageInfo->blocked += damageInfo->blocked;
- if (damage < int32(damageInfo->blocked))
- damageInfo->blocked = uint32(damage);
+ value *= 2; // double blocked percent
+ damageInfo->blocked = CalculatePct(damage, value);
damage -= damageInfo->blocked;
}
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_RANGED);
+ ApplyResilience(victim, &damage, crit);
break;
}
// Magical Attacks
@@ -1050,7 +1024,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
}
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_SPELL);
+ ApplyResilience(victim, &damage, crit);
break;
}
default:
@@ -1208,10 +1182,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, damageInfo->damageSchoolMask) - 1.0f) * 100;
- uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
-
- // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
- mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
if (mod != 0)
AddPct(damageInfo->damage, mod);
break;
@@ -1231,19 +1201,9 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
case MELEE_HIT_BLOCK:
damageInfo->TargetState = VICTIMSTATE_HIT;
damageInfo->HitInfo |= HITINFO_BLOCK;
- damageInfo->procEx |= PROC_EX_BLOCK;
- damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
- // double blocked amount if block is critical
- if (damageInfo->target->isBlockCritical())
- damageInfo->blocked_amount+=damageInfo->blocked_amount;
- if (damageInfo->blocked_amount >= damageInfo->damage)
- {
- damageInfo->TargetState = VICTIMSTATE_BLOCKS;
- damageInfo->blocked_amount = damageInfo->damage;
- damageInfo->procEx |= PROC_EX_FULL_BLOCK;
- }
- else
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
+ damageInfo->procEx |= PROC_EX_BLOCK | PROC_EX_NORMAL_HIT;
+ // 30% damage blocked, double blocked amount if block is critical
+ damageInfo->blocked_amount = CalculatePct(damageInfo->damage, damageInfo->target->isBlockCritical() ? damageInfo->target->GetBlockPercent() * 2 : damageInfo->target->GetBlockPercent());
damageInfo->damage -= damageInfo->blocked_amount;
damageInfo->cleanDamage += damageInfo->blocked_amount;
break;
@@ -1276,10 +1236,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
int32 resilienceReduction = damageInfo->damage;
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_RANGED);
+ ApplyResilience(victim, &resilienceReduction, damageInfo->hitOutCome == MELEE_HIT_CRIT);
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
@@ -1368,8 +1325,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
if (victim->getLevel() < 30)
Probability = 0.65f * victim->getLevel() + 0.5f;
- uint32 VictimDefense=victim->GetDefenseSkillValue();
- uint32 AttackerMeleeSkill=GetUnitMeleeSkill();
+ uint32 VictimDefense = victim->GetMaxSkillValueForLevel(this);
+ uint32 AttackerMeleeSkill = GetMaxSkillValueForLevel();
Probability *= AttackerMeleeSkill/(float)VictimDefense*0.16;
@@ -1429,6 +1386,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
int32 overkill = int32(damage) - int32(GetHealth());
data << uint32(overkill > 0 ? overkill : 0); // Overkill
data << uint32(i_spellProto->SchoolMask);
+ data << uint32(0); // FIX ME: Send resisted damage, both fully resisted and partly resisted
victim->SendMessageToSet(&data, true);
victim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
@@ -1471,6 +1429,14 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
{
float armor = float(victim->GetArmor());
+ // bypass enemy armor by SPELL_AURA_BYPASS_ARMOR_FOR_CASTER
+ int32 armorBypassPct = 0;
+ AuraEffectList const & reductionAuras = victim->GetAuraEffectsByType(SPELL_AURA_BYPASS_ARMOR_FOR_CASTER);
+ for (AuraEffectList::const_iterator i = reductionAuras.begin(); i != reductionAuras.end(); ++i)
+ if ((*i)->GetCasterGUID() == GetGUID())
+ armorBypassPct += (*i)->GetAmount();
+ armor = CalculatePct(armor, 100 - std::min(armorBypassPct, 100));
+
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
@@ -1478,14 +1444,6 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
- AuraEffectList const& resIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator j = resIgnoreAurasAb.begin(); j != resIgnoreAurasAb.end(); ++j)
- {
- if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL
- && (*j)->IsAffectedOnSpell(spellInfo))
- armor = floor(AddPct(armor, -(*j)->GetAmount()));
- }
-
AuraEffectList const& resIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = resIgnoreAuras.begin(); j != resIgnoreAuras.end(); ++j)
{
@@ -1493,27 +1451,9 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
armor = floor(AddPct(armor, -(*j)->GetAmount()));
}
- // Apply Player CR_ARMOR_PENETRATION rating and buffs from stances\specializations etc.
+ // Apply Player CR_ARMOR_PENETRATION rating
if (GetTypeId() == TYPEID_PLAYER)
{
- float bonusPct = 0;
- AuraEffectList const& armorPenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT);
- for (AuraEffectList::const_iterator itr = armorPenAuras.begin(); itr != armorPenAuras.end(); ++itr)
- {
- if ((*itr)->GetSpellInfo()->EquippedItemClass == -1)
- {
- if (!spellInfo || (*itr)->IsAffectedOnSpell(spellInfo) || (*itr)->GetMiscValue() & spellInfo->GetSchoolMask())
- bonusPct += (*itr)->GetAmount();
- else if (!(*itr)->GetMiscValue() && !(*itr)->HasSpellClassMask())
- bonusPct += (*itr)->GetAmount();
- }
- else
- {
- if (ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo()))
- bonusPct += (*itr)->GetAmount();
- }
- }
-
float maxArmorPen = 0;
if (victim->getLevel() < 60)
maxArmorPen = float(400 + 85 * victim->getLevel());
@@ -1523,7 +1463,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
// Cap armor penetration to this number
maxArmorPen = std::min((armor + maxArmorPen) / 3, armor);
// Figure out how much armor do we ignore
- float armorPen = CalculatePct(maxArmorPen, bonusPct + ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION));
+ float armorPen = CalculatePct(maxArmorPen, ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION));
// Got the value, apply it
armor -= std::min(armorPen, maxArmorPen);
}
@@ -1602,11 +1542,6 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
float damageResisted = float(damage * i / 10);
- AuraEffectList const& ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
- if (((*j)->GetMiscValue() & schoolMask) && (*j)->IsAffectedOnSpell(spellInfo))
- AddPct(damageResisted, -(*j)->GetAmount());
-
AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
if ((*j)->GetMiscValue() & schoolMask)
@@ -1633,7 +1568,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
if (!((*itr)->GetMiscValue() & schoolMask))
continue;
- if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
+ if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectingSpell(spellInfo))
auraAbsorbMod = float((*itr)->GetAmount());
}
@@ -1757,40 +1692,6 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
- for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
- continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
-
- // Damage can be splitted only if aura has an alive caster
- Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->isAlive())
- continue;
-
- int32 splitDamage = (*itr)->GetAmount();
-
- // absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
-
- dmgInfo.AbsorbDamage(splitDamage);
-
- uint32 splitted = splitDamage;
- uint32 splitted_absorb = 0;
- DealDamageMods(caster, splitted, &splitted_absorb);
-
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
-
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
- }
-
- // We're going to call functions which can modify content of the list during iteration over it's elements
- // Let's copy the list so we can prevent iterator invalidation
AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
{
@@ -1953,7 +1854,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy
// Miss chance based on melee
//float miss_chance = MeleeMissChanceCalc(victim, attType);
- float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(GetMaxSkillValueForLevel(this)), 0);
+ float miss_chance = MeleeSpellMissChance(victim, attType, 0);
// Critical hit chance
float crit_chance = GetUnitCriticalChance(attType, victim);
@@ -1977,11 +1878,8 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
- int32 attackerWeaponSkill = GetWeaponSkillValue(attType, victim);
- int32 victimDefenseSkill = victim->GetDefenseSkillValue(this);
-
// bonus from skills is 0.04%
- int32 skillBonus = 4 * (attackerWeaponSkill - victimMaxSkillValueForLevel);
+ int32 skillBonus = 4 * (attackerMaxSkillValueForLevel - victimMaxSkillValueForLevel);
int32 sum = 0, tmp = 0;
int32 roll = urand (0, 10000);
@@ -2090,11 +1988,9 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
getLevel() < victim->getLevelForTarget(this))
{
// cap possible value (with bonuses > max skill)
- int32 skill = attackerWeaponSkill;
- int32 maxskill = attackerMaxSkillValueForLevel;
- skill = (skill > maxskill) ? maxskill : skill;
+ int32 skill = attackerMaxSkillValueForLevel;
- tmp = (10 + (victimDefenseSkill - skill)) * 100;
+ tmp = (10 + (victimMaxSkillValueForLevel - skill)) * 100;
tmp = tmp > 4000 ? 4000 : tmp;
if (roll < (sum += tmp))
{
@@ -2110,10 +2006,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
!(GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH))
{
// when their weapon skill is 15 or more above victim's defense skill
- tmp = victimDefenseSkill;
- int32 tmpmax = victimMaxSkillValueForLevel;
- // having defense above your maximum (from items, talents etc.) has no effect
- tmp = tmp > tmpmax ? tmpmax : tmp;
+ tmp = victimMaxSkillValueForLevel;
// tmp = mob's level * 5 - player's current defense skill
tmp = attackerMaxSkillValueForLevel - tmp;
if (tmp >= 15)
@@ -2211,7 +2104,7 @@ void Unit::SendMeleeAttackStop(Unit* victim)
TC_LOG_INFO(LOG_FILTER_UNITS, "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
}
-bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
+bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType /*attackType*/)
{
// These spells can't be blocked
if (spellProto && spellProto->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK)
@@ -2224,9 +2117,7 @@ bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttac
victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK)
return false;
- float blockChance = victim->GetUnitBlockChance();
- blockChance += (int32(GetWeaponSkillValue(attackType)) - int32(victim->GetMaxSkillValueForLevel())) * 0.04f;
- if (roll_chance_f(blockChance))
+ if (roll_chance_f(victim->GetUnitBlockChance()))
return true;
}
return false;
@@ -2289,19 +2180,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
attType = RANGED_ATTACK;
- int32 attackerWeaponSkill;
- // skill value for these spells (for example judgements) is 5* level
- if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED && !spell->IsRangedWeaponSpell())
- attackerWeaponSkill = getLevel() * 5;
- // bonus from skills is 0.04% per skill Diff
- else
- attackerWeaponSkill = int32(GetWeaponSkillValue(attType, victim));
-
- int32 skillDiff = attackerWeaponSkill - int32(victim->GetMaxSkillValueForLevel(this));
-
uint32 roll = urand (0, 10000);
- uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, skillDiff, spell->Id) * 100.0f);
+ uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, spell->Id) * 100.0f);
// Roll miss
uint32 tmp = missChance;
if (roll < tmp)
@@ -2388,7 +2269,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
AuraEffectList const& ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spell))
+ if (!(*i)->IsAffectingSpell(spell))
continue;
switch ((*i)->GetMiscValue())
{
@@ -2404,7 +2285,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
if (canDodge)
{
// Roll dodge
- int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f) - skillDiff * 4;
+ int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f);
// Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
dodgeChance += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE) * 100;
dodgeChance = int32(float(dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
@@ -2423,7 +2304,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
if (canParry)
{
// Roll parry
- int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f) - skillDiff * 4;
+ int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f);
// Reduce parry chance by attacker expertise rating
if (GetTypeId() == TYPEID_PLAYER)
parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
@@ -2439,7 +2320,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
if (canBlock)
{
- int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f) - skillDiff * 4;
+ int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f);
if (blockChance < 0)
blockChance = 0;
tmp += blockChance;
@@ -2477,21 +2358,11 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell)
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
- // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
- modHitChance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask);
-
// Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
if (!(spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT))
{
// Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
- // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
- if (spell->IsTargetingArea())
- modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
-
- // Decrease hit chance from victim rating bonus
- if (victim->GetTypeId() == TYPEID_PLAYER)
- modHitChance -= int32(victim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
}
int32 HitChance = modHitChance * 100;
@@ -2519,26 +2390,6 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell)
int32 resist_chance = victim->GetMechanicResistChance(spell) * 100;
tmp += resist_chance;
- // Chance resist debuff
- if (!spell->IsPositive())
- {
- bool bNegativeAura = true;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (spell->Effects[i].ApplyAuraName == 0)
- {
- bNegativeAura = false;
- break;
- }
- }
-
- if (bNegativeAura)
- {
- tmp += victim->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100;
- tmp += victim->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100;
- }
- }
-
// Roll chance
if (rand < tmp)
return SPELL_MISS_RESIST;
@@ -2614,41 +2465,11 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca
return SPELL_MISS_NONE;
}
-uint32 Unit::GetShieldBlockValue(uint32 soft_cap, uint32 hard_cap) const
-{
- uint32 value = GetShieldBlockValue();
- if (value >= hard_cap)
- {
- value = (soft_cap + hard_cap) / 2;
- }
- else if (value > soft_cap)
- {
- value = soft_cap + ((value - soft_cap) / 2);
- }
-
- return value;
-}
-
uint32 Unit::GetUnitMeleeSkill(Unit const* target) const
{
return (target ? getLevelForTarget(target) : getLevel()) * 5;
}
-uint32 Unit::GetDefenseSkillValue(Unit const* target) const
-{
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // in PvP use full skill instead current skill value
- uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER)
- ? ToPlayer()->GetMaxSkillValue(SKILL_DEFENSE)
- : ToPlayer()->GetSkillValue(SKILL_DEFENSE);
- value += uint32(ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
- return value;
- }
- else
- return GetUnitMeleeSkill(target);
-}
-
float Unit::GetUnitDodgeChance() const
{
if (IsNonMeleeSpellCasted(false) || HasUnitState(UNIT_STATE_CONTROLLED))
@@ -2704,9 +2525,6 @@ float Unit::GetUnitMissChance(WeaponAttackType attType) const
{
float miss_chance = 5.00f;
- if (Player const* player = ToPlayer())
- miss_chance += player->GetMissPercentageFromDefence();
-
if (attType == RANGED_ATTACK)
miss_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
else
@@ -2725,7 +2543,7 @@ float Unit::GetUnitBlockChance() const
if (player->CanBlock())
{
Item* tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetTemplate()->Block)
+ if (tmpitem && !tmpitem->IsBroken())
return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
}
// is player but has no block ability or no not broken shield equipped
@@ -2782,65 +2600,11 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victi
crit += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
- // reduce crit chance from Rating for players
- if (attackType != RANGED_ATTACK)
- {
- ApplyResilience(victim, &crit, NULL, false, CR_CRIT_TAKEN_MELEE);
- // Glyph of barkskin
- if (victim->HasAura(63057) && victim->HasAura(22812))
- crit -= 25.0f;
- }
- else
- ApplyResilience(victim, &crit, NULL, false, CR_CRIT_TAKEN_RANGED);
-
- // Apply crit chance from defence skill
- crit += (int32(GetMaxSkillValueForLevel(victim)) - int32(victim->GetDefenseSkillValue(this))) * 0.04f;
-
if (crit < 0.0f)
crit = 0.0f;
return crit;
}
-uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) const
-{
- uint32 value = 0;
- if (Player const* player = ToPlayer())
- {
- Item* item = player->GetWeaponForAttack(attType, true);
-
- // feral or unarmed skill only for base attack
- if (attType != BASE_ATTACK && !item)
- return 0;
-
- if (IsInFeralForm())
- return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
-
- // weapon skill or (unarmed for base attack and fist weapons)
- uint32 skill;
- if (item && item->GetSkill() != SKILL_FIST_WEAPONS)
- skill = item->GetSkill();
- else
- skill = SKILL_UNARMED;
-
- // in PvP use full skill instead current skill value
- value = (target && target->IsControlledByPlayer())
- ? player->GetMaxSkillValue(skill)
- : player->GetSkillValue(skill);
- // Modify value from ratings
- value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL));
- switch (attType)
- {
- case BASE_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND)); break;
- case OFF_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND)); break;
- case RANGED_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED)); break;
- default: break;
- }
- }
- else
- value = GetUnitMeleeSkill(target);
- return value;
-}
-
void Unit::_DeleteRemovedAuras()
{
while (!m_removedAuras.empty())
@@ -2909,7 +2673,9 @@ void Unit::_UpdateSpells(uint32 time)
void Unit::_UpdateAutoRepeatSpell()
{
// check "realtime" interrupts
- if ((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCasted(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75))
+ // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCasted(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75)) &&
+ !HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo))
{
// cancel wand shoot
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75)
@@ -4313,7 +4079,7 @@ bool Unit::HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const* affecte
{
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
return true;
return false;
}
@@ -4373,7 +4139,7 @@ AuraEffect* Unit::IsScriptOverriden(SpellInfo const* spell, int32 script) const
for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
if ((*i)->GetMiscValue() == script)
- if ((*i)->IsAffectedOnSpell(spell))
+ if ((*i)->IsAffectingSpell(spell))
return (*i);
}
return NULL;
@@ -4631,7 +4397,7 @@ int32 Unit::GetTotalAuraModifierByAffectMask(AuraType auratype, SpellInfo const*
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
modifier += (*i)->GetAmount();
}
@@ -4650,7 +4416,7 @@ float Unit::GetTotalAuraMultiplierByAffectMask(AuraType auratype, SpellInfo cons
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
AddPct(multiplier, (*i)->GetAmount());
}
@@ -4668,7 +4434,7 @@ int32 Unit::GetMaxPositiveAuraModifierByAffectMask(AuraType auratype, SpellInfo
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() > modifier)
+ if ((*i)->IsAffectingSpell(affectedSpell) && (*i)->GetAmount() > modifier)
modifier = (*i)->GetAmount();
}
@@ -4682,7 +4448,7 @@ int32 Unit::GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() < modifier)
+ if ((*i)->IsAffectingSpell(affectedSpell) && (*i)->GetAmount() < modifier)
modifier = (*i)->GetAmount();
}
@@ -5059,8 +4825,11 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo)
data << float(0);
data << float(0);
data << float(0);
- data << float(0); // Found in a loop with 1 iteration
- data << float(0); // ditto ^
+ for (uint8 i = 0; i < 2; ++i)
+ {
+ data << float(0);
+ data << float(0);
+ }
data << uint32(0);
}
@@ -5082,6 +4851,127 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
SendAttackStateUpdate(&dmgInfo);
}
+bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 /*procEx*/, uint32 cooldown)
+{
+ // Get triggered aura spell info
+ SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
+
+ // Get effect index used for the proc
+ uint32 effIndex = triggeredByAura->GetEffIndex();
+
+ // Power amount required to proc the spell
+ int32 powerAmountRequired = triggeredByAura->GetAmount();
+ // Power type required to proc
+ Powers powerRequired = Powers(auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].MiscValue);
+
+ // Set trigger spell id, target, custom basepoints
+ uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
+
+ Unit* target = NULL;
+ int32 basepoints0 = 0;
+
+ Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
+ ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
+
+ /* Try handle unknown trigger spells or with invalid power amount or misc value
+ if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL || powerAmountRequired == NULL || powerRequired >= MAX_POWER)
+ {
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ break;
+ }
+ }
+ }*/
+
+ // All ok. Check current trigger spell
+ SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
+ if (triggerEntry == NULL)
+ {
+ // Not cast unknown spell
+ // TC_LOG_ERROR("Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 in EffectTriggered[%d], not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
+ return false;
+ }
+
+ // not allow proc extra attack spell at extra attack
+ if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
+ return false;
+
+ if (!powerRequired || !powerAmountRequired)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 powerAmountRequired in EffectAmount[%d] or 0 powerRequired in EffectMiscValue, not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
+ return false;
+ }
+
+ if (GetPower(powerRequired) != powerAmountRequired)
+ return false;
+
+ // Custom requirements (not listed in procEx) Warning! damage dealing after this
+ // Custom triggered spells
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_DRUID:
+ {
+ // Eclipse Mastery Driver Passive
+ if (auraSpellInfo->Id == 79577)
+ {
+ uint32 solarEclipseMarker = 67483;
+ uint32 lunarEclipseMarker = 67484;
+
+ switch (effIndex)
+ {
+ case 0:
+ {
+ // Do not proc if proc spell isnt starfire and starsurge
+ if (procSpell->Id != 2912 && procSpell->Id != 78674)
+ return false;
+
+ if (HasAura(solarEclipseMarker))
+ {
+ RemoveAurasDueToSpell(solarEclipseMarker);
+ CastSpell(this, lunarEclipseMarker, true);
+ }
+ break;
+ }
+ case 1:
+ {
+ // Do not proc if proc spell isnt wrath and starsurge
+ if (procSpell->Id != 5176 && procSpell->Id != 78674)
+ return false;
+
+ if (HasAura(lunarEclipseMarker))
+ {
+ RemoveAurasDueToSpell(lunarEclipseMarker);
+ CastSpell(this, solarEclipseMarker, true);
+ }
+
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
+ return false;
+
+ // try detect target manually if not set
+ if (target == NULL)
+ target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry && triggerEntry->IsPositive() ? this : victim;
+
+ if (basepoints0)
+ CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
+ else
+ CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
+
+ if (cooldown && GetTypeId() == TYPEID_PLAYER)
+ ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
+
+ return true;
+}
+
//victim may be NULL
bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
@@ -5482,6 +5372,19 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker
break;
}
+ case 47020: // Enter vehicle XT-002 (Scrapbot)
+ {
+ if (GetTypeId() != TYPEID_UNIT)
+ return false;
+
+ Unit* vehicleBase = GetVehicleBase();
+ if (!vehicleBase)
+ return false;
+
+ // Todo: Check if this amount is blizzlike
+ vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
+ break;
+ }
}
break;
}
@@ -5494,7 +5397,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// mana reward
- basepoints0 = CalculatePct(int32(GetMaxPower(POWER_MANA)), triggerAmount);
+ basepoints0 = CalculatePct(GetMaxPower(POWER_MANA), triggerAmount);
target = this;
triggered_spell_id = 29442;
break;
@@ -5516,7 +5419,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
break;
}
- // Hot Streak
+ // Hot Streak & Improved Hot Streak
if (dummySpell->SpellIconID == 2999)
{
if (effIndex != 0)
@@ -5529,7 +5432,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (procEx & PROC_EX_CRITICAL_HIT)
{
counter->SetAmount(counter->GetAmount() * 2);
- if (counter->GetAmount() < 100) // not enough
+ if (counter->GetAmount() < 100 && dummySpell->Id != 44445) // not enough or Hot Streak spell
return true;
// Crititcal counted -> roll chance
if (roll_chance_i(triggerAmount))
@@ -5574,29 +5477,22 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (!player)
return false;
- SpellCooldowns const cooldowns = player->GetSpellCooldowns();
- // remove cooldowns on all ranks of Frost Nova
- for (SpellCooldowns::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr)
- {
- SpellInfo const* cdSpell = sSpellMgr->GetSpellInfo(itr->first);
- // Frost Nova
- if (cdSpell && cdSpell->SpellFamilyName == SPELLFAMILY_MAGE
- && cdSpell->SpellFamilyFlags[0] & 0x00000040)
- player->RemoveSpellCooldown(cdSpell->Id, true);
- }
+ // Remove Frost Nova cooldown
+ player->RemoveSpellCooldown(122, true);
break;
}
- case 47020: // Enter vehicle XT-002 (Scrapbot)
+ // Permafrost
+ case 11175:
+ case 12569:
+ case 12571:
{
- if (GetTypeId() != TYPEID_UNIT)
+ if (!GetGuardianPet())
return false;
- Unit* vehicleBase = GetVehicleBase();
- if (!vehicleBase)
- return false;
-
- /// @todo Check if this amount is blizzlike
- vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
+ // heal amount
+ basepoints0 = CalculatePct(damage, triggerAmount);
+ target = this;
+ triggered_spell_id = 91394;
break;
}
}
@@ -5612,14 +5508,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
RemoveAura(dummySpell->Id);
return false;
}
- // Improved Spell Reflection
- case 59088:
- case 59089:
- {
- triggered_spell_id = 59725;
- target = this;
- break;
- }
}
// Retaliation
@@ -5655,12 +5543,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Glyph of Blocking
- if (dummySpell->Id == 58375)
- {
- triggered_spell_id = 58374;
- break;
- }
// Glyph of Sunder Armor
if (dummySpell->Id == 58387)
{
@@ -5746,39 +5628,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Soul Leech
case 30293:
case 30295:
- case 30296:
{
- // Improved Soul Leech
- AuraEffectList const& SoulLeechAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = SoulLeechAuras.begin(); i != SoulLeechAuras.end(); ++i)
- {
- if ((*i)->GetId() == 54117 || (*i)->GetId() == 54118)
- {
- if ((*i)->GetEffIndex() != 0)
- continue;
- basepoints0 = int32((*i)->GetAmount());
- target = GetGuardianPet();
- if (target)
- {
- // regen mana for pet
- CastCustomSpell(target, 54607, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- }
- // regen mana for caster
- CastCustomSpell(this, 59117, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- // Get second aura of spell for replenishment effect on party
- if (AuraEffect const* aurEff = (*i)->GetBase()->GetEffect(EFFECT_1))
- {
- // Replenishment - roll chance
- if (roll_chance_i(aurEff->GetAmount()))
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- }
- break;
- }
- }
- // health
basepoints0 = CalculatePct(int32(damage), triggerAmount);
target = this;
triggered_spell_id = 30294;
+ // Replenishment
+ CastSpell(this, 57669, true, castItem, triggeredByAura);
break;
}
// Shadowflame (Voidheart Raiment set bonus)
@@ -5833,15 +5688,15 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (triggeredByAura->GetCasterGUID() != victim->GetGUID())
return false;
- // Energize 0.25% of max. mana
+ // Energize 1% of max. mana
victim->CastSpell(victim, 57669, true, castItem, triggeredByAura);
return true; // no hidden cooldown
}
// Body and Soul
if (dummySpell->SpellIconID == 2218)
{
- // Proc only from Abolish desease on self cast
- if (procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount))
+ // Proc only from Cure Disease on self cast
+ if (procSpell->Id != 528 || victim != this || !roll_chance_i(triggerAmount))
return false;
triggered_spell_id = 64136;
target = this;
@@ -5856,9 +5711,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// heal amount
- int32 total = CalculatePct(int32(damage), triggerAmount);
- int32 team = total / 5;
- int32 self = total - team;
+ int32 self = CalculatePct(int32(damage), triggerAmount);
+ int32 team = CalculatePct(int32(damage), triggerAmount / 2);
CastCustomSpell(this, 15290, &team, &self, NULL, true, castItem, triggeredByAura);
return true; // no hidden cooldown
}
@@ -5877,9 +5731,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Improved Shadowform
- case 47570:
+ // Phantasm
case 47569:
+ case 47570:
{
if (!roll_chance_i(triggerAmount))
return false;
@@ -5890,9 +5744,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Glyph of Dispel Magic
case 55677:
{
- // Dispel Magic shares spellfamilyflag with abolish disease
- if (procSpell->SpellIconID != 74)
- return false;
if (!target || !target->IsFriendlyTo(this))
return false;
@@ -5952,8 +5803,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (procSpell->SpellIconID != 62)
return false;
- int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
- basepoints0 = int32(CalculatePct(GetCreatePowers(POWER_MANA), mana_perc) / 10);
+ basepoints0 = int32(CalculatePct(GetCreatePowers(POWER_MANA), triggerAmount) / 5);
triggered_spell_id = 54833;
target = this;
break;
@@ -5964,7 +5814,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 54846;
break;
}
- // Glyph of Shred
+ // Glyph of Bloodletting
case 54815:
{
if (!target)
@@ -5973,15 +5823,14 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// try to find spell Rip on the target
if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00800000, 0x0, 0x0, GetGUID()))
{
- // Rip's max duration, note: spells which modifies Rip's duration also counted like Glyph of Rip
+ // Rip's max duration, note: spells which modifies Rip's duration also counted
uint32 CountMin = AurEff->GetBase()->GetMaxDuration();
// just Rip's max duration without other spells
uint32 CountMax = AurEff->GetSpellInfo()->GetMaxDuration();
// add possible auras' and Glyph of Shred's max duration
- CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Shred -> +6 seconds
- CountMax += HasAura(54818) ? 4 * IN_MILLISECONDS : 0; // Glyph of Rip -> +4 seconds
+ CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Bloodletting -> +6 seconds
CountMax += HasAura(60141) ? 4 * IN_MILLISECONDS : 0; // Rip Duration/Lacerate Damage -> +4 seconds
// if min < max -> that means caster didn't cast 3 shred yet
@@ -5996,19 +5845,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// if not found Rip
return false;
}
- // Glyph of Rake
- case 54821:
- {
- if (procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
- {
- if (target && target->GetTypeId() == TYPEID_UNIT)
- {
- triggered_spell_id = 54820;
- break;
- }
- }
- return false;
- }
// Leader of the Pack
case 24932:
{
@@ -6017,13 +5853,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
target = this;
triggered_spell_id = 34299;
- if (triggeredByAura->GetCasterGUID() != GetGUID())
- break;
- int32 basepoints1 = triggerAmount * 2;
- // Improved Leader of the Pack
- // Check cooldown of heal spell cooldown
- if (GetTypeId() == TYPEID_PLAYER && !ToPlayer()->HasSpellCooldown(34299))
- CastCustomSpell(this, 60889, &basepoints1, 0, 0, true, 0, triggeredByAura);
+ // Regenerate 4% mana
+ int32 mana = CalculatePct(GetCreateMana(), triggerAmount);
+ CastCustomSpell(this, 68285, &mana, NULL, NULL, true, castItem, triggeredByAura);
break;
}
// Healing Touch (Dreamwalker Raiment set)
@@ -6035,15 +5867,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 28742;
break;
}
- // Glyph of Rejuvenation
- case 54754:
- {
- if (!victim || !victim->HealthBelowPct(uint32(triggerAmount)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 54755;
- break;
- }
// Healing Touch Refund (Idol of Longevity trinket)
case 28847:
{
@@ -6131,35 +5954,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return true;
}
}
- // Eclipse
- if (dummySpell->SpellIconID == 2856 && GetTypeId() == TYPEID_PLAYER)
- {
- if (!procSpell || effIndex != 0)
- return false;
-
- bool isWrathSpell = (procSpell->SpellFamilyFlags[0] & 1);
-
- if (!roll_chance_f(dummySpell->ProcChance * (isWrathSpell ? 0.6f : 1.0f)))
- return false;
-
- target = this;
- if (target->HasAura(isWrathSpell ? 48517 : 48518))
- return false;
-
- triggered_spell_id = isWrathSpell ? 48518 : 48517;
- break;
- }
break;
}
case SPELLFAMILY_ROGUE:
{
switch (dummySpell->Id)
{
- case 56800: // Glyph of Backstab
- {
- triggered_spell_id = 63975;
- break;
- }
case 32748: // Deadly Throw Interrupt
{
// Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw
@@ -6173,27 +5973,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
switch (dummySpell->SpellIconID)
{
- case 2116: // Quick Recovery
- {
- if (!procSpell)
- return false;
-
- // energy cost save
- basepoints0 = CalculatePct(int32(procSpell->ManaCost), triggerAmount);
- if (basepoints0 <= 0)
- return false;
-
- target = this;
- triggered_spell_id = 31663;
- break;
- }
case 2909: // Cut to the Chase
{
// "refresh your Slice and Dice duration to its 5 combo point maximum"
// lookup Slice and Dice
- if (AuraEffect const* aur = GetAuraEffect(SPELL_AURA_MOD_MELEE_HASTE, SPELLFAMILY_ROGUE, 0x40000, 0, 0))
+ if (Aura* aur = GetAura(5171))
{
- aur->GetBase()->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
+ aur->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
return true;
}
return false;
@@ -6212,8 +5998,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
case 267: // Improved Mend Pet
{
- int32 chance = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
- if (!roll_chance_i(chance))
+ if (!roll_chance_i(triggerAmount))
return false;
triggered_spell_id = 24406;
@@ -6224,23 +6009,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (!procSpell)
return false;
- Spell* spell = ToPlayer()->m_spellModTakingSpell;
-
- // Disable charge drop because of Lock and Load
- ToPlayer()->SetSpellModTakingSpell(spell, false);
-
- // Explosive Shot
- if (procSpell->SpellFamilyFlags[2] & 0x200)
- {
- if (!victim)
- return false;
- if (AuraEffect const* pEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DUMMY, SPELLFAMILY_HUNTER, 0x0, 0x80000000, 0x0, GetGUID()))
- basepoints0 = pEff->GetSpellInfo()->CalcPowerCost(this, SpellSchoolMask(pEff->GetSpellInfo()->SchoolMask)) * 4/10/3;
- }
- else
- basepoints0 = procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)) * 4/10;
-
- ToPlayer()->SetSpellModTakingSpell(spell, true);
+ basepoints0 = CalculatePct(procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)), triggerAmount);
if (basepoints0 <= 0)
return false;
@@ -6249,50 +6018,18 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 34720;
break;
}
- case 3406: // Hunting Party
- {
- triggered_spell_id = 57669;
- target = this;
- break;
- }
case 3560: // Rapid Recuperation
{
- // This effect only from Rapid Killing (mana regen)
+ // This effect only from Rapid Killing (focus regen)
if (!(procSpell->SpellFamilyFlags[1] & 0x01000000))
return false;
target = this;
-
- switch (dummySpell->Id)
- {
- case 53228: // Rank 1
- triggered_spell_id = 56654;
- break;
- case 53232: // Rank 2
- triggered_spell_id = 58882;
- break;
- }
- break;
- }
- case 3579: // Lock and Load
- {
- // Proc only from periodic (from trap activation proc another aura of this spell)
- if (!(procFlag & PROC_FLAG_DONE_PERIODIC) || !roll_chance_i(triggerAmount))
- return false;
- triggered_spell_id = 56453;
- target = this;
+ triggered_spell_id = 58883;
+ basepoints0 = CalculatePct(GetMaxPower(POWER_FOCUS), triggerAmount);
break;
}
}
-
- switch (dummySpell->Id)
- {
- case 57870: // Glyph of Mend Pet
- {
- victim->CastSpell(victim, 57894, true, NULL, NULL, GetGUID());
- return true;
- }
- }
break;
}
case SPELLFAMILY_PALADIN:
@@ -6339,7 +6076,22 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (triggered_spell_id && beaconTarget)
{
- victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, NULL, NULL, true);
+ int32 percent = 0;
+ switch (procSpell->Id)
+ {
+ case 85673: // Word of Glory
+ case 20473: // Holy Shock
+ case 19750: // Flash of Light
+ case 82326: // Divine Light
+ case 85222: // Light of Dawn
+ percent = triggerAmount; // 50% heal from these spells
+ break;
+ case 635: // Holy Light
+ percent = triggerAmount * 2; // 100% heal from Holy Light
+ break;
+ }
+ basepoints0 = CalculatePct(damage, percent);
+ victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, NULL, NULL, true, 0, triggeredByAura);
return true;
}
@@ -6350,35 +6102,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
target = this;
triggered_spell_id = 31930;
- // replenishment
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- break;
- }
- // Sanctified Wrath
- if (dummySpell->SpellIconID == 3029)
- {
- triggered_spell_id = 57318;
- target = this;
- basepoints0 = triggerAmount;
- CastCustomSpell(target, triggered_spell_id, &basepoints0, &basepoints0, NULL, true, castItem, triggeredByAura);
- return true;
- }
- // Righteous Vengeance
- if (dummySpell->SpellIconID == 3025)
- {
- // 4 damage tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 61840;
- // Add remaining ticks to damage done
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
- break;
- }
- // Sheath of Light
- if (dummySpell->SpellIconID == 3030)
- {
- // 4 healing tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 54203;
break;
}
switch (dummySpell->Id)
@@ -6400,38 +6123,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Heart of the Crusader
- case 20335: // rank 1
- triggered_spell_id = 21183;
- break;
- case 20336: // rank 2
- triggered_spell_id = 54498;
- break;
- case 20337: // rank 3
- triggered_spell_id = 54499;
- break;
- // Judgement of Light
- case 20185:
- {
if (!victim)
return false;
- // 2% of maximum health
- basepoints0 = int32(victim->CountPctFromMaxHealth(2));
- victim->CastCustomSpell(victim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
- return true;
- }
- // Judgement of Wisdom
- case 20186:
- {
- if (victim && victim->isAlive() && victim->getPowerType() == POWER_MANA)
- {
- // 2% of base mana
- basepoints0 = int32(CalculatePct(victim->GetCreateMana(), 2));
- victim->CastCustomSpell(victim, 20268, &basepoints0, NULL, NULL, true, 0, triggeredByAura);
- }
- return true;
- }
// Holy Power (Redemption Armor set)
case 28789:
{
@@ -6463,10 +6157,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
break;
}
- // Seal of Vengeance (damage calc on apply aura)
case 31801:
{
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
+ if (effIndex != 0) // effect 2 used by seal unleashing code
return false;
// At melee attack or Hammer of the Righteous spell damage considered as melee attack
@@ -6479,7 +6172,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 31803;
- // On target with 5 stacks of Holy Vengeance direct damage is done
+ // On target with 5 stacks of Censure direct damage is done
if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
{
if (aur->GetStackAmount() == 5)
@@ -6495,61 +6188,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
break;
}
- // Seal of Corruption
- case 53736:
- {
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
- return false;
-
- // At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = !procSpell || procSpell->Id == 53595;
- // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
-
- if (!stacker && !damager)
- return false;
-
- triggered_spell_id = 53742;
-
- // On target with 5 stacks of Blood Corruption direct damage is done
- if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
- {
- if (aur->GetStackAmount() == 5)
- {
- if (stacker)
- aur->RefreshDuration();
- CastSpell(victim, 53739, true);
- return true;
- }
- }
-
- if (!stacker)
- return false;
- break;
- }
- // Spiritual Attunement
- case 31785:
- case 33776:
- {
- // if healed by another unit (victim)
- if (this == victim)
- return false;
-
- // heal amount
- basepoints0 = int32(CalculatePct(std::min(damage, GetMaxHealth() - GetHealth()), triggerAmount));
- target = this;
-
- if (basepoints0)
- triggered_spell_id = 31786;
- break;
- }
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
case 40470:
{
if (!procSpell)
return false;
- float chance;
+ float chance;
// Flash of light/Holy light
if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
@@ -6571,13 +6216,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
break;
}
- // Glyph of Holy Light
- case 54937:
- {
- triggered_spell_id = 54968;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
// Item - Paladin T8 Holy 2P Bonus
case 64890:
{
@@ -6657,14 +6295,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
switch (dummySpell->Id)
{
- // Tidal Force
- case 55198:
- {
- // Remove aura stack from caster
- RemoveAuraFromStack(55166);
- // drop charges
- return false;
- }
// Totemic Power (The Earthshatterer set)
case 28823:
{
@@ -6737,26 +6367,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// Now amount of extra power stored in 1 effect of Enchant spell
- // Get it by item enchant id
- uint32 spellId;
- switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)))
- {
- case 283: spellId = 8232; break; // 1 Rank
- case 284: spellId = 8235; break; // 2 Rank
- case 525: spellId = 10486; break; // 3 Rank
- case 1669:spellId = 16362; break; // 4 Rank
- case 2636:spellId = 25505; break; // 5 Rank
- case 3785:spellId = 58801; break; // 6 Rank
- case 3786:spellId = 58803; break; // 7 Rank
- case 3787:spellId = 58804; break; // 8 Rank
- default:
- {
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
- castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)), dummySpell->Id);
- return false;
- }
- }
-
+ uint32 spellId = 8232;
SpellInfo const* windfurySpellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!windfurySpellInfo)
{
@@ -6924,23 +6535,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// if not found Flame Shock
return false;
}
- case 63280: // Glyph of Totem of Wrath
- {
- if (procSpell->SpellIconID != 2019)
- return false;
-
- if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot
- {
- if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(totem->m_spells[0]))
- {
- int32 bp0 = CalculatePct(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount);
- int32 bp1 = CalculatePct(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount);
- CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true);
- return true;
- }
- }
- return false;
- }
break;
}
// Frozen Power
@@ -7012,109 +6606,19 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
return true;
}
- // Improved Water Shield
- if (dummySpell->SpellIconID == 2287)
- {
- // Default chance for Healing Wave and Riptide
- float chance = (float)triggeredByAura->GetAmount();
-
- if (procSpell->SpellFamilyFlags[0] & 0x80)
- // Lesser Healing Wave - 0.6 of default
- chance *= 0.6f;
- else if (procSpell->SpellFamilyFlags[0] & 0x100)
- // Chain heal - 0.3 of default
- chance *= 0.3f;
-
- if (!roll_chance_f(chance))
- return false;
-
- // Water Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020, 0))
- {
- uint32 spell = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- CastSpell(this, spell, true, castItem, triggeredByAura);
- return true;
- }
- return false;
- }
- // Lightning Overload
- if (dummySpell->SpellIconID == 2018) // only this spell has SpellFamily Shaman SpellIconID == 2018 and dummy aura
- {
- if (!procSpell || GetTypeId() != TYPEID_PLAYER || !victim)
- return false;
-
- // custom cooldown processing case
- if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(dummySpell->Id))
- return false;
-
- uint32 spellId = 0;
- // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost
- switch (procSpell->Id)
- {
- // Lightning Bolt
- case 403: spellId = 45284; break; // Rank 1
- case 529: spellId = 45286; break; // Rank 2
- case 548: spellId = 45287; break; // Rank 3
- case 915: spellId = 45288; break; // Rank 4
- case 943: spellId = 45289; break; // Rank 5
- case 6041: spellId = 45290; break; // Rank 6
- case 10391: spellId = 45291; break; // Rank 7
- case 10392: spellId = 45292; break; // Rank 8
- case 15207: spellId = 45293; break; // Rank 9
- case 15208: spellId = 45294; break; // Rank 10
- case 25448: spellId = 45295; break; // Rank 11
- case 25449: spellId = 45296; break; // Rank 12
- case 49237: spellId = 49239; break; // Rank 13
- case 49238: spellId = 49240; break; // Rank 14
- // Chain Lightning
- case 421: spellId = 45297; break; // Rank 1
- case 930: spellId = 45298; break; // Rank 2
- case 2860: spellId = 45299; break; // Rank 3
- case 10605: spellId = 45300; break; // Rank 4
- case 25439: spellId = 45301; break; // Rank 5
- case 25442: spellId = 45302; break; // Rank 6
- case 49270: spellId = 49268; break; // Rank 7
- case 49271: spellId = 49269; break; // Rank 8
- default:
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
- return false;
- }
-
- // Chain Lightning
- if (procSpell->SpellFamilyFlags[0] & 0x2)
- {
- // Chain lightning has [LightOverload_Proc_Chance] / [Max_Number_of_Targets] chance to proc of each individual target hit.
- // A maxed LO would have a 33% / 3 = 11% chance to proc of each target.
- // LO chance was already "accounted" at the proc chance roll, now need to divide the chance by [Max_Number_of_Targets]
- float chance = 100.0f / procSpell->Effects[effIndex].ChainTarget;
- if (!roll_chance_f(chance))
- return false;
-
- // Remove cooldown (Chain Lightning - has Category Recovery time)
- ToPlayer()->RemoveSpellCooldown(spellId);
- }
-
- CastSpell(victim, spellId, true, castItem, triggeredByAura);
-
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
-
- return true;
- }
// Static Shock
if (dummySpell->SpellIconID == 3059)
{
// Lightning Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
+ if (GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
{
- uint32 spell = sSpellMgr->GetSpellWithRank(26364, aurEff->GetSpellInfo()->GetRank());
+ uint32 spell = 26364;
// custom cooldown processing case
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(spell))
ToPlayer()->RemoveSpellCooldown(spell);
CastSpell(target, spell, true, castItem, triggeredByAura);
- aurEff->GetBase()->DropCharge();
return true;
}
return false;
@@ -7123,7 +6627,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
case SPELLFAMILY_DEATHKNIGHT:
{
- // Blood-Caked Strike - Blood-Caked Blade
+ // Blood-Caked Blade
if (dummySpell->SpellIconID == 138)
{
if (!target || !target->isAlive())
@@ -7132,14 +6636,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell;
break;
}
- // Improved Blood Presence
- if (dummySpell->SpellIconID == 2636)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
// Butchery
if (dummySpell->SpellIconID == 2664)
{
@@ -7173,13 +6669,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
else
return false;
}
- // Mark of Blood
- if (dummySpell->Id == 49005)
- {
- /// @todo need more info (cooldowns/PPM)
- triggered_spell_id = 61607;
- break;
- }
// Unholy Blight
if (dummySpell->Id == 49194)
{
@@ -7198,21 +6687,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
break;
}
- // Vendetta
- if (dummySpell->SpellFamilyFlags[0] & 0x10000)
- {
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- triggered_spell_id = 50181;
- target = this;
- break;
- }
- // Necrosis
- if (dummySpell->SpellIconID == 2709)
- {
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 51460;
- break;
- }
// Threat of Thassarian
if (dummySpell->SpellIconID == 2023)
{
@@ -7225,45 +6699,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
switch (procSpell->Id)
{
- // Obliterate
- case 49020: triggered_spell_id = 66198; break; // Rank 1
- case 51423: triggered_spell_id = 66972; break; // Rank 2
- case 51424: triggered_spell_id = 66973; break; // Rank 3
- case 51425: triggered_spell_id = 66974; break; // Rank 4
-
- // Frost Strike
- case 49143: triggered_spell_id = 66196; break; // Rank 1
- case 51416: triggered_spell_id = 66958; break; // Rank 2
- case 51417: triggered_spell_id = 66959; break; // Rank 3
- case 51418: triggered_spell_id = 66960; break; // Rank 4
- case 51419: triggered_spell_id = 66961; break; // Rank 5
- case 55268: triggered_spell_id = 66962; break; // Rank 6
-
- // Plague Strike
- case 45462: triggered_spell_id = 66216; break; // Rank 1
- case 49917: triggered_spell_id = 66988; break; // Rank 2
- case 49918: triggered_spell_id = 66989; break; // Rank 3
- case 49919: triggered_spell_id = 66990; break; // Rank 4
- case 49920: triggered_spell_id = 66991; break; // Rank 5
- case 49921: triggered_spell_id = 66992; break; // Rank 6
-
- // Death Strike
- case 49998: triggered_spell_id = 66188; break; // Rank 1
- case 49999: triggered_spell_id = 66950; break; // Rank 2
- case 45463: triggered_spell_id = 66951; break; // Rank 3
- case 49923: triggered_spell_id = 66952; break; // Rank 4
- case 49924: triggered_spell_id = 66953; break; // Rank 5
-
- // Rune Strike
- case 56815: triggered_spell_id = 66217; break; // Rank 1
-
- // Blood Strike
- case 45902: triggered_spell_id = 66215; break; // Rank 1
- case 49926: triggered_spell_id = 66975; break; // Rank 2
- case 49927: triggered_spell_id = 66976; break; // Rank 3
- case 49928: triggered_spell_id = 66977; break; // Rank 4
- case 49929: triggered_spell_id = 66978; break; // Rank 5
- case 49930: triggered_spell_id = 66979; break; // Rank 6
+ case 49020: triggered_spell_id = 66198; break; // Obliterate
+ case 49143: triggered_spell_id = 66196; break; // Frost Strike
+ case 45462: triggered_spell_id = 66216; break; // Plague Strike
+ case 49998: triggered_spell_id = 66188; break; // Death Strike
+ case 56815: triggered_spell_id = 66217; break; // Rune Strike
+ case 45902: triggered_spell_id = 66215; break; // Blood Strike
default:
return false;
}
@@ -7282,51 +6723,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Wandering Plague
- if (dummySpell->SpellIconID == 1614)
- {
- if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, victim)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 50526;
- break;
- }
- // Sudden Doom
- if (dummySpell->SpellIconID == 1939 && GetTypeId() == TYPEID_PLAYER)
- {
- SpellChainNode const* chain = NULL;
- // get highest rank of the Death Coil spell
- PlayerSpellMap const& sp_list = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
- {
- // check if shown in spell book
- if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
- continue;
-
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(itr->first);
- if (!spellProto)
- continue;
-
- if (spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT
- && spellProto->SpellFamilyFlags[0] & 0x2000)
- {
- SpellChainNode const* newChain = sSpellMgr->GetSpellChainNode(itr->first);
-
- // No chain entry or entry lower than found entry
- if (!chain || !newChain || (chain->rank < newChain->rank))
- {
- triggered_spell_id = itr->first;
- chain = newChain;
- }
- else
- continue;
- // Found spell is last in chain - do not need to look more
- // Optimisation for most common case
- if (chain && chain->last->Id == itr->first)
- break;
- }
- }
- }
break;
}
case SPELLFAMILY_POTION:
@@ -7417,9 +6813,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return true;
}
+ /*
+ */
+
+
// Used in case when access to whole aura is needed
// All procs should be handled like this...
-bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, uint32 cooldown, bool * handled)
+bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown, bool * handled)
{
SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
@@ -7477,30 +6877,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
break;
case SPELLFAMILY_PALADIN:
{
- // Infusion of Light
- if (procSpell && dummySpell->SpellIconID == 3021)
- {
- // Flash of Light HoT on Flash of Light when Sacred Shield active
- if (procSpell->SpellFamilyFlags[0] & 0x40000000 && procSpell->SpellIconID == 242)
- {
- *handled = true;
- if (victim && victim->HasAura(53601))
- {
- int32 bp0 = CalculatePct(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue());
- // Item - Paladin T9 Holy 4P Bonus
- if (AuraEffect const* aurEff = GetAuraEffect(67191, 0))
- AddPct(bp0, aurEff->GetAmount());
- CastCustomSpell(victim, 66922, &bp0, NULL, NULL, true);
- return true;
- }
- }
- // but should not proc on non-critical Holy Shocks
- else if ((procSpell->SpellFamilyFlags[0] & 0x200000 || procSpell->SpellFamilyFlags[1] & 0x10000) && !(procEx & PROC_EX_CRITICAL_HIT))
- *handled = true;
- break;
- }
// Judgements of the Just
- else if (dummySpell->SpellIconID == 3015)
+ if (dummySpell->SpellIconID == 3015)
{
*handled = true;
CastSpell(victim, 68055, true);
@@ -7531,24 +6909,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
}
case SPELLFAMILY_MAGE:
{
- // Combustion
switch (dummySpell->Id)
{
- case 11129:
- {
- *handled = true;
- Unit* caster = triggeredByAura->GetCaster();
- if (!caster || !damage)
- return false;
-
- // last charge and crit
- if (triggeredByAura->GetCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT))
- return true; // charge counting (will removed)
-
- CastSpell(this, 28682, true);
-
- return (procEx & PROC_EX_CRITICAL_HIT) ? true : false;
- }
// Empowered Fire
case 31656:
case 31657:
@@ -7777,6 +7139,13 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
RemoveAurasDueToSpell(50240);
break;
}
+ // Warrior - Vigilance, SPELLFAMILY_GENERIC
+ if (auraSpellInfo->Id == 50720)
+ {
+ target = triggeredByAura->GetCaster();
+ if (!target)
+ return false;
+ }
}
break;
case SPELLFAMILY_MAGE:
@@ -7802,71 +7171,11 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
}
break;
- case SPELLFAMILY_WARLOCK:
- {
- // Drain Soul
- if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000)
- {
- // Improved Drain Soul
- Unit::AuraEffectList const& mAddFlatModifier = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
- {
- if ((*i)->GetMiscValue() == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellInfo()->SpellIconID == 113)
- {
- int32 value2 = CalculateSpellDamage(this, (*i)->GetSpellInfo(), 2);
- basepoints0 = int32(CalculatePct(GetMaxPower(POWER_MANA), value2));
- // Drain Soul
- CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- break;
- }
- }
- // Not remove charge (aura removed on death in any cases)
- // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura
- return false;
- }
- // Nether Protection
- else if (auraSpellInfo->SpellIconID == 1985)
- {
- if (!procSpell)
- return false;
- switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
- {
- case SPELL_SCHOOL_NORMAL:
- return false; // ignore
- case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break;
- case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break;
- case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break;
- case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break;
- case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break;
- case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
- default:
- return false;
- }
- }
- break;
- }
case SPELLFAMILY_PRIEST:
{
// Greater Heal Refund
if (auraSpellInfo->Id == 37594)
trigger_spell_id = 37595;
- // Blessed Recovery
- else if (auraSpellInfo->SpellIconID == 1875)
- {
- switch (auraSpellInfo->Id)
- {
- case 27811: trigger_spell_id = 27813; break;
- case 27815: trigger_spell_id = 27817; break;
- case 27816: trigger_spell_id = 27818; break;
- default:
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
- return false;
- }
- basepoints0 = CalculatePct(int32(damage), triggerAmount) / 3;
- target = this;
- // Add remaining ticks to healing done
- basepoints0 += GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_HEAL);
- }
break;
}
case SPELLFAMILY_DRUID:
@@ -7880,8 +7189,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
{
case FORM_NONE: trigger_spell_id = 37344; break;
case FORM_CAT: trigger_spell_id = 37341; break;
- case FORM_BEAR:
- case FORM_DIREBEAR: trigger_spell_id = 37340; break;
+ case FORM_BEAR: trigger_spell_id = 37340; break;
case FORM_TREE: trigger_spell_id = 37342; break;
case FORM_MOONKIN: trigger_spell_id = 37343; break;
default:
@@ -7895,8 +7203,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
switch (GetShapeshiftForm())
{
case FORM_CAT: trigger_spell_id = 67355; break;
- case FORM_BEAR:
- case FORM_DIREBEAR: trigger_spell_id = 67354; break;
+ case FORM_BEAR: trigger_spell_id = 67354; break;
default:
return false;
}
@@ -8012,42 +7319,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
break;
}
default:
- // Illumination
- if (auraSpellInfo->SpellIconID == 241)
- {
- if (!procSpell)
- return false;
- // procspell is triggered spell but we need mana cost of original casted spell
- uint32 originalSpellId = procSpell->Id;
- // Holy Shock heal
- if (procSpell->SpellFamilyFlags[1] & 0x00010000)
- {
- switch (procSpell->Id)
- {
- case 25914: originalSpellId = 20473; break;
- case 25913: originalSpellId = 20929; break;
- case 25903: originalSpellId = 20930; break;
- case 27175: originalSpellId = 27174; break;
- case 33074: originalSpellId = 33072; break;
- case 48820: originalSpellId = 48824; break;
- case 48821: originalSpellId = 48825; break;
- default:
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id);
- return false;
- }
- }
- SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId);
- if (!originalSpell)
- {
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu", originalSpellId);
- return false;
- }
- // percent stored in effect 1 (class scripts) base points
- int32 cost = int32(originalSpell->ManaCost + CalculatePct(GetCreateMana(), originalSpell->ManaCostPercentage));
- basepoints0 = CalculatePct(cost, auraSpellInfo->Effects[1].CalcValue());
- trigger_spell_id = 20272;
- target = this;
- }
break;
}
break;
@@ -8082,77 +7353,26 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
case 30881: // Nature's Guardian Rank 1
case 30883: // Nature's Guardian Rank 2
case 30884: // Nature's Guardian Rank 3
- case 30885: // Nature's Guardian Rank 4
- case 30886: // Nature's Guardian Rank 5
{
- if (HealthBelowPct(30))
+ if (!HealthBelowPctDamaged(30, damage))
{
- basepoints0 = int32(auraSpellInfo->Effects[EFFECT_0].CalcValue() * GetMaxHealth() / 100.0f);
+ basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
target = this;
trigger_spell_id = 31616;
- /// @todo Threat part
+ if (victim && victim->isAlive())
+ victim->getThreatManager().modifyThreatPercent(this, -10);
}
else
return false;
break;
}
- default:
- {
- // Lightning Shield (overwrite non existing triggered spell call in spell.dbc
- if (auraSpellInfo->SpellFamilyFlags[0] & 0x400)
- {
- trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank());
- }
- // Nature's Guardian
- else if (auraSpellInfo->SpellIconID == 2013)
- {
- // Check health condition - should drop to less 30% (damage deal after this!)
- if (!HealthBelowPctDamaged(30, damage))
- return false;
-
- if (victim && victim->isAlive())
- victim->getThreatManager().modifyThreatPercent(this, -10);
-
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- trigger_spell_id = 31616;
- target = this;
- }
- }
}
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
- // Acclimation
- if (auraSpellInfo->SpellIconID == 1930)
- {
- if (!procSpell)
- return false;
- switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
- {
- case SPELL_SCHOOL_NORMAL:
- return false; // ignore
- case SPELL_SCHOOL_HOLY: trigger_spell_id = 50490; break;
- case SPELL_SCHOOL_FIRE: trigger_spell_id = 50362; break;
- case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break;
- case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break;
- case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break;
- case SPELL_SCHOOL_ARCANE: trigger_spell_id = 50486; break;
- default:
- return false;
- }
- }
- // Blood Presence (Improved)
- else if (auraSpellInfo->Id == 63611)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- trigger_spell_id = 50475;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- }
// Item - Death Knight T10 Melee 4P Bonus
- else if (auraSpellInfo->Id == 70656)
+ if (auraSpellInfo->Id == 70656)
{
if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT)
return false;
@@ -8226,7 +7446,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
ItemTemplate const* weapon = item->GetTemplate();
- float weaponDPS = weapon->getDPS();
+ float weaponDPS = weapon->DPS;
float attackPower = GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f;
float weaponSpeed = float(weapon->Delay) / 1000.0f;
basepoints0 = int32((weaponDPS + attackPower) * weaponSpeed);
@@ -8251,7 +7471,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// Deflection
case 52420:
{
- if (!HealthBelowPct(35))
+ if (!HealthBelowPctDamaged(35, damage))
return false;
break;
}
@@ -8264,16 +7484,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
break;
}
- // Deadly Swiftness (Rank 1)
- case 31255:
- {
- // whenever you deal damage to a target who is below 20% health.
- if (!victim || !victim->isAlive() || victim->HealthAbovePct(20))
- return false;
-
- target = this;
- trigger_spell_id = 22588;
- }
// Greater Heal Refund (Avatar Raiment set)
case 37594:
{
@@ -8308,24 +7518,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// Decimation
case 63156:
case 63158:
- // Can proc only if target has hp below 35%
- if (!victim || !victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, procSpell, this))
+ // Can proc only if target has hp below 25%
+ if (!victim || !victim->HealthBelowPct(auraSpellInfo->Effects[EFFECT_1].CalcValue()))
return false;
break;
// Deathbringer Saurfang - Blood Beast's Blood Link
case 72176:
basepoints0 = 3;
break;
- case 15337: // Improved Spirit Tap (Rank 1)
- case 15338: // Improved Spirit Tap (Rank 2)
- {
- if (procSpell->SpellFamilyFlags[0] & 0x800000)
- if ((procSpell->Id != 58381) || !roll_chance_i(50))
- return false;
-
- target = victim;
- break;
- }
// Professor Putricide - Ooze Spell Tank Protection
case 71770:
if (victim)
@@ -8346,52 +7546,11 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
break;
}
- // Blade Barrier
- if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85 && procSpell)
- {
- Player* player = ToPlayer();
- if (!player || player->getClass() != CLASS_DEATH_KNIGHT)
- return false;
-
- if (!player->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
- return false;
- }
-
- // Rime
- else if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 56)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Howling Blast
- ToPlayer()->RemoveSpellCategoryCooldown(1248, true);
- }
-
// Custom basepoints/target for exist spell
// dummy basepoints or other customs
switch (trigger_spell_id)
{
// Auras which should proc on area aura source (caster in this case):
- // Turn the Tables
- case 52914:
- case 52915:
- case 52910:
- // Honor Among Thieves
- case 52916:
- {
- target = triggeredByAura->GetBase()->GetCaster();
- if (!target)
- return false;
-
- if (cooldown && target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->HasSpellCooldown(trigger_spell_id))
- return false;
-
- target->CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
-
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
- return true;
- }
// Cast positive spell on enemy target
case 7099: // Curse of Mending
case 39703: // Curse of Mending
@@ -8401,14 +7560,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
target = victim;
break;
}
- // Combo points add triggers (need add combopoint only for main target, and after possible combopoints reset)
- case 15250: // Rogue Setup
- {
- // applied only for main target
- if (!victim || (GetTypeId() == TYPEID_PLAYER && victim != ToPlayer()->GetSelectedUnit()))
- return false;
- break; // continue normal case
- }
// Finish movies that add combo
case 14189: // Seal Fate (Netherblade set)
case 14157: // Ruthlessness
@@ -8425,12 +7576,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
CastSpell(this, 70721, true);
break;
}
- // Shamanistic Rage triggered spell
- case 30824:
- {
- basepoints0 = int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), triggerAmount));
- break;
- }
// Enlightenment (trigger only from mana cost spells)
case 35095:
{
@@ -8438,22 +7583,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
break;
}
- // Demonic Pact
- case 48090:
- {
- // Get talent aura from owner
- if (isPet())
- if (Unit* owner = GetOwner())
- {
- if (AuraEffect* aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0))
- {
- basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); /// @todo Is it right?
- CastCustomSpell(this, trigger_spell_id, &basepoints0, &basepoints0, NULL, true, castItem, triggeredByAura);
- return true;
- }
- }
- break;
- }
case 46916: // Slam! (Bloodsurge proc)
case 52437: // Sudden Death
{
@@ -8492,35 +7621,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
CastSpell(this, 70831, true, castItem, triggeredByAura);
break;
}
- // Astral Shift
- case 52179:
- {
- if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
-
- // Need stun, fear or silence mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
- return false;
- break;
- }
- // Burning Determination
- case 54748:
- {
- if (!procSpell)
- return false;
- // Need Interrupt or Silenced mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE))))
- return false;
- break;
- }
- // Lock and Load
- case 56453:
- {
- // Proc only from Frost/Freezing trap activation or from Freezing Arrow (the periodic dmg proc handled elsewhere)
- if (!(procFlags & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount))
- return false;
- break;
- }
// Glyph of Death's Embrace
case 58679:
{
@@ -8583,7 +7683,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return true;
}
-bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown)
+bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 cooldown)
{
int32 scriptId = triggeredByAura->GetMiscValue();
@@ -8597,27 +7697,6 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au
switch (scriptId)
{
- case 836: // Improved Blizzard (Rank 1)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12484;
- break;
- }
- case 988: // Improved Blizzard (Rank 2)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12485;
- break;
- }
- case 989: // Improved Blizzard (Rank 3)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12486;
- break;
- }
case 4533: // Dreamwalker Raiment 2 pieces bonus
{
// Chance 50%
@@ -8637,26 +7716,6 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au
case 4537: // Dreamwalker Raiment 6 pieces bonus
triggered_spell_id = 28750; // Blessing of the Claw
break;
- case 5497: // Improved Mana Gems
- triggered_spell_id = 37445; // Mana Surge
- break;
- case 7010: // Revitalize - can proc on full hp target
- case 7011:
- case 7012:
- {
- if (!roll_chance_i(triggeredByAura->GetAmount()))
- return false;
- switch (victim->getPowerType())
- {
- case POWER_MANA: triggered_spell_id = 48542; break;
- case POWER_RAGE: triggered_spell_id = 48541; break;
- case POWER_ENERGY: triggered_spell_id = 48540; break;
- case POWER_RUNIC_POWER: triggered_spell_id = 48543; break;
- default:
- break;
- }
- break;
- }
default:
break;
}
@@ -8720,10 +7779,6 @@ void Unit::setPowerType(Powers new_powertype)
case POWER_ENERGY:
SetMaxPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY));
break;
- case POWER_HAPPINESS:
- SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- SetPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- break;
}
}
@@ -9193,7 +8248,7 @@ bool Unit::HasAuraState(AuraStateType flag, SpellInfo const* spellProto, Unit co
{
AuraEffectList const& stateAuras = Caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
for (AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(spellProto))
+ if ((*j)->IsAffectingSpell(spellProto))
return true;
}
// Check per caster aura state
@@ -9227,7 +8282,7 @@ void Unit::SetOwnerGUID(uint64 owner)
SetFieldNotifyFlag(UF_FLAG_OWNER);
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
BuildValuesUpdateBlockForPlayer(&udata, player);
udata.BuildPacket(&packet);
@@ -9541,7 +8596,7 @@ void Unit::SetCharm(Unit* charm, bool apply)
if (_isWalkingBeforeCharm)
{
charm->SetWalk(false);
- charm->SendMovementFlagUpdate();
+ charm->SendMovementWalkMode();
}
m_Controlled.insert(charm);
@@ -9579,7 +8634,7 @@ void Unit::SetCharm(Unit* charm, bool apply)
if (charm->IsWalking() != _isWalkingBeforeCharm)
{
charm->SetWalk(_isWalkingBeforeCharm);
- charm->SendMovementFlagUpdate(true); // send packet to self, to update movement state on player.
+ charm->SendMovementWalkMode();
}
if (charm->GetTypeId() == TYPEID_PLAYER
@@ -9616,7 +8671,7 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
// use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
if (gain)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth);
}
@@ -9933,26 +8988,40 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
AddPct(DoneTotalMod, (*i)->GetAmount());
+ // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
+ AddPct(DoneTotalMod, GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC, spellProto->Mechanic));
+
// done scripted mod (take it from owner)
Unit const* owner = GetOwner() ? GetOwner() : this;
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
switch ((*i)->GetMiscValue())
{
case 4920: // Molten Fury
case 4919:
- case 6917: // Death's Embrace
- case 6926:
- case 6928:
{
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
}
+ case 6917: // Death's Embrace damage effect
+ case 6926:
+ case 6928:
+ {
+ // Health at 25% or less (25% stored at effect 2 of the spell)
+ if (victim->HealthBelowPct(CalculateSpellDamage(this, (*i)->GetSpellInfo(), EFFECT_2)))
+ AddPct(DoneTotalMod, (*i)->GetAmount());
+ }
+ case 6916: // Death's Embrace heal effect
+ case 6925:
+ case 6927:
+ if (HealthBelowPct(CalculateSpellDamage(this, (*i)->GetSpellInfo(), EFFECT_2)))
+ AddPct(DoneTotalMod, (*i)->GetAmount());
+ break;
// Soul Siphon
case 4992:
case 4993:
@@ -9980,12 +9049,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
AddPct(DoneTotalMod, modPercent);
break;
}
- case 6916: // Death's Embrace
- case 6925:
- case 6927:
- if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, spellProto, this))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
case 5481: // Starfire Bonus
{
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0))
@@ -10004,65 +9067,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += (*i)->GetAmount();
break;
}
- // Tundra Stalker
- // Merciless Combat
- case 7277:
- {
- // Merciless Combat
- if ((*i)->GetSpellInfo()->SpellIconID == 2656)
- {
- if (!victim->HealthAbovePct(35))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- // Tundra Stalker
- else
- {
- // Frost Fever (target debuff)
- if (victim->HasAura(55095))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- break;
- }
- // Rage of Rivendare
- case 7293:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
- AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
- break;
- }
- // Twisted Faith
- case 7377:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Marked for Death
- case 7598:
- case 7599:
- case 7600:
- case 7601:
- case 7602:
- {
- if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Dirty Deeds
- case 6427:
- case 6428:
- case 6579:
- case 6580:
- {
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
- {
- // effect 0 has expected value but in negative state
- int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
- AddPct(DoneTotalMod, bonus);
- }
- break;
- }
}
}
@@ -10072,89 +9076,35 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
case SPELLFAMILY_MAGE:
// Ice Lance
if (spellProto->SpellIconID == 186)
- {
if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- {
- // Glyph of Ice Lance
- if (owner->HasAura(56377) && victim->getLevel() > owner->getLevel())
- DoneTotalMod *= 4.0f;
- else
- DoneTotalMod *= 3.0f;
- }
- }
+ DoneTotalMod *= 2.0f;
// Torment the weak
- if (spellProto->SpellFamilyFlags[0] & 0x20600021 || spellProto->SpellFamilyFlags[1] & 0x9000)
+ if (spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_ARCANE)
+ {
if (victim->HasAuraWithMechanic((1<<MECHANIC_SNARE)|(1<<MECHANIC_SLOW_ATTACK)))
{
AuraEffectList const& mDumyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i)
- if ((*i)->GetSpellInfo()->SpellIconID == 3263)
+ {
+ if ((*i)->GetSpellInfo()->SpellIconID == 2215)
{
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
}
+ }
}
+ }
break;
case SPELLFAMILY_PRIEST:
- // Mind Flay
- if (spellProto->SpellFamilyFlags[0] & 0x800000)
- {
- // Glyph of Shadow Word: Pain
- if (AuraEffect* aurEff = GetAuraEffect(55687, 0))
- // Increase Mind Flay damage if Shadow Word: Pain present on target
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
- // Twisted Faith - Mind Flay part
- if (AuraEffect* aurEff = GetAuraEffect(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, SPELLFAMILY_PRIEST, 2848, 1))
- // Increase Mind Flay damage if Shadow Word: Pain present on target
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
// Smite
- else if (spellProto->SpellFamilyFlags[0] & 0x80)
+ if (spellProto->SpellFamilyFlags[0] & 0x80)
{
// Glyph of Smite
if (AuraEffect* aurEff = GetAuraEffect(55692, 0))
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, GetGUID()))
AddPct(DoneTotalMod, aurEff->GetAmount());
}
- // Shadow Word: Death
- else if (spellProto->SpellFamilyFlags[1] & 0x2)
- {
- // Glyph of Shadow Word: Death
- if (AuraEffect* aurEff = GetAuraEffect(55682, 1))
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
- break;
- case SPELLFAMILY_PALADIN:
- // Judgement of Vengeance/Judgement of Corruption
- if ((spellProto->SpellFamilyFlags[1] & 0x400000) && spellProto->SpellIconID == 2292)
- {
- // Get stack of Holy Vengeance/Blood Corruption on the target added by caster
- uint32 stacks = 0;
- Unit::AuraEffectList const& auras = victim->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
- for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- if (((*itr)->GetId() == 31803 || (*itr)->GetId() == 53742) && (*itr)->GetCasterGUID() == GetGUID())
- {
- stacks = (*itr)->GetBase()->GetStackAmount();
- break;
- }
- // + 10% for each application of Holy Vengeance/Blood Corruption on the target
- if (stacks)
- AddPct(DoneTotalMod, 10 * stacks);
- }
- break;
- case SPELLFAMILY_DRUID:
- // Thorns
- if (spellProto->SpellFamilyFlags[0] & 0x100)
- {
- // Brambles
- if (AuraEffect* aurEff = GetAuraEffectOfRankedSpell(16836, 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
break;
case SPELLFAMILY_WARLOCK:
// Fire and Brimstone
@@ -10172,59 +9122,17 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
// Drain Soul - increased damage for targets under 25 % HP
if (spellProto->SpellFamilyFlags[0] & 0x00004000)
if (HasAura(100001))
- DoneTotalMod *= 4;
- // Shadow Bite (15% increase from each dot)
+ DoneTotalMod *= 2;
+ // Shadow Bite (30% increase from each dot)
if (spellProto->SpellFamilyFlags[1] & 0x00400000 && isPet())
if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
- AddPct(DoneTotalMod, 15 * count);
- break;
- case SPELLFAMILY_HUNTER:
- // Steady Shot
- if (spellProto->SpellFamilyFlags[1] & 0x1)
- if (AuraEffect* aurEff = GetAuraEffect(56826, 0)) // Glyph of Steady Shot
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_HUNTER, 0x00004000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
+ AddPct(DoneTotalMod, 30 * count);
break;
case SPELLFAMILY_DEATHKNIGHT:
- // Improved Icy Touch
- if (spellProto->SpellFamilyFlags[0] & 0x2)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
// Sigil of the Vengeful Heart
if (spellProto->SpellFamilyFlags[0] & 0x2000)
if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1))
- AddPct(DoneTotal, aurEff->GetAmount());
-
- // Glacier Rot
- if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
- if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
- // Impurity (dummy effect)
- if (GetTypeId() == TYPEID_PLAYER)
- {
- PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
- {
- if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
- continue;
- switch (itr->first)
- {
- case 49220:
- case 49633:
- case 49635:
- case 49636:
- case 49638:
- {
- if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
- AddPct(ApCoeffMod, proto->Effects[0].CalcValue());
- }
- break;
- }
- }
- }
+ DoneTotal += aurEff->GetAmount();
break;
}
@@ -10321,8 +9229,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
{
if (GetTypeId() != TYPEID_PLAYER)
continue;
- float mod = ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE) * (-8.0f);
- AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
+ AddPct(TakenTotalMod, (*i)->GetAmount());
}
break;
}
@@ -10331,7 +9238,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
- if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
// Mod damage from spell mechanic
@@ -10406,6 +9313,10 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
// Base value
DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
+ // Check if we are ever using mana - PaperDollFrame.lua
+ if (GetPowerIndex(POWER_MANA) != MAX_POWERS)
+ DoneAdvertisedBenefit += std::max(0, int32(GetStat(STAT_INTELLECT)) - 10); // spellpower from intellect
+
// Damage bonus from stats
AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i)
@@ -10488,24 +9399,21 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
crit_chance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask);
// Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
- ApplyResilience(victim, &crit_chance, NULL, false, CR_CRIT_TAKEN_SPELL);
}
// scripted (increase crit chance ... against ... target by x%
AuraEffectList const& mOverrideClassScript = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!((*i)->IsAffectedOnSpell(spellProto)))
+ if (!((*i)->IsAffectingSpell(spellProto)))
continue;
- int32 modChance = 0;
+
switch ((*i)->GetMiscValue())
{
- // Shatter
- case 911: modChance+= 16;
- case 910: modChance+= 17;
- case 849: modChance+= 17;
+ // Shatter
+ case 911:
if (!victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
break;
- crit_chance+=modChance;
+ AddPct(crit_chance, (*i)->GetAmount()*20);
break;
case 7917: // Glyph of Shadowburn
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
@@ -10631,13 +9539,18 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
+ AuraEffectList const& critAuras = victim->GetAuraEffectsByType(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER);
+ for (AuraEffectList::const_iterator i = critAuras.begin(); i != critAuras.end(); ++i)
+ if ((*i)->GetCasterGUID() == GetGUID() && (*i)->IsAffectingSpell(spellProto))
+ crit_chance += (*i)->GetAmount();
+
crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f;
if (roll_chance_f(crit_chance))
return true;
return false;
}
-uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* /*victim*/)
{
// Calculate critical bonus
int32 crit_bonus = damage;
@@ -10657,9 +9570,6 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
crit_mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100;
- if (victim)
- crit_mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, victim->GetCreatureTypeMask());
-
if (crit_bonus != 0)
AddPct(crit_bonus, crit_mod);
@@ -10677,30 +9587,12 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
return crit_bonus;
}
-uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* /*spellProto*/, uint32 damage, Unit* /*victim*/)
{
// Calculate critical bonus
- int32 crit_bonus;
- switch (spellProto->DmgClass)
- {
- case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
- case SPELL_DAMAGE_CLASS_RANGED:
- /// @todo write here full calculation for melee/ranged spells
- crit_bonus = damage;
- break;
- default:
- crit_bonus = damage / 2; // for spells is 50%
- break;
- }
-
- if (victim)
- {
- uint32 creatureTypeMask = victim->GetCreatureTypeMask();
- crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
- }
+ int32 crit_bonus = damage;
- if (crit_bonus > 0)
- damage += crit_bonus;
+ damage += crit_bonus;
damage = int32(float(damage) * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
@@ -10731,7 +9623,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
switch ((*i)->GetMiscValue())
{
@@ -10746,12 +9638,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
if (victim->HealthBelowPct(50))
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
- case 7798: // Glyph of Regrowth
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
case 8477: // Nourish Heal Boost
{
int32 stepPercent = (*i)->GetAmount();
@@ -10771,12 +9657,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
AddPct(DoneTotalMod, modPercent);
break;
}
- case 7871: // Glyph of Lesser Healing Wave
- {
- if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
default:
break;
}
@@ -10828,10 +9708,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
coeff /= 100.0f;
}
- // Earthliving - 0.45% of normal hot coeff
- if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
- factorMod *= 0.45f;
-
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
@@ -10890,18 +9766,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
TakenTotalMod *= 1.2f;
}
- if (damagetype == DOT)
- {
- // Healing over time taken percent
- float minval_hot = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT));
- if (minval_hot)
- AddPct(TakenTotalMod, minval_hot);
-
- float maxval_hot = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT));
- if (maxval_hot)
- AddPct(TakenTotalMod, maxval_hot);
- }
-
// Check for table values
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
float coeff = 0;
@@ -10932,16 +9796,12 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
coeff /= 100.0f;
}
- // Earthliving - 0.45% of normal hot coeff
- if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
- factorMod *= 0.45f;
-
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
}
AuraEffectList const& mHealingGet= GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED);
for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
- if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -10978,6 +9838,10 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
// Base value
advertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
+ // Check if we are ever using mana - PaperDollFrame.lua
+ if (GetPowerIndex(POWER_MANA) != MAX_POWERS)
+ advertisedBenefit += std::max(0, int32(GetStat(STAT_INTELLECT)) - 10); // spellpower from intellect
+
// Healing bonus from stats
AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i)
@@ -11242,80 +10106,13 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
AddPct(DoneTotalMod, (*i)->GetAmount());
- // done scripted mod (take it from owner)
- Unit* owner = GetOwner() ? GetOwner() : this;
- AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
- {
- if (!(*i)->IsAffectedOnSpell(spellProto))
- continue;
-
- switch ((*i)->GetMiscValue())
- {
- // Tundra Stalker
- // Merciless Combat
- case 7277:
- {
- // Merciless Combat
- if ((*i)->GetSpellInfo()->SpellIconID == 2656)
- {
- if (!victim->HealthAbovePct(35))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- // Tundra Stalker
- else
- {
- // Frost Fever (target debuff)
- if (victim->HasAura(55095))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- break;
- }
- // Rage of Rivendare
- case 7293:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
- AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
- break;
- }
- // Marked for Death
- case 7598:
- case 7599:
- case 7600:
- case 7601:
- case 7602:
- {
- if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Dirty Deeds
- case 6427:
- case 6428:
- {
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
- {
- // effect 0 has expected value but in negative state
- int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
- AddPct(DoneTotalMod, bonus);
- }
- break;
- }
- }
- }
-
- // Custom scripted damage
+ // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
if (spellProto)
- switch (spellProto->SpellFamilyName)
- {
- case SPELLFAMILY_DEATHKNIGHT:
- // Glacier Rot
- if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
- if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
- AddPct(DoneTotalMod, aurEff->GetAmount());
- break;
- }
+ AddPct(DoneTotalMod, GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC, spellProto->Mechanic));
+
+ // done scripted mod (take it from owner)
+ // Unit* owner = GetOwner() ? GetOwner() : this;
+ // AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod;
@@ -11368,7 +10165,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
- if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
// Mod damage from spell mechanic
@@ -11399,7 +10196,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
{
if (GetTypeId() != TYPEID_PLAYER)
continue;
- float mod = ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE) * (-8.0f);
+ float mod = ToPlayer()->GetRatingBonusValue(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN) * (-8.0f);
AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
}
break;
@@ -11549,8 +10346,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
data << uint32(VehicleId);
SendMessageToSet(&data, true);
- data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
- player->GetSession()->SendPacket(&data);
+ player->SendOnCancelExpectedVehicleRideAura();
// mounts can also have accessories
GetVehicleKit()->InstallAllAccessories(false);
@@ -11569,11 +10365,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
player->UnsummonPetTemporaryIfAny();
}
- WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
- data.append(GetPackGUID());
- data << uint32(sWorld->GetGameTime()); // Packet counter
- data << player->GetCollisionHeight(true);
- player->GetSession()->SendPacket(&data);
+ player->SendMovementSetCollisionHeight(player->GetCollisionHeight(true));
}
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
@@ -11588,13 +10380,7 @@ void Unit::Dismount()
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT);
if (Player* thisPlayer = ToPlayer())
- {
- WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
- data.append(GetPackGUID());
- data << uint32(sWorld->GetGameTime()); // Packet counter
- data << thisPlayer->GetCollisionHeight(false);
- thisPlayer->GetSession()->SendPacket(&data);
- }
+ thisPlayer->SendMovementSetCollisionHeight(thisPlayer->GetCollisionHeight(false));
WorldPacket data(SMSG_DISMOUNT, 8);
data.appendPackGUID(GetGUID());
@@ -11629,6 +10415,64 @@ void Unit::Dismount()
}
}
+MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
+{
+ if (!mountType)
+ return NULL;
+
+ MountTypeEntry const* mountTypeEntry = sMountTypeStore.LookupEntry(mountType);
+ if (!mountTypeEntry)
+ return NULL;
+
+ uint32 zoneId, areaId;
+ GetZoneAndAreaId(zoneId, areaId);
+ uint32 ridingSkill = 5000;
+ if (GetTypeId() == TYPEID_PLAYER)
+ ridingSkill = ToPlayer()->GetSkillValue(SKILL_RIDING);
+
+ for (uint32 i = MAX_MOUNT_CAPABILITIES; i > 0; --i)
+ {
+ MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(mountTypeEntry->MountCapability[i - 1]);
+ if (!mountCapability)
+ continue;
+
+ if (ridingSkill < mountCapability->RequiredRidingSkill)
+ continue;
+
+ if (HasExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING))
+ {
+ if (!(mountCapability->Flags & MOUNT_FLAG_CAN_PITCH))
+ continue;
+ }
+ else if (HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
+ {
+ if (!(mountCapability->Flags & MOUNT_FLAG_CAN_SWIM))
+ continue;
+ }
+ else if (!(mountCapability->Flags & 0x1)) // unknown flags, checked in 4.2.2 14545 client
+ {
+ if (!(mountCapability->Flags & 0x2))
+ continue;
+ }
+
+ if (mountCapability->RequiredMap != -1 && int32(GetMapId()) != mountCapability->RequiredMap)
+ continue;
+
+ if (mountCapability->RequiredArea && (mountCapability->RequiredArea != zoneId && mountCapability->RequiredArea != areaId))
+ continue;
+
+ if (mountCapability->RequiredAura && !HasAura(mountCapability->RequiredAura))
+ continue;
+
+ if (mountCapability->RequiredSpell && (GetTypeId() != TYPEID_PLAYER || !ToPlayer()->HasSpell(mountCapability->RequiredSpell)))
+ continue;
+
+ return mountCapability;
+ }
+
+ return NULL;
+}
+
bool Unit::isServiceProvider() const
{
return HasFlag(UNIT_NPC_FLAGS,
@@ -11832,13 +10676,17 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UBER))
return false;
}
+
// check flags
if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_UNK_16)
|| (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
- || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
- || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))
+ || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)))
+ return false;
+
+ if ((!bySpell || !(bySpell->AttributesEx8 & SPELL_ATTR8_ATTACK_IGNORE_IMMUNE_TO_PC_FLAG))
+ && (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))
// check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
- || (GetEntry() != WORLD_TRIGGER && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)))
+ && GetEntry() != WORLD_TRIGGER)
return false;
// CvC case - can attack each other only when one of them is hostile
@@ -12069,16 +10917,16 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
if (dVal == 0)
return 0;
- int32 curPower = (int32)GetPower(power);
+ int32 curPower = GetPower(power);
int32 val = dVal + curPower;
- if (val <= 0)
+ if (val <= GetMinPower(power))
{
- SetPower(power, 0);
+ SetPower(power, GetMinPower(power));
return -curPower;
}
- int32 maxPower = (int32)GetMaxPower(power);
+ int32 maxPower = GetMaxPower(power);
if (val < maxPower)
{
@@ -12100,7 +10948,7 @@ int32 Unit::ModifyPowerPct(Powers power, float pct, bool apply)
float amount = (float)GetMaxPower(power);
ApplyPercentModFloatVar(amount, pct, apply);
- return ModifyPower(power, (int32)amount - (int32)GetMaxPower(power));
+ return ModifyPower(power, (int32)amount - GetMaxPower(power));
}
uint32 Unit::GetAttackTime(WeaponAttackType att) const
@@ -12313,100 +11161,35 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
propagateSpeedChange();
- WorldPacket data;
- if (!forced)
+ static Opcodes const moveTypeToOpcode[MAX_MOVE_TYPE][3] =
+ {
+ {SMSG_SPLINE_MOVE_SET_WALK_SPEED, SMSG_MOVE_SET_WALK_SPEED, SMSG_MOVE_UPDATE_WALK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_RUN_SPEED, SMSG_MOVE_SET_RUN_SPEED, SMSG_MOVE_UPDATE_RUN_SPEED },
+ {SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_UPDATE_RUN_BACK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_SWIM_SPEED, SMSG_MOVE_SET_SWIM_SPEED, SMSG_MOVE_UPDATE_SWIM_SPEED },
+ {SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_UPDATE_SWIM_BACK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_TURN_RATE, SMSG_MOVE_SET_TURN_RATE, SMSG_MOVE_UPDATE_TURN_RATE },
+ {SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_UPDATE_FLIGHT_SPEED },
+ {SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED},
+ {SMSG_SPLINE_MOVE_SET_PITCH_RATE, SMSG_MOVE_SET_PITCH_RATE, SMSG_MOVE_UPDATE_PITCH_RATE },
+ };
+
+ if (GetTypeId() == TYPEID_PLAYER)
{
- switch (mtype)
- {
- case MOVE_WALK:
- data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_RUN:
- data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM:
- data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_TURN_RATE:
- data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_FLIGHT:
- data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_FLIGHT_BACK:
- data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_PITCH_RATE:
- data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
- break;
- default:
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
+ // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
+ // and do it only for real sent packets and use run for run/mounted as client expected
+ ++ToPlayer()->m_forced_speed_changes[mtype];
- BuildMovementPacket(&data);
- data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
+ if (!isInCombat())
+ if (Pet* pet = ToPlayer()->GetPet())
+ pet->SetSpeed(mtype, m_speed_rate[mtype], forced);
}
- else
- {
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
- // and do it only for real sent packets and use run for run/mounted as client expected
- ++ToPlayer()->m_forced_speed_changes[mtype];
- if (!isInCombat())
- if (Pet* pet = ToPlayer()->GetPet())
- pet->SetSpeed(mtype, m_speed_rate[mtype], forced);
- }
+ static MovementStatusElements const speedVal = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&speedVal);
+ extra.Data.floatData = GetSpeed(mtype);
- switch (mtype)
- {
- case MOVE_WALK:
- data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
- break;
- case MOVE_RUN:
- data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM:
- data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_TURN_RATE:
- data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
- break;
- case MOVE_FLIGHT:
- data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
- break;
- case MOVE_FLIGHT_BACK:
- data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_PITCH_RATE:
- data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
- break;
- default:
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
- data.append(GetPackGUID());
- data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
- if (mtype == MOVE_RUN)
- data << uint8(0); // new 2.1.0
- data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
- }
+ Movement::PacketSender(this, moveTypeToOpcode[mtype][0], moveTypeToOpcode[mtype][1], moveTypeToOpcode[mtype][2], &extra).Send();
}
void Unit::setDeathState(DeathState s)
@@ -12852,20 +11635,6 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
}
break;
- case SPELLFAMILY_PALADIN:
- if ((spellProto->SpellFamilyFlags[0] & 0x00000002) && spellProto->SpellIconID == 298)
- {
- // Glyph of Blessing of Might
- if (AuraEffect* aurEff = GetAuraEffect(57958, 0))
- duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
- }
- else if ((spellProto->SpellFamilyFlags[0] & 0x00010000) && spellProto->SpellIconID == 306)
- {
- // Glyph of Blessing of Wisdom
- if (AuraEffect* aurEff = GetAuraEffect(57979, 0))
- duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
- }
- break;
}
}
return std::max(duration, 0);
@@ -13046,7 +11815,7 @@ uint32 Unit::GetCreatureType() const
if (GetTypeId() == TYPEID_PLAYER)
{
ShapeshiftForm form = GetShapeshiftForm();
- SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->creatureType > 0)
return ssEntry->creatureType;
else
@@ -13070,7 +11839,7 @@ void Unit::SetShapeshiftForm(ShapeshiftForm form)
bool Unit::IsInFeralForm() const
{
ShapeshiftForm form = GetShapeshiftForm();
- return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR;
+ return form == FORM_CAT || form == FORM_BEAR;
}
bool Unit::IsInDisallowedMountForm() const
@@ -13126,7 +11895,6 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
case UNIT_MOD_RAGE:
case UNIT_MOD_FOCUS:
case UNIT_MOD_ENERGY:
- case UNIT_MOD_HAPPINESS:
case UNIT_MOD_RUNE:
case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break;
@@ -13246,8 +12014,7 @@ Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const
case UNIT_MOD_RAGE: return POWER_RAGE;
case UNIT_MOD_FOCUS: return POWER_FOCUS;
case UNIT_MOD_ENERGY: return POWER_ENERGY;
- case UNIT_MOD_HAPPINESS: return POWER_HAPPINESS;
- case UNIT_MOD_RUNE: return POWER_RUNE;
+ case UNIT_MOD_RUNE: return POWER_RUNES;
case UNIT_MOD_RUNIC_POWER: return POWER_RUNIC_POWER;
default:
case UNIT_MOD_MANA: return POWER_MANA;
@@ -13258,14 +12025,14 @@ float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const
{
if (attType == RANGED_ATTACK)
{
- int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS);
+ int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER);
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER));
}
else
{
- int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS);
+ int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER);
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER));
@@ -13358,22 +12125,45 @@ void Unit::SetMaxHealth(uint32 val)
SetHealth(val);
}
-void Unit::SetPower(Powers power, uint32 val)
+int32 Unit::GetPower(Powers power) const
+{
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return 0;
+
+ return GetUInt32Value(UNIT_FIELD_POWER1 + powerIndex);
+}
+
+int32 Unit::GetMaxPower(Powers power) const
{
- if (GetPower(power) == val)
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return 0;
+
+ return GetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex);
+}
+
+void Unit::SetPower(Powers power, int32 val)
+{
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
return;
- uint32 maxPower = GetMaxPower(power);
+ int32 maxPower = int32(GetMaxPower(power));
if (maxPower < val)
val = maxPower;
- SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
+ SetInt32Value(UNIT_FIELD_POWER1 + powerIndex, val);
- WorldPacket data(SMSG_POWER_UPDATE);
- data.append(GetPackGUID());
- data << uint8(power);
- data << uint32(val);
- SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
+ if (IsInWorld())
+ {
+ WorldPacket data(SMSG_POWER_UPDATE, 8 + 4 + 1 + 4);
+ data.append(GetPackGUID());
+ data << uint32(1); //power count
+ data << uint8(powerIndex);
+ data << int32(val);
+ SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
+ }
// group update
if (Player* player = ToPlayer())
@@ -13389,17 +12179,17 @@ void Unit::SetPower(Powers power, uint32 val)
if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
}
-
- // Update the pet's character sheet with happiness damage bonus
- if (pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
- pet->UpdateDamagePhysical(BASE_ATTACK);
}
}
-void Unit::SetMaxPower(Powers power, uint32 val)
+void Unit::SetMaxPower(Powers power, int32 val)
{
- uint32 cur_power = GetPower(power);
- SetStatInt32Value(UNIT_FIELD_MAXPOWER1 + power, val);
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return;
+
+ int32 cur_power = GetPower(power);
+ SetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex, val);
// group update
if (GetTypeId() == TYPEID_PLAYER)
@@ -13421,19 +12211,45 @@ void Unit::SetMaxPower(Powers power, uint32 val)
SetPower(power, val);
}
-uint32 Unit::GetCreatePowers(Powers power) const
+uint32 Unit::GetPowerIndex(uint32 powerType) const
+{
+ /// This is here because hunter pets are of the warrior class.
+ /// With the current implementation, the core only gives them
+ /// POWER_RAGE, so we enforce the class to hunter so that they
+ /// effectively get focus power.
+ uint32 classId = getClass();
+ if (ToPet() && ToPet()->getPetType() == HUNTER_PET)
+ classId = CLASS_HUNTER;
+
+ return GetPowerIndexByClass(powerType, classId);
+}
+
+int32 Unit::GetCreatePowers(Powers power) const
{
- // Only hunter pets have POWER_FOCUS and POWER_HAPPINESS
switch (power)
{
- case POWER_MANA: return GetCreateMana();
- case POWER_RAGE: return 1000;
- case POWER_FOCUS: return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100);
- case POWER_ENERGY: return 100;
- case POWER_HAPPINESS: return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 1050000);
- case POWER_RUNIC_POWER: return 1000;
- case POWER_RUNE: return 0;
- case POWER_HEALTH: return 0;
+ case POWER_MANA:
+ return GetCreateMana();
+ case POWER_RAGE:
+ return 1000;
+ case POWER_FOCUS:
+ if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_HUNTER)
+ return 100;
+ return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100);
+ case POWER_ENERGY:
+ return 100;
+ case POWER_RUNIC_POWER:
+ return 1000;
+ case POWER_RUNES:
+ return 0;
+ case POWER_SOUL_SHARDS:
+ return 3;
+ case POWER_ECLIPSE:
+ return 100;
+ case POWER_HOLY_POWER:
+ return 3;
+ case POWER_HEALTH:
+ return 0;
default:
break;
}
@@ -13844,6 +12660,7 @@ bool InitTriggerAuraData()
isNonTriggerAura[i] = false;
isAlwaysTriggeredAura[i] = false;
}
+ isTriggerAura[SPELL_AURA_PROC_ON_POWER_AMOUNT] = true;
isTriggerAura[SPELL_AURA_DUMMY] = true;
isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true;
isTriggerAura[SPELL_AURA_MOD_THREAT] = true;
@@ -13873,6 +12690,7 @@ bool InitTriggerAuraData()
isTriggerAura[SPELL_AURA_MOD_MECHANIC_RESISTANCE] = true;
isTriggerAura[SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS] = true;
isTriggerAura[SPELL_AURA_MOD_MELEE_HASTE] = true;
+ isTriggerAura[SPELL_AURA_MOD_MELEE_HASTE_3] = true;
isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE] = true;
isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE] = true;
isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE] = true;
@@ -13942,19 +12760,6 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
// For melee/ranged based attack need update skills and set some Aura states if victim present
if (procFlag & MELEE_BASED_TRIGGER_MASK && target)
{
- // Update skills here for players
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // On melee based hit/miss/resist need update skill (for victim and attacker)
- if (procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))
- {
- if (target->GetTypeId() != TYPEID_PLAYER && target->GetCreatureType() != CREATURE_TYPE_CRITTER)
- ToPlayer()->UpdateCombatSkills(target, attType, isVictim);
- }
- // Update defence if player is victim and parry/dodge/block
- else if (isVictim && procExtra & (PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))
- ToPlayer()->UpdateCombatSkills(target, attType, true);
- }
// If exist crit/parry/dodge/block need update aura state (for victim and attacker)
if (procExtra & (PROC_EX_CRITICAL_HIT|PROC_EX_PARRY|PROC_EX_DODGE|PROC_EX_BLOCK))
{
@@ -14136,6 +12941,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
switch (triggeredByAura->GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
+ case SPELL_AURA_PROC_TRIGGER_SPELL_2:
{
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
// Don`t drop charge or add cooldown for not started trigger
@@ -14161,10 +12967,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
takeCharges = true;
break;
}
+ case SPELL_AURA_PROC_ON_POWER_AMOUNT:
+ {
+ TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleAuraProcOnPowerAmount(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
case SPELL_AURA_OBS_MOD_POWER:
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
case SPELL_AURA_MOD_MELEE_HASTE:
+ case SPELL_AURA_MOD_MELEE_HASTE_3:
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());
takeCharges = true;
break;
@@ -14449,21 +13263,12 @@ void Unit::StopMoving()
{
ClearUnitState(UNIT_STATE_MOVING);
- // not need send any packets if not in world
- if (!IsInWorld())
+ // not need send any packets if not in world or not moving
+ if (!IsInWorld() || movespline->Finalized())
return;
Movement::MoveSplineInit init(this);
- init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), false);
- init.SetFacing(GetOrientation());
- init.Launch();
-}
-
-void Unit::SendMovementFlagUpdate(bool self /* = false */)
-{
- WorldPacket data;
- BuildHeartBeatMsg(&data);
- SendMessageToSet(&data, self);
+ init.Stop();
}
bool Unit::IsSitState() const
@@ -14651,11 +13456,27 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val, !apply);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ if (att == BASE_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE, val, !apply);
+ else if (att == RANGED_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, val, !apply);
+ }
}
else
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply);
ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, -val, apply);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ if (att == BASE_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE, -val, apply);
+ else if (att == RANGED_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, -val, apply);
+ }
}
m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct);
}
@@ -14663,9 +13484,15 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
void Unit::ApplyCastTimePercentMod(float val, bool apply)
{
if (val > 0)
+ {
ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, val, !apply);
+ ApplyPercentModFloatValue(UNIT_MOD_CAST_HASTE, val, !apply);
+ }
else
+ {
ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, -val, apply);
+ ApplyPercentModFloatValue(UNIT_MOD_CAST_HASTE, -val, apply);
+ }
}
uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const
@@ -14845,11 +13672,6 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
}
}
-bool Unit::IsUnderLastManaUseEffect() const
-{
- return getMSTimeDiff(m_lastManaUse, getMSTime()) < 5000;
-}
-
void Unit::SetContestedPvP(Player* attackedPlayer)
{
Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
@@ -15154,6 +13976,21 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura)
return true;
}
+void Unit::SendDurabilityLoss(Player* receiver, uint32 percent)
+{
+ WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 4);
+ data << uint32(percent);
+ receiver->GetSession()->SendPacket(&data);
+}
+
+void Unit::PlayOneShotAnimKit(uint32 id)
+{
+ WorldPacket data(SMSG_PLAY_ONE_SHOT_ANIM_KIT, 7+2);
+ data.appendPackGUID(GetGUID());
+ data << uint16(id);
+ SendMessageToSet(&data, true);
+}
+
void Unit::Kill(Unit* victim, bool durabilityLoss)
{
// Prevent killing unit twice (and giving reward from kill twice)
@@ -15253,7 +14090,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
if (player)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim);
// if talent known but not triggered (check priest class for speedup check)
bool spiritOfRedemption = false;
@@ -15309,11 +14146,13 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// only if not player and not controlled by player pet. And not at BG
if ((durabilityLoss && !player && !victim->ToPlayer()->InBattleground()) || (player && sWorld->getBoolConfig(CONFIG_DURABILITY_LOSS_IN_PVP)))
{
- TC_LOG_DEBUG(LOG_FILTER_UNITS, "We are dead, losing %f percent durability", sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH));
- plrVictim->DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH), false);
+ double baseLoss = sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH);
+ uint32 loss = uint32(baseLoss - (baseLoss * plrVictim->GetTotalAuraMultiplier(SPELL_AURA_MOD_DURABILITY_LOSS)));
+ TC_LOG_DEBUG(LOG_FILTER_UNITS, "We are dead, losing %u percent durability", loss);
+ // Durability loss is calculated more accurately again for each item in Player::DurabilityLoss
+ plrVictim->DurabilityLossAll(baseLoss, false);
// durability lost message
- WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0);
- plrVictim->GetSession()->SendPacket(&data);
+ SendDurabilityLoss(plrVictim, loss);
}
// Call KilledUnit for creatures
if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
@@ -15529,6 +14368,63 @@ void Unit::SetControlled(bool apply, UnitState state)
}
}
+void Unit::SendMoveRoot(uint32 value)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_MOVE_ROOT, 1 + 8 + 4);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[5]);
+
+ data << uint32(value);
+
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[6]);
+
+ SendMessageToSet(&data, true);
+}
+
+void Unit::SendMoveUnroot(uint32 value)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_MOVE_UNROOT, 1 + 8 + 4);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[6]);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(value);
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+
+ SendMessageToSet(&data, true);
+}
+
void Unit::SetStunned(bool apply)
{
if (apply)
@@ -15548,10 +14444,7 @@ void Unit::SetStunned(bool apply)
else
SetStandState(UNIT_STAND_STATE_STAND);
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
- data.append(GetPackGUID());
- data << uint32(0);
- SendMessageToSet(&data, true);
+ SendMoveRoot(0);
CastStop();
}
@@ -15567,11 +14460,7 @@ void Unit::SetStunned(bool apply)
if (!HasUnitState(UNIT_STATE_ROOT)) // prevent moving if it also has root effect
{
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
- data.append(GetPackGUID());
- data << uint32(0);
- SendMessageToSet(&data, true);
-
+ SendMoveUnroot(0);
RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
}
}
@@ -15581,9 +14470,6 @@ void Unit::SetRooted(bool apply)
{
if (apply)
{
- if (m_rootTimes > 0) // blizzard internal check?
- m_rootTimes++;
-
// MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
// this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
// setting MOVEMENTFLAG_ROOT
@@ -15591,18 +14477,30 @@ void Unit::SetRooted(bool apply)
AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
if (GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- data.append(GetPackGUID());
- data << m_rootTimes;
- SendMessageToSet(&data, true);
- }
+ SendMoveRoot(m_movementCounter++);
else
{
+ ObjectGuid guid = GetGUID();
WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8);
- data.append(GetPackGUID());
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[0]);
+ data.FlushBits();
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[4]);
SendMessageToSet(&data, true);
- ToCreature()->StopMoving();
+ StopMoving();
}
}
else
@@ -15610,16 +14508,28 @@ void Unit::SetRooted(bool apply)
if (!HasUnitState(UNIT_STATE_STUNNED)) // prevent moving if it also has stun effect
{
if (GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
- data.append(GetPackGUID());
- data << ++m_rootTimes;
- SendMessageToSet(&data, true);
- }
+ SendMoveUnroot(m_movementCounter++);
else
{
+ ObjectGuid guid = GetGUID();
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
- data.append(GetPackGUID());
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[4]);
+ data.FlushBits();
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
SendMessageToSet(&data, true);
}
@@ -16170,33 +15080,43 @@ void Unit::SetAuraStack(uint32 spellId, Unit* target, uint32 stack)
aura->SetStackAmount(stack);
}
-void Unit::SendPlaySpellVisual(uint32 id)
-{
- WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 8 + 4);
- data << uint64(GetGUID());
- data << uint32(id); // SpellVisualKit.dbc index
- SendMessageToSet(&data, false);
-}
-
-void Unit::SendPlaySpellImpact(uint64 guid, uint32 id)
-{
- WorldPacket data(SMSG_PLAY_SPELL_IMPACT, 8 + 4);
- data << uint64(guid); // target
- data << uint32(id); // SpellVisualKit.dbc index
- SendMessageToSet(&data, false);
+void Unit::SendPlaySpellVisualKit(uint32 id, uint32 unkParam)
+{
+ ObjectGuid guid = GetGUID();
+
+ WorldPacket data(SMSG_PLAY_SPELL_VISUAL_KIT, 4 + 4+ 4 + 8);
+ data << uint32(0);
+ data << uint32(id); // SpellVisualKit.dbc index
+ data << uint32(unkParam);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.FlushBits();
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[5]);
+ SendMessageToSet(&data, true);
}
-void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const
+void Unit::ApplyResilience(Unit const* victim, int32* damage, bool isCrit) const
{
// player mounted on multi-passenger mount is also classified as vehicle
if (IsVehicle() || (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER))
return;
- Unit const* source = NULL;
- if (GetTypeId() == TYPEID_PLAYER)
- source = this;
- else if (GetTypeId() == TYPEID_UNIT && GetOwner() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
- source = GetOwner();
+ // Don't consider resilience if not in PvP - player or pet
+ if (!GetCharmerOrOwnerPlayerOrPlayerItself())
+ return;
Unit const* target = NULL;
if (victim->GetTypeId() == TYPEID_PLAYER)
@@ -16207,49 +15127,14 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
if (!target)
return;
- switch (type)
- {
- case CR_CRIT_TAKEN_MELEE:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetMeleeCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetMeleeCritDamageReduction(*damage);
- *damage -= target->GetMeleeDamageReduction(*damage);
- }
- break;
- case CR_CRIT_TAKEN_RANGED:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetRangedCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetRangedCritDamageReduction(*damage);
- *damage -= target->GetRangedDamageReduction(*damage);
- }
- break;
- case CR_CRIT_TAKEN_SPELL:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetSpellCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetSpellCritDamageReduction(*damage);
- *damage -= target->GetSpellDamageReduction(*damage);
- }
- break;
- default:
- break;
- }
+ if (isCrit)
+ *damage -= target->GetCritDamageReduction(*damage);
+ *damage -= target->GetDamageReduction(*damage);
}
// Melee based spells can be miss, parry or dodge on this step
// Crit or block - determined on damage calculation phase! (and can be both in some time)
-float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
+float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, uint32 spellId) const
{
//calculate miss chance
float missChance = victim->GetUnitMissChance(attType);
@@ -16257,14 +15142,6 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, i
if (!spellId && haveOffhandWeapon())
missChance += 19;
- // bonus from skills is 0.04%
- //miss_chance -= skillDiff * 0.04f;
- int32 diff = -skillDiff;
- if (victim->GetTypeId() == TYPEID_PLAYER)
- missChance += diff > 0 ? diff * 0.04f : diff * 0.02f;
- else
- missChance += diff > 10 ? 1 + (diff - 10) * 0.4f : diff * 0.1f;
-
// Calculate hit chance
float hitChance = 100.0f;
@@ -16360,11 +15237,47 @@ void Unit::UpdateObjectVisibility(bool forced)
}
}
+void Unit::SendMoveKnockBack(Player* player, float speedXY, float speedZ, float vcos, float vsin)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, (1+8+4+4+4+4+4));
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[4]);
+
+ data.WriteByteSeq(guid[1]);
+
+ data << float(vsin);
+ data << uint32(0);
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[7]);
+
+ data << float(speedXY);
+
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[3]);
+
+ data << float(speedZ);
+ data << float(vcos);
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[0]);
+
+ player->GetSession()->SendPacket(&data);
+}
+
void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
{
Player* player = NULL;
if (GetTypeId() == TYPEID_PLAYER)
- player = (Player*)this;
+ player = ToPlayer();
else if (Unit* charmer = GetCharmer())
{
player = charmer->ToPlayer();
@@ -16373,23 +15286,12 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
}
if (!player)
- {
GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
- }
else
{
float vcos, vsin;
GetSinCos(x, y, vsin, vcos);
-
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
- data.append(GetPackGUID());
- data << uint32(0); // counter
- data << float(vcos); // x direction
- data << float(vsin); // y direction
- data << float(speedXY); // Horizontal speed
- data << float(-speedZ); // Z Movement speed (vertical)
-
- player->GetSession()->SendPacket(&data);
+ SendMoveKnockBack(player, speedXY, -speedZ, vcos, vsin);
}
}
@@ -16439,6 +15341,72 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
return 892;
}
}
+ else if (getRace() == RACE_TROLL)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 0: // Red
+ case 1:
+ return 33668;
+ case 2: // Yellow
+ case 3:
+ return 33667;
+ case 4: // Blue
+ case 5:
+ case 6:
+ return 33666;
+ case 7: // Purple
+ case 10:
+ return 33665;
+ default: // original - white
+ return 33669;
+ }
+ }
+ else if (getRace() == RACE_WORGEN)
+ {
+ // Based on Skin color
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch (skinColor)
+ {
+ case 1: // Brown
+ return 33662;
+ case 2: // Black
+ case 7:
+ return 33661;
+ case 4: // yellow
+ return 33664;
+ case 3: // White
+ case 5:
+ return 33663;
+ default: // original - Gray
+ return 33660;
+ }
+ }
+ // Female
+ else
+ {
+ switch (skinColor)
+ {
+ case 5: // Brown
+ case 6:
+ return 33662;
+ case 7: // Black
+ case 8:
+ return 33661;
+ case 3: // yellow
+ case 4:
+ return 33664;
+ case 2: // White
+ return 33663;
+ default: // original - Gray
+ return 33660;
+ }
+ }
+ }
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
@@ -16473,30 +15441,32 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
}
}
// Female
- else switch (skinColor)
+ else
{
- case 10: // White
- return 29409;
- case 6: // Light Brown
- case 7:
- return 29410;
- case 4: // Brown
- case 5:
- return 29411;
- case 0: // Dark
- case 1:
- case 2:
- case 3:
- return 29412;
- default: // original - Grey
- return 8571;
+ switch (skinColor)
+ {
+ case 10: // White
+ return 29409;
+ case 6: // Light Brown
+ case 7:
+ return 29410;
+ case 4: // Brown
+ case 5:
+ return 29411;
+ case 0: // Dark
+ case 1:
+ case 2:
+ case 3:
+ return 29412;
+ default: // original - Grey
+ return 8571;
+ }
}
}
else if (Player::TeamForRace(getRace()) == ALLIANCE)
return 892;
else
return 8571;
- case FORM_DIREBEAR:
case FORM_BEAR:
// Based on Hair color
if (getRace() == RACE_NIGHTELF)
@@ -16518,6 +15488,73 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
return 2281;
}
}
+ else if (getRace() == RACE_TROLL)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 0: // Red
+ case 1:
+ return 33657;
+ case 2: // Yellow
+ case 3:
+ return 33659;
+ case 7: // Purple
+ case 10:
+ return 33656;
+ case 8: // White
+ case 9:
+ case 11:
+ case 12:
+ return 33658;
+ default: // original - Blue
+ return 33655;
+ }
+ }
+ else if (getRace() == RACE_WORGEN)
+ {
+ // Based on Skin color
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch (skinColor)
+ {
+ case 1: // Brown
+ return 33652;
+ case 2: // Black
+ case 7:
+ return 33651;
+ case 4: // Yellow
+ return 33653;
+ case 3: // White
+ case 5:
+ return 33654;
+ default: // original - Gray
+ return 33650;
+ }
+ }
+ // Female
+ else
+ {
+ switch (skinColor)
+ {
+ case 5: // Brown
+ case 6:
+ return 33652;
+ case 7: // Black
+ case 8:
+ return 33651;
+ case 3: // yellow
+ case 4:
+ return 33654;
+ case 2: // White
+ return 33653;
+ default: // original - Gray
+ return 33650;
+ }
+ }
+ }
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
@@ -16552,23 +15589,26 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
}
}
// Female
- else switch (skinColor)
+ else
{
- case 0: // Dark (Black)
- case 1:
- return 29418;
- case 2: // White
- case 3:
- return 29419;
- case 6: // Light Brown/Grey
- case 7:
- case 8:
- case 9:
- return 29420;
- case 10: // Completly White
- return 29421;
- default: // original - Brown
- return 2289;
+ switch (skinColor)
+ {
+ case 0: // Dark (Black)
+ case 1:
+ return 29418;
+ case 2: // White
+ case 3:
+ return 29419;
+ case 6: // Light Brown/Grey
+ case 7:
+ case 8:
+ case 9:
+ return 29420;
+ case 10: // Completly White
+ return 29421;
+ default: // original - Brown
+ return 2289;
+ }
}
}
else if (Player::TeamForRace(getRace()) == ALLIANCE)
@@ -16589,7 +15629,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
}
uint32 modelid = 0;
- SpellShapeshiftEntry const* formEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* formEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (formEntry && formEntry->modelID_A)
{
// Take the alliance modelid as default
@@ -16690,6 +15730,21 @@ uint32 Unit::GetModelForTotem(PlayerTotemType totemType)
}
break;
}
+ case RACE_GOBLIN:
+ {
+ switch (totemType)
+ {
+ case SUMMON_TYPE_TOTEM_FIRE: // fire
+ return 30783;
+ case SUMMON_TYPE_TOTEM_EARTH: // earth
+ return 30782;
+ case SUMMON_TYPE_TOTEM_WATER: // water
+ return 30784;
+ case SUMMON_TYPE_TOTEM_AIR: // air
+ return 30781;
+ }
+ break;
+ }
}
return 0;
}
@@ -16703,16 +15758,7 @@ void Unit::JumpTo(float speedXY, float speedZ, bool forward)
{
float vcos = std::cos(angle+GetOrientation());
float vsin = std::sin(angle+GetOrientation());
-
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
- data.append(GetPackGUID());
- data << uint32(0); // Sequence
- data << float(vcos); // x direction
- data << float(vsin); // y direction
- data << float(speedXY); // Horizontal speed
- data << float(-speedZ); // Z Movement speed (vertical)
-
- ToPlayer()->GetSession()->SendPacket(&data);
+ SendMoveKnockBack(ToPlayer(), speedXY, -speedZ, vcos, vsin);
}
}
@@ -16957,58 +16003,6 @@ void Unit::_ExitVehicle(Position const* exitPosition)
}
}
-void Unit::BuildMovementPacket(ByteBuffer *data) const
-{
- *data << uint32(GetUnitMovementFlags()); // movement flags
- *data << uint16(GetExtraUnitMovementFlags()); // 2.3.0
- *data << uint32(getMSTime()); // time / counter
- *data << GetPositionX();
- *data << GetPositionY();
- *data << GetPositionZMinusOffset();
- *data << GetOrientation();
-
- // 0x00000200
- if (GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT)
- {
- if (m_vehicle)
- data->append(m_vehicle->GetBase()->GetPackGUID());
- else if (GetTransport())
- data->append(GetTransport()->GetPackGUID());
- else
- *data << (uint8)0;
-
- *data << float (GetTransOffsetX());
- *data << float (GetTransOffsetY());
- *data << float (GetTransOffsetZ());
- *data << float (GetTransOffsetO());
- *data << uint32(GetTransTime());
- *data << uint8 (GetTransSeat());
-
- if (GetExtraUnitMovementFlags() & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
- *data << uint32(m_movementInfo.t_time2);
- }
-
- // 0x02200000
- if ((GetUnitMovementFlags() & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))
- || (m_movementInfo.flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
- *data << (float)m_movementInfo.pitch;
-
- *data << (uint32)m_movementInfo.fallTime;
-
- // 0x00001000
- if (GetUnitMovementFlags() & MOVEMENTFLAG_FALLING)
- {
- *data << (float)m_movementInfo.j_zspeed;
- *data << (float)m_movementInfo.j_sinAngle;
- *data << (float)m_movementInfo.j_cosAngle;
- *data << (float)m_movementInfo.j_xyspeed;
- }
-
- // 0x04000000
- if (GetUnitMovementFlags() & MOVEMENTFLAG_SPLINE_ELEVATION)
- *data << (float)m_movementInfo.splineElevation;
-}
-
bool Unit::IsFalling() const
{
return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR) || movespline->isFalling();
@@ -17036,20 +16030,326 @@ void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool cas
}
}
+void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusElement* extras /*= NULL*/)
+{
+ MovementInfo const& mi = m_movementInfo;
+
+ bool hasMovementFlags = GetUnitMovementFlags() != 0;
+ bool hasMovementFlags2 = GetExtraUnitMovementFlags() != 0;
+ bool hasTimestamp = true;
+ bool hasOrientation = !G3D::fuzzyEq(GetOrientation(), 0.0f);
+ bool hasTransportData = GetTransGUID() != 0;
+ bool hasSpline = IsSplineEnabled();
+
+ bool hasTransportTime2;
+ bool hasTransportTime3;
+ bool hasPitch;
+ bool hasFallData;
+ bool hasFallDirection;
+ bool hasSplineElevation;
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ hasTimestamp = m_movementInfo.time != 0;
+ hasTransportTime2 = m_movementInfo.bits.hasTransportTime2;
+ hasTransportTime3 = m_movementInfo.bits.hasTransportTime3;
+ hasPitch = m_movementInfo.bits.hasPitch;
+ hasFallData = m_movementInfo.bits.hasFallData;
+ hasFallDirection = m_movementInfo.bits.hasFallDirection;
+ hasSplineElevation = m_movementInfo.bits.hasSplineElevation;
+ }
+ else
+ {
+ hasTransportTime2 = HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT);
+ hasTransportTime3 = false;
+ hasPitch = HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
+ hasFallDirection = HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ hasFallData = hasFallDirection; // FallDirection implies that FallData is set as well
+ // the only case when hasFallData = 1 && hasFallDirection = 0
+ // is for MSG_MOVE_LAND, which is handled above, in player case
+ hasSplineElevation = HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
+ }
+
+ MovementStatusElements const* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
+ if (!sequence)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Unit::WriteMovementInfo: No movement sequence found for opcode %s", GetOpcodeNameForLogging(data.GetOpcode()).c_str());
+ return;
+ }
+
+ ObjectGuid guid = GetGUID();
+ ObjectGuid tguid = hasTransportData ? GetTransGUID() : 0;
+
+ for (; *sequence != MSEEnd; ++sequence)
+ {
+ MovementStatusElements const& element = *sequence;
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ data.WriteBit(guid[element - MSEHasGuidByte0]);
+ break;
+ case MSEHasTransportGuidByte0:
+ case MSEHasTransportGuidByte1:
+ case MSEHasTransportGuidByte2:
+ case MSEHasTransportGuidByte3:
+ case MSEHasTransportGuidByte4:
+ case MSEHasTransportGuidByte5:
+ case MSEHasTransportGuidByte6:
+ case MSEHasTransportGuidByte7:
+ if (hasTransportData)
+ data.WriteBit(tguid[element - MSEHasTransportGuidByte0]);
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ data.WriteByteSeq(guid[element - MSEGuidByte0]);
+ break;
+ case MSETransportGuidByte0:
+ case MSETransportGuidByte1:
+ case MSETransportGuidByte2:
+ case MSETransportGuidByte3:
+ case MSETransportGuidByte4:
+ case MSETransportGuidByte5:
+ case MSETransportGuidByte6:
+ case MSETransportGuidByte7:
+ if (hasTransportData)
+ data.WriteByteSeq(tguid[element - MSETransportGuidByte0]);
+ break;
+ case MSEHasMovementFlags:
+ data.WriteBit(!hasMovementFlags);
+ break;
+ case MSEHasMovementFlags2:
+ data.WriteBit(!hasMovementFlags2);
+ break;
+ case MSEHasTimestamp:
+ data.WriteBit(!hasTimestamp);
+ break;
+ case MSEHasOrientation:
+ data.WriteBit(!hasOrientation);
+ break;
+ case MSEHasTransportData:
+ data.WriteBit(hasTransportData);
+ break;
+ case MSEHasTransportTime2:
+ if (hasTransportData)
+ data.WriteBit(hasTransportTime2);
+ break;
+ case MSEHasTransportTime3:
+ if (hasTransportData)
+ data.WriteBit(hasTransportTime3);
+ break;
+ case MSEHasPitch:
+ data.WriteBit(!hasPitch);
+ break;
+ case MSEHasFallData:
+ data.WriteBit(hasFallData);
+ break;
+ case MSEHasFallDirection:
+ if (hasFallData)
+ data.WriteBit(hasFallDirection);
+ break;
+ case MSEHasSplineElevation:
+ data.WriteBit(!hasSplineElevation);
+ break;
+ case MSEHasSpline:
+ data.WriteBit(hasSpline);
+ break;
+ case MSEMovementFlags:
+ if (hasMovementFlags)
+ data.WriteBits(GetUnitMovementFlags(), 30);
+ break;
+ case MSEMovementFlags2:
+ if (hasMovementFlags2)
+ data.WriteBits(GetExtraUnitMovementFlags(), 12);
+ break;
+ case MSETimestamp:
+ if (hasTimestamp)
+ data << getMSTime();
+ break;
+ case MSEPositionX:
+ data << GetPositionX();
+ break;
+ case MSEPositionY:
+ data << GetPositionY();
+ break;
+ case MSEPositionZ:
+ data << GetPositionZ();
+ break;
+ case MSEOrientation:
+ if (hasOrientation)
+ data << GetOrientation();
+ break;
+ case MSETransportPositionX:
+ if (hasTransportData)
+ data << GetTransOffsetX();
+ break;
+ case MSETransportPositionY:
+ if (hasTransportData)
+ data << GetTransOffsetY();
+ break;
+ case MSETransportPositionZ:
+ if (hasTransportData)
+ data << GetTransOffsetZ();
+ break;
+ case MSETransportOrientation:
+ if (hasTransportData)
+ data << GetTransOffsetO();
+ break;
+ case MSETransportSeat:
+ if (hasTransportData)
+ data << GetTransSeat();
+ break;
+ case MSETransportTime:
+ if (hasTransportData)
+ data << GetTransTime();
+ break;
+ case MSETransportTime2:
+ if (hasTransportData && hasTransportTime2)
+ data << mi.t_time2;
+ break;
+ case MSETransportTime3:
+ if (hasTransportData && hasTransportTime3)
+ data << mi.t_time3;
+ break;
+ case MSEPitch:
+ if (hasPitch)
+ data << mi.pitch;
+ break;
+ case MSEFallTime:
+ if (hasFallData)
+ data << mi.fallTime;
+ break;
+ case MSEFallVerticalSpeed:
+ if (hasFallData)
+ data << mi.j_zspeed;
+ break;
+ case MSEFallCosAngle:
+ if (hasFallData && hasFallDirection)
+ data << mi.j_cosAngle;
+ break;
+ case MSEFallSinAngle:
+ if (hasFallData && hasFallDirection)
+ data << mi.j_sinAngle;
+ break;
+ case MSEFallHorizontalSpeed:
+ if (hasFallData && hasFallDirection)
+ data << mi.j_xyspeed;
+ break;
+ case MSESplineElevation:
+ if (hasSplineElevation)
+ data << mi.splineElevation;
+ break;
+ case MSECounter:
+ data << m_movementCounter++;
+ break;
+ case MSEZeroBit:
+ data.WriteBit(0);
+ break;
+ case MSEOneBit:
+ data.WriteBit(1);
+ break;
+ case MSEExtraElement:
+ extras->WriteNextElement(data);
+ break;
+ default:
+ ASSERT(Movement::PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+ }
+}
+
void Unit::SendTeleportPacket(Position& pos)
{
- Position oldPos = { GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation() };
- if (GetTypeId() == TYPEID_UNIT)
- Relocate(&pos);
+ // SMSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport
+ // MSG_MOVE_TELEPORT is sent to self in order to trigger MSG_MOVE_TELEPORT_ACK and update the position server side
+
+ // This oldPos actually contains the destination position if the Unit is a Player.
+ Position oldPos = {GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation()};
- WorldPacket data2(MSG_MOVE_TELEPORT, 38);
- data2.append(GetPackGUID());
- BuildMovementPacket(&data2);
if (GetTypeId() == TYPEID_UNIT)
- Relocate(&oldPos);
+ Relocate(&pos); // Relocate the unit to its new position in order to build the packets correctly.
+
+ ObjectGuid guid = GetGUID();
+ ObjectGuid transGuid = GetTransGUID();
+
+ WorldPacket data(SMSG_MOVE_UPDATE_TELEPORT, 38);
+ WriteMovementInfo(data);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data2(MSG_MOVE_TELEPORT, 38);
+ data2.WriteBit(guid[6]);
+ data2.WriteBit(guid[0]);
+ data2.WriteBit(guid[3]);
+ data2.WriteBit(guid[2]);
+ data2.WriteBit(0); // unknown
+ data2.WriteBit(uint64(transGuid));
+ data2.WriteBit(guid[1]);
+ if (transGuid)
+ {
+ data2.WriteBit(transGuid[1]);
+ data2.WriteBit(transGuid[3]);
+ data2.WriteBit(transGuid[2]);
+ data2.WriteBit(transGuid[5]);
+ data2.WriteBit(transGuid[0]);
+ data2.WriteBit(transGuid[7]);
+ data2.WriteBit(transGuid[6]);
+ data2.WriteBit(transGuid[4]);
+ }
+ data2.WriteBit(guid[4]);
+ data2.WriteBit(guid[7]);
+ data2.WriteBit(guid[5]);
+ data2.FlushBits();
+
+ if (transGuid)
+ {
+ data2.WriteByteSeq(transGuid[6]);
+ data2.WriteByteSeq(transGuid[5]);
+ data2.WriteByteSeq(transGuid[1]);
+ data2.WriteByteSeq(transGuid[7]);
+ data2.WriteByteSeq(transGuid[0]);
+ data2.WriteByteSeq(transGuid[2]);
+ data2.WriteByteSeq(transGuid[4]);
+ data2.WriteByteSeq(transGuid[3]);
+ }
+
+ data2 << uint32(0); // counter
+ data2.WriteByteSeq(guid[1]);
+ data2.WriteByteSeq(guid[2]);
+ data2.WriteByteSeq(guid[3]);
+ data2.WriteByteSeq(guid[5]);
+ data2 << float(GetPositionX());
+ data2.WriteByteSeq(guid[4]);
+ data2 << float(GetOrientation());
+ data2.WriteByteSeq(guid[7]);
+ data2 << float(GetPositionZMinusOffset());
+ data2.WriteByteSeq(guid[0]);
+ data2.WriteByteSeq(guid[6]);
+ data2 << float(GetPositionY());
+ ToPlayer()->SendDirectMessage(&data2); // Send the MSG_MOVE_TELEPORT packet to self.
+ }
+
+ // Relocate the player/creature to its old position, so we can broadcast to nearby players correctly
if (GetTypeId() == TYPEID_PLAYER)
Relocate(&pos);
- SendMessageToSet(&data2, false);
+ else
+ Relocate(&oldPos);
+
+ // Broadcast the packet to everyone except self.
+ SendMessageToSet(&data, false);
}
bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool teleport)
@@ -17113,7 +16413,7 @@ void Unit::SendThreatListUpdate()
{
uint32 count = getThreatManager().getThreatList().size();
- //TC_LOG_DEBUG(LOG_FILTER_UNITS, "WORLD: Send SMSG_THREAT_UPDATE Message");
+ TC_LOG_DEBUG(LOG_FILTER_UNITS, "WORLD: Send SMSG_THREAT_UPDATE Message");
WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8);
data.append(GetPackGUID());
data << uint32(count);
@@ -17165,27 +16465,22 @@ void Unit::SendRemoveFromThreatListOpcode(HostileReference* pHostileReference)
SendMessageToSet(&data, false);
}
-void Unit::RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker)
+// baseRage means damage taken when attacker = false
+void Unit::RewardRage(uint32 baseRage, bool attacker)
{
float addRage;
- float rageconversion = ((0.0091107836f * getLevel() * getLevel()) + 3.225598133f * getLevel()) + 4.2652911f;
-
- // Unknown if correct, but lineary adjust rage conversion above level 70
- if (getLevel() > 70)
- rageconversion += 13.27f * (getLevel() - 70);
-
if (attacker)
{
- addRage = (damage / rageconversion * 7.5f + weaponSpeedHitFactor) / 2;
-
+ addRage = baseRage;
// talent who gave more rage on attack
AddPct(addRage, GetTotalAuraModifier(SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT));
}
else
{
- addRage = damage / rageconversion * 2.5f;
-
+ // Calculate rage from health and damage taken
+ //! ToDo: Check formula
+ addRage = floor(0.5f + (25.7f * baseRage / GetMaxHealth()));
// Berserker Rage effect
if (HasAura(18499))
addRage *= 2.0f;
@@ -17449,70 +16744,100 @@ bool Unit::SetHover(bool enable)
void Unit::SendMovementHover()
{
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->SendMovementSetHover(HasUnitMovementFlag(MOVEMENTFLAG_HOVER));
-
- WorldPacket data(MSG_MOVE_HOVER, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
+ if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_HOVER, SMSG_MOVE_SET_HOVER).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_HOVER, SMSG_MOVE_UNSET_HOVER).Send();
}
void Unit::SendMovementWaterWalking()
{
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->SendMovementSetWaterWalking(HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING));
-
- WorldPacket data(MSG_MOVE_WATER_WALK, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
+ if (HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WATER_WALK, SMSG_MOVE_WATER_WALK).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_LAND_WALK, SMSG_MOVE_LAND_WALK).Send();
}
void Unit::SendMovementFeatherFall()
{
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->SendMovementSetFeatherFall(HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW));
+ if (HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FEATHER_FALL, SMSG_MOVE_FEATHER_FALL).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_NORMAL_FALL, SMSG_MOVE_NORMAL_FALL).Send();
+}
- WorldPacket data(MSG_MOVE_FEATHER_FALL, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
+void Unit::SendMovementCanFlyChange()
+{
+ if (HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FLYING, SMSG_MOVE_SET_CAN_FLY).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_FLYING, SMSG_MOVE_UNSET_CAN_FLY).Send();
}
-void Unit::SendMovementGravityChange()
+void Unit::SendMovementDisableGravity()
{
- WorldPacket data(MSG_MOVE_GRAVITY_CHNG, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
+ if (HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_DISABLE, SMSG_MOVE_GRAVITY_DISABLE).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_ENABLE, SMSG_MOVE_GRAVITY_ENABLE).Send();
}
-void Unit::SendMovementCanFlyChange()
+void Unit::SendMovementWalkMode()
{
- /*!
- if ( a3->MoveFlags & MOVEMENTFLAG_CAN_FLY )
- {
- v4->MoveFlags |= 0x1000000u;
- result = 1;
- }
- else
- {
- if ( v4->MoveFlags & MOVEMENTFLAG_FLYING )
- CMovement::DisableFlying(v4);
- v4->MoveFlags &= 0xFEFFFFFFu;
- result = 1;
- }
- */
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->SendMovementSetCanFly(CanFly());
+ ///@ TODO: Find proper opcode for walk mode setting in player mind controlling a player case
+ if (HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WALK_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_RUN_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send();
+}
- WorldPacket data(MSG_MOVE_UPDATE_CAN_FLY, 64);
+void Unit::SendMovementSwimming()
+{
+ if (HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_START_SWIM, NULL_OPCODE).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_STOP_SWIM, NULL_OPCODE).Send();
+}
+
+void Unit::SendSetPlayHoverAnim(bool enable)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_SET_PLAY_HOVER_ANIM, 10);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(enable);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[6]);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[6]);
+
+ SendMessageToSet(&data, true);
+}
+
+void Unit::SendMovementSetSplineAnim(Movement::AnimType anim)
+{
+ WorldPacket data(SMSG_SPLINE_MOVE_SET_ANIM, 8 + 4);
data.append(GetPackGUID());
- BuildMovementPacket(&data);
+ data << uint32(anim);
SendMessageToSet(&data, false);
}
+bool Unit::IsSplineEnabled() const
+{
+ return movespline->Initialized() && !movespline->Finalized();
+}
+
void Unit::SetTarget(uint64 guid)
{
if (!_focusSpell)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 4b2d9ccd64a..f164b04644b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -28,6 +28,7 @@
#include "Object.h"
#include "SpellAuraDefines.h"
#include "ThreatManager.h"
+#include "MoveSplineInit.h"
#define WORLD_TRIGGER 12999
@@ -210,7 +211,7 @@ enum ShapeshiftForm
FORM_BEAR = 0x05,
FORM_AMBIENT = 0x06,
FORM_GHOUL = 0x07,
- FORM_DIREBEAR = 0x08,
+ FORM_DIREBEAR = 0x08, // Removed in 4.0.1
FORM_STEVES_GHOUL = 0x09,
FORM_THARONJA_SKELETON = 0x0A,
FORM_TEST_OF_STRENGTH = 0x0B,
@@ -354,6 +355,11 @@ class Vehicle;
class VehicleJoinEvent;
class TransportBase;
class SpellCastTargets;
+namespace Movement
+{
+ class ExtraMovementStatusElement;
+ class MoveSpline;
+}
typedef std::list<Unit*> UnitList;
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
@@ -418,6 +424,7 @@ enum TriggerCastFlags
TRIGGERED_DISALLOW_PROC_EVENTS = 0x00020000, //! Disallows proc events from triggered spell (default)
TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
+ TRIGGERED_IGNORE_TARGET_CHECK = 0x00100000, //! Will ignore most target checks (mostly DBC target checks)
TRIGGERED_FULL_MASK = 0xFFFFFFFF
};
@@ -433,9 +440,13 @@ enum UnitMods
UNIT_MOD_RAGE,
UNIT_MOD_FOCUS,
UNIT_MOD_ENERGY,
- UNIT_MOD_HAPPINESS,
+ UNIT_MOD_UNUSED, // Old UNIT_MOD_HAPPINESS
UNIT_MOD_RUNE,
UNIT_MOD_RUNIC_POWER,
+ UNIT_MOD_SOUL_SHARDS,
+ UNIT_MOD_ECLIPSE,
+ UNIT_MOD_HOLY_POWER,
+ UNIT_MOD_ALTERNATIVE,
UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
UNIT_MOD_RESISTANCE_HOLY,
UNIT_MOD_RESISTANCE_FIRE,
@@ -455,7 +466,7 @@ enum UnitMods
UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
UNIT_MOD_POWER_START = UNIT_MOD_MANA,
- UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1
+ UNIT_MOD_POWER_END = UNIT_MOD_ALTERNATIVE + 1
};
enum BaseModGroup
@@ -556,34 +567,35 @@ enum WeaponAttackType
enum CombatRating
{
- CR_WEAPON_SKILL = 0,
- CR_DEFENSE_SKILL = 1,
- CR_DODGE = 2,
- CR_PARRY = 3,
- CR_BLOCK = 4,
- CR_HIT_MELEE = 5,
- CR_HIT_RANGED = 6,
- CR_HIT_SPELL = 7,
- CR_CRIT_MELEE = 8,
- CR_CRIT_RANGED = 9,
- CR_CRIT_SPELL = 10,
- CR_HIT_TAKEN_MELEE = 11,
- CR_HIT_TAKEN_RANGED = 12,
- CR_HIT_TAKEN_SPELL = 13,
- CR_CRIT_TAKEN_MELEE = 14,
- CR_CRIT_TAKEN_RANGED = 15,
- CR_CRIT_TAKEN_SPELL = 16,
- CR_HASTE_MELEE = 17,
- CR_HASTE_RANGED = 18,
- CR_HASTE_SPELL = 19,
- CR_WEAPON_SKILL_MAINHAND = 20,
- CR_WEAPON_SKILL_OFFHAND = 21,
- CR_WEAPON_SKILL_RANGED = 22,
- CR_EXPERTISE = 23,
- CR_ARMOR_PENETRATION = 24
-};
-
-#define MAX_COMBAT_RATING 25
+ CR_WEAPON_SKILL = 0,
+ CR_DEFENSE_SKILL = 1, // Removed in 4.0.1
+ CR_DODGE = 2,
+ CR_PARRY = 3,
+ CR_BLOCK = 4,
+ CR_HIT_MELEE = 5,
+ CR_HIT_RANGED = 6,
+ CR_HIT_SPELL = 7,
+ CR_CRIT_MELEE = 8,
+ CR_CRIT_RANGED = 9,
+ CR_CRIT_SPELL = 10,
+ CR_HIT_TAKEN_MELEE = 11, // Deprecated since Cataclysm
+ CR_HIT_TAKEN_RANGED = 12, // Deprecated since Cataclysm
+ CR_HIT_TAKEN_SPELL = 13, // Deprecated since Cataclysm
+ CR_RESILIENCE_CRIT_TAKEN = 14,
+ CR_RESILIENCE_PLAYER_DAMAGE_TAKEN = 15,
+ CR_CRIT_TAKEN_SPELL = 16, // Deprecated since Cataclysm
+ CR_HASTE_MELEE = 17,
+ CR_HASTE_RANGED = 18,
+ CR_HASTE_SPELL = 19,
+ CR_WEAPON_SKILL_MAINHAND = 20,
+ CR_WEAPON_SKILL_OFFHAND = 21,
+ CR_WEAPON_SKILL_RANGED = 22,
+ CR_EXPERTISE = 23,
+ CR_ARMOR_PENETRATION = 24,
+ CR_MASTERY = 25,
+};
+
+#define MAX_COMBAT_RATING 26
enum DamageEffectType
{
@@ -660,7 +672,7 @@ enum NPCFlags
{
UNIT_NPC_FLAG_NONE = 0x00000000,
UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100%
- UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok
+ UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // 100%
UNIT_NPC_FLAG_UNK1 = 0x00000004,
UNIT_NPC_FLAG_UNK2 = 0x00000008,
UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100%
@@ -684,7 +696,10 @@ enum NPCFlags
UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click)
- UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000 // players with mounts that have vehicle data should have it set
+ UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
+ UNIT_NPC_FLAG_REFORGER = 0x08000000, // reforging
+ UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x10000000, // transmogrification
+ UNIT_NPC_FLAG_VAULTKEEPER = 0x20000000 // void storage
};
enum MovementFlags
@@ -699,28 +714,26 @@ enum MovementFlags
MOVEMENTFLAG_PITCH_UP = 0x00000040,
MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
MOVEMENTFLAG_WALKING = 0x00000100, // Walking
- MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
- MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
- MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
- MOVEMENTFLAG_FALLING = 0x00001000, // damage dealt on that type of falling
- MOVEMENTFLAG_FALLING_FAR = 0x00002000,
- MOVEMENTFLAG_PENDING_STOP = 0x00004000,
- MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000,
- MOVEMENTFLAG_PENDING_FORWARD = 0x00010000,
- MOVEMENTFLAG_PENDING_BACKWARD = 0x00020000,
- MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00040000,
- MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00080000,
- MOVEMENTFLAG_PENDING_ROOT = 0x00100000,
- MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
- MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying
- MOVEMENTFLAG_DESCENDING = 0x00800000,
- MOVEMENTFLAG_CAN_FLY = 0x01000000, // Appears when unit can fly AND also walk
- MOVEMENTFLAG_FLYING = 0x02000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity
- MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
- MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
- MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
- MOVEMENTFLAG_FALLING_SLOW = 0x20000000, // active rogue safe fall spell (passive)
- MOVEMENTFLAG_HOVER = 0x40000000, // hover, cannot jump
+ MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000200, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
+ MOVEMENTFLAG_ROOT = 0x00000400, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
+ MOVEMENTFLAG_FALLING = 0x00000800, // damage dealt on that type of falling
+ MOVEMENTFLAG_FALLING_FAR = 0x00001000,
+ MOVEMENTFLAG_PENDING_STOP = 0x00002000,
+ MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00004000,
+ MOVEMENTFLAG_PENDING_FORWARD = 0x00008000,
+ MOVEMENTFLAG_PENDING_BACKWARD = 0x00010000,
+ MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00020000,
+ MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00040000,
+ MOVEMENTFLAG_PENDING_ROOT = 0x00080000,
+ MOVEMENTFLAG_SWIMMING = 0x00100000, // appears with fly flag also
+ MOVEMENTFLAG_ASCENDING = 0x00200000, // press "space" when flying
+ MOVEMENTFLAG_DESCENDING = 0x00400000,
+ MOVEMENTFLAG_CAN_FLY = 0x00800000, // Appears when unit can fly AND also walk
+ MOVEMENTFLAG_FLYING = 0x01000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity
+ MOVEMENTFLAG_SPLINE_ELEVATION = 0x02000000, // used for flight paths
+ MOVEMENTFLAG_WATERWALKING = 0x04000000, // prevent unit from falling through water
+ MOVEMENTFLAG_FALLING_SLOW = 0x08000000, // active rogue safe fall spell (passive)
+ MOVEMENTFLAG_HOVER = 0x10000000, // hover, cannot jump
/// @todo Check if PITCH_UP and PITCH_DOWN really belong here..
MOVEMENTFLAG_MASK_MOVING =
@@ -734,6 +747,12 @@ enum MovementFlags
MOVEMENTFLAG_MASK_MOVING_FLY =
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING,
+ // Movement flags allowed for creature in CreateObject - we need to keep all other enabled serverside
+ // to properly calculate all movement
+ MOVEMENTFLAG_MASK_CREATURE_ALLOWED =
+ MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_ROOT | MOVEMENTFLAG_SWIMMING |
+ MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_WATERWALKING | MOVEMENTFLAG_FALLING_SLOW | MOVEMENTFLAG_HOVER,
+
/// @todo if needed: add more flags to this masks that are exclusive to players
MOVEMENTFLAG_MASK_PLAYER_ONLY =
MOVEMENTFLAG_FLYING
@@ -743,20 +762,20 @@ enum MovementFlags2
MOVEMENTFLAG2_NONE = 0x00000000,
MOVEMENTFLAG2_NO_STRAFE = 0x00000001,
MOVEMENTFLAG2_NO_JUMPING = 0x00000002,
- MOVEMENTFLAG2_UNK3 = 0x00000004, // Overrides various clientside checks
- MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000008,
- MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000010,
- MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000020,
- MOVEMENTFLAG2_UNK7 = 0x00000040,
- MOVEMENTFLAG2_UNK8 = 0x00000080,
- MOVEMENTFLAG2_UNK9 = 0x00000100,
- MOVEMENTFLAG2_UNK10 = 0x00000200,
- MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000400,
- MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000800,
- MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00001000,
- MOVEMENTFLAG2_UNK14 = 0x00002000,
- MOVEMENTFLAG2_UNK15 = 0x00004000,
- MOVEMENTFLAG2_UNK16 = 0x00008000
+ MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000004,
+ MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000008,
+ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000010,
+ MOVEMENTFLAG2_UNK5 = 0x00000020,
+ MOVEMENTFLAG2_UNK6 = 0x00000040,
+ MOVEMENTFLAG2_UNK7 = 0x00000080,
+ MOVEMENTFLAG2_UNK8 = 0x00000100,
+ MOVEMENTFLAG2_UNK9 = 0x00000200,
+ MOVEMENTFLAG2_UNK10 = 0x00000400,
+ MOVEMENTFLAG2_UNK11 = 0x00000800,
+ MOVEMENTFLAG2_UNK12 = 0x00001000,
+ MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00002000,
+ MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00004000,
+ MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00008000
};
enum UnitTypeMask
@@ -774,10 +793,6 @@ enum UnitTypeMask
UNIT_MASK_ACCESSORY = 0x00000200
};
-namespace Movement{
- class MoveSpline;
-}
-
struct DiminishingReturn
{
DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count)
@@ -1070,7 +1085,8 @@ enum CommandStates
COMMAND_STAY = 0,
COMMAND_FOLLOW = 1,
COMMAND_ATTACK = 2,
- COMMAND_ABANDON = 3
+ COMMAND_ABANDON = 3,
+ COMMAND_MOVE_TO = 4
};
#define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF)
@@ -1370,10 +1386,11 @@ class Unit : public WorldObject
Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
void setPowerType(Powers power);
- uint32 GetPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); }
- uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); }
- void SetPower(Powers power, uint32 val);
- void SetMaxPower(Powers power, uint32 val);
+ int32 GetPower(Powers power) const;
+ int32 GetMinPower(Powers power) const { return power == POWER_ECLIPSE ? -100 : 0; }
+ int32 GetMaxPower(Powers power) const;
+ void SetPower(Powers power, int32 val);
+ void SetMaxPower(Powers power, int32 val);
// returns the change in power
int32 ModifyPower(Powers power, int32 val);
int32 ModifyPowerPct(Powers power, float pct, bool apply = true);
@@ -1419,6 +1436,10 @@ class Unit : public WorldObject
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount, uint32 vehicleId = 0, uint32 creatureEntry = 0);
void Dismount();
+ MountCapabilityEntry const* GetMountCapability(uint32 mountType) const;
+
+ void SendDurabilityLoss(Player* receiver, uint32 percent);
+ void PlayOneShotAnimKit(uint32 id);
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb);
@@ -1448,23 +1469,12 @@ class Unit : public WorldObject
void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss);
// player or player's pet resilience (-1%)
- float GetMeleeCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_MELEE); }
- float GetRangedCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_RANGED); }
- float GetSpellCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_SPELL); }
-
- // player or player's pet resilience (-1%)
- uint32 GetMeleeCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_MELEE, 2.2f, 33.0f, damage); }
- uint32 GetRangedCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_RANGED, 2.2f, 33.0f, damage); }
- uint32 GetSpellCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_SPELL, 2.2f, 33.0f, damage); }
+ uint32 GetCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_CRIT_TAKEN, 2.2f, 33.0f, damage); }
+ uint32 GetDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, 2.0f, 100.0f, damage); }
- // player or player's pet resilience (-1%), cap 100%
- uint32 GetMeleeDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_MELEE, 2.0f, 100.0f, damage); }
- uint32 GetRangedDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_RANGED, 2.0f, 100.0f, damage); }
- uint32 GetSpellDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_SPELL, 2.0f, 100.0f, damage); }
+ void ApplyResilience(Unit const* victim, int32 * damage, bool isCrit) const;
- void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const;
-
- float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
+ float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const;
SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell);
SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell);
SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false);
@@ -1477,11 +1487,10 @@ class Unit : public WorldObject
int32 GetMechanicResistChance(const SpellInfo* spell) const;
bool CanUseAttackType(uint8 attacktype) const;
- virtual uint32 GetShieldBlockValue() const =0;
- uint32 GetShieldBlockValue(uint32 soft_cap, uint32 hard_cap) const;
+ virtual uint32 GetBlockPercent() const { return 30; }
+
uint32 GetUnitMeleeSkill(Unit const* target = NULL) const;
- uint32 GetDefenseSkillValue(Unit const* target = NULL) const;
- uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const;
+
float GetWeaponProcChance() const;
float GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spellProto) const;
@@ -1542,7 +1551,7 @@ class Unit : public WorldObject
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
int32 HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical = false);
- void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powerType);
+ void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powertype);
void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
uint32 SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage);
@@ -1560,8 +1569,7 @@ class Unit : public WorldObject
Aura* AddAura(uint32 spellId, Unit* target);
Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target);
void SetAuraStack(uint32 spellId, Unit* target, uint32 stack);
- void SendPlaySpellVisual(uint32 id);
- void SendPlaySpellImpact(uint64 guid, uint32 id);
+ void SendPlaySpellVisualKit(uint32 id, uint32 unkParam);
void DeMorph();
@@ -1582,14 +1590,12 @@ class Unit : public WorldObject
void UpdateOrientation(float orientation);
void UpdateHeight(float newZ);
+ void SendMoveKnockBack(Player* player, float speedXY, float speedZ, float vcos, float vsin);
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
void JumpTo(float speedXY, float speedZ, bool forward = true);
void JumpTo(WorldObject* obj, float speedZ);
void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false);
- //void SetFacing(float ori, WorldObject* obj = NULL);
- //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
- void SendMovementFlagUpdate(bool self = false);
/*! These methods send the same packet to the client in apply and unapply case.
The client-side interpretation of this packet depends on the presence of relevant movementflags
@@ -1599,8 +1605,13 @@ class Unit : public WorldObject
void SendMovementHover();
void SendMovementFeatherFall();
void SendMovementWaterWalking();
- void SendMovementGravityChange();
void SendMovementCanFlyChange();
+ void SendMovementDisableGravity();
+ void SendMovementWalkMode();
+ void SendMovementSwimming();
+
+ void SendSetPlayHoverAnim(bool enable);
+ void SendMovementSetSplineAnim(Movement::AnimType anim);
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);}
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
@@ -1619,8 +1630,6 @@ class Unit : public WorldObject
void SendClearTarget();
- void BuildHeartBeatMsg(WorldPacket* data) const;
-
bool isAlive() const { return (m_deathState == ALIVE); }
bool isDying() const { return (m_deathState == JUST_DIED); }
bool isDead() const { return (m_deathState == DEAD || m_deathState == CORPSE); }
@@ -1816,7 +1825,8 @@ class Unit : public WorldObject
uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); }
void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); }
uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); }
- uint32 GetCreatePowers(Powers power) const;
+ uint32 GetPowerIndex(uint32 powerType) const;
+ int32 GetCreatePowers(Powers power) const;
float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); }
float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); }
float GetCreateStat(Stats stat) const { return m_createStats[stat]; }
@@ -1969,9 +1979,6 @@ class Unit : public WorldObject
uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
- void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; }
- bool IsUnderLastManaUseEffect() const;
-
void SetContestedPvP(Player* attackedPlayer = NULL);
uint32 GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const;
@@ -2030,6 +2037,7 @@ class Unit : public WorldObject
uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.flags2 & f; }
uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.flags2; }
void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; }
+ bool IsSplineEnabled() const;
float GetPositionZMinusOffset() const;
@@ -2107,7 +2115,7 @@ class Unit : public WorldObject
void _ExitVehicle(Position const* exitPosition = NULL);
void _EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp = NULL);
- void BuildMovementPacket(ByteBuffer *data) const;
+ void WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusElement* extras = NULL);
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING); }
bool isTurning() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_TURNING); }
@@ -2116,7 +2124,7 @@ class Unit : public WorldObject
bool IsFalling() const;
void SetCanFly(bool apply);
- void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
+ void RewardRage(uint32 baseRage, bool attacker);
virtual float GetFollowAngle() const { return static_cast<float>(M_PI/2); }
@@ -2222,6 +2230,7 @@ class Unit : public WorldObject
void DisableSpline();
private:
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent);
+ bool HandleAuraProcOnPowerAmount(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled);
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
@@ -2230,21 +2239,26 @@ class Unit : public WorldObject
bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);
void UpdateSplineMovement(uint32 t_diff);
+ void UpdateSplinePosition();
// player or player's pet
float GetCombatRatingReduction(CombatRating cr) const;
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
+ protected:
+ void SendMoveRoot(uint32 value);
+ void SendMoveUnroot(uint32 value);
void SetFeared(bool apply);
void SetConfused(bool apply);
void SetStunned(bool apply);
void SetRooted(bool apply);
- uint32 m_rootTimes;
+ uint32 m_movementCounter; ///< Incrementing counter used in movement packets
+
+ private:
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;
- uint32 m_lastManaUse; // msecs
TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 5cfb9cc2fae..797430683f4 100755..100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -517,10 +517,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
_me->RemoveCharmedBy(unit);
if (_me->IsInWorld())
- {
- unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
unit->m_movementInfo.ClearTransport();
- }
// only for flyable vehicles
if (unit->IsFlying())
@@ -559,6 +556,7 @@ void Vehicle::RelocatePassengers()
float px, py, pz, po;
passenger->m_movementInfo.t_pos.GetPosition(px, py, pz, po);
CalculatePassengerPosition(px, py, pz, &po);
+
passenger->UpdatePosition(px, py, pz, po);
}
}
@@ -838,7 +836,6 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
if (Seat->second.SeatInfo->m_flags && !(Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING))
Passenger->AddUnitState(UNIT_STATE_ONVEHICLE);
- Passenger->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
VehicleSeatEntry const* veSeat = Seat->second.SeatInfo;
Passenger->m_movementInfo.t_pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ);
Passenger->m_movementInfo.t_time = 0; // 1 for player
diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h
index dd73ab3a01b..55c47df86ad 100644
--- a/src/server/game/Entities/Vehicle/VehicleDefines.h
+++ b/src/server/game/Entities/Vehicle/VehicleDefines.h
@@ -32,7 +32,29 @@ enum PowerType
POWER_HEAT = 101,
POWER_OOZE = 121,
POWER_BLOOD = 141,
- POWER_WRATH = 142
+ POWER_WRATH = 142,
+ POWER_ARCANE_ENERGY = 143,
+ POWER_LIFE_ENERGY = 144,
+ POWER_SUN_ENERGY = 145,
+ POWER_SWING_VELOCITY = 146,
+ POWER_SHADOWFLAME_ENERGY = 147,
+ POWER_BLUE_POWER = 148,
+ POWER_PURPLE_POWER = 149,
+ POWER_GREEN_POWER = 150,
+ POWER_ORANGE_POWER = 151,
+ POWER_ENERGY_2 = 153,
+ POWER_ARCANEENERGY = 161,
+ POWER_WIND_POWER_1 = 162,
+ POWER_WIND_POWER_2 = 163,
+ POWER_WIND_POWER_3 = 164,
+ POWER_FUEL = 165,
+ POWER_SUN_POWER = 166,
+ POWER_TWILIGHT_ENERGY = 169,
+ POWER_VENOM = 174,
+ POWER_ORANGE_POWER_2 = 176,
+ POWER_CONSUMING_FLAME = 177,
+ POWER_PYROCLASTIC_FRENZY = 178,
+ POWER_FLASHFIRE = 179,
};
enum VehicleFlags
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 670eed672e6..54e1ca6a5d6 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -793,8 +793,8 @@ void GameEventMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5
- QueryResult result = WorldDatabase.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost FROM game_event_npc_vendor ORDER BY guid, slot ASC");
+ // 0 1 2 3 4 5 6
+ QueryResult result = WorldDatabase.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost, type FROM game_event_npc_vendor ORDER BY guid, slot ASC");
if (!result)
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 vendor additions in game events. DB table `game_event_npc_vendor` is empty.");
@@ -820,6 +820,7 @@ void GameEventMgr::LoadFromDB()
newEntry.maxcount = fields[3].GetUInt32();
newEntry.incrtime = fields[4].GetUInt32();
newEntry.ExtendedCost = fields[5].GetUInt32();
+ newEntry.Type = fields[6].GetUInt8();
// get the event npc flag for checking if the npc will be vendor during the event or not
uint32 event_npc_flag = 0;
NPCFlagList& flist = mGameEventNPCFlags[event_id];
@@ -838,7 +839,7 @@ void GameEventMgr::LoadFromDB()
newEntry.entry = data->id;
// check validity with event's npcflag
- if (!sObjectMgr->IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, NULL, NULL, event_npc_flag))
+ if (!sObjectMgr->IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, newEntry.Type, NULL, NULL, event_npc_flag))
continue;
vendors.push_back(newEntry);
@@ -1171,9 +1172,9 @@ void GameEventMgr::UpdateEventNPCVendor(uint16 event_id, bool activate)
for (NPCVendorList::iterator itr = mGameEventVendors[event_id].begin(); itr != mGameEventVendors[event_id].end(); ++itr)
{
if (activate)
- sObjectMgr->AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, false);
+ sObjectMgr->AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, itr->Type, false);
else
- sObjectMgr->RemoveVendorItem(itr->entry, itr->item, false);
+ sObjectMgr->RemoveVendorItem(itr->entry, itr->item, itr->Type, false);
}
}
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index ad4ddeeba88..994f32f75d6 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -86,6 +86,7 @@ struct NPCVendorEntry
int32 maxcount; // 0 for infinite
uint32 incrtime; // time for restore items amount if maxcount != 0
uint32 ExtendedCost;
+ uint8 Type; // 1 item, 2 currency
};
class Player;
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index afc27b74ecc..e9c8ea57ce2 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -94,6 +94,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, uint64 guid)
case HIGHGUID_UNIT: return GetCreature(p, guid);
case HIGHGUID_PET: return GetPet(p, guid);
case HIGHGUID_DYNAMICOBJECT: return GetDynamicObject(p, guid);
+ case HIGHGUID_AREATRIGGER: return GetAreaTrigger(p, guid);
case HIGHGUID_CORPSE: return GetCorpse(p, guid);
default: return NULL;
}
@@ -130,6 +131,9 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, uint64 guid, u
if (typemask & TYPEMASK_DYNAMICOBJECT)
return GetDynamicObject(p, guid);
break;
+ case HIGHGUID_AREATRIGGER:
+ if (typemask & TYPEMASK_AREATRIGGER)
+ return GetAreaTrigger(p, guid);
case HIGHGUID_CORPSE:
break;
}
@@ -152,6 +156,11 @@ DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, uint64 gui
return GetObjectInMap(guid, u.GetMap(), (DynamicObject*)NULL);
}
+AreaTrigger* ObjectAccessor::GetAreaTrigger(WorldObject const& u, uint64 guid)
+{
+ return GetObjectInMap(guid, u.GetMap(), (AreaTrigger*)NULL);
+}
+
Unit* ObjectAccessor::GetUnit(WorldObject const& u, uint64 guid)
{
return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL);
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 1abe3550729..67af4ba0218 100644
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -146,6 +146,7 @@ class ObjectAccessor
static Corpse* GetCorpse(WorldObject const& u, uint64 guid);
static GameObject* GetGameObject(WorldObject const& u, uint64 guid);
static DynamicObject* GetDynamicObject(WorldObject const& u, uint64 guid);
+ static AreaTrigger* GetAreaTrigger(WorldObject const& u, uint64 guid);
static Unit* GetUnit(WorldObject const&, uint64 guid);
static Creature* GetCreature(WorldObject const& u, uint64 guid);
static Pet* GetPet(WorldObject const&, uint64 guid);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 2290a7c088e..2fb304c52e7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -23,6 +23,8 @@
#include "Chat.h"
#include "Common.h"
#include "DatabaseEnv.h"
+#include "DB2Structure.h"
+#include "DB2Stores.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GossipDef.h"
@@ -171,7 +173,9 @@ LanguageDesc lang_description[LANGUAGES_COUNT] =
{ LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI },
{ LANG_ZOMBIE, 0, 0 },
{ LANG_GNOMISH_BINARY, 0, 0 },
- { LANG_GOBLIN_BINARY, 0, 0 }
+ { LANG_GOBLIN_BINARY, 0, 0 },
+ { LANG_WORGEN, 69270, SKILL_LANG_WORGEN },
+ { LANG_GOBLIN, 69269, SKILL_LANG_GOBLIN }
};
LanguageDesc const* GetLanguageDescByID(uint32 lang)
@@ -226,6 +230,7 @@ ObjectMgr::ObjectMgr():
_itemTextId(1),
_mailId(1),
_hiPetNumber(1),
+ _voidItemId(1),
_hiCharGuid(1),
_hiCreatureGuid(1),
_hiPetGuid(1),
@@ -234,14 +239,12 @@ ObjectMgr::ObjectMgr():
_hiGoGuid(1),
_hiDoGuid(1),
_hiCorpseGuid(1),
+ _hiAreaTriggerGuid(1),
_hiMoTransGuid(1)
{
for (uint8 i = 0; i < MAX_CLASSES; ++i)
- {
- _playerClassInfo[i] = NULL;
for (uint8 j = 0; j < MAX_RACES; ++j)
_playerInfo[j][i] = NULL;
- }
}
ObjectMgr::~ObjectMgr()
@@ -252,14 +255,6 @@ ObjectMgr::~ObjectMgr()
for (PetLevelInfoContainer::iterator i = _petInfoStore.begin(); i != _petInfoStore.end(); ++i)
delete[] i->second;
- // free only if loaded
- for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
- {
- if (_playerClassInfo[class_])
- delete[] _playerClassInfo[class_]->levelInfo;
- delete _playerClassInfo[class_];
- }
-
for (int race = 0; race < MAX_RACES; ++race)
{
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
@@ -274,6 +269,7 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear();
_cacheTrainerSpellStore.clear();
+ _graveyardOrientations.clear();
for (DungeonEncounterContainer::iterator itr =_dungeonEncounterStore.begin(); itr != _dungeonEncounterStore.end(); ++itr)
for (DungeonEncounterList::iterator encounterItr = itr->second.begin(); encounterItr != itr->second.end(); ++encounterItr)
@@ -294,6 +290,34 @@ void ObjectMgr::AddLocaleString(std::string const& s, LocaleConstant locale, Str
}
}
+void ObjectMgr::LoadGraveyardOrientations()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _graveyardOrientations.clear();
+
+ QueryResult result = WorldDatabase.Query("SELECT id, orientation FROM graveyard_orientation");
+
+ if (!result)
+ return;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ if (!sWorldSafeLocsStore.LookupEntry(id))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Graveyard %u referenced in graveyard_orientation doesn't exist.", id);
+ continue;
+ }
+ _graveyardOrientations[id] = fields[1].GetFloat();
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %lu graveyard orientations in %u ms", (unsigned long)_graveyardOrientations.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadCreatureLocales()
{
uint32 oldMSTime = getMSTime();
@@ -392,19 +416,19 @@ void ObjectMgr::LoadCreatureTemplates()
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, "
- // 9 10 11 12 13 14 15 16 17 18 19 20 21
- "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, "
- // 22 23 24 25 26 27 28 29 30 31 32 33
- "scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, "
- // 34 35 36 37 38 39 40 41 42 43
- "dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, "
- // 44 45 46 47 48 49 50 51 52 53 54
- "type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, "
- // 55 56 57 58 59 60 61 62 63 64 65 66 67
- "spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
- // 68 69 70 71 72 73 74 75 76 77 78
- "InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
- // 79 80 81 82 83 84
+ // 9 10 11 12 13 14 15 16 17 18 19 20 21
+ "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, "
+ // 22 23 24 25 26 27 28 29 30 31 32 33 34
+ "speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, "
+ // 35 36 37 38 39 40 41 42 43
+ "dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, "
+ // 44 45 46 47 48 49 50 51 52 53 54
+ "type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, "
+ // 55 56 57 58 59 60 61 62 63 64 65 66 67 68
+ "spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
+ // 69 70 71 72 73 74 75 76 77 78 79 80
+ "InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
+ // 81 82 83 84 85 86
" questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName "
"FROM creature_template;");
@@ -444,27 +468,27 @@ void ObjectMgr::LoadCreatureTemplates()
creatureTemplate.minlevel = fields[14].GetUInt8();
creatureTemplate.maxlevel = fields[15].GetUInt8();
creatureTemplate.expansion = uint32(fields[16].GetInt16());
- creatureTemplate.faction_A = uint32(fields[17].GetUInt16());
- creatureTemplate.faction_H = uint32(fields[18].GetUInt16());
- creatureTemplate.npcflag = fields[19].GetUInt32();
- creatureTemplate.speed_walk = fields[20].GetFloat();
- creatureTemplate.speed_run = fields[21].GetFloat();
- creatureTemplate.scale = fields[22].GetFloat();
- creatureTemplate.rank = uint32(fields[23].GetUInt8());
- creatureTemplate.mindmg = fields[24].GetFloat();
- creatureTemplate.maxdmg = fields[25].GetFloat();
- creatureTemplate.dmgschool = uint32(fields[26].GetInt8());
- creatureTemplate.attackpower = fields[27].GetUInt32();
- creatureTemplate.dmg_multiplier = fields[28].GetFloat();
- creatureTemplate.baseattacktime = fields[29].GetUInt32();
- creatureTemplate.rangeattacktime = fields[30].GetUInt32();
- creatureTemplate.unit_class = uint32(fields[31].GetUInt8());
- creatureTemplate.unit_flags = fields[32].GetUInt32();
- creatureTemplate.unit_flags2 = fields[33].GetUInt32();
- creatureTemplate.dynamicflags = fields[34].GetUInt32();
- creatureTemplate.family = uint32(fields[35].GetUInt8());
- creatureTemplate.trainer_type = uint32(fields[36].GetUInt8());
- creatureTemplate.trainer_spell = fields[37].GetUInt32();
+ creatureTemplate.expansionUnknown = uint32(fields[17].GetUInt16());
+ creatureTemplate.faction_A = uint32(fields[18].GetUInt16());
+ creatureTemplate.faction_H = uint32(fields[19].GetUInt16());
+ creatureTemplate.npcflag = fields[20].GetUInt32();
+ creatureTemplate.speed_walk = fields[21].GetFloat();
+ creatureTemplate.speed_run = fields[22].GetFloat();
+ creatureTemplate.scale = fields[23].GetFloat();
+ creatureTemplate.rank = uint32(fields[24].GetUInt8());
+ creatureTemplate.mindmg = fields[25].GetFloat();
+ creatureTemplate.maxdmg = fields[26].GetFloat();
+ creatureTemplate.dmgschool = uint32(fields[27].GetInt8());
+ creatureTemplate.attackpower = fields[28].GetUInt32();
+ creatureTemplate.dmg_multiplier = fields[29].GetFloat();
+ creatureTemplate.baseattacktime = fields[30].GetUInt32();
+ creatureTemplate.rangeattacktime = fields[31].GetUInt32();
+ creatureTemplate.unit_class = uint32(fields[32].GetUInt8());
+ creatureTemplate.unit_flags = fields[33].GetUInt32();
+ creatureTemplate.unit_flags2 = fields[34].GetUInt32();
+ creatureTemplate.dynamicflags = fields[35].GetUInt32();
+ creatureTemplate.family = uint32(fields[36].GetUInt8());
+ creatureTemplate.trainer_type = uint32(fields[37].GetUInt8());
creatureTemplate.trainer_class = uint32(fields[38].GetUInt8());
creatureTemplate.trainer_race = uint32(fields[39].GetUInt8());
creatureTemplate.minrangedmg = fields[40].GetFloat();
@@ -472,37 +496,39 @@ void ObjectMgr::LoadCreatureTemplates()
creatureTemplate.rangedattackpower = uint32(fields[42].GetUInt16());
creatureTemplate.type = uint32(fields[43].GetUInt8());
creatureTemplate.type_flags = fields[44].GetUInt32();
- creatureTemplate.lootid = fields[45].GetUInt32();
- creatureTemplate.pickpocketLootId = fields[46].GetUInt32();
- creatureTemplate.SkinLootId = fields[47].GetUInt32();
+ creatureTemplate.type_flags2 = fields[45].GetUInt32();
+ creatureTemplate.lootid = fields[46].GetUInt32();
+ creatureTemplate.pickpocketLootId = fields[47].GetUInt32();
+ creatureTemplate.SkinLootId = fields[48].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- creatureTemplate.resistance[i] = fields[48 + i -1].GetInt16();
+ creatureTemplate.resistance[i] = fields[49 + i - 1].GetInt16();
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
- creatureTemplate.spells[i] = fields[54 + i].GetUInt32();
-
- creatureTemplate.PetSpellDataId = fields[62].GetUInt32();
- creatureTemplate.VehicleId = fields[63].GetUInt32();
- creatureTemplate.mingold = fields[64].GetUInt32();
- creatureTemplate.maxgold = fields[65].GetUInt32();
- creatureTemplate.AIName = fields[66].GetString();
- creatureTemplate.MovementType = uint32(fields[67].GetUInt8());
- creatureTemplate.InhabitType = uint32(fields[68].GetUInt8());
- creatureTemplate.HoverHeight = fields[69].GetFloat();
- creatureTemplate.ModHealth = fields[70].GetFloat();
- creatureTemplate.ModMana = fields[71].GetFloat();
- creatureTemplate.ModArmor = fields[72].GetFloat();
- creatureTemplate.RacialLeader = fields[73].GetBool();
+ creatureTemplate.spells[i] = fields[55 + i].GetUInt32();
+
+ creatureTemplate.PetSpellDataId = fields[63].GetUInt32();
+ creatureTemplate.VehicleId = fields[64].GetUInt32();
+ creatureTemplate.mingold = fields[65].GetUInt32();
+ creatureTemplate.maxgold = fields[66].GetUInt32();
+ creatureTemplate.AIName = fields[67].GetString();
+ creatureTemplate.MovementType = uint32(fields[68].GetUInt8());
+ creatureTemplate.InhabitType = uint32(fields[69].GetUInt8());
+ creatureTemplate.HoverHeight = fields[70].GetFloat();
+ creatureTemplate.ModHealth = fields[71].GetFloat();
+ creatureTemplate.ModMana = fields[72].GetFloat();
+ creatureTemplate.ModManaExtra = fields[73].GetFloat();
+ creatureTemplate.ModArmor = fields[74].GetFloat();
+ creatureTemplate.RacialLeader = fields[75].GetBool();
for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- creatureTemplate.questItems[i] = fields[74 + i].GetUInt32();
+ creatureTemplate.questItems[i] = fields[76 + i].GetUInt32();
- creatureTemplate.movementId = fields[80].GetUInt32();
- creatureTemplate.RegenHealth = fields[81].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[82].GetUInt32();
- creatureTemplate.flags_extra = fields[83].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[84].GetCString());
+ creatureTemplate.movementId = fields[82].GetUInt32();
+ creatureTemplate.RegenHealth = fields[83].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[84].GetUInt32();
+ creatureTemplate.flags_extra = fields[85].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[86].GetCString());
++count;
}
@@ -664,12 +690,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
continue;
}
- if (cInfo->trainer_spell != difficultyInfo->trainer_spell)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
if (!difficultyInfo->AIName.empty())
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) lists difficulty %u mode entry %u with `AIName` filled in. `AIName` of difficulty 0 mode creature is always used instead.",
@@ -866,12 +886,18 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
}
- if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1))
+ if (cInfo->expansion > MAX_CREATURE_BASE_HP)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with `exp` %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
const_cast<CreatureTemplate*>(cInfo)->expansion = 0;
}
+ if (cInfo->expansionUnknown > MAX_CREATURE_BASE_HP)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with `exp_unk` %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansionUnknown);
+ const_cast<CreatureTemplate*>(cInfo)->expansionUnknown = 0;
+ }
+
if (uint32 badFlags = (cInfo->flags_extra & ~CREATURE_FLAG_EXTRA_DB_ALLOWED))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with disallowed `flags_extra` %u, removing incorrect flag.", cInfo->Entry, badFlags);
@@ -1576,7 +1602,7 @@ void ObjectMgr::LoadCreatures()
}
if (data.spawnMask & ~spawnMasks[data.mapid])
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u) spawnMasks[data.mapid]: %u.", guid, data.spawnMask, data.mapid, spawnMasks[data.mapid]);
bool ok = true;
for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff)
@@ -2117,582 +2143,504 @@ void ObjectMgr::LoadItemLocales()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %lu Item locale strings in %u ms", (unsigned long)_itemLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadItemTemplates()
+void FillItemDamageFields(float* minDamage, float* maxDamage, float* dps, uint32 itemLevel, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32 delay, float statScalingFactor, uint32 inventoryType, uint32 flags2)
{
- uint32 oldMSTime = getMSTime();
-
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT entry, class, subclass, SoundOverrideSubclass, name, displayid, Quality, Flags, FlagsExtra, BuyCount, BuyPrice, SellPrice, InventoryType, "
- // 13 14 15 16 17 18 19 20
- "AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, requiredspell, requiredhonorrank, "
- // 21 22 23 24 25 26 27 28
- "RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, maxcount, stackable, ContainerSlots, StatsCount, stat_type1, "
- // 29 30 31 32 33 34 35 36 37 38
- "stat_value1, stat_type2, stat_value2, stat_type3, stat_value3, stat_type4, stat_value4, stat_type5, stat_value5, stat_type6, "
- // 39 40 41 42 43 44 45 46 47
- "stat_value6, stat_type7, stat_value7, stat_type8, stat_value8, stat_type9, stat_value9, stat_type10, stat_value10, "
- // 48 49 50 51 52 53 54 55 56 57 58
- "ScalingStatDistribution, ScalingStatValue, dmg_min1, dmg_max1, dmg_type1, dmg_min2, dmg_max2, dmg_type2, armor, holy_res, fire_res, "
- // 59 60 61 62 63 64 65 66 67 68
- "nature_res, frost_res, shadow_res, arcane_res, delay, ammo_type, RangedModRange, spellid_1, spelltrigger_1, spellcharges_1, "
- // 69 70 71 72 73 74 75
- "spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, spellid_2, spelltrigger_2, spellcharges_2, "
- // 76 77 78 79 80 81 82
- "spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, spellid_3, spelltrigger_3, spellcharges_3, "
- // 83 84 85 86 87 88 89
- "spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, spellid_4, spelltrigger_4, spellcharges_4, "
- // 90 91 92 93 94 95 96
- "spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, spellid_5, spelltrigger_5, spellcharges_5, "
- // 97 98 99 100 101 102 103 104 105
- "spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, bonding, description, PageText, LanguageID, PageMaterial, "
- // 106 107 108 109 110 111 112 113 114 115 116 117
- "startquest, lockid, Material, sheath, RandomProperty, RandomSuffix, block, itemset, MaxDurability, area, Map, BagFamily, "
- // 118 119 120 121 122 123 124 125
- "TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, "
- // 126 127 128 129 130 131 132 133
- "GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, "
- // 134 135 136
- "FoodType, minMoneyLoot, maxMoneyLoot, flagsCustom FROM item_template");
-
- if (!result)
- {
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 item templates. DB table `item_template` is empty.");
+ *minDamage = *maxDamage = *dps = 0.0f;
+ if (itemClass != ITEM_CLASS_WEAPON || quality > ITEM_QUALITY_ARTIFACT)
return;
- }
- _itemTemplateStore.rehash(result->GetRowCount());
- uint32 count = 0;
- bool enforceDBCAttributes = sWorld->getBoolConfig(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES);
+ DBCStorage<ItemDamageEntry>* store = NULL;
+ // get the right store here
+ if (inventoryType > 0xD + 13)
+ return;
- do
+ switch (inventoryType)
{
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
-
- ItemTemplate& itemTemplate = _itemTemplateStore[entry];
-
- itemTemplate.ItemId = entry;
- itemTemplate.Class = uint32(fields[1].GetUInt8());
- itemTemplate.SubClass = uint32(fields[2].GetUInt8());
- itemTemplate.SoundOverrideSubclass = int32(fields[3].GetInt8());
- itemTemplate.Name1 = fields[4].GetString();
- itemTemplate.DisplayInfoID = fields[5].GetUInt32();
- itemTemplate.Quality = uint32(fields[6].GetUInt8());
- itemTemplate.Flags = uint32(fields[7].GetInt64());
- itemTemplate.Flags2 = fields[8].GetUInt32();
- itemTemplate.BuyCount = uint32(fields[9].GetUInt8());
- itemTemplate.BuyPrice = int32(fields[10].GetInt64());
- itemTemplate.SellPrice = fields[11].GetUInt32();
- itemTemplate.InventoryType = uint32(fields[12].GetUInt8());
- itemTemplate.AllowableClass = fields[13].GetInt32();
- itemTemplate.AllowableRace = fields[14].GetInt32();
- itemTemplate.ItemLevel = uint32(fields[15].GetUInt16());
- itemTemplate.RequiredLevel = uint32(fields[16].GetUInt8());
- itemTemplate.RequiredSkill = uint32(fields[17].GetUInt16());
- itemTemplate.RequiredSkillRank = uint32(fields[18].GetUInt16());
- itemTemplate.RequiredSpell = fields[19].GetUInt32();
- itemTemplate.RequiredHonorRank = fields[20].GetUInt32();
- itemTemplate.RequiredCityRank = fields[21].GetUInt32();
- itemTemplate.RequiredReputationFaction = uint32(fields[22].GetUInt16());
- itemTemplate.RequiredReputationRank = uint32(fields[23].GetUInt16());
- itemTemplate.MaxCount = fields[24].GetInt32();
- itemTemplate.Stackable = fields[25].GetInt32();
- itemTemplate.ContainerSlots = uint32(fields[26].GetUInt8());
- itemTemplate.StatsCount = uint32(fields[27].GetUInt8());
-
- for (uint8 i = 0; i < itemTemplate.StatsCount; ++i)
- {
- itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i*2].GetUInt8());
- itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i*2].GetInt16());
- }
-
- itemTemplate.ScalingStatDistribution = uint32(fields[48].GetUInt16());
- itemTemplate.ScalingStatValue = fields[49].GetInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- itemTemplate.Damage[i].DamageMin = fields[50 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageMax = fields[51 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageType = uint32(fields[52 + i*3].GetUInt8());
- }
-
- itemTemplate.Armor = uint32(fields[56].GetUInt16());
- itemTemplate.HolyRes = uint32(fields[57].GetUInt8());
- itemTemplate.FireRes = uint32(fields[58].GetUInt8());
- itemTemplate.NatureRes = uint32(fields[59].GetUInt8());
- itemTemplate.FrostRes = uint32(fields[60].GetUInt8());
- itemTemplate.ShadowRes = uint32(fields[61].GetUInt8());
- itemTemplate.ArcaneRes = uint32(fields[62].GetUInt8());
- itemTemplate.Delay = uint32(fields[63].GetUInt16());
- itemTemplate.AmmoType = uint32(fields[64].GetUInt8());
- itemTemplate.RangedModRange = fields[65].GetFloat();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
- {
- itemTemplate.Spells[i].SpellId = fields[66 + i*7 ].GetInt32();
- itemTemplate.Spells[i].SpellTrigger = uint32(fields[67 + i*7].GetUInt8());
- itemTemplate.Spells[i].SpellCharges = int32(fields[68 + i*7].GetInt16());
- itemTemplate.Spells[i].SpellPPMRate = fields[69 + i*7].GetFloat();
- itemTemplate.Spells[i].SpellCooldown = fields[70 + i*7].GetInt32();
- itemTemplate.Spells[i].SpellCategory = uint32(fields[71 + i*7].GetUInt16());
- itemTemplate.Spells[i].SpellCategoryCooldown = fields[72 + i*7].GetInt32();
- }
-
- itemTemplate.Bonding = uint32(fields[101].GetUInt8());
- itemTemplate.Description = fields[102].GetString();
- itemTemplate.PageText = fields[103].GetUInt32();
- itemTemplate.LanguageID = uint32(fields[104].GetUInt8());
- itemTemplate.PageMaterial = uint32(fields[105].GetUInt8());
- itemTemplate.StartQuest = fields[106].GetUInt32();
- itemTemplate.LockID = fields[107].GetUInt32();
- itemTemplate.Material = int32(fields[108].GetInt8());
- itemTemplate.Sheath = uint32(fields[109].GetUInt8());
- itemTemplate.RandomProperty = fields[110].GetUInt32();
- itemTemplate.RandomSuffix = fields[111].GetInt32();
- itemTemplate.Block = fields[112].GetUInt32();
- itemTemplate.ItemSet = fields[113].GetUInt32();
- itemTemplate.MaxDurability = uint32(fields[114].GetUInt16());
- itemTemplate.Area = fields[115].GetUInt32();
- itemTemplate.Map = uint32(fields[116].GetUInt16());
- itemTemplate.BagFamily = fields[117].GetUInt32();
- itemTemplate.TotemCategory = fields[118].GetUInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
- {
- itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8());
- itemTemplate.Socket[i].Content = fields[120 + i*2].GetUInt32();
- }
-
- itemTemplate.socketBonus = fields[125].GetUInt32();
- itemTemplate.GemProperties = fields[126].GetUInt32();
- itemTemplate.RequiredDisenchantSkill = uint32(fields[127].GetInt16());
- itemTemplate.ArmorDamageModifier = fields[128].GetFloat();
- itemTemplate.Duration = fields[129].GetUInt32();
- itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16());
- itemTemplate.HolidayId = fields[131].GetUInt32();
- itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString());
- itemTemplate.DisenchantID = fields[133].GetUInt32();
- itemTemplate.FoodType = uint32(fields[134].GetUInt8());
- itemTemplate.MinMoneyLoot = fields[135].GetUInt32();
- itemTemplate.MaxMoneyLoot = fields[136].GetUInt32();
- itemTemplate.FlagsCu = fields[137].GetUInt32();
-
- // Checks
-
- ItemEntry const* dbcitem = sItemStore.LookupEntry(entry);
-
- if (dbcitem)
- {
- if (itemTemplate.Class != dbcitem->Class)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct class %u, must be %u .", entry, itemTemplate.Class, dbcitem->Class);
- if (enforceDBCAttributes)
- itemTemplate.Class = dbcitem->Class;
- }
-
- if (itemTemplate.SoundOverrideSubclass != dbcitem->SoundOverrideSubclass)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct SoundOverrideSubclass (%i), must be %i .", entry, itemTemplate.SoundOverrideSubclass, dbcitem->SoundOverrideSubclass);
- if (enforceDBCAttributes)
- itemTemplate.SoundOverrideSubclass = dbcitem->SoundOverrideSubclass;
- }
- if (itemTemplate.Material != dbcitem->Material)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct material (%i), must be %i .", entry, itemTemplate.Material, dbcitem->Material);
- if (enforceDBCAttributes)
- itemTemplate.Material = dbcitem->Material;
- }
- if (itemTemplate.InventoryType != dbcitem->InventoryType)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct inventory type (%u), must be %u .", entry, itemTemplate.InventoryType, dbcitem->InventoryType);
- if (enforceDBCAttributes)
- itemTemplate.InventoryType = dbcitem->InventoryType;
- }
- if (itemTemplate.DisplayInfoID != dbcitem->DisplayId)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct display id (%u), must be %u .", entry, itemTemplate.DisplayInfoID, dbcitem->DisplayId);
- if (enforceDBCAttributes)
- itemTemplate.DisplayInfoID = dbcitem->DisplayId;
- }
- if (itemTemplate.Sheath != dbcitem->Sheath)
+ case INVTYPE_AMMO:
+ store = &sItemDamageAmmoStore;
+ break;
+ case INVTYPE_2HWEAPON:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageTwoHandCasterStore;
+ else
+ store = &sItemDamageTwoHandStore;
+ break;
+ case INVTYPE_RANGED:
+ case INVTYPE_THROWN:
+ case INVTYPE_RANGEDRIGHT:
+ switch (itemSubClass)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct sheathid (%u), must be %u .", entry, itemTemplate.Sheath, dbcitem->Sheath);
- if (enforceDBCAttributes)
- itemTemplate.Sheath = dbcitem->Sheath;
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ store = &sItemDamageWandStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ store = &sItemDamageThrownStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ store = &sItemDamageRangedStore;
+ break;
+ default:
+ return;
}
+ break;
+ case INVTYPE_WEAPON:
+ case INVTYPE_WEAPONMAINHAND:
+ case INVTYPE_WEAPONOFFHAND:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageOneHandCasterStore;
+ else
+ store = &sItemDamageOneHandStore;
+ break;
+ default:
+ return;
+ }
- }
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not exist in item.dbc! (not correct id?).", entry);
-
- if (itemTemplate.Class >= MAX_ITEM_CLASS)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Class value (%u)", entry, itemTemplate.Class);
- itemTemplate.Class = ITEM_CLASS_MISC;
- }
-
- if (itemTemplate.SubClass >= MaxItemSubclassValues[itemTemplate.Class])
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Subclass value (%u) for class %u", entry, itemTemplate.SubClass, itemTemplate.Class);
- itemTemplate.SubClass = 0;// exist for all item classes
- }
-
- if (itemTemplate.Quality >= MAX_ITEM_QUALITY)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Quality value (%u)", entry, itemTemplate.Quality);
- itemTemplate.Quality = ITEM_QUALITY_NORMAL;
- }
-
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(HORDE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_HORDE_ONLY);
-
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has value (%u) in `Flags2` flags (ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) and ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, this is a wrong combination.",
- entry, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY, ITEM_FLAGS_EXTRA_HORDE_ONLY);
- }
- else if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(ALLIANCE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_ALLIANCE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY);
- }
-
- if (itemTemplate.BuyCount <= 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).", entry, itemTemplate.BuyCount);
- itemTemplate.BuyCount = 1;
- }
-
- if (itemTemplate.InventoryType >= MAX_INVTYPE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong InventoryType value (%u)", entry, itemTemplate.InventoryType);
- itemTemplate.InventoryType = INVTYPE_NON_EQUIP;
- }
-
- if (itemTemplate.RequiredSkill >= MAX_SKILL_TYPE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong RequiredSkill value (%u)", entry, itemTemplate.RequiredSkill);
- itemTemplate.RequiredSkill = 0;
- }
-
- {
- // can be used in equip slot, as page read use in inventory, or spell casting at use
- bool req = itemTemplate.InventoryType != INVTYPE_NON_EQUIP || itemTemplate.PageText;
- if (!req)
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellId)
- {
- req = true;
- break;
- }
- }
-
- if (req)
- {
- if (!(itemTemplate.AllowableClass & CLASSMASK_ALL_PLAYABLE))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have any playable classes (%u) in `AllowableClass` and can't be equipped or used.", entry, itemTemplate.AllowableClass);
+ if (!store)
+ return;
- if (!(itemTemplate.AllowableRace & RACEMASK_ALL_PLAYABLE))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have any playable races (%u) in `AllowableRace` and can't be equipped or used.", entry, itemTemplate.AllowableRace);
- }
- }
+ ItemDamageEntry const* damageInfo = store->LookupEntry(itemLevel);
+ if (!damageInfo)
+ return;
- if (itemTemplate.RequiredSpell && !sSpellMgr->GetSpellInfo(itemTemplate.RequiredSpell))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has a wrong (non-existing) spell in RequiredSpell (%u)", entry, itemTemplate.RequiredSpell);
- itemTemplate.RequiredSpell = 0;
- }
+ *dps = damageInfo->DPS[quality];
+ float avgDamage = *dps * delay * 0.001f;
+ *minDamage = (statScalingFactor * -0.5f + 1.0f) * avgDamage;
+ *maxDamage = floor(float(avgDamage* (statScalingFactor * 0.5f + 1.0f) + 0.5f));
+}
- if (itemTemplate.RequiredReputationRank >= MAX_REPUTATION_RANK)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.", entry, itemTemplate.RequiredReputationRank);
+uint32 FillItemArmor(uint32 itemlevel, uint32 itemClass, uint32 itemSubclass, uint32 quality, uint32 inventoryType)
+{
+ if (quality > ITEM_QUALITY_ARTIFACT)
+ return 0;
- if (itemTemplate.RequiredReputationFaction)
- {
- if (!sFactionStore.LookupEntry(itemTemplate.RequiredReputationFaction))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)", entry, itemTemplate.RequiredReputationFaction);
- itemTemplate.RequiredReputationFaction = 0;
- }
+ // all items but shields
+ if (itemClass != ITEM_CLASS_ARMOR || itemSubclass != ITEM_SUBCLASS_ARMOR_SHIELD)
+ {
+ ItemArmorQualityEntry const* armorQuality = sItemArmorQualityStore.LookupEntry(itemlevel);
+ ItemArmorTotalEntry const* armorTotal = sItemArmorTotalStore.LookupEntry(itemlevel);
+ if (!armorQuality || !armorTotal)
+ return 0;
- if (itemTemplate.RequiredReputationRank == MIN_REPUTATION_RANK)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.", entry);
- }
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
- if (itemTemplate.MaxCount < -1)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.", entry, itemTemplate.MaxCount);
- itemTemplate.MaxCount = -1;
- }
+ ArmorLocationEntry const* location = sArmorLocationStore.LookupEntry(inventoryType);
+ if (!location)
+ return 0;
- if (itemTemplate.Stackable == 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = 1;
- }
- else if (itemTemplate.Stackable < -1)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = -1;
- }
+ if (itemSubclass < ITEM_SUBCLASS_ARMOR_CLOTH)
+ return 0;
- if (itemTemplate.ContainerSlots > MAX_BAG_SIZE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).", entry, itemTemplate.ContainerSlots, MAX_BAG_SIZE);
- itemTemplate.ContainerSlots = MAX_BAG_SIZE;
- }
+ return uint32(armorQuality->Value[quality] * armorTotal->Value[itemSubclass - 1] * location->Value[itemSubclass - 1] + 0.5f);
+ }
- if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
- itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
- }
+ // shields
+ ItemArmorShieldEntry const* shield = sItemArmorShieldStore.LookupEntry(itemlevel);
+ if (!shield)
+ return 0;
- for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
- {
- // for ItemStatValue != 0
- if (itemTemplate.ItemStat[j].ItemStatValue && itemTemplate.ItemStat[j].ItemStatType >= MAX_ITEM_MOD)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong (non-existing?) stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- itemTemplate.ItemStat[j].ItemStatType = 0;
- }
+ return uint32(shield->Value[quality] + 0.5f);
+}
- switch (itemTemplate.ItemStat[j].ItemStatType)
- {
- case ITEM_MOD_SPELL_HEALING_DONE:
- case ITEM_MOD_SPELL_DAMAGE_DONE:
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has deprecated stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- break;
- default:
- break;
- }
- }
+uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventoryType, uint32 quality, uint32 itemLevel)
+{
+ if (itemClass != ITEM_CLASS_ARMOR && itemClass != ITEM_CLASS_WEAPON)
+ return 0;
- for (uint8 j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j)
- {
- if (itemTemplate.Damage[j].DamageType >= MAX_SPELL_SCHOOL)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong dmg_type%d (%u)", entry, j+1, itemTemplate.Damage[j].DamageType);
- itemTemplate.Damage[j].DamageType = 0;
- }
- }
+ static float const qualityMultipliers[MAX_ITEM_QUALITY] =
+ {
+ 1.0f, 1.0f, 1.0f, 1.17f, 1.37f, 1.68f, 0.0f, 0.0f
+ };
- // special format
- if ((itemTemplate.Spells[0].SpellId == 483) || (itemTemplate.Spells[0].SpellId == 55884))
- {
- // spell_1
- if (itemTemplate.Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format", entry, 0+1, itemTemplate.Spells[0].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
+ static float const armorMultipliers[MAX_INVTYPE] =
+ {
+ 0.00f, // INVTYPE_NON_EQUIP
+ 0.59f, // INVTYPE_HEAD
+ 0.00f, // INVTYPE_NECK
+ 0.59f, // INVTYPE_SHOULDERS
+ 0.00f, // INVTYPE_BODY
+ 1.00f, // INVTYPE_CHEST
+ 0.35f, // INVTYPE_WAIST
+ 0.75f, // INVTYPE_LEGS
+ 0.49f, // INVTYPE_FEET
+ 0.35f, // INVTYPE_WRISTS
+ 0.35f, // INVTYPE_HANDS
+ 0.00f, // INVTYPE_FINGER
+ 0.00f, // INVTYPE_TRINKET
+ 0.00f, // INVTYPE_WEAPON
+ 1.00f, // INVTYPE_SHIELD
+ 0.00f, // INVTYPE_RANGED
+ 0.00f, // INVTYPE_CLOAK
+ 0.00f, // INVTYPE_2HWEAPON
+ 0.00f, // INVTYPE_BAG
+ 0.00f, // INVTYPE_TABARD
+ 1.00f, // INVTYPE_ROBE
+ 0.00f, // INVTYPE_WEAPONMAINHAND
+ 0.00f, // INVTYPE_WEAPONOFFHAND
+ 0.00f, // INVTYPE_HOLDABLE
+ 0.00f, // INVTYPE_AMMO
+ 0.00f, // INVTYPE_THROWN
+ 0.00f, // INVTYPE_RANGEDRIGHT
+ 0.00f, // INVTYPE_QUIVER
+ 0.00f, // INVTYPE_RELIC
+ };
- // spell_2 have learning spell
- if (itemTemplate.Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.", entry, 1+1, itemTemplate.Spells[1].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (!itemTemplate.Spells[1].SpellId)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not have an expected spell in spellid_%d in special learning format.", entry, 1+1);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[1].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, NULL))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[1].SpellId == 483) || (itemTemplate.Spells[1].SpellId == 55884))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- }
+ static float const weaponMultipliers[MAX_ITEM_SUBCLASS_WEAPON] =
+ {
+ 0.89f, // ITEM_SUBCLASS_WEAPON_AXE
+ 1.03f, // ITEM_SUBCLASS_WEAPON_AXE2
+ 0.77f, // ITEM_SUBCLASS_WEAPON_BOW
+ 0.77f, // ITEM_SUBCLASS_WEAPON_GUN
+ 0.89f, // ITEM_SUBCLASS_WEAPON_MACE
+ 1.03f, // ITEM_SUBCLASS_WEAPON_MACE2
+ 1.03f, // ITEM_SUBCLASS_WEAPON_POLEARM
+ 0.89f, // ITEM_SUBCLASS_WEAPON_SWORD
+ 1.03f, // ITEM_SUBCLASS_WEAPON_SWORD2
+ 0.00f, // ITEM_SUBCLASS_WEAPON_Obsolete
+ 1.03f, // ITEM_SUBCLASS_WEAPON_STAFF
+ 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC
+ 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC2
+ 0.64f, // ITEM_SUBCLASS_WEAPON_FIST_WEAPON
+ 0.00f, // ITEM_SUBCLASS_WEAPON_MISCELLANEOUS
+ 0.64f, // ITEM_SUBCLASS_WEAPON_DAGGER
+ 0.64f, // ITEM_SUBCLASS_WEAPON_THROWN
+ 0.00f, // ITEM_SUBCLASS_WEAPON_SPEAR
+ 0.77f, // ITEM_SUBCLASS_WEAPON_CROSSBOW
+ 0.64f, // ITEM_SUBCLASS_WEAPON_WAND
+ 0.64f, // ITEM_SUBCLASS_WEAPON_FISHING_POLE
+ };
- // spell_3*, spell_4*, spell_5* is empty
- for (uint8 j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[j].SpellId != 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong spell in spellid_%d (%d) for learning special format", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
- // normal spell list
- else
- {
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || itemTemplate.Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
+ float levelPenalty = 1.0f;
+ if (itemLevel <= 28)
+ levelPenalty = 0.966f - float(28u - itemLevel) / 54.0f;
- if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, NULL))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[j].SpellId == 483) || (itemTemplate.Spells[j].SpellId == 55884))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
- }
+ if (itemClass == ITEM_CLASS_ARMOR)
+ {
+ if (inventoryType > INVTYPE_ROBE)
+ return 0;
- if (itemTemplate.Bonding >= MAX_BIND_TYPE)
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Bonding value (%u)", entry, itemTemplate.Bonding);
+ return 5 * uint32(23.0f * qualityMultipliers[quality] * armorMultipliers[inventoryType] * levelPenalty + 0.5f);
+ }
- if (itemTemplate.PageText && !GetPageText(itemTemplate.PageText))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has non existing first page (Id:%u)", entry, itemTemplate.PageText);
+ return 5 * uint32(17.0f * qualityMultipliers[quality] * weaponMultipliers[itemSubClass] * levelPenalty + 0.5f);
+};
- if (itemTemplate.LockID && !sLockStore.LookupEntry(itemTemplate.LockID))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong LockID (%u)", entry, itemTemplate.LockID);
+void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, ItemTemplate const& itemTemplate)
+{
+ *disenchantID = 0;
+ *(int32*)requiredDisenchantSkill = -1;
+ if ((itemTemplate.Flags & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) ||
+ itemTemplate.Bonding == BIND_QUEST_ITEM || itemTemplate.Area || itemTemplate.Map ||
+ itemTemplate.Stackable > 1 ||
+ itemTemplate.Quality < ITEM_QUALITY_UNCOMMON || itemTemplate.Quality > ITEM_QUALITY_EPIC ||
+ !(itemTemplate.Class == ITEM_CLASS_ARMOR || itemTemplate.Class == ITEM_CLASS_WEAPON) ||
+ !(Item::GetSpecialPrice(&itemTemplate) || sItemCurrencyCostStore.LookupEntry(itemTemplate.ItemId)))
+ return;
- if (itemTemplate.Sheath >= MAX_SHEATHETYPE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Sheath (%u)", entry, itemTemplate.Sheath);
- itemTemplate.Sheath = SHEATHETYPE_NONE;
- }
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
+ {
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
- if (itemTemplate.RandomProperty)
+ if (disenchant->ItemClass == itemTemplate.Class &&
+ disenchant->ItemQuality == itemTemplate.Quality &&
+ disenchant->MinItemLevel <= itemTemplate.ItemLevel &&
+ disenchant->MaxItemLevel >= itemTemplate.ItemLevel)
{
- // To be implemented later
- if (itemTemplate.RandomProperty == -1)
- itemTemplate.RandomProperty = 0;
-
- else if (!sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomProperty)))
+ if (disenchant->Id == 60 || disenchant->Id == 61) // epic item disenchant ilvl range 66-99 (classic)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)", entry, itemTemplate.RandomProperty);
- itemTemplate.RandomProperty = 0;
+ if (itemTemplate.RequiredLevel > 60 || itemTemplate.RequiredSkillRank > 300)
+ continue; // skip to epic item disenchant ilvl range 90-199 (TBC)
}
- }
-
- if (itemTemplate.RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomSuffix)))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong RandomSuffix (%u)", entry, itemTemplate.RandomSuffix);
- itemTemplate.RandomSuffix = 0;
- }
-
- if (itemTemplate.ItemSet && !sItemSetStore.LookupEntry(itemTemplate.ItemSet))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) have wrong ItemSet (%u)", entry, itemTemplate.ItemSet);
- itemTemplate.ItemSet = 0;
- }
-
- if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area);
-
- if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Map (%u)", entry, itemTemplate.Map);
-
- if (itemTemplate.BagFamily)
- {
- // check bits
- for (uint32 j = 0; j < sizeof(itemTemplate.BagFamily)*8; ++j)
+ else if (disenchant->Id == 66 || disenchant->Id == 67) // epic item disenchant ilvl range 90-199 (TBC)
{
- uint32 mask = 1 << j;
- if ((itemTemplate.BagFamily & mask) == 0)
+ if (itemTemplate.RequiredLevel <= 60 || (itemTemplate.RequiredSkill && itemTemplate.RequiredSkillRank <= 300))
continue;
-
- ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1);
- if (!bf)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- continue;
- }
-
- if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask)
- {
- CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemTemplate.ItemId);
- if (!ctEntry)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- }
- }
}
- }
- if (itemTemplate.TotemCategory && !sTotemCategoryStore.LookupEntry(itemTemplate.TotemCategory))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong TotemCategory (%u)", entry, itemTemplate.TotemCategory);
-
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SOCKETS; ++j)
- {
- if (itemTemplate.Socket[j].Color && (itemTemplate.Socket[j].Color & SOCKET_COLOR_ALL) != itemTemplate.Socket[j].Color)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong socketColor_%d (%u)", entry, j+1, itemTemplate.Socket[j].Color);
- itemTemplate.Socket[j].Color = 0;
- }
+ *disenchantID = disenchant->Id;
+ *requiredDisenchantSkill = disenchant->RequiredDisenchantSkill;
+ return;
}
+ }
+}
- if (itemTemplate.GemProperties && !sGemPropertiesStore.LookupEntry(itemTemplate.GemProperties))
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong GemProperties (%u)", entry, itemTemplate.GemProperties);
-
- if (itemTemplate.FoodType >= MAX_PET_DIET)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong FoodType value (%u)", entry, itemTemplate.FoodType);
- itemTemplate.FoodType = 0;
- }
+void ObjectMgr::LoadItemTemplates()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 sparseCount = 0;
+ uint32 dbCount = 0;
- if (itemTemplate.ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(itemTemplate.ItemLimitCategory))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong LimitCategory value (%u)", entry, itemTemplate.ItemLimitCategory);
- itemTemplate.ItemLimitCategory = 0;
- }
+ for (uint32 itemId = 0; itemId < sItemSparseStore.GetNumRows(); ++itemId)
+ {
+ ItemSparseEntry const* sparse = sItemSparseStore.LookupEntry(itemId);
+ ItemEntry const* db2Data = sItemStore.LookupEntry(itemId);
+ if (!sparse || !db2Data)
+ continue;
- if (itemTemplate.HolidayId && !sHolidaysStore.LookupEntry(itemTemplate.HolidayId))
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) has wrong HolidayId value (%u)", entry, itemTemplate.HolidayId);
- itemTemplate.HolidayId = 0;
- }
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = db2Data->Class;
+ itemTemplate.SubClass = db2Data->SubClass;
+ itemTemplate.SoundOverrideSubclass = db2Data->SoundOverrideSubclass;
+ itemTemplate.Name1 = sparse->Name->Str[sWorld->GetDefaultDbcLocale()];
+ itemTemplate.DisplayInfoID = db2Data->DisplayId;
+ itemTemplate.Quality = sparse->Quality;
+ itemTemplate.Flags = sparse->Flags;
+ itemTemplate.Flags2 = sparse->Flags2;
+ itemTemplate.Unk430_1 = sparse->Unk430_1;
+ itemTemplate.Unk430_2 = sparse->Unk430_2;
+ itemTemplate.BuyCount = std::max(sparse->BuyCount, 1u);
+ itemTemplate.BuyPrice = sparse->BuyPrice;
+ itemTemplate.SellPrice = sparse->SellPrice;
+ itemTemplate.InventoryType = db2Data->InventoryType;
+ itemTemplate.AllowableClass = sparse->AllowableClass;
+ itemTemplate.AllowableRace = sparse->AllowableRace;
+ itemTemplate.ItemLevel = sparse->ItemLevel;
+ itemTemplate.RequiredLevel = sparse->RequiredLevel;
+ itemTemplate.RequiredSkill = sparse->RequiredSkill;
+ itemTemplate.RequiredSkillRank = sparse->RequiredSkillRank;
+ itemTemplate.RequiredSpell = sparse->RequiredSpell;
+ itemTemplate.RequiredHonorRank = sparse->RequiredHonorRank;
+ itemTemplate.RequiredCityRank = sparse->RequiredCityRank;
+ itemTemplate.RequiredReputationFaction = sparse->RequiredReputationFaction;
+ itemTemplate.RequiredReputationRank = sparse->RequiredReputationRank;
+ itemTemplate.MaxCount = sparse->MaxCount;
+ itemTemplate.Stackable = sparse->Stackable;
+ itemTemplate.ContainerSlots = sparse->ContainerSlots;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = sparse->ItemStatType[i];
+ itemTemplate.ItemStat[i].ItemStatValue = sparse->ItemStatValue[i];
+ itemTemplate.ItemStat[i].ItemStatUnk1 = sparse->ItemStatUnk1[i];
+ itemTemplate.ItemStat[i].ItemStatUnk2 = sparse->ItemStatUnk2[i];
+ }
+
+ itemTemplate.ScalingStatDistribution = sparse->ScalingStatDistribution;
+
+ // cache item damage
+ FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, sparse->ItemLevel,
+ db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->Delay, sparse->StatScalingFactor,
+ sparse->InventoryType, sparse->Flags2);
+
+ itemTemplate.DamageType = sparse->DamageType;
+ itemTemplate.Armor = FillItemArmor(sparse->ItemLevel, db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->InventoryType);
+ itemTemplate.Delay = sparse->Delay;
+ itemTemplate.RangedModRange = sparse->RangedModRange;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ itemTemplate.Spells[i].SpellId = sparse->SpellId[i];
+ itemTemplate.Spells[i].SpellTrigger = sparse->SpellTrigger[i];
+ itemTemplate.Spells[i].SpellCharges = sparse->SpellCharges[i];
+ itemTemplate.Spells[i].SpellCooldown = sparse->SpellCooldown[i];
+ itemTemplate.Spells[i].SpellCategory = sparse->SpellCategory[i];
+ itemTemplate.Spells[i].SpellCategoryCooldown = sparse->SpellCategoryCooldown[i];
+ }
+
+ itemTemplate.SpellPPMRate = 0.0f;
+ itemTemplate.Bonding = sparse->Bonding;
+ itemTemplate.Description = sparse->Description->Str[sWorld->GetDefaultDbcLocale()];
+ itemTemplate.PageText = sparse->PageText;
+ itemTemplate.LanguageID = sparse->LanguageID;
+ itemTemplate.PageMaterial = sparse->PageMaterial;
+ itemTemplate.StartQuest = sparse->StartQuest;
+ itemTemplate.LockID = sparse->LockID;
+ itemTemplate.Material = sparse->Material;
+ itemTemplate.Sheath = sparse->Sheath;
+ itemTemplate.RandomProperty = sparse->RandomProperty;
+ itemTemplate.RandomSuffix = sparse->RandomSuffix;
+ itemTemplate.ItemSet = sparse->ItemSet;
+ itemTemplate.MaxDurability = FillMaxDurability(db2Data->Class, db2Data->SubClass, sparse->InventoryType, sparse->Quality, sparse->ItemLevel);
+ itemTemplate.Area = sparse->Area;
+ itemTemplate.Map = sparse->Map;
+ itemTemplate.BagFamily = sparse->BagFamily;
+ itemTemplate.TotemCategory = sparse->TotemCategory;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
+ {
+ itemTemplate.Socket[i].Color = sparse->Color[i];
+ itemTemplate.Socket[i].Content = sparse->Content[i];
+ }
+
+ itemTemplate.socketBonus = sparse->SocketBonus;
+ itemTemplate.GemProperties = sparse->GemProperties;
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate);
+
+ itemTemplate.ArmorDamageModifier = sparse->ArmorDamageModifier;
+ itemTemplate.Duration = sparse->Duration;
+ itemTemplate.ItemLimitCategory = sparse->ItemLimitCategory;
+ itemTemplate.HolidayId = sparse->HolidayId;
+ itemTemplate.StatScalingFactor = sparse->StatScalingFactor;
+ itemTemplate.CurrencySubstitutionId = sparse->CurrencySubstitutionId;
+ itemTemplate.CurrencySubstitutionCount = sparse->CurrencySubstitutionCount;
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++sparseCount;
+ }
+
+ // Load missing items from item_template AND overwrite data from Item-sparse.db2 (item_template is supposed to contain Item-sparse.adb data)
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ QueryResult result = WorldDatabase.Query("SELECT entry, Class, SubClass, SoundOverrideSubclass, Name, DisplayId, Quality, Flags, FlagsExtra, Unk430_1, Unk430_2, BuyCount, BuyPrice, SellPrice, "
+ // 14 15 16 17 18 19 20 21
+ "InventoryType, AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredSpell, "
+ // 22 23 24 25 26 27 28
+ "RequiredHonorRank, RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, MaxCount, Stackable, ContainerSlots, "
+ // 29 30 31 32 33 34 35 36
+ "stat_type1, stat_value1, stat_unk1_1, stat_unk2_1, stat_type2, stat_value2, stat_unk1_2, stat_unk2_2, "
+ // 37 38 39 40 41 42 43 44
+ "stat_type3, stat_value3, stat_unk1_3, stat_unk2_3, stat_type4, stat_value4, stat_unk1_4, stat_unk2_4, "
+ // 45 46 47 48 49 50 51 52
+ "stat_type5, stat_value5, stat_unk1_5, stat_unk2_5, stat_type6, stat_value6, stat_unk1_6, stat_unk2_6, "
+ // 53 54 55 56 57 58 59 60
+ "stat_type7, stat_value7, stat_unk1_7, stat_unk2_7, stat_type8, stat_value8, stat_unk1_8, stat_unk2_8, "
+ // 61 62 63 64 65 66 67 68
+ "stat_type9, stat_value9, stat_unk1_9, stat_unk2_9, stat_type10, stat_value10, stat_unk1_10, stat_unk2_10, "
+ // 69 70 71 72
+ "ScalingStatDistribution, DamageType, Delay, RangedModRange, "
+ // 73 74 75 76 77 78
+ "spellid_1, spelltrigger_1, spellcharges_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, "
+ // 79 80 81 82 83 84
+ "spellid_2, spelltrigger_2, spellcharges_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, "
+ // 85 86 87 88 89 90
+ "spellid_3, spelltrigger_3, spellcharges_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, "
+ // 91 92 93 94 95 96
+ "spellid_4, spelltrigger_4, spellcharges_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, "
+ // 97 98 99 100 101 102
+ "spellid_5, spelltrigger_5, spellcharges_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, "
+ // 103 104 105 106 107 108 109 110
+ "Bonding, Description, PageText, LanguageID, PageMaterial, StartQuest, LockID, Material, "
+ // 111 112 113 114 115 116 117 118
+ "Sheath, RandomProperty, RandomSuffix, ItemSet, Area, Map, BagFamily, TotemCategory, "
+ // 119 120 121 122 123 124 125
+ "SocketColor_1, SocketContent_1, SocketColor_2, SocketContent_2, SocketColor_3, SocketContent_3, SocketBonus, "
+ // 126 127 128 129 130 131
+ "GemProperties, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, StatScalingFactor, "
+ // 132 133
+ "CurrencySubstitutionId, CurrencySubstitutionCount "
+ "FROM item_template");
- if (itemTemplate.FlagsCu & ITEM_FLAGS_CU_DURATION_REAL_TIME && !itemTemplate.Duration)
+ if (result)
+ {
+ do
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry %u) has flag ITEM_FLAGS_CU_DURATION_REAL_TIME but it does not have duration limit", entry);
- itemTemplate.FlagsCu &= ~ITEM_FLAGS_CU_DURATION_REAL_TIME;
- }
-
- ++count;
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (_itemTemplateStore.find(itemId) != _itemTemplateStore.end())
+ --sparseCount;
+
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = uint32(fields[1].GetUInt8());
+ itemTemplate.SubClass = uint32(fields[2].GetUInt8());
+ itemTemplate.SoundOverrideSubclass = fields[3].GetInt32();
+ itemTemplate.Name1 = fields[4].GetString();
+ itemTemplate.DisplayInfoID = fields[5].GetUInt32();
+ itemTemplate.Quality = uint32(fields[6].GetUInt8());
+ itemTemplate.Flags = uint32(fields[7].GetInt64());
+ itemTemplate.Flags2 = fields[8].GetUInt32();
+ itemTemplate.Unk430_1 = fields[9].GetFloat();
+ itemTemplate.Unk430_2 = fields[10].GetFloat();
+ itemTemplate.BuyCount = uint32(fields[11].GetUInt8());
+ itemTemplate.BuyPrice = int32(fields[12].GetInt64());
+ itemTemplate.SellPrice = fields[13].GetUInt32();
+
+ itemTemplate.InventoryType = uint32(fields[14].GetUInt8());
+ itemTemplate.AllowableClass = fields[15].GetInt32();
+ itemTemplate.AllowableRace = fields[16].GetInt32();
+ itemTemplate.ItemLevel = uint32(fields[17].GetUInt16());
+ itemTemplate.RequiredLevel = uint32(fields[18].GetUInt8());
+ itemTemplate.RequiredSkill = uint32(fields[19].GetUInt16());
+ itemTemplate.RequiredSkillRank = uint32(fields[20].GetUInt16());
+ itemTemplate.RequiredSpell = fields[21].GetUInt32();
+ itemTemplate.RequiredHonorRank = fields[22].GetUInt32();
+ itemTemplate.RequiredCityRank = fields[23].GetUInt32();
+ itemTemplate.RequiredReputationFaction = uint32(fields[24].GetUInt16());
+ itemTemplate.RequiredReputationRank = uint32(fields[25].GetUInt16());
+ itemTemplate.MaxCount = fields[26].GetInt32();
+ itemTemplate.Stackable = fields[27].GetInt32();
+ itemTemplate.ContainerSlots = uint32(fields[28].GetUInt8());
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = uint32(fields[29 + i * 4 + 0].GetUInt8());
+ itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i * 4 + 1].GetInt16());
+ itemTemplate.ItemStat[i].ItemStatUnk1 = fields[29 + i * 4 + 2].GetInt32();
+ itemTemplate.ItemStat[i].ItemStatUnk2 = fields[29 + i * 4 + 3].GetInt32();
+ }
+
+ itemTemplate.ScalingStatDistribution = uint32(fields[69].GetUInt16());
+
+ // cache item damage
+ FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, itemTemplate.ItemLevel,
+ itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[71].GetUInt16(),
+ fields[131].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags2);
+
+ itemTemplate.DamageType = fields[70].GetUInt8();
+ itemTemplate.Armor = FillItemArmor(itemTemplate.ItemLevel, itemTemplate.Class,
+ itemTemplate.SubClass, itemTemplate.Quality,
+ itemTemplate.InventoryType);
+
+ itemTemplate.Delay = fields[71].GetUInt16();
+ itemTemplate.RangedModRange = fields[72].GetFloat();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ itemTemplate.Spells[i].SpellId = fields[73 + 6 * i + 0].GetInt32();
+ itemTemplate.Spells[i].SpellTrigger = uint32(fields[73 + 6 * i + 1].GetUInt8());
+ itemTemplate.Spells[i].SpellCharges = int32(fields[73 + 6 * i + 2].GetInt16());
+ itemTemplate.Spells[i].SpellCooldown = fields[73 + 6 * i + 3].GetInt32();
+ itemTemplate.Spells[i].SpellCategory = uint32(fields[73 + 6 * i + 4].GetUInt16());
+ itemTemplate.Spells[i].SpellCategoryCooldown = fields[73 + 6 * i + 5].GetInt32();
+ }
+
+ itemTemplate.SpellPPMRate = 0.0f;
+ itemTemplate.Bonding = uint32(fields[103].GetUInt8());
+ itemTemplate.Description = fields[104].GetString();
+ itemTemplate.PageText = fields[105].GetUInt32();
+ itemTemplate.LanguageID = uint32(fields[106].GetUInt8());
+ itemTemplate.PageMaterial = uint32(fields[107].GetUInt8());
+ itemTemplate.StartQuest = fields[108].GetUInt32();
+ itemTemplate.LockID = fields[109].GetUInt32();
+ itemTemplate.Material = int32(fields[110].GetInt8());
+ itemTemplate.Sheath = uint32(fields[111].GetUInt8());
+ itemTemplate.RandomProperty = fields[112].GetUInt32();
+ itemTemplate.RandomSuffix = fields[113].GetInt32();
+ itemTemplate.ItemSet = fields[114].GetUInt32();
+ itemTemplate.MaxDurability = FillMaxDurability(itemTemplate.Class, itemTemplate.SubClass,
+ itemTemplate.InventoryType, itemTemplate.Quality, itemTemplate.ItemLevel);
+
+ itemTemplate.Area = fields[115].GetUInt32();
+ itemTemplate.Map = uint32(fields[116].GetUInt16());
+ itemTemplate.BagFamily = fields[117].GetUInt32();
+ itemTemplate.TotemCategory = fields[118].GetUInt32();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
+ {
+ itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8());
+ itemTemplate.Socket[i].Content = fields[119 + i * 2 + 1].GetUInt32();
+ }
+
+ itemTemplate.socketBonus = fields[125].GetUInt32();
+ itemTemplate.GemProperties = fields[126].GetUInt32();
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate);
+
+ itemTemplate.ArmorDamageModifier = fields[127].GetFloat();
+ itemTemplate.Duration = fields[128].GetUInt32();
+ itemTemplate.ItemLimitCategory = uint32(fields[129].GetInt16());
+ itemTemplate.HolidayId = fields[130].GetUInt32();
+ itemTemplate.StatScalingFactor = fields[131].GetFloat();
+ itemTemplate.CurrencySubstitutionId = fields[132].GetInt32();
+ itemTemplate.CurrencySubstitutionCount = fields[133].GetInt32();
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++dbCount;
+ } while (result->NextRow());
}
- while (result->NextRow());
// Check if item templates for DBC referenced character start outfit are present
std::set<uint32> notFoundOutfit;
@@ -2717,124 +2665,77 @@ void ObjectMgr::LoadItemTemplates()
for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr)
TC_LOG_ERROR(LOG_FILTER_SQL, "Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr);
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item templates from Item-sparse.db2 and %u from database in %u ms", sparseCount, dbCount, GetMSTimeDiffToNow(oldMSTime));
}
-ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry)
-{
- ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry);
- if (itr != _itemTemplateStore.end())
- return &(itr->second);
-
- return NULL;
-}
-
-void ObjectMgr::LoadItemSetNameLocales()
+void ObjectMgr::LoadItemTemplateAddon()
{
uint32 oldMSTime = getMSTime();
+ uint32 count = 0;
- _itemSetNameLocaleStore.clear(); // need for reload case
-
- QueryResult result = WorldDatabase.Query("SELECT `entry`, `name_loc1`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc5`, `name_loc6`, `name_loc7`, `name_loc8` FROM `locales_item_set_names`");
-
- if (!result)
- return;
-
- do
+ QueryResult result = WorldDatabase.Query("SELECT Id, FlagsCu, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance FROM item_template_addon");
+ if (result)
{
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
-
- ItemSetNameLocale& data = _itemSetNameLocaleStore[entry];
-
- for (uint8 i = 1; i < TOTAL_LOCALES; ++i)
- AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Name);
- } while (result->NextRow());
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Item %u specified in `item_template_addon` does not exist, skipped.", itemId);
+ continue;
+ }
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded " UI64FMTD " Item set name locale strings in %u ms", uint64(_itemSetNameLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
+ uint32 minMoneyLoot = fields[3].GetUInt32();
+ uint32 maxMoneyLoot = fields[4].GetUInt32();
+ if (minMoneyLoot > maxMoneyLoot)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Minimum money loot specified in `item_template_addon` for item %u was greater than maximum amount, swapping.", itemId);
+ std::swap(minMoneyLoot, maxMoneyLoot);
+ }
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+ itemTemplate.FlagsCu = fields[1].GetUInt32();
+ itemTemplate.FoodType = fields[2].GetUInt8();
+ itemTemplate.MinMoneyLoot = minMoneyLoot;
+ itemTemplate.MaxMoneyLoot = maxMoneyLoot;
+ itemTemplate.SpellPPMRate = fields[5].GetFloat();
+ ++count;
+ } while (result->NextRow());
+ }
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item addon templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadItemSetNames()
+void ObjectMgr::LoadItemScriptNames()
{
uint32 oldMSTime = getMSTime();
-
- _itemSetNameStore.clear(); // needed for reload case
-
- std::set<uint32> itemSetItems;
-
- // fill item set member ids
- for (uint32 entryId = 0; entryId < sItemSetStore.GetNumRows(); ++entryId)
- {
- ItemSetEntry const* setEntry = sItemSetStore.LookupEntry(entryId);
- if (!setEntry)
- continue;
-
- for (uint32 i = 0; i < MAX_ITEM_SET_ITEMS; ++i)
- if (setEntry->itemId[i])
- itemSetItems.insert(setEntry->itemId[i]);
- }
-
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT `entry`, `name`, `InventoryType` FROM `item_set_names`");
-
- if (!result)
- {
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 item set names. DB table `item_set_names` is empty.");
- return;
- }
-
- _itemSetNameStore.rehash(result->GetRowCount());
uint32 count = 0;
- do
- {
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
- if (itemSetItems.find(entry) == itemSetItems.end())
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item set name (Entry: %u) not found in ItemSet.dbc, data useless.", entry);
- continue;
- }
-
- ItemSetNameEntry &data = _itemSetNameStore[entry];
- data.name = fields[1].GetString();
-
- uint32 invType = fields[2].GetUInt8();
- if (invType >= MAX_INVTYPE)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item set name (Entry: %u) has wrong InventoryType value (%u)", entry, invType);
- invType = INVTYPE_NON_EQUIP;
- }
-
- data.InventoryType = invType;
- itemSetItems.erase(entry);
- ++count;
- } while (result->NextRow());
-
- if (!itemSetItems.empty())
+ QueryResult result = WorldDatabase.Query("SELECT Id, ScriptName FROM item_script_names");
+ if (result)
{
- ItemTemplate const* pProto;
- for (std::set<uint32>::iterator itr = itemSetItems.begin(); itr != itemSetItems.end(); ++itr)
+ do
{
- uint32 entry = *itr;
- // add data from item_template if available
- pProto = sObjectMgr->GetItemTemplate(entry);
- if (pProto)
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item set part (Entry: %u) does not have entry in `item_set_names`, adding data from `item_template`.", entry);
- ItemSetNameEntry &data = _itemSetNameStore[entry];
- data.name = pProto->Name1;
- data.InventoryType = pProto->InventoryType;
- ++count;
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Item %u specified in `item_script_names` does not exist, skipped.", itemId);
+ continue;
}
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Item set part (Entry: %u) does not have entry in `item_set_names`, set will not display properly.", entry);
- }
+
+ _itemTemplateStore[itemId].ScriptId = GetScriptId(fields[1].GetCString());
+ ++count;
+ } while (result->NextRow());
}
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item set names in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item script names in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry)
+{
+ ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry);
+ if (itr != _itemTemplateStore.end())
+ return &(itr->second);
+ return NULL;
}
void ObjectMgr::LoadVehicleTemplateAccessories()
@@ -3337,88 +3238,6 @@ void ObjectMgr::LoadPlayerInfo()
}
}
- // Loading levels data (class only dependent)
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Player Create Level HP/Mana Data...");
- {
- uint32 oldMSTime = getMSTime();
-
- // 0 1 2 3
- QueryResult result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats");
-
- if (!result)
- {
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 level health/mana definitions. DB table `game_event_condition` is empty.");
- exit(1);
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
-
- uint32 current_class = fields[0].GetUInt8();
- if (current_class >= MAX_CLASSES)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Wrong class %u in `player_classlevelstats` table, ignoring.", current_class);
- continue;
- }
-
- uint8 current_level = fields[1].GetUInt8(); // Can't be > than STRONG_MAX_LEVEL (hardcoded level maximum) due to var type
- if (current_level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
- {
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Unused (> MaxPlayerLevel in worldserver.conf) level %u in `player_classlevelstats` table, ignoring.", current_level);
- ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
- continue;
- }
-
- PlayerClassInfo* info = _playerClassInfo[current_class];
- if (!info)
- {
- info = new PlayerClassInfo();
- info->levelInfo = new PlayerClassLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)];
- _playerClassInfo[current_class] = info;
- }
-
- PlayerClassLevelInfo& levelInfo = info->levelInfo[current_level-1];
-
- levelInfo.basehealth = fields[2].GetUInt16();
- levelInfo.basemana = fields[3].GetUInt16();
-
- ++count;
- }
- while (result->NextRow());
-
- // Fill gaps and check integrity
- for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
- {
- // skip non existed classes
- if (!sChrClassesStore.LookupEntry(class_))
- continue;
-
- PlayerClassInfo* pClassInfo = _playerClassInfo[class_];
-
- // fatal error if no level 1 data
- if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Class %i Level 1 does not have health/mana data!", class_);
- exit(1);
- }
-
- // fill level gaps
- for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
- {
- if (pClassInfo->levelInfo[level].basehealth == 0)
- {
- TC_LOG_ERROR(LOG_FILTER_SQL, "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level+1, level);
- pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1];
- }
- }
- }
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u level health/mana definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
- }
-
// Loading levels data (class/race dependent)
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Player Create Level Stats Data...");
{
@@ -3585,17 +3404,25 @@ void ObjectMgr::LoadPlayerInfo()
}
}
-void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const
+void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, uint32& baseHP, uint32& baseMana) const
{
if (level < 1 || class_ >= MAX_CLASSES)
return;
- PlayerClassInfo const* pInfo = _playerClassInfo[class_];
-
if (level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
level = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
- *info = pInfo->levelInfo[level-1];
+ GtOCTBaseHPByClassEntry const* hp = sGtOCTBaseHPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
+ GtOCTBaseMPByClassEntry const* mp = sGtOCTBaseMPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
+
+ if (!hp || !mp)
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Tried to get non-existant Class-Level combination data for base hp/mp. Class %u Level %u", class_, level);
+ return;
+ }
+
+ baseHP = uint32(hp->ratio);
+ baseMana = uint32(mp->ratio);
}
void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const
@@ -3707,33 +3534,37 @@ void ObjectMgr::LoadQuests()
"RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, "
// 21 22 23 24 25 26 27 28 29 30 31
"PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestIdChain, RewardXPId, RewardOrRequiredMoney, RewardMoneyMaxLevel, RewardSpell, RewardSpellCast, RewardHonor, RewardHonorMultiplier, "
- // 32 33 34 35 36 37 38 39 40 41 42
- "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
- // 43 44 45 46 47 48 49 50
- "RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, "
- // 51 52 53 54 55 56 57 58 59 60 61 62
+ // 32 33 34 35 36 37 38 39 40 41 42 43
+ "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, MinimapTargetMark, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
+ // 44 45 46 47 48 49 50 51 52 53 54 55 56
+ "RewardSkillId, RewardSkillPoints, RewardReputationMask, QuestGiverPortrait, QuestTurnInPortrait, RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, "
+ // 57 58 59 60 61 62 63 64 65 66 67 68
"RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6, RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6, "
- // 63 64 65 66 67 68 69 70 71 72
+ // 69 70 71 72 73 74 75 76 77 78
"RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5, RewardFactionValueId1, RewardFactionValueId2, RewardFactionValueId3, RewardFactionValueId4, RewardFactionValueId5, "
- // 73 74 75 76 77
+ // 79 80 81 82 83
"RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, "
- // 78 79 80 81
- "PointMapId, PointX, PointY, PointOption, "
- // 82 83 84 85 86 87 88
- "Title, Objectives, Details, EndText, OfferRewardText, RequestItemsText, CompletedText, "
- // 89 90 91 92 93 94 95 96
+ // 84 85 86 87 88 89 90 91 92 93 94
+ "PointMapId, PointX, PointY, PointOption, Title, Objectives, Details, EndText, CompletedText, OfferRewardText, RequestItemsText, "
+ // 95 96 97 98 99 100 101 102
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
- // 97 98 99 100 101 102 103 104
+ // 103 104 105 106 107 108 109 110
"RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, "
- // 105 106 107 108 109 110 111 112 113 114 115 116
+ // 111 112 113 114 115 116 117 118 119 120 121 122
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
- // 117 118 119 120 121 122 123 124 125
- "RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, "
- // 126 127 128 129 130 131 132 133 134 135
+ // 123 124 125 126 127 128 129 130 131
+ "RequiredSpell, RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, "
+ // 132 133 134 135 136 137 138 139
+ "RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, "
+ // 140 141 142 143 144 145 146 147
+ "RequiredCurrencyId1, RequiredCurrencyId2, RequiredCurrencyId3, RequiredCurrencyId4, RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, "
+ // 148 149 150 151 152 153
+ "QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, "
+ // 154 155 156 157 158 159 160 161 162 163
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, "
- // 136 137 138 139 140 141 142 143
+ // 164 165 166 167 168 169 170 171
"OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, "
- // 144
+ // 173
"WDBVerified"
" FROM quest_template");
if (!result)
@@ -3769,11 +3600,11 @@ void ObjectMgr::LoadQuests()
if (qinfo->GetQuestMethod() >= 3)
TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `Method` = %u, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestMethod());
- if (qinfo->Flags & ~QUEST_TRINITY_FLAGS_DB_ALLOWED)
+ if (qinfo->SpecialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u",
- qinfo->GetQuestId(), qinfo->Flags >> 20, QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20);
- qinfo->Flags &= QUEST_TRINITY_FLAGS_DB_ALLOWED;
+ qinfo->GetQuestId(), qinfo->SpecialFlags, QUEST_SPECIAL_FLAGS_DB_ALLOWED);
+ qinfo->SpecialFlags &= QUEST_SPECIAL_FLAGS_DB_ALLOWED;
}
if (qinfo->Flags & QUEST_FLAGS_DAILY && qinfo->Flags & QUEST_FLAGS_WEEKLY)
@@ -3784,28 +3615,28 @@ void ObjectMgr::LoadQuests()
if (qinfo->Flags & QUEST_FLAGS_DAILY)
{
- if (!(qinfo->Flags & QUEST_TRINITY_FLAGS_REPEATABLE))
+ if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Daily Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->Flags |= QUEST_TRINITY_FLAGS_REPEATABLE;
+ qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
if (qinfo->Flags & QUEST_FLAGS_WEEKLY)
{
- if (!(qinfo->Flags & QUEST_TRINITY_FLAGS_REPEATABLE))
+ if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->Flags |= QUEST_TRINITY_FLAGS_REPEATABLE;
+ qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
- if (qinfo->Flags & QUEST_TRINITY_FLAGS_MONTHLY)
+ if (qinfo->Flags & QUEST_SPECIAL_FLAGS_MONTHLY)
{
- if (!(qinfo->Flags & QUEST_TRINITY_FLAGS_REPEATABLE))
+ if (!(qinfo->Flags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Monthly quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->Flags |= QUEST_TRINITY_FLAGS_REPEATABLE;
+ qinfo->Flags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
@@ -3823,6 +3654,12 @@ void ObjectMgr::LoadQuests()
}
}
+ if (qinfo->MinLevel == uint32(-1) || qinfo->MinLevel > DEFAULT_MAX_LEVEL)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u should be disabled because `MinLevel` = %i", qinfo->GetQuestId(), int32(qinfo->MinLevel));
+ // no changes needed, sending -1 in SMSG_QUEST_QUERY_RESPONSE is valid
+ }
+
// client quest log visual (area case)
if (qinfo->ZoneOrSort > 0)
{
@@ -4023,7 +3860,7 @@ void ObjectMgr::LoadQuests()
// no changes, quest can't be done for this requirement
}
- qinfo->SetFlag(QUEST_TRINITY_FLAGS_DELIVER);
+ qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER);
if (!sObjectMgr->GetItemTemplate(id))
{
@@ -4032,7 +3869,7 @@ void ObjectMgr::LoadQuests()
qinfo->RequiredItemCount[j] = 0; // prevent incorrect work of quest
}
}
- else if (qinfo->RequiredItemCount[j]>0)
+ else if (qinfo->RequiredItemCount[j] > 0)
{
TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredItemId%d` = 0 but `RequiredItemCount%d` = %u, quest can't be done.",
qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredItemCount[j]);
@@ -4091,12 +3928,12 @@ void ObjectMgr::LoadQuests()
if (found)
{
- if (!qinfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ if (!qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1);
// this will prevent quest completing without objective
- const_cast<Quest*>(qinfo)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT);
+ const_cast<Quest*>(qinfo)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
}
}
else
@@ -4130,7 +3967,7 @@ void ObjectMgr::LoadQuests()
{
// In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast
- qinfo->SetFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO);
+ qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO);
if (!qinfo->RequiredNpcOrGoCount[j])
{
@@ -4310,26 +4147,149 @@ void ObjectMgr::LoadQuests()
qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId());
}
+ for (uint8 j = 0; j < QUEST_REWARD_CURRENCY_COUNT; ++j)
+ {
+ if (qinfo->RewardCurrencyId[j])
+ {
+ if (qinfo->RewardCurrencyCount[j] == 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardCurrencyId%d` = %u but `RewardCurrencyCount%d` = 0, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RewardCurrencyId[j], j+1);
+ // no changes, quest can't be done for this requirement
+ }
+
+ if (!sCurrencyTypesStore.LookupEntry(qinfo->RewardCurrencyId[j]))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardCurrencyId%d` = %u but currency with entry %u does not exist, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RewardCurrencyId[j], qinfo->RewardCurrencyId[j]);
+ qinfo->RewardCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+ else if (qinfo->RewardCurrencyCount[j] > 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardCurrencyId%d` = 0 but `RewardCurrencyCount%d` = %u, quest can't be done.",
+ qinfo->GetQuestId(), j+1, j+1, qinfo->RewardCurrencyCount[j]);
+ qinfo->RewardCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+
+ for (uint8 j = 0; j < QUEST_REQUIRED_CURRENCY_COUNT; ++j)
+ {
+ if (qinfo->RequiredCurrencyId[j])
+ {
+ if (qinfo->RequiredCurrencyCount[j] == 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredCurrencyId%d` = %u but `RequiredCurrencyCount%d` = 0, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], j+1);
+ // no changes, quest can't be done for this requirement
+ }
+
+ if (!sCurrencyTypesStore.LookupEntry(qinfo->RequiredCurrencyId[j]))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredCurrencyId%d` = %u but currency with entry %u does not exist, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], qinfo->RequiredCurrencyId[j]);
+ qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+ else if (qinfo->RequiredCurrencyCount[j] > 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredCurrencyId%d` = 0 but `RequiredCurrencyCount%d` = %u, quest can't be done.",
+ qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredCurrencyCount[j]);
+ qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+
+ if (qinfo->SoundAccept)
+ {
+ if (!sSoundEntriesStore.LookupEntry(qinfo->SoundAccept))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `SoundAccept` = %u but sound %u does not exist, set to 0.",
+ qinfo->GetQuestId(), qinfo->SoundAccept, qinfo->SoundAccept);
+ qinfo->SoundAccept = 0; // no sound will be played
+ }
+ }
+
+ if (qinfo->SoundTurnIn)
+ {
+ if (!sSoundEntriesStore.LookupEntry(qinfo->SoundTurnIn))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `SoundTurnIn` = %u but sound %u does not exist, set to 0.",
+ qinfo->GetQuestId(), qinfo->SoundTurnIn, qinfo->SoundTurnIn);
+ qinfo->SoundTurnIn = 0; // no sound will be played
+ }
+ }
+
+ if (qinfo->RequiredSpell > 0)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RequiredSpell);
+
+ if (!spellInfo)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredSpell` = %u but spell %u does not exist, quest will not require a spell.",
+ qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell);
+ qinfo->RequiredSpell = 0; // no spell will be required
+ }
+
+ else if (!SpellMgr::IsSpellValid(spellInfo))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RequiredSpell` = %u but spell %u is broken, quest will not require a spell.",
+ qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell);
+ qinfo->RequiredSpell = 0; // no spell will be required
+ }
+
+ /* Can we require talents?
+ else if (GetTalentSpellCost(qinfo->RewardSpellCast))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast);
+ qinfo->RewardSpellCast = 0; // no spell will be casted on player
+ }
+ }*/
+ }
+
+ if (qinfo->RewardSkillId)
+ {
+ if (!sSkillLineStore.LookupEntry(qinfo->RewardSkillId))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardSkillId` = %u but this skill does not exist",
+ qinfo->GetQuestId(), qinfo->RewardSkillId);
+ }
+ if (!qinfo->RewardSkillPoints)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardSkillId` = %u but `RewardSkillPoints` is 0",
+ qinfo->GetQuestId(), qinfo->RewardSkillId);
+ }
+ }
+
+ if (qinfo->RewardSkillPoints)
+ {
+ if (qinfo->RewardSkillPoints > sWorld->GetConfigMaxSkillValue())
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardSkillPoints` = %u but max possible skill is %u, quest can't be done.",
+ qinfo->GetQuestId(), qinfo->RewardSkillPoints, sWorld->GetConfigMaxSkillValue());
+ // no changes, quest can't be done for this requirement
+ }
+ if (!qinfo->RewardSkillId)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `RewardSkillPoints` = %u but `RewardSkillId` is 0",
+ qinfo->GetQuestId(), qinfo->RewardSkillPoints);
+ }
+ }
+
// fill additional data stores
if (qinfo->PrevQuestId)
{
if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end())
- {
TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId());
- }
else
- {
qinfo->prevQuests.push_back(qinfo->PrevQuestId);
- }
}
if (qinfo->NextQuestId)
{
QuestMap::iterator qNextItr = _questTemplates.find(abs(qinfo->GetNextQuestId()));
if (qNextItr == _questTemplates.end())
- {
TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
- }
else
{
int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId());
@@ -4340,12 +4300,12 @@ void ObjectMgr::LoadQuests()
if (qinfo->ExclusiveGroup)
mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId()));
if (qinfo->LimitTime)
- qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED);
+ qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED);
if (qinfo->RequiredPlayerKills)
- qinfo->SetFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL);
+ qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL);
}
- // check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
+ // check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
@@ -4365,12 +4325,12 @@ void ObjectMgr::LoadQuests()
if (!quest)
continue;
- if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.", spellInfo->Id, quest_id);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.", spellInfo->Id, quest_id);
// this will prevent quest completing without objective
- const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT);
+ const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
}
}
}
@@ -4385,14 +4345,14 @@ void ObjectMgr::LoadQuestLocales()
_questLocaleStore.clear(); // need for reload case
QueryResult result = WorldDatabase.Query("SELECT Id, "
- "Title_loc1, Details_loc1, Objectives_loc1, OfferRewardText_loc1, RequestItemsText_loc1, EndText_loc1, CompletedText_loc1, ObjectiveText1_loc1, ObjectiveText2_loc1, ObjectiveText3_loc1, ObjectiveText4_loc1, "
- "Title_loc2, Details_loc2, Objectives_loc2, OfferRewardText_loc2, RequestItemsText_loc2, EndText_loc2, CompletedText_loc2, ObjectiveText1_loc2, ObjectiveText2_loc2, ObjectiveText3_loc2, ObjectiveText4_loc2, "
- "Title_loc3, Details_loc3, Objectives_loc3, OfferRewardText_loc3, RequestItemsText_loc3, EndText_loc3, CompletedText_loc3, ObjectiveText1_loc3, ObjectiveText2_loc3, ObjectiveText3_loc3, ObjectiveText4_loc3, "
- "Title_loc4, Details_loc4, Objectives_loc4, OfferRewardText_loc4, RequestItemsText_loc4, EndText_loc4, CompletedText_loc4, ObjectiveText1_loc4, ObjectiveText2_loc4, ObjectiveText3_loc4, ObjectiveText4_loc4, "
- "Title_loc5, Details_loc5, Objectives_loc5, OfferRewardText_loc5, RequestItemsText_loc5, EndText_loc5, CompletedText_loc5, ObjectiveText1_loc5, ObjectiveText2_loc5, ObjectiveText3_loc5, ObjectiveText4_loc5, "
- "Title_loc6, Details_loc6, Objectives_loc6, OfferRewardText_loc6, RequestItemsText_loc6, EndText_loc6, CompletedText_loc6, ObjectiveText1_loc6, ObjectiveText2_loc6, ObjectiveText3_loc6, ObjectiveText4_loc6, "
- "Title_loc7, Details_loc7, Objectives_loc7, OfferRewardText_loc7, RequestItemsText_loc7, EndText_loc7, CompletedText_loc7, ObjectiveText1_loc7, ObjectiveText2_loc7, ObjectiveText3_loc7, ObjectiveText4_loc7, "
- "Title_loc8, Details_loc8, Objectives_loc8, OfferRewardText_loc8, RequestItemsText_loc8, EndText_loc8, CompletedText_loc8, ObjectiveText1_loc8, ObjectiveText2_loc8, ObjectiveText3_loc8, ObjectiveText4_loc8"
+ "Title_loc1, Details_loc1, Objectives_loc1, OfferRewardText_loc1, RequestItemsText_loc1, EndText_loc1, CompletedText_loc1, ObjectiveText1_loc1, ObjectiveText2_loc1, ObjectiveText3_loc1, ObjectiveText4_loc1, QuestGiverTextWindow_loc1, QuestGiverTargetName_loc1, QuestTurnTextWindow_loc1, QuestTurnTargetName_loc1,"
+ "Title_loc2, Details_loc2, Objectives_loc2, OfferRewardText_loc2, RequestItemsText_loc2, EndText_loc2, CompletedText_loc2, ObjectiveText1_loc2, ObjectiveText2_loc2, ObjectiveText3_loc2, ObjectiveText4_loc2, QuestGiverTextWindow_loc2, QuestGiverTargetName_loc2, QuestTurnTextWindow_loc2, QuestTurnTargetName_loc2,"
+ "Title_loc3, Details_loc3, Objectives_loc3, OfferRewardText_loc3, RequestItemsText_loc3, EndText_loc3, CompletedText_loc3, ObjectiveText1_loc3, ObjectiveText2_loc3, ObjectiveText3_loc3, ObjectiveText4_loc3, QuestGiverTextWindow_loc3, QuestGiverTargetName_loc3, QuestTurnTextWindow_loc3, QuestTurnTargetName_loc3,"
+ "Title_loc4, Details_loc4, Objectives_loc4, OfferRewardText_loc4, RequestItemsText_loc4, EndText_loc4, CompletedText_loc4, ObjectiveText1_loc4, ObjectiveText2_loc4, ObjectiveText3_loc4, ObjectiveText4_loc4, QuestGiverTextWindow_loc4, QuestGiverTargetName_loc4, QuestTurnTextWindow_loc4, QuestTurnTargetName_loc4,"
+ "Title_loc5, Details_loc5, Objectives_loc5, OfferRewardText_loc5, RequestItemsText_loc5, EndText_loc5, CompletedText_loc5, ObjectiveText1_loc5, ObjectiveText2_loc5, ObjectiveText3_loc5, ObjectiveText4_loc5, QuestGiverTextWindow_loc5, QuestGiverTargetName_loc5, QuestTurnTextWindow_loc5, QuestTurnTargetName_loc5,"
+ "Title_loc6, Details_loc6, Objectives_loc6, OfferRewardText_loc6, RequestItemsText_loc6, EndText_loc6, CompletedText_loc6, ObjectiveText1_loc6, ObjectiveText2_loc6, ObjectiveText3_loc6, ObjectiveText4_loc6, QuestGiverTextWindow_loc6, QuestGiverTargetName_loc6, QuestTurnTextWindow_loc6, QuestTurnTargetName_loc6,"
+ "Title_loc7, Details_loc7, Objectives_loc7, OfferRewardText_loc7, RequestItemsText_loc7, EndText_loc7, CompletedText_loc7, ObjectiveText1_loc7, ObjectiveText2_loc7, ObjectiveText3_loc7, ObjectiveText4_loc7, QuestGiverTextWindow_loc7, QuestGiverTargetName_loc7, QuestTurnTextWindow_loc7, QuestTurnTargetName_loc7,"
+ "Title_loc8, Details_loc8, Objectives_loc8, OfferRewardText_loc8, RequestItemsText_loc8, EndText_loc8, CompletedText_loc8, ObjectiveText1_loc8, ObjectiveText2_loc8, ObjectiveText3_loc8, ObjectiveText4_loc8, QuestGiverTextWindow_loc8, QuestGiverTargetName_loc8, QuestTurnTextWindow_loc8, QuestTurnTargetName_loc8"
" FROM locales_quest");
if (!result)
@@ -4410,16 +4370,21 @@ void ObjectMgr::LoadQuestLocales()
{
LocaleConstant locale = (LocaleConstant) i;
- AddLocaleString(fields[1 + 11 * (i - 1)].GetString(), locale, data.Title);
- AddLocaleString(fields[1 + 11 * (i - 1) + 1].GetString(), locale, data.Details);
- AddLocaleString(fields[1 + 11 * (i - 1) + 2].GetString(), locale, data.Objectives);
- AddLocaleString(fields[1 + 11 * (i - 1) + 3].GetString(), locale, data.OfferRewardText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 4].GetString(), locale, data.RequestItemsText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 5].GetString(), locale, data.EndText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 6].GetString(), locale, data.CompletedText);
+ AddLocaleString(fields[1 + 15 * (i - 1)].GetString(), locale, data.Title);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 1].GetString(), locale, data.Details);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 2].GetString(), locale, data.Objectives);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 3].GetString(), locale, data.OfferRewardText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 4].GetString(), locale, data.RequestItemsText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 5].GetString(), locale, data.EndText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 6].GetString(), locale, data.CompletedText);
for (uint8 k = 0; k < 4; ++k)
- AddLocaleString(fields[1 + 11 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveText[k]);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveText[k]);
+
+ AddLocaleString(fields[1 + 15 * (i - 1) + 11].GetString(), locale, data.QuestGiverTextWindow);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 12].GetString(), locale, data.QuestGiverTargetName);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 13].GetString(), locale, data.QuestTurnTextWindow);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 14].GetString(), locale, data.QuestTurnTargetName);
}
} while (result->NextRow());
@@ -4541,13 +4506,13 @@ void ObjectMgr::LoadScripts(ScriptsType type)
continue;
}
- if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",
tableName.c_str(), tmp.QuestExplored.QuestID, tmp.id);
// this will prevent quest completing without objective
- const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT);
+ const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
// continue; - quest objective requirement set and command can be allowed
}
@@ -5112,7 +5077,7 @@ void ObjectMgr::LoadInstanceEncounters()
if (lastEncounterDungeon && !sLFGMgr->GetLFGDungeonEntry(lastEncounterDungeon))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName, lastEncounterDungeon);
continue;
}
@@ -5121,7 +5086,7 @@ void ObjectMgr::LoadInstanceEncounters()
{
if (itr != dungeonLastBosses.end())
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` specified encounter %u (%s) as last encounter but %u (%s) is already marked as one, skipped!", entry, dungeonEncounter->encounterName[0], itr->second->id, itr->second->encounterName[0]);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` specified encounter %u (%s) as last encounter but %u (%s) is already marked as one, skipped!", entry, dungeonEncounter->encounterName, itr->second->id, itr->second->encounterName);
continue;
}
@@ -5135,7 +5100,7 @@ void ObjectMgr::LoadInstanceEncounters()
CreatureTemplate const* creatureInfo = GetCreatureTemplate(creditEntry);
if (!creatureInfo)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName);
continue;
}
const_cast<CreatureTemplate*>(creatureInfo)->flags_extra |= CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
@@ -5144,12 +5109,12 @@ void ObjectMgr::LoadInstanceEncounters()
case ENCOUNTER_CREDIT_CAST_SPELL:
if (!sSpellMgr->GetSpellInfo(creditEntry))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName);
continue;
}
break;
default:
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName);
continue;
}
@@ -5317,7 +5282,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
bool has_items = fields[4].GetBool();
m->expire_time = time_t(fields[5].GetUInt32());
m->deliver_time = 0;
- m->COD = fields[6].GetUInt32();
+ m->COD = fields[6].GetUInt64();
m->checked = fields[7].GetUInt8();
m->mailTemplateId = fields[8].GetInt16();
@@ -5430,12 +5395,12 @@ void ObjectMgr::LoadQuestAreaTriggers()
continue;
}
- if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID);
// this will prevent quest completing without objective
- const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT);
+ const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
// continue; - quest modified to required objective and trigger can be allowed.
}
@@ -5533,8 +5498,8 @@ uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, ui
if (!node || node->map_id != mapid || (!node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981)) // dk flight
continue;
- uint8 field = (uint8)((i - 1) / 32);
- uint32 submask = 1<<((i-1)%32);
+ uint8 field = (uint8)((i - 1) / 8);
+ uint32 submask = 1 << ((i-1) % 8);
// skip not taxi network nodes
if ((sTaxiNodesMask[field] & submask) == 0)
@@ -5935,7 +5900,7 @@ void ObjectMgr::LoadAreaTriggerTeleports()
uint32 Trigger_ID = fields[0].GetUInt32();
- AreaTrigger at;
+ AreaTriggerStruct at;
at.target_mapId = fields[1].GetUInt16();
at.target_X = fields[2].GetFloat();
@@ -6069,7 +6034,7 @@ void ObjectMgr::LoadAccessRequirements()
/*
* Searches for the areatrigger which teleports players out of the given map with instance_template.parent field support
*/
-AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
+AreaTriggerStruct const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
{
bool useParentDbValue = false;
uint32 parentId = 0;
@@ -6102,7 +6067,7 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
/**
* Searches for the areatrigger which teleports players to the given map
*/
-AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
+AreaTriggerStruct const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
{
for (AreaTriggerContainer::const_iterator itr = _areaTriggerStore.begin(); itr != _areaTriggerStore.end(); ++itr)
{
@@ -6171,6 +6136,10 @@ void ObjectMgr::SetHighestGuids()
result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups");
if (result)
sGroupMgr->SetGroupDbStoreSize((*result)[0].GetUInt32()+1);
+
+ result = CharacterDatabase.Query("SELECT MAX(itemId) from character_void_storage");
+ if (result)
+ _voidItemId = (*result)[0].GetUInt64()+1;
}
uint32 ObjectMgr::GenerateAuctionID()
@@ -6242,6 +6211,11 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
ASSERT(_hiCorpseGuid < 0xFFFFFFFE && "Corpse guid overflow!");
return _hiCorpseGuid++;
}
+ case HIGHGUID_AREATRIGGER:
+ {
+ ASSERT(_hiAreaTriggerGuid < 0xFFFFFFFE && "AreaTrigger guid overflow!");
+ return _hiAreaTriggerGuid++;
+ }
case HIGHGUID_DYNAMICOBJECT:
{
ASSERT(_hiDoGuid < 0xFFFFFFFE && "DynamicObject guid overflow!");
@@ -6318,7 +6292,7 @@ inline void CheckGOSpellId(GameObjectTemplate const* goInfo, uint32 dataN, uint3
goInfo->entry, goInfo->type, N, dataN, dataN);
}
-inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32 const& dataN, uint32 N)
+inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32& dataN, uint32 N)
{
if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR))
return;
@@ -6327,7 +6301,7 @@ inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32
goInfo->entry, goInfo->type, N, dataN, UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
- const_cast<uint32&>(dataN) = 0;
+ dataN = 0;
}
inline void CheckGONoDamageImmuneId(GameObjectTemplate* goTemplate, uint32 dataN, uint32 N)
@@ -6357,8 +6331,10 @@ void ObjectMgr::LoadGameObjectTemplate()
QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, questItem1, questItem2, questItem3, "
// 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
"questItem4, questItem5, questItem6, data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, "
- // 29 30 31 32 33 34 35 36 37 38 39 40 41
- "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, AIName, ScriptName "
+ // 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
+ "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25, data26, data27, data28, "
+ // 45 46 47 48 49 50
+ "data29, data30, data31, unkInt32, AIName, ScriptName "
"FROM gameobject_template");
if (!result)
@@ -6392,10 +6368,11 @@ void ObjectMgr::LoadGameObjectTemplate()
got.questItems[i] = fields[10 + i].GetUInt32();
for (uint8 i = 0; i < MAX_GAMEOBJECT_DATA; ++i)
- got.raw.data[i] = fields[16 + i].GetInt32(); // data1 and data6 can be -1
+ got.raw.data[i] = fields[16 + i].GetUInt32();
- got.AIName = fields[40].GetString();
- got.ScriptId = GetScriptId(fields[41].GetCString());
+ got.unkInt32 = fields[48].GetInt32();
+ got.AIName = fields[49].GetString();
+ got.ScriptId = GetScriptId(fields[50].GetCString());
// Checks
@@ -6627,7 +6604,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry)
if (list0.empty() || list1.empty())
{
CreatureTemplate const* cinfo = GetCreatureTemplate(entry);
- char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale());
+ const char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale());
if (!petname)
return cinfo->Name;
@@ -6642,8 +6619,16 @@ uint32 ObjectMgr::GeneratePetNumber()
return ++_hiPetNumber;
}
+uint64 ObjectMgr::GenerateVoidStorageItemId()
+{
+ return ++_voidItemId;
+}
+
void ObjectMgr::LoadCorpses()
{
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
+
uint32 oldMSTime = getMSTime();
PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES));
@@ -6658,7 +6643,7 @@ void ObjectMgr::LoadCorpses()
{
Field* fields = result->Fetch();
uint32 guid = fields[16].GetUInt32();
- CorpseType type = CorpseType(fields[13].GetUInt8());
+ CorpseType type = CorpseType(fields[12].GetUInt8());
if (type >= MAX_CORPSE_TYPE)
{
TC_LOG_ERROR(LOG_FILTER_GENERAL, "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
@@ -6839,8 +6824,8 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
_repSpilloverTemplateStore.clear(); // for reload case
- uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4 FROM reputation_spillover_template");
+ uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4, faction5, rate_5, rank_5 FROM reputation_spillover_template");
if (!result)
{
@@ -6868,6 +6853,9 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
repTemplate.faction[3] = fields[10].GetUInt16();
repTemplate.faction_rate[3] = fields[11].GetFloat();
repTemplate.faction_rank[3] = fields[12].GetUInt8();
+ repTemplate.faction[4] = fields[13].GetUInt16();
+ repTemplate.faction_rate[4] = fields[14].GetFloat();
+ repTemplate.faction_rank[4] = fields[15].GetUInt8();
FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
@@ -6933,6 +6921,12 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
TC_LOG_ERROR(LOG_FILTER_SQL, "Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[3]);
continue;
}
+ FactionEntry const* factionEntry4 = sFactionStore.LookupEntry(repTemplate.faction[4]);
+ if (repTemplate.faction[4] && !factionEntry4)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[4]);
+ continue;
+ }
_repSpilloverTemplateStore[factionId] = repTemplate;
@@ -7710,12 +7704,10 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial)
{
switch (pSkill->categoryId)
{
- case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE;
+ case SKILL_CATEGORY_LANGUAGES:
+ return SKILL_RANGE_LANGUAGE;
case SKILL_CATEGORY_WEAPON:
- if (pSkill->id != SKILL_FIST_WEAPONS)
- return SKILL_RANGE_LEVEL;
- else
- return SKILL_RANGE_MONO;
+ return SKILL_RANGE_LEVEL;
case SKILL_CATEGORY_ARMOR:
case SKILL_CATEGORY_CLASS:
if (pSkill->id != SKILL_LOCKPICKING)
@@ -8027,7 +8019,7 @@ void ObjectMgr::LoadTrainerSpell()
if (!result)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!");
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!");
return;
}
@@ -8054,11 +8046,12 @@ void ObjectMgr::LoadTrainerSpell()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %d Trainers in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *skip_vendors)
+int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, uint8 type, std::set<uint32> *skip_vendors)
{
// find all items from the reference vendor
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_NPC_VENDOR_REF);
stmt->setUInt32(0, uint32(item));
+ stmt->setUInt8(1, type);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
@@ -8073,19 +8066,20 @@ int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *s
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(vendor, -item_id, skip_vendors);
+ count += LoadReferenceVendor(vendor, -item_id, type, skip_vendors);
else
{
- int32 maxcount = fields[1].GetUInt8();
+ int32 maxcount = fields[1].GetUInt32();
uint32 incrtime = fields[2].GetUInt32();
uint32 ExtendedCost = fields[3].GetUInt32();
+ uint8 type = fields[4].GetUInt8();
- if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, NULL, skip_vendors))
+ if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, type, NULL, skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[vendor];
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost);
+ vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
++count;
}
} while (result->NextRow());
@@ -8104,11 +8098,11 @@ void ObjectMgr::LoadVendors()
std::set<uint32> skip_vendors;
- QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor ORDER BY entry, slot ASC");
+ QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor ORDER BY entry, slot ASC");
if (!result)
{
- TC_LOG_ERROR(LOG_FILTER_SQL, ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!");
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!");
return;
}
@@ -8123,19 +8117,20 @@ void ObjectMgr::LoadVendors()
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(entry, -item_id, &skip_vendors);
+ count += LoadReferenceVendor(entry, -item_id, 0, &skip_vendors);
else
{
- uint32 maxcount = fields[2].GetUInt8();
+ uint32 maxcount = fields[2].GetUInt32();
uint32 incrtime = fields[3].GetUInt32();
uint32 ExtendedCost = fields[4].GetUInt32();
+ uint8 type = fields[5].GetUInt8();
- if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, NULL, &skip_vendors))
+ if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, type, NULL, &skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[entry];
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost);
+ vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
++count;
}
}
@@ -8191,9 +8186,9 @@ void ObjectMgr::LoadGossipMenuItems()
_gossipMenuItemsStore.clear();
QueryResult result = WorldDatabase.Query(
- // 0 1 2 3 4
+ // 0 1 2 3 4 5
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
- // 5 6 7 8 9
+ // 6 7 8 9 10
"action_menu_id, action_poi_id, box_coded, box_money, box_text "
"FROM gossip_menu_option ORDER BY menu_id, id");
@@ -8246,10 +8241,10 @@ void ObjectMgr::LoadGossipMenuItems()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u gossip_menu_option entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, bool persist /*= true*/)
+void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist /*= true*/)
{
VendorItemData& vList = _cacheVendorItemStore[entry];
- vList.AddItem(item, maxcount, incrtime, extendedCost);
+ vList.AddItem(item, maxcount, incrtime, extendedCost, type);
if (persist)
{
@@ -8260,18 +8255,19 @@ void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32
stmt->setUInt8(2, maxcount);
stmt->setUInt32(3, incrtime);
stmt->setUInt32(4, extendedCost);
+ stmt->setUInt8(5, type);
WorldDatabase.Execute(stmt);
}
}
-bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= true*/)
+bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, uint8 type, bool persist /*= true*/)
{
CacheVendorItemContainer::iterator iter = _cacheVendorItemStore.find(entry);
if (iter == _cacheVendorItemStore.end())
return false;
- if (!iter->second.RemoveItem(item))
+ if (!iter->second.RemoveItem(item, type))
return false;
if (persist)
@@ -8280,6 +8276,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= tru
stmt->setUInt32(0, entry);
stmt->setUInt32(1, item);
+ stmt->setUInt8(2, type);
WorldDatabase.Execute(stmt);
}
@@ -8287,7 +8284,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= tru
return true;
}
-bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
+bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, uint8 type, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
{
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(vendor_entry);
if (!cInfo)
@@ -8314,12 +8311,13 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max
return false;
}
- if (!sObjectMgr->GetItemTemplate(item_id))
+ if ((type == ITEM_VENDOR_TYPE_ITEM && !sObjectMgr->GetItemTemplate(id)) ||
+ (type == ITEM_VENDOR_TYPE_CURRENCY && !sCurrencyTypesStore.LookupEntry(id)))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, id, type);
else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore", vendor_entry, item_id);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u, type %u), ignore", vendor_entry, id, type);
return false;
}
@@ -8328,41 +8326,44 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max
if (player)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, ExtendedCost);
else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", item_id, ExtendedCost, vendor_entry);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", id, ExtendedCost, vendor_entry);
return false;
}
- if (maxcount > 0 && incrtime == 0)
+ if (type == ITEM_VENDOR_TYPE_ITEM) // not applicable to currencies
{
- if (player)
- ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount);
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, item_id, vendor_entry);
- return false;
- }
- else if (maxcount == 0 && incrtime > 0)
- {
- if (player)
- ChatHandler(player->GetSession()).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0");
- else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", item_id, vendor_entry);
- return false;
+ if (maxcount > 0 && incrtime == 0)
+ {
+ if (player)
+ ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount);
+ else
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, id, vendor_entry);
+ return false;
+ }
+ else if (maxcount == 0 && incrtime > 0)
+ {
+ if (player)
+ ChatHandler(player->GetSession()).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0");
+ else
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", id, vendor_entry);
+ return false;
+ }
}
VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry);
if (!vItems)
return true; // later checks for non-empty lists
- if (vItems->FindItemCostPair(item_id, ExtendedCost))
+ if (vItems->FindItemCostPair(id, ExtendedCost, type))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, id, ExtendedCost, type);
else
- TC_LOG_ERROR(LOG_FILTER_SQL, "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Table `npc_vendor` has duplicate items %u (with extended cost %u, type %u) for vendor (Entry: %u), ignoring", id, ExtendedCost, type, vendor_entry);
return false;
}
- if (vItems->GetItemCount() >= MAX_VENDOR_ITEMS)
+ if (vItems->GetItemCount() >= MAX_VENDOR_ITEMS) // FIXME: GetItemCount range 0...255 MAX_VENDOR_ITEMS = 300
{
if (player)
ChatHandler(player->GetSession()).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS);
@@ -8388,7 +8389,7 @@ void ObjectMgr::LoadScriptNames()
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
- "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
+ "SELECT DISTINCT(ScriptName) FROM item_script_names WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
@@ -8518,8 +8519,8 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit
void ObjectMgr::LoadCreatureClassLevelStats()
{
uint32 oldMSTime = getMSTime();
-
- QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor FROM creature_classlevelstats");
+ // 0 1 2 3 4 5 6 7
+ QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basehp3, basemana, basearmor FROM creature_classlevelstats");
if (!result)
{
@@ -8538,10 +8539,10 @@ void ObjectMgr::LoadCreatureClassLevelStats()
CreatureBaseStats stats;
for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i)
- stats.BaseHealth[i] = fields[i + 2].GetInt16();
+ stats.BaseHealth[i] = fields[i + 2].GetUInt32();
- stats.BaseMana = fields[5].GetInt16();
- stats.BaseArmor = fields[6].GetInt16();
+ stats.BaseMana = fields[6].GetUInt32();
+ stats.BaseArmor = fields[7].GetUInt32();
if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0)
TC_LOG_ERROR(LOG_FILTER_SQL, "Creature base stats for level %u has invalid class %u", Level, Class);
@@ -8714,6 +8715,74 @@ void ObjectMgr::LoadFactionChangeReputations()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u faction change reputation pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadHotfixData()
+{
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT entry, type, UNIX_TIMESTAMP(hotfixDate) FROM hotfix_data");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 hotfix info entries. DB table `hotfix_data` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ _hotfixData.reserve(result->GetRowCount());
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ HotfixInfo info;
+ info.Entry = fields[0].GetUInt32();
+ info.Type = fields[1].GetUInt32();
+ info.Timestamp = fields[2].GetUInt64();
+ _hotfixData.push_back(info);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u hotfix info entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadMissingKeyChains()
+{
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT keyId, k1, k2, k3, k4, k5, k6, k7, k8, "
+ "k9, k10, k11, k12, k13, k14, k15, k16, "
+ "k17, k18, k19, k20, k21, k22, k23, k24, "
+ "k25, k26, k27, k28, k29, k30, k31, k32 "
+ "FROM keychain_db2 ORDER BY keyId DESC");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 KeyChain entries. DB table `keychain_db2` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+
+ KeyChainEntry* kce = sKeyChainStore.CreateEntry(id, true);
+ kce->Id = id;
+ for (uint32 i = 0; i < KEYCHAIN_SIZE; ++i)
+ kce->Key[i] = fields[1 + i].GetUInt8();
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u KeyChain entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadFactionChangeSpells()
{
uint32 oldMSTime = getMSTime();
@@ -8784,6 +8853,99 @@ void ObjectMgr::LoadFactionChangeTitles()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadPhaseDefinitions()
+{
+ _PhaseDefinitionStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3 4 5
+ QueryResult result = WorldDatabase.Query("SELECT zoneId, entry, phasemask, phaseId, terrainswapmap, flags FROM `phase_definitions` ORDER BY `entry` ASC");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ PhaseDefinition PhaseDefinition;
+
+ PhaseDefinition.zoneId = fields[0].GetUInt32();
+ PhaseDefinition.entry = fields[1].GetUInt32();
+ PhaseDefinition.phasemask = fields[2].GetUInt32();
+ PhaseDefinition.phaseId = fields[3].GetUInt32();
+ PhaseDefinition.terrainswapmap = fields[4].GetUInt32();
+ PhaseDefinition.flags = fields[5].GetUInt32();
+
+ // Checks
+ if ((PhaseDefinition.flags & PHASE_FLAG_OVERWRITE_EXISTING) && (PhaseDefinition.flags & PHASE_FLAG_NEGATE_PHASE))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Flags defined in phase_definitions in zoneId %d and entry %u does contain PHASE_FLAG_OVERWRITE_EXISTING and PHASE_FLAG_NEGATE_PHASE. Setting flags to PHASE_FLAG_OVERWRITE_EXISTING", PhaseDefinition.zoneId, PhaseDefinition.entry);
+ PhaseDefinition.flags &= ~PHASE_FLAG_NEGATE_PHASE;
+ }
+
+ _PhaseDefinitionStore[PhaseDefinition.zoneId].push_back(PhaseDefinition);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u phasing definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadSpellPhaseInfo()
+{
+ _SpellPhaseStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT id, phasemask, terrainswapmap FROM `spell_phase`");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spell dbc infos. DB table `spell_phase` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ SpellPhaseInfo spellPhaseInfo;
+ spellPhaseInfo.spellId = fields[0].GetUInt32();
+
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellPhaseInfo.spellId);
+ if (!spell)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Spell %u defined in `spell_phase` does not exists, skipped.", spellPhaseInfo.spellId);
+ continue;
+ }
+
+ if (!spell->HasAura(SPELL_AURA_PHASE))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Spell %u defined in `spell_phase` does not have aura effect type SPELL_AURA_PHASE, useless value.", spellPhaseInfo.spellId);
+ continue;
+ }
+
+ spellPhaseInfo.phasemask = fields[1].GetUInt32();
+ spellPhaseInfo.terrainswapmap = fields[2].GetUInt32();
+
+ _SpellPhaseStore[spellPhaseInfo.spellId] = spellPhaseInfo;
+
+ ++count;
+ }
+ while (result->NextRow());
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell dbc infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry)
{
GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 266fe8ee35c..793f32de6bf 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -42,11 +42,12 @@
#include <limits>
#include "ConditionMgr.h"
#include <functional>
+#include "PhaseMgr.h"
+#include "DB2Stores.h"
class Item;
+class PhaseMgr;
struct AccessRequirement;
-struct PlayerClassInfo;
-struct PlayerClassLevelInfo;
struct PlayerInfo;
struct PlayerLevelInfo;
@@ -401,7 +402,7 @@ struct SpellClickInfo
typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoContainer;
typedef std::pair<SpellClickInfoContainer::const_iterator, SpellClickInfoContainer::const_iterator> SpellClickInfoMapBounds;
-struct AreaTrigger
+struct AreaTriggerStruct
{
uint32 target_mapId;
float target_X;
@@ -444,7 +445,6 @@ typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDat
typedef UNORDERED_MAP<uint32, CreatureLocale> CreatureLocaleContainer;
typedef UNORDERED_MAP<uint32, GameObjectLocale> GameObjectLocaleContainer;
typedef UNORDERED_MAP<uint32, ItemLocale> ItemLocaleContainer;
-typedef UNORDERED_MAP<uint32, ItemSetNameLocale> ItemSetNameLocaleContainer;
typedef UNORDERED_MAP<uint32, QuestLocale> QuestLocaleContainer;
typedef UNORDERED_MAP<uint32, NpcTextLocale> NpcTextLocaleContainer;
typedef UNORDERED_MAP<uint32, PageTextLocale> PageTextLocaleContainer;
@@ -584,6 +584,7 @@ struct GraveYardData
};
typedef std::multimap<uint32, GraveYardData> GraveYardContainer;
+typedef UNORDERED_MAP<uint32 /* graveyard Id */, float /* orientation */> GraveyardOrientationContainer;
typedef std::pair<GraveYardContainer::const_iterator, GraveYardContainer::const_iterator> GraveYardMapBounds;
typedef std::pair<GraveYardContainer::iterator, GraveYardContainer::iterator> GraveYardMapBoundsNonConst;
@@ -638,6 +639,15 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef UNORDERED_MAP<uint32, DungeonEncounterList> DungeonEncounterContainer;
+struct HotfixInfo
+{
+ uint32 Type;
+ uint32 Timestamp;
+ uint32 Entry;
+};
+
+typedef std::vector<HotfixInfo> HotfixData;
+
class PlayerDumpReader;
class ObjectMgr
@@ -654,7 +664,7 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, Quest*> QuestMap;
- typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerContainer;
+ typedef UNORDERED_MAP<uint32, AreaTriggerStruct> AreaTriggerContainer;
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptContainer;
@@ -674,7 +684,7 @@ class ObjectMgr
GameObjectTemplate const* GetGameObjectTemplate(uint32 entry);
GameObjectTemplateContainer const* GetGameObjectTemplates() const { return &_gameObjectTemplateStore; }
- int LoadReferenceVendor(int32 vendor, int32 item_id, std::set<uint32> *skip_vendors);
+ int LoadReferenceVendor(int32 vendor, int32 item, uint8 type, std::set<uint32> *skip_vendors);
void LoadGameObjectTemplate();
void AddGameobjectInfo(GameObjectTemplate* goinfo);
@@ -691,25 +701,11 @@ class ObjectMgr
ItemTemplate const* GetItemTemplate(uint32 entry);
ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; }
- ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId)
- {
- ItemSetNameContainer::iterator itr = _itemSetNameStore.find(itemId);
- if (itr != _itemSetNameStore.end())
- return &itr->second;
- return NULL;
- }
-
InstanceTemplate const* GetInstanceTemplate(uint32 mapId);
PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint8 level) const;
- PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const
- {
- if (class_ >= MAX_CLASSES)
- return NULL;
- return _playerClassInfo[class_];
- }
- void GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const;
+ void GetPlayerClassLevelInfo(uint32 class_, uint8 level, uint32& baseHP, uint32& baseMana) const;
PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const;
@@ -760,7 +756,7 @@ class ObjectMgr
void LoadGraveyardZones();
GraveYardData const* FindGraveYardData(uint32 id, uint32 zone);
- AreaTrigger const* GetAreaTrigger(uint32 trigger) const
+ AreaTriggerStruct const* GetAreaTrigger(uint32 trigger) const
{
AreaTriggerContainer::const_iterator itr = _areaTriggerStore.find(trigger);
if (itr != _areaTriggerStore.end())
@@ -776,8 +772,8 @@ class ObjectMgr
return NULL;
}
- AreaTrigger const* GetGoBackTrigger(uint32 Map) const;
- AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const;
+ AreaTriggerStruct const* GetGoBackTrigger(uint32 Map) const;
+ AreaTriggerStruct const* GetMapEntranceTrigger(uint32 Map) const;
uint32 GetAreaTriggerScriptId(uint32 trigger_id);
SpellScriptsBounds GetSpellScriptsBounds(uint32 spellId);
@@ -895,6 +891,7 @@ class ObjectMgr
void LoadDbScriptStrings();
void LoadCreatureClassLevelStats();
void LoadCreatureLocales();
+ void LoadGraveyardOrientations();
void LoadCreatureTemplates();
void LoadCreatureTemplateAddons();
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
@@ -908,9 +905,9 @@ class ObjectMgr
void LoadGameObjectLocales();
void LoadGameobjects();
void LoadItemTemplates();
+ void LoadItemTemplateAddon();
+ void LoadItemScriptNames();
void LoadItemLocales();
- void LoadItemSetNames();
- void LoadItemSetNameLocales();
void LoadQuestLocales();
void LoadNpcTextLocales();
void LoadPageTextLocales();
@@ -960,6 +957,12 @@ class ObjectMgr
void LoadTrainerSpell();
void AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, uint32 reqSkill, uint32 reqSkillValue, uint32 reqLevel);
+ void LoadPhaseDefinitions();
+ void LoadSpellPhaseInfo();
+
+ PhaseDefinitionStore const* GetPhaseDefinitionStore() { return &_PhaseDefinitionStore; }
+ SpellPhaseStore const* GetSpellPhaseStore() { return &_SpellPhaseStore; }
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint8 level);
uint32 GetXPForLevel(uint8 level) const;
@@ -980,6 +983,7 @@ class ObjectMgr
uint64 GenerateEquipmentSetGuid();
uint32 GenerateMailID();
uint32 GeneratePetNumber();
+ uint64 GenerateVoidStorageItemId();
typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
@@ -1054,12 +1058,6 @@ class ObjectMgr
if (itr == _itemLocaleStore.end()) return NULL;
return &itr->second;
}
- ItemSetNameLocale const* GetItemSetNameLocale(uint32 entry) const
- {
- ItemSetNameLocaleContainer::const_iterator itr = _itemSetNameLocaleStore.find(entry);
- if (itr == _itemSetNameLocaleStore.end())return NULL;
- return &itr->second;
- }
QuestLocale const* GetQuestLocale(uint32 entry) const
{
QuestLocaleContainer::const_iterator itr = _questLocaleStore.find(entry);
@@ -1162,9 +1160,19 @@ class ObjectMgr
return &iter->second;
}
- void AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, bool persist = true); // for event
- bool RemoveVendorItem(uint32 entry, uint32 item, bool persist = true); // for event
- bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
+
+ float const* GetGraveyardOrientation(uint32 id) const
+ {
+ GraveyardOrientationContainer::const_iterator iter = _graveyardOrientations.find(id);
+ if (iter != _graveyardOrientations.end())
+ return &iter->second;
+
+ return NULL;
+ }
+
+ void AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist = true); // for event
+ bool RemoveVendorItem(uint32 entry, uint32 item, uint8 type, bool persist = true); // for event
+ bool IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
void LoadScriptNames();
ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; }
@@ -1219,6 +1227,21 @@ class ObjectMgr
void LoadFactionChangeSpells();
void LoadFactionChangeTitles();
+ void LoadHotfixData();
+ HotfixData const& GetHotfixData() const { return _hotfixData; }
+ time_t GetHotfixDate(uint32 entry, uint32 type) const
+ {
+ time_t ret = 0;
+ for (HotfixData::const_iterator itr = _hotfixData.begin(); itr != _hotfixData.end(); ++itr)
+ if (itr->Entry == entry && itr->Type == type)
+ if (itr->Timestamp > ret)
+ ret = itr->Timestamp;
+
+ return ret ? ret : time(NULL);
+ }
+
+ void LoadMissingKeyChains();
+
private:
// first free id for selected id type
uint32 _auctionId;
@@ -1226,6 +1249,7 @@ class ObjectMgr
uint32 _itemTextId;
uint32 _mailId;
uint32 _hiPetNumber;
+ uint64 _voidItemId;
// first free low guid for selected guid type
uint32 _hiCharGuid;
@@ -1236,6 +1260,7 @@ class ObjectMgr
uint32 _hiGoGuid;
uint32 _hiDoGuid;
uint32 _hiCorpseGuid;
+ uint32 _hiAreaTriggerGuid;
uint32 _hiMoTransGuid;
QuestMap _questTemplates;
@@ -1289,6 +1314,9 @@ class ObjectMgr
PageTextContainer _pageTextStore;
InstanceTemplateContainer _instanceTemplateStore;
+ PhaseDefinitionStore _PhaseDefinitionStore;
+ SpellPhaseStore _SpellPhaseStore;
+
private:
void LoadScripts(ScriptsType type);
void CheckScripts(ScriptsType type, std::set<int32>& ids);
@@ -1303,8 +1331,6 @@ class ObjectMgr
// PetLevelInfoContainer[creature_id][level]
PetLevelInfoContainer _petInfoStore; // [creature_id][level]
- PlayerClassInfo* _playerClassInfo[MAX_CLASSES];
-
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
PlayerInfo* _playerInfo[MAX_RACES][MAX_CLASSES];
@@ -1322,9 +1348,6 @@ class ObjectMgr
HalfNameContainer _petHalfName0;
HalfNameContainer _petHalfName1;
- typedef UNORDERED_MAP<uint32, ItemSetNameEntry> ItemSetNameContainer;
- ItemSetNameContainer _itemSetNameStore;
-
MapObjectGuids _mapObjectGuidsStore;
CreatureDataContainer _creatureDataStore;
CreatureTemplateContainer _creatureTemplateStore;
@@ -1342,7 +1365,6 @@ class ObjectMgr
ItemTemplateContainer _itemTemplateStore;
ItemLocaleContainer _itemLocaleStore;
- ItemSetNameLocaleContainer _itemSetNameLocaleStore;
QuestLocaleContainer _questLocaleStore;
NpcTextLocaleContainer _npcTextLocaleStore;
PageTextLocaleContainer _pageTextLocaleStore;
@@ -1353,6 +1375,8 @@ class ObjectMgr
CacheVendorItemContainer _cacheVendorItemStore;
CacheTrainerSpellContainer _cacheTrainerSpellStore;
+ GraveyardOrientationContainer _graveyardOrientations;
+
std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate
std::set<uint32> _hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate
@@ -1363,6 +1387,7 @@ class ObjectMgr
GO_TO_GO,
GO_TO_CREATURE // GO is dependant on creature
};
+ HotfixData _hotfixData;
};
#define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance()
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index ad48e4fd128..0cb2f32f621 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -30,6 +30,7 @@ class DynamicObject;
class GameObject;
class Pet;
class Player;
+class AreaTrigger;
#define MAX_NUMBER_OF_CELLS 8
@@ -57,13 +58,14 @@ class Player;
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
-typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
+typedef TYPELIST_5(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/, AreaTrigger) AllGridObjectTypes;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType;
typedef GridRefManager<GameObject> GameObjectMapType;
typedef GridRefManager<Player> PlayerMapType;
+typedef GridRefManager<AreaTrigger> AreaTriggerMapType;
enum GridMapTypeMask
{
@@ -72,7 +74,8 @@ enum GridMapTypeMask
GRID_MAP_TYPE_MASK_DYNAMICOBJECT = 0x04,
GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08,
GRID_MAP_TYPE_MASK_PLAYER = 0x10,
- GRID_MAP_TYPE_MASK_ALL = 0x1F
+ GRID_MAP_TYPE_MASK_AREATRIGGER = 0x20,
+ GRID_MAP_TYPE_MASK_ALL = 0x3F
};
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 24f8cbda1a2..088189737a9 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -362,3 +362,4 @@ bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &);
+template void ObjectUpdater::Visit<AreaTrigger>(AreaTriggerMapType &);
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index f52b6443872..073546d7764 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -25,6 +25,7 @@
#include "Corpse.h"
#include "Object.h"
+#include "AreaTrigger.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "Player.h"
@@ -45,7 +46,7 @@ namespace Trinity
std::set<Unit*> i_visibleNow;
Player::ClientGUIDs vis_guids;
- VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {}
+ VisibleNotifier(Player &player) : i_player(player), i_data(player.GetMapId()), vis_guids(player.m_clientGUIDs) {}
template<class T> void Visit(GridRefManager<T> &m);
void SendToSelf(void);
};
@@ -118,6 +119,7 @@ namespace Trinity
void Visit(GameObjectMapType &m) { updateObjects<GameObject>(m); }
void Visit(DynamicObjectMapType &m) { updateObjects<DynamicObject>(m); }
void Visit(CorpseMapType &m) { updateObjects<Corpse>(m); }
+ void Visit(AreaTriggerMapType &m) { updateObjects<AreaTrigger>(m); }
};
struct MessageDistDeliverer
@@ -183,6 +185,7 @@ namespace Trinity
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};
@@ -203,6 +206,7 @@ namespace Trinity
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};
@@ -223,6 +227,7 @@ namespace Trinity
void Visit(CorpseMapType &m);
void Visit(GameObjectMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};
@@ -281,6 +286,15 @@ namespace Trinity
i_do(itr->getSource());
}
+ void Visit(AreaTriggerMapType &m)
+ {
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ if (itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
+ }
+
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};
@@ -1375,6 +1389,25 @@ namespace Trinity
uint64 _GUID;
};
+ class HeightDifferenceCheck
+ {
+ public:
+ HeightDifferenceCheck(WorldObject* go, float diff, bool reverse)
+ : _baseObject(go), _difference(diff), _reverse(reverse)
+ {
+ }
+
+ bool operator()(WorldObject* unit) const
+ {
+ return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse;
+ }
+
+ private:
+ WorldObject* _baseObject;
+ float _difference;
+ bool _reverse;
+ };
+
class UnitAuraCheck
{
public:
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 40b2df3706b..6c7d69e57a0 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -164,6 +164,28 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
}
}
+template<class Check>
+void Trinity::WorldObjectSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ // already found
+ if (i_object)
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ {
+ i_object = itr->getSource();
+ return;
+ }
+ }
+}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
@@ -246,6 +268,22 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m)
}
template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
@@ -300,6 +338,17 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
i_objects.push_back(itr->getSource());
}
+template<class Check>
+void Trinity::WorldObjectListSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
+}
+
// Gameobject searchers
template<class Check>
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index 09c9f40899b..3c7833baf15 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -24,6 +24,7 @@
#include "GameObject.h"
#include "DynamicObject.h"
#include "Corpse.h"
+#include "AreaTrigger.h"
#include "World.h"
#include "CellImpl.h"
#include "CreatureAI.h"
@@ -234,7 +235,9 @@ template void ObjectGridUnloader::Visit(CreatureMapType &);
template void ObjectGridUnloader::Visit(GameObjectMapType &);
template void ObjectGridUnloader::Visit(DynamicObjectMapType &);
template void ObjectGridUnloader::Visit(CorpseMapType &);
+template void ObjectGridUnloader::Visit(AreaTriggerMapType &);
template void ObjectGridCleaner::Visit(CreatureMapType &);
template void ObjectGridCleaner::Visit<GameObject>(GameObjectMapType &);
template void ObjectGridCleaner::Visit<DynamicObject>(DynamicObjectMapType &);
template void ObjectGridCleaner::Visit<Corpse>(CorpseMapType &);
+template void ObjectGridCleaner::Visit<AreaTrigger>(AreaTriggerMapType &);
diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h
index 11f91670a5f..dfd308f187e 100644
--- a/src/server/game/Grids/ObjectGridLoader.h
+++ b/src/server/game/Grids/ObjectGridLoader.h
@@ -40,6 +40,7 @@ class ObjectGridLoader
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &) const {}
void Visit(DynamicObjectMapType&) const {}
+ void Visit(AreaTriggerMapType &) const {}
void LoadN(void);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 59da04f3673..9d27ca61511 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -266,6 +266,37 @@ void Group::ConvertToRaid()
player->UpdateForQuestWorldObjects();
}
+void Group::ConvertToGroup()
+{
+ if (m_memberSlots.size() > 5)
+ return; // What message error should we send?
+
+ m_groupType = GroupType(GROUPTYPE_NORMAL);
+
+ if (m_subGroupsCounts)
+ {
+ delete[] m_subGroupsCounts;
+ m_subGroupsCounts = NULL;
+ }
+
+ if (!isBGGroup() && !isBFGroup())
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_TYPE);
+
+ stmt->setUInt8(0, uint8(m_groupType));
+ stmt->setUInt32(1, m_dbStoreId);
+
+ CharacterDatabase.Execute(stmt);
+ }
+
+ SendUpdate();
+
+ // update quest related GO states (quest activity dependent from raid membership)
+ for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
+ player->UpdateForQuestWorldObjects();
+}
+
bool Group::AddInvite(Player* player)
{
if (!player || player->GetGroupInvite())
@@ -437,7 +468,7 @@ bool Group::AddMember(Player* player)
// Broadcast new player group member fields to rest of the group
player->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
- UpdateData groupData;
+ UpdateData groupData(player->GetMapId());
WorldPacket groupDataPacket;
// Broadcast group members' fields to player
@@ -457,7 +488,7 @@ bool Group::AddMember(Player* player)
if (member->HaveAtClient(player))
{
- UpdateData newData;
+ UpdateData newData(player->GetMapId());
WorldPacket newDataPacket;
player->BuildValuesUpdateBlockForPlayer(&newData, member);
if (newData.HasData())
@@ -781,6 +812,7 @@ void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r)
data << uint32(r.itemCount); // items in stack
data << uint32(countDown); // the countdown time to choose "need" or "greed"
data << uint8(r.rollVoteMask); // roll type mask
+ data << uint8(r.totalPlayersRolling); // maybe the number of players rolling for it???
for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
{
@@ -811,6 +843,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p,
if (!canNeed)
voteMask &= ~ROLL_FLAG_TYPE_NEED;
data << uint8(voteMask); // roll type mask
+ data << uint8(r.totalPlayersRolling); // maybe the number of players rolling for it???
p->GetSession()->SendPacket(&data);
}
@@ -824,7 +857,7 @@ void Group::SendLootRoll(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber,
data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(roll.itemRandomSuffix); // randomSuffix
data << uint32(roll.itemRandomPropId); // Item random property ID
- data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
+ data << uint32(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed
@@ -848,7 +881,7 @@ void Group::SendLootRollWon(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumb
data << uint32(roll.itemRandomSuffix); // randomSuffix
data << uint32(roll.itemRandomPropId); // Item random property
data << uint64(targetGuid); // guid of the player who won.
- data << uint8(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL
+ data << uint32(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL
data << uint8(rollType); // rollType related to SMSG_LOOT_ROLL
for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr)
@@ -1492,6 +1525,7 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot)
{
data << uint8(sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0); // FIXME - Dungeon save status? 2 = done
data << uint32(sLFGMgr->GetDungeon(m_guid));
+ data << uint8(0); // 4.x new
}
data << uint64(m_guid);
@@ -1524,7 +1558,6 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot)
data << uint8(m_lootThreshold); // loot threshold
data << uint8(m_dungeonDifficulty); // Dungeon Difficulty
data << uint8(m_raidDifficulty); // Raid Difficulty
- data << uint8(0); // 3.3
}
player->GetSession()->SendPacket(&data);
@@ -1547,6 +1580,21 @@ void Group::UpdatePlayerOutOfRange(Player* player)
}
}
+void Group::BroadcastAddonMessagePacket(WorldPacket* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group, uint64 ignore)
+{
+ for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player* player = itr->getSource();
+ if (!player || (ignore != 0 && player->GetGUID() == ignore) || (ignorePlayersInBGRaid && player->GetGroup() != this))
+ continue;
+
+ if (WorldSession* session = player->GetSession())
+ if (session && (group == -1 || itr->getSubGroup() == group))
+ if (session->IsAddonRegistered(prefix))
+ session->SendPacket(packet);
+ }
+}
+
void Group::BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group, uint64 ignore)
{
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1761,7 +1809,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->GetTypeID());
if (!bgEntry)
- return ERR_GROUP_JOIN_BATTLEGROUND_FAIL; // shouldn't happen
+ return ERR_BATTLEGROUND_JOIN_FAILED; // shouldn't happen
// check for min / max count
uint32 memberscount = GetMembersCount();
@@ -1826,7 +1874,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
if (bgOrTemplate->isArena() && memberscount != MinPlayerCount)
return ERR_ARENA_TEAM_PARTY_SIZE;
- return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID());
+ return ERR_BATTLEGROUND_NONE;
}
//===================================================
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 356a1a59663..8bc52e158c7 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -94,34 +94,38 @@ enum GroupType
enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
- GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags
- GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32
- GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32
- GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8
- GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16
- GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16
- GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16
- GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16
- GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16
- GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk
- GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid
- GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string
- GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id
- GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint32 pet cur health
- GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint32 pet max health
- GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type
- GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power
- GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power
- GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras...
- GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc)
- GROUP_UPDATE_PET = 0x0007FC00, // all pet flags
- GROUP_UPDATE_FULL = 0x0007FFFF // all known flags
+ GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16 (GroupMemberStatusFlag)
+ GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 (HP)
+ GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 (HP)
+ GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // int16 (power value)
+ GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // int16 (power value)
+ GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 (level value)
+ GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 (zone id)
+ GROUP_UPDATE_FLAG_UNK100 = 0x00000100, // int16 (unk)
+ GROUP_UPDATE_FLAG_POSITION = 0x00000200, // uint16 (x), uint16 (y), uint16 (z)
+ GROUP_UPDATE_FLAG_AURAS = 0x00000400, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
+ GROUP_UPDATE_FLAG_PET_GUID = 0x00000800, // uint64 (pet guid)
+ GROUP_UPDATE_FLAG_PET_NAME = 0x00001000, // cstring (name, NULL terminated string)
+ GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00002000, // uint16 (model id)
+ GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00004000, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00008000, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00010000, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00020000, // uint16 (power value)
+ GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00040000, // uint16 (power value)
+ GROUP_UPDATE_FLAG_PET_AURAS = 0x00080000, // [see GROUP_UPDATE_FLAG_AURAS]
+ GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00100000, // int32 (vehicle seat id)
+ GROUP_UPDATE_FLAG_PHASE = 0x00200000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
+
+ GROUP_UPDATE_PET = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
+ GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE |
+ GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER | GROUP_UPDATE_FLAG_PET_AURAS, // all pet flags
+ GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
+ GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER |
+ GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION |
+ GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_PET | GROUP_UPDATE_FLAG_PHASE // all known flags, except UNK100 and VEHICLE_SEAT
};
-#define GROUP_UPDATE_FLAGS_COUNT 20
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
-static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 2, 2, 2, 1, 2, 2, 2, 2, 4, 8, 8, 1, 2, 2, 2, 1, 2, 2, 8};
-
class Roll : public LootValidatorRef
{
public:
@@ -240,6 +244,7 @@ class Group
void ConvertToLFG();
void ConvertToRaid();
+ void ConvertToGroup();
void SetBattlegroundGroup(Battleground* bg);
void SetBattlefieldGroup(Battlefield* bf);
@@ -268,6 +273,7 @@ class Group
void UpdatePlayerOutOfRange(Player* player);
// ignore: GUID of player that will be ignored
void BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group = -1, uint64 ignore = 0);
+ void BroadcastAddonMessagePacket(WorldPacket* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group = -1, uint64 ignore = 0);
void BroadcastReadyCheck(WorldPacket* packet);
void OfflineReadyCheck();
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 0369615da53..87f2a485f75 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -22,6 +22,7 @@
#include "Config.h"
#include "DatabaseEnv.h"
#include "Guild.h"
+#include "GuildFinderMgr.h"
#include "GuildMgr.h"
#include "Language.h"
#include "Log.h"
@@ -153,9 +154,13 @@ inline void Guild::LogHolder::AddEvent(SQLTransaction& trans, LogEntry* entry)
// Writes information about all events into packet.
inline void Guild::LogHolder::WritePacket(WorldPacket& data) const
{
- data << uint8(m_log.size());
+ ByteBuffer buffer;
+ data.WriteBits(m_log.size(), 23);
for (GuildLog::const_iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
- (*itr)->WritePacket(data);
+ (*itr)->WritePacket(data, buffer);
+
+ data.FlushBits();
+ data.append(buffer);
}
inline uint32 Guild::LogHolder::GetNextGUID()
@@ -189,20 +194,56 @@ void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
+void Guild::EventLogEntry::WritePacket(WorldPacket& data, ByteBuffer& content) const
{
- // Event type
- data << uint8(m_eventType);
- // Player 1
- data << uint64(MAKE_NEW_GUID(m_playerGuid1, 0, HIGHGUID_PLAYER));
- // Player 2 not for left/join guild events
- if (m_eventType != GUILD_EVENT_LOG_JOIN_GUILD && m_eventType != GUILD_EVENT_LOG_LEAVE_GUILD)
- data << uint64(MAKE_NEW_GUID(m_playerGuid2, 0, HIGHGUID_PLAYER));
- // New Rank - only for promote/demote guild events
- if (m_eventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || m_eventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
- data << uint8(m_newRank);
+ ObjectGuid guid1 = MAKE_NEW_GUID(m_playerGuid1, 0, HIGHGUID_PLAYER);
+ ObjectGuid guid2 = MAKE_NEW_GUID(m_playerGuid2, 0, HIGHGUID_PLAYER);
+
+ data.WriteBit(guid1[2]);
+ data.WriteBit(guid1[4]);
+ data.WriteBit(guid2[7]);
+ data.WriteBit(guid2[6]);
+ data.WriteBit(guid1[3]);
+ data.WriteBit(guid2[3]);
+ data.WriteBit(guid2[5]);
+ data.WriteBit(guid1[7]);
+ data.WriteBit(guid1[5]);
+ data.WriteBit(guid1[0]);
+ data.WriteBit(guid2[4]);
+ data.WriteBit(guid2[2]);
+ data.WriteBit(guid2[0]);
+ data.WriteBit(guid2[1]);
+ data.WriteBit(guid1[1]);
+ data.WriteBit(guid1[6]);
+
+ content.WriteByteSeq(guid2[3]);
+ content.WriteByteSeq(guid2[2]);
+ content.WriteByteSeq(guid2[5]);
+
+ // New Rank
+ content << uint8(m_newRank);
+
+ content.WriteByteSeq(guid2[4]);
+ content.WriteByteSeq(guid1[0]);
+ content.WriteByteSeq(guid1[4]);
+
// Event timestamp
- data << uint32(::time(NULL) - m_timestamp);
+ content << uint32(::time(NULL) - m_timestamp);
+
+ content.WriteByteSeq(guid1[7]);
+ content.WriteByteSeq(guid1[3]);
+ content.WriteByteSeq(guid2[0]);
+ content.WriteByteSeq(guid2[6]);
+ content.WriteByteSeq(guid2[7]);
+ content.WriteByteSeq(guid1[5]);
+
+ // Event type
+ content << uint8(m_eventType);
+
+ content.WriteByteSeq(guid2[1]);
+ content.WriteByteSeq(guid1[2]);
+ content.WriteByteSeq(guid1[6]);
+ content.WriteByteSeq(guid1[1]);
}
// BankEventLogEntry
@@ -230,29 +271,101 @@ void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
+void Guild::BankEventLogEntry::WritePacket(WorldPacket& data, ByteBuffer& content) const
{
- data << uint8(m_eventType);
- data << uint64(MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER));
+ ObjectGuid logGuid = MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER);
- switch (m_eventType)
- {
- case GUILD_BANK_LOG_DEPOSIT_ITEM:
- case GUILD_BANK_LOG_WITHDRAW_ITEM:
- data << uint32(m_itemOrMoney);
- data << uint32(m_itemStackCount);
- break;
- case GUILD_BANK_LOG_MOVE_ITEM:
- case GUILD_BANK_LOG_MOVE_ITEM2:
- data << uint32(m_itemOrMoney);
- data << uint32(m_itemStackCount);
- data << uint8(m_destTabId);
- break;
- default:
- data << uint32(m_itemOrMoney);
- }
+ bool hasItem = m_eventType == GUILD_BANK_LOG_DEPOSIT_ITEM || m_eventType == GUILD_BANK_LOG_WITHDRAW_ITEM ||
+ m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2;
+
+ bool itemMoved = (m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2);
+
+ bool hasStack = (hasItem && m_itemStackCount > 1) || itemMoved;
+
+ data.WriteBit(IsMoneyEvent());
+ data.WriteBit(logGuid[4]);
+ data.WriteBit(logGuid[1]);
+ data.WriteBit(hasItem);
+ data.WriteBit(hasStack);
+ data.WriteBit(logGuid[2]);
+ data.WriteBit(logGuid[5]);
+ data.WriteBit(logGuid[3]);
+ data.WriteBit(logGuid[6]);
+ data.WriteBit(logGuid[0]);
+ data.WriteBit(itemMoved);
+ data.WriteBit(logGuid[7]);
+
+ content.WriteByteSeq(logGuid[6]);
+ content.WriteByteSeq(logGuid[1]);
+ content.WriteByteSeq(logGuid[5]);
+ if (hasStack)
+ content << uint32(m_itemStackCount);
+
+ content << uint8(m_eventType);
+ content.WriteByteSeq(logGuid[2]);
+ content.WriteByteSeq(logGuid[4]);
+ content.WriteByteSeq(logGuid[0]);
+ content.WriteByteSeq(logGuid[7]);
+ content.WriteByteSeq(logGuid[3]);
+ if (hasItem)
+ content << uint32(m_itemOrMoney);
+
+ content << uint32(time(NULL) - m_timestamp);
+
+ if (IsMoneyEvent())
+ content << uint64(m_itemOrMoney);
- data << uint32(time(NULL) - m_timestamp);
+ if (itemMoved)
+ content << uint8(m_destTabId);
+}
+
+void Guild::NewsLogEntry::SaveToDB(SQLTransaction& trans) const
+{
+ uint8 index = 0;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_NEWS);
+ stmt->setUInt32( index, m_guildId);
+ stmt->setUInt32(++index, GetGUID());
+ stmt->setUInt8 (++index, GetType());
+ stmt->setUInt32(++index, GetPlayerGuid());
+ stmt->setUInt32(++index, GetFlags());
+ stmt->setUInt32(++index, GetValue());
+ stmt->setUInt64(++index, GetTimestamp());
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+}
+
+void Guild::NewsLogEntry::WritePacket(WorldPacket& data, ByteBuffer& /*content*/) const
+{
+ data.WriteBits(0, 26); // Not yet implemented used for guild achievements
+ ObjectGuid guid = GetPlayerGuid();
+
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[5]);
+
+ data << uint32(GetFlags()); // 1 sticky
+ data << uint32(GetValue());
+ data << uint32(0); // always 0
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(GetGUID());
+ data << uint32(GetType());
+ data.AppendPackedTime(GetTimestamp());
}
// RankInfo
@@ -301,20 +414,6 @@ void Guild::RankInfo::CreateMissingTabsIfNeeded(uint8 tabs, SQLTransaction& tran
}
}
-void Guild::RankInfo::WritePacket(WorldPacket& data) const
-{
- data << uint32(m_rights);
- if (m_bankMoneyPerDay == GUILD_WITHDRAW_MONEY_UNLIMITED)
- data << uint32(GUILD_WITHDRAW_MONEY_UNLIMITED);
- else
- data << uint32(m_bankMoneyPerDay);
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- data << uint32(m_bankTabRightsAndSlots[i].GetRights());
- data << uint32(m_bankTabRightsAndSlots[i].GetSlots());
- }
-}
-
void Guild::RankInfo::SetName(std::string const& name)
{
if (m_name == name)
@@ -443,64 +542,6 @@ void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB)
}
}
-inline void Guild::BankTab::WritePacket(WorldPacket& data) const
-{
- uint8 count = 0;
-
- size_t pos = data.wpos();
- data << uint8(0);
-
- for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
- if (WriteSlotPacket(data, slotId))
- ++count;
-
- data.put<uint8>(pos, count);
-}
-
-// Writes information about contents of specified slot into packet.
-bool Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignoreEmpty /* = true */) const
-{
- Item* pItem = GetItem(slotId);
- uint32 itemEntry = pItem ? pItem->GetEntry() : 0;
-
- if (!itemEntry && ignoreEmpty)
- return false;
-
- data << uint8(slotId);
- data << uint32(itemEntry);
- if (itemEntry)
- {
- data << uint32(0); // 3.3.0 (0x00018020, 0x00018000)
-
-
- if (uint32 random = pItem->GetItemRandomPropertyId())
- {
- data << uint32(random); // Random item property id
- data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor
- }
- else
- data << uint32(0);
-
- data << uint32(pItem->GetCount()); // ITEM_FIELD_STACK_COUNT
- data << uint32(0);
- data << uint8(abs(pItem->GetSpellCharges())); // Spell charges
-
- uint8 enchCount = 0;
- size_t enchCountPos = data.wpos();
-
- data << uint8(enchCount); // Number of enchantments
- for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
- if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
- {
- data << uint8(i);
- data << uint32(enchId);
- ++enchCount;
- }
- data.put<uint8>(enchCountPos, enchCount);
- }
- return true;
-}
-
void Guild::BankTab::SetInfo(std::string const& name, std::string const& icon)
{
if (m_name == name && m_icon == icon)
@@ -566,19 +607,20 @@ bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
void Guild::BankTab::SendText(Guild const* guild, WorldSession* session) const
{
- WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1 + m_text.size() + 1);
- data << uint8(m_tabId);
- data << m_text;
+ WorldPacket data(SMSG_GUILD_BANK_QUERY_TEXT_RESULT, 1 + m_text.size() + 1);
+ data.WriteBits(m_text.length(), 14);
+ data << uint32(m_tabId);
+ data.WriteString(m_text);
if (session)
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_QUERY_GUILD_BANK_TEXT [%s]: Tabid: %u, Text: %s"
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_QUERY_TEXT_RESULT [%s]: Tabid: %u, Text: %s"
, session->GetPlayerInfo().c_str(), m_tabId, m_text.c_str());
session->SendPacket(&data);
}
else
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_QUERY_GUILD_BANK_TEXT [Broadcast]: Tabid: %u, Text: %s", m_tabId, m_text.c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_QUERY_TEXT_RESULT [Broadcast]: Tabid: %u, Text: %s", m_tabId, m_text.c_str());
guild->BroadcastPacket(&data);
}
}
@@ -591,15 +633,17 @@ void Guild::Member::SetStats(Player* player)
m_class = player->getClass();
m_zoneId = player->GetZoneId();
m_accountId = player->GetSession()->GetAccountId();
+ m_achievementPoints = player->GetAchievementPoints();
}
-void Guild::Member::SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId)
+void Guild::Member::SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId, uint32 reputation)
{
m_name = name;
m_level = level;
m_class = _class;
m_zoneId = zoneId;
m_accountId = accountId;
+ m_totalReputation = reputation;
}
void Guild::Member::SetPublicNote(std::string const& publicNote)
@@ -664,12 +708,16 @@ bool Guild::Member::LoadFromDB(Field* fields)
for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS; ++i)
m_bankWithdraw[i] = fields[5 + i].GetUInt32();
- SetStats(fields[12].GetString(),
- fields[13].GetUInt8(), // characters.level
- fields[14].GetUInt8(), // characters.class
- fields[15].GetUInt16(), // characters.zone
- fields[16].GetUInt32()); // characters.account
- m_logoutTime = fields[17].GetUInt32(); // characters.logout_time
+ SetStats(fields[14].GetString(),
+ fields[15].GetUInt8(), // characters.level
+ fields[16].GetUInt8(), // characters.class
+ fields[17].GetUInt16(), // characters.zone
+ fields[18].GetUInt32(), // characters.account
+ 0);
+ m_logoutTime = fields[19].GetUInt32(); // characters.logout_time
+ m_totalActivity = 0;
+ m_weekActivity = 0;
+ m_weekReputation = 0;
if (!CheckStats())
return false;
@@ -700,24 +748,6 @@ bool Guild::Member::CheckStats() const
return true;
}
-void Guild::Member::WritePacket(WorldPacket& data) const
-{
- data << uint64(m_guid)
- << uint8(m_flags)
- << m_name
- << uint32(m_rankId)
- << uint8(m_level)
- << uint8(m_class)
- << uint8(0)
- << uint32(m_zoneId);
-
- if (!m_flags)
- data << float(float(::time(NULL) - m_logoutTime) / DAY);
-
- data << m_publicNote
- << m_officerNote;
-}
-
// Decreases amount of money/slots left for today.
// If (tabId == GUILD_BANK_MAX_TABS) decrease money amount.
// Otherwise decrease remaining items amount for specified tab.
@@ -736,10 +766,16 @@ void Guild::Member::UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId,
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::Member::ResetValues()
+void Guild::Member::ResetValues(bool weekly /* = false*/)
{
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
m_bankWithdraw[tabId] = 0;
+
+ if (weekly)
+ {
+ m_weekActivity = 0;
+ m_weekReputation = 0;
+ }
}
// Get amount of money/slots left for today.
@@ -846,13 +882,13 @@ bool Guild::PlayerMoveItemData::InitItem()
// Anti-WPE protection. Do not move non-empty bags to bank.
if (m_pItem->IsNotEmptyBag())
{
- m_pPlayer->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, m_pItem);
+ m_pPlayer->SendEquipError(EQUIP_ERR_DESTROY_NONEMPTY_BAG, m_pItem);
m_pItem = NULL;
}
// Bound items cannot be put into bank.
else if (!m_pItem->CanBeTraded())
{
- m_pPlayer->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, m_pItem);
+ m_pPlayer->SendEquipError(EQUIP_ERR_CANT_SWAP, m_pItem);
m_pItem = NULL;
}
}
@@ -1077,11 +1113,11 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
uint32 count = pItem->GetCount();
// Soulbound items cannot be moved
if (pItem->IsSoulBound())
- return EQUIP_ERR_CANT_DROP_SOULBOUND;
+ return EQUIP_ERR_DROP_BOUND_ITEM;
// Make sure destination bank tab exists
if (m_container >= m_pGuild->_GetPurchasedTabsSize())
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// Slot explicitely specified. Check it.
if (m_slotId != NULL_SLOT)
@@ -1092,7 +1128,7 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
pItemDest = NULL;
if (!_ReserveSpace(m_slotId, pItem, pItemDest, count))
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
if (count == 0)
return EQUIP_ERR_OK;
@@ -1122,7 +1158,12 @@ Guild::Guild():
m_createdDate(0),
m_accountsNumber(0),
m_bankMoney(0),
- m_eventLog(NULL)
+ m_eventLog(NULL),
+ m_newsLog(NULL),
+ m_achievementMgr(this),
+ _level(1),
+ _experience(0),
+ _todayExperience(0)
{
memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*));
}
@@ -1135,6 +1176,8 @@ Guild::~Guild()
// Cleanup
delete m_eventLog;
m_eventLog = NULL;
+ delete m_newsLog;
+ m_newsLog = NULL;
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
{
@@ -1167,6 +1210,9 @@ bool Guild::Create(Player* pLeader, std::string const& name)
m_motd = "No message set.";
m_bankMoney = 0;
m_createdDate = ::time(NULL);
+ _level = 1;
+ _experience = 0;
+ _todayExperience = 0;
_CreateLogHolders();
TC_LOG_DEBUG(LOG_FILTER_GUILD, "GUILD: creating guild [%s] for leader %s (%u)",
@@ -1199,7 +1245,10 @@ bool Guild::Create(Player* pLeader, std::string const& name)
bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER); // Add guildmaster
if (ret)
+ {
+ _BroadcastEvent(GE_FOUNDER, 0);
sScriptMgr->OnGuildCreate(this, pLeader, name);
+ }
return ret;
}
@@ -1252,9 +1301,28 @@ void Guild::Disband()
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
+
+ sGuildFinderMgr->DeleteGuild(m_id);
+
sGuildMgr->RemoveGuild(m_id);
}
+void Guild::SaveToDB()
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_EXPERIENCE);
+ stmt->setUInt32(0, GetLevel());
+ stmt->setUInt64(1, GetExperience());
+ stmt->setUInt64(2, GetTodayExperience());
+ stmt->setUInt32(3, GetId());
+ trans->Append(stmt);
+
+ m_achievementMgr.SaveToDB(trans);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value)
{
if (Member* member = GetMember(player->GetGUID()))
@@ -1262,7 +1330,10 @@ void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value)
switch (dataid)
{
case GUILD_MEMBER_DATA_ZONEID:
- member->SetZoneID(value);
+ member->SetZoneId(value);
+ break;
+ case GUILD_MEMBER_DATA_ACHIEVEMENT_POINTS:
+ member->SetAchievementPoints(value);
break;
case GUILD_MEMBER_DATA_LEVEL:
member->SetLevel(value);
@@ -1300,18 +1371,84 @@ bool Guild::SetName(std::string const& name)
void Guild::HandleRoster(WorldSession* session /*= NULL*/)
{
+ ByteBuffer memberData(100);
// Guess size
- WorldPacket data(SMSG_GUILD_ROSTER, (4 + m_motd.length() + 1 + m_info.length() + 1 + 4 + _GetRanksSize() * (4 + 4 + GUILD_BANK_MAX_TABS * (4 + 4)) + m_members.size() * 50));
- data << uint32(m_members.size());
- data << m_motd;
- data << m_info;
-
- data << uint32(_GetRanksSize());
- for (Ranks::const_iterator ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
- ritr->WritePacket(data);
+ WorldPacket data(SMSG_GUILD_ROSTER, 100);
+ data.WriteBits(m_motd.length(), 11);
+ data.WriteBits(m_members.size(), 18);
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- itr->second->WritePacket(data);
+ {
+ Member* member = itr->second;
+ size_t pubNoteLength = member->GetPublicNote().length();
+ size_t offNoteLength = member->GetOfficerNote().length();
+
+ ObjectGuid guid = member->GetGUID();
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(0); // Has Authenticator
+ data.WriteBit(0); // Can Scroll of Ressurect
+ data.WriteBits(pubNoteLength, 8);
+ data.WriteBits(offNoteLength, 8);
+ data.WriteBit(guid[0]);
+ data.WriteBits(member->GetName().length(), 7);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+
+ memberData << uint8(member->GetClass());
+ memberData << uint32(member->GetTotalReputation());
+ memberData.WriteByteSeq(guid[0]);
+ memberData << uint64(member->GetWeekActivity());
+ memberData << uint32(member->GetRankId());
+ memberData << uint32(member->GetAchievementPoints());
+
+ // for (2 professions)
+ memberData << uint32(0) << uint32(0) << uint32(0);
+ memberData << uint32(0) << uint32(0) << uint32(0);
+
+ memberData.WriteByteSeq(guid[2]);
+ memberData << uint8(member->GetFlags());
+ memberData << uint32(member->GetZoneId());
+ memberData << uint64(member->GetTotalActivity());
+ memberData.WriteByteSeq(guid[7]);
+ memberData << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - member->GetWeekReputation());
+
+ if (pubNoteLength)
+ memberData.WriteString(member->GetPublicNote());
+
+ memberData.WriteByteSeq(guid[3]);
+ memberData << uint8(member->GetLevel());
+ memberData << int32(0); // unk
+ memberData.WriteByteSeq(guid[5]);
+ memberData.WriteByteSeq(guid[4]);
+ memberData << uint8(0); // unk
+ memberData.WriteByteSeq(guid[1]);
+ memberData << float(member->IsOnline() ? 0.0f : float(::time(NULL) - member->GetLogoutTime()) / DAY);
+
+ if (offNoteLength)
+ memberData.WriteString(member->GetOfficerNote());
+
+ memberData.WriteByteSeq(guid[6]);
+ memberData.WriteString(member->GetName());
+ }
+
+ size_t infoLength = m_info.length();
+ data.WriteBits(infoLength, 12);
+
+ data.FlushBits();
+ data.append(memberData);
+
+ if (infoLength)
+ data.WriteString(m_info);
+
+ data.WriteString(m_motd);
+ data << uint32(m_accountsNumber);
+ data << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP));
+ data.AppendPackedTime(m_createdDate);
+ data << uint32(0);
if (session)
{
@@ -1328,7 +1465,8 @@ void Guild::HandleRoster(WorldSession* session /*= NULL*/)
void Guild::HandleQuery(WorldSession* session)
{
WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, 8 * 32 + 200); // Guess size
- data << uint32(m_id);
+
+ data << uint64(GetGUID());
data << m_name;
// Rank name
@@ -1340,6 +1478,24 @@ void Guild::HandleQuery(WorldSession* session)
data << uint8(0); // Empty string
}
+ // Rank order of creation
+ for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
+ {
+ if (i < _GetRanksSize())
+ data << uint32(i);
+ else
+ data << uint32(0);
+ }
+
+ // Rank order of "importance" (sorting by rights)
+ for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
+ {
+ if (i < _GetRanksSize())
+ data << uint32(m_ranks[i].GetId());
+ else
+ data << uint32(0);
+ }
+
m_emblemInfo.WritePacket(data);
data << uint32(_GetRanksSize()); // Number of ranks used
@@ -1347,6 +1503,44 @@ void Guild::HandleQuery(WorldSession* session)
TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_QUERY_RESPONSE [%s]", session->GetPlayerInfo().c_str());
}
+void Guild::SendGuildRankInfo(WorldSession* session) const
+{
+ ByteBuffer rankData(100);
+ WorldPacket data(SMSG_GUILD_RANK, 100);
+
+ data.WriteBits(_GetRanksSize(), 18);
+
+ for (uint8 i = 0; i < _GetRanksSize(); i++)
+ {
+ RankInfo const* rankInfo = GetRankInfo(i);
+ if (!rankInfo)
+ continue;
+
+ data.WriteBits(rankInfo->GetName().length(), 7);
+
+ rankData << uint32(rankInfo->GetId());
+
+ for (uint8 j = 0; j < GUILD_BANK_MAX_TABS; ++j)
+ {
+ rankData << uint32(rankInfo->GetBankTabSlotsPerDay(j));
+ rankData << uint32(rankInfo->GetBankTabRights(j));
+ }
+
+ rankData << uint32(rankInfo->GetBankMoneyPerDay());
+ rankData << uint32(rankInfo->GetRights());
+
+ if (rankInfo->GetName().length())
+ rankData.WriteString(rankInfo->GetName());
+
+ rankData << uint32(i);
+ }
+
+ data.FlushBits();
+ data.append(rankData);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_RANK [%s]", session->GetPlayerInfo().c_str());
+}
+
void Guild::HandleSetMOTD(WorldSession* session, std::string const& motd)
{
if (m_motd == motd)
@@ -1394,11 +1588,11 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo)
Player* player = session->GetPlayer();
if (!_IsLeader(player))
SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER); // "Only guild leaders can create emblems."
- else if (!player->HasEnoughMoney(EMBLEM_PRICE))
+ else if (!player->HasEnoughMoney(uint64(EMBLEM_PRICE)))
SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY); // "You can't afford to do that."
else
{
- player->ModifyMoney(-int32(EMBLEM_PRICE));
+ player->ModifyMoney(-int64(EMBLEM_PRICE));
m_emblemInfo = emblemInfo;
m_emblemInfo.SaveToDB(m_id);
@@ -1409,20 +1603,20 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo)
}
}
-void Guild::HandleSetLeader(WorldSession* session, std::string const& name)
+void Guild::HandleSetNewGuildMaster(WorldSession* session, std::string const& name)
{
Player* player = session->GetPlayer();
- // Only leader can assign new leader
+ // Only the guild master can throne a new guild master
if (!_IsLeader(player))
SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS);
- // Old leader must be a member of guild
- else if (Member* pOldLeader = GetMember(player->GetGUID()))
+ // Old GM must be a guild member
+ else if (Member* oldGuildMaster = GetMember(player->GetGUID()))
{
- // New leader must be a member of guild
- if (Member* pNewLeader = GetMember(name))
+ // Same for the new one
+ if (Member* newGuildMaster = GetMember(name))
{
- _SetLeaderGUID(pNewLeader);
- pOldLeader->ChangeRank(GR_OFFICER);
+ _SetLeaderGUID(newGuildMaster);
+ oldGuildMaster->ChangeRank(GR_INITIATE);
_BroadcastEvent(GE_LEADER_CHANGED, 0, player->GetName().c_str(), name.c_str());
}
}
@@ -1445,19 +1639,19 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string
_BroadcastEvent(GE_BANK_TAB_UPDATED, 0, aux, name.c_str(), icon.c_str());
}
-void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool isPublic)
+void Guild::HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic)
{
// Player must have rights to set public/officer note
if (!_HasRankRight(session->GetPlayer(), isPublic ? GR_RIGHT_EPNOTE : GR_RIGHT_EOFFNOTE))
SendCommandResult(session, GUILD_COMMAND_PUBLIC_NOTE, ERR_GUILD_PERMISSIONS);
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
if (isPublic)
member->SetPublicNote(note);
else
member->SetOfficerNote(note);
- HandleRoster(session);
+ HandleRoster(session); // FIXME - We should send SMSG_GUILD_MEMBER_UPDATE_NOTE
}
}
@@ -1479,7 +1673,7 @@ void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string c
char aux[2];
sprintf(aux, "%u", rankId);
- _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str());
+ _BroadcastEvent(GE_RANK_UPDATED, 0, aux);
}
}
@@ -1503,10 +1697,10 @@ void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId)
if (!tabCost)
return;
- if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client
+ if (!player->HasEnoughMoney(uint64(tabCost))) // Should not happen, this is checked by client
return;
- player->ModifyMoney(-int32(tabCost));
+ player->ModifyMoney(-int64(tabCost));
_CreateNewBankTab();
_BroadcastEvent(GE_BANK_TAB_PURCHASED, 0);
@@ -1532,12 +1726,14 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name);
return;
}
+
// Invited player cannot be in another guild
- if (pInvitee->GetGuildId())
+ /*if (pInvitee->GetGuildId())
{
SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, name);
return;
- }
+ }*/
+
// Invited player cannot be invited
if (pInvitee->GetGuildIdInvited())
{
@@ -1558,9 +1754,65 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
pInvitee->SetGuildIdInvited(m_id);
_LogEvent(GUILD_EVENT_LOG_INVITE_PLAYER, player->GetGUIDLow(), pInvitee->GetGUIDLow());
- WorldPacket data(SMSG_GUILD_INVITE, 8 + 10); // Guess size
- data << player->GetName();
- data << m_name;
+ WorldPacket data(SMSG_GUILD_INVITE, 100);
+ data << uint32(GetLevel());
+ data << uint32(m_emblemInfo.GetBorderStyle());
+ data << uint32(m_emblemInfo.GetBorderColor());
+ data << uint32(m_emblemInfo.GetStyle());
+ data << uint32(m_emblemInfo.GetBackgroundColor());
+ data << uint32(m_emblemInfo.GetColor());
+
+ ObjectGuid oldGuildGuid = MAKE_NEW_GUID(pInvitee->GetGuildId(), 0, pInvitee->GetGuildId() ? uint32(HIGHGUID_GUILD) : 0);
+ ObjectGuid newGuildGuid = GetGUID();
+
+ data.WriteBit(newGuildGuid[3]);
+ data.WriteBit(newGuildGuid[2]);
+ data.WriteBits(pInvitee->GetGuildName().length(), 8);
+ data.WriteBit(newGuildGuid[1]);
+ data.WriteBit(oldGuildGuid[6]);
+ data.WriteBit(oldGuildGuid[4]);
+ data.WriteBit(oldGuildGuid[1]);
+ data.WriteBit(oldGuildGuid[5]);
+ data.WriteBit(oldGuildGuid[7]);
+ data.WriteBit(oldGuildGuid[2]);
+ data.WriteBit(newGuildGuid[7]);
+ data.WriteBit(newGuildGuid[0]);
+ data.WriteBit(newGuildGuid[6]);
+ data.WriteBits(m_name.length(), 8);
+ data.WriteBit(oldGuildGuid[3]);
+ data.WriteBit(oldGuildGuid[0]);
+ data.WriteBit(newGuildGuid[5]);
+ data.WriteBits(player->GetName().size(), 7);
+ data.WriteBit(newGuildGuid[4]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(newGuildGuid[1]);
+ data.WriteByteSeq(oldGuildGuid[3]);
+ data.WriteByteSeq(newGuildGuid[6]);
+ data.WriteByteSeq(oldGuildGuid[2]);
+ data.WriteByteSeq(oldGuildGuid[1]);
+ data.WriteByteSeq(newGuildGuid[0]);
+
+ if (!pInvitee->GetGuildName().empty())
+ data.WriteString(pInvitee->GetGuildName());
+
+ data.WriteByteSeq(newGuildGuid[7]);
+ data.WriteByteSeq(newGuildGuid[2]);
+
+ data.WriteString(player->GetName());
+
+ data.WriteByteSeq(oldGuildGuid[7]);
+ data.WriteByteSeq(oldGuildGuid[6]);
+ data.WriteByteSeq(oldGuildGuid[5]);
+ data.WriteByteSeq(oldGuildGuid[0]);
+ data.WriteByteSeq(newGuildGuid[4]);
+
+ data.WriteString(m_name);
+
+ data.WriteByteSeq(newGuildGuid[5]);
+ data.WriteByteSeq(newGuildGuid[3]);
+ data.WriteByteSeq(oldGuildGuid[4]);
pInvitee->GetSession()->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_INVITE [%s]", pInvitee->GetName().c_str());
}
@@ -1584,9 +1836,10 @@ void Guild::HandleLeaveMember(WorldSession* session)
if (m_members.size() > 1)
// Leader cannot leave if he is not the last member
SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_LEADER_LEAVE);
+ else if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_UNDELETABLE_LEVEL))
+ SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL);
else
- // Guild is disbanded if leader leaves.
- Disband();
+ Disband(); // Guild is disbanded if leader leaves.
}
else
{
@@ -1601,14 +1854,17 @@ void Guild::HandleLeaveMember(WorldSession* session)
sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId());
}
-void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
+void Guild::HandleRemoveMember(WorldSession* session, uint64 guid)
{
Player* player = session->GetPlayer();
+
// Player must have rights to remove members
if (!_HasRankRight(player, GR_RIGHT_REMOVE))
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_PERMISSIONS);
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
+ std::string name = member->GetName();
+
// Guild masters cannot be removed
if (member->IsRank(GR_GUILDMASTER))
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_LEADER_LEAVE);
@@ -1620,17 +1876,17 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_RANK_TOO_HIGH_S, name);
else
{
- uint64 guid = member->GetGUID();
// After call to DeleteMember pointer to member becomes invalid
DeleteMember(guid, false, true);
_LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), GUID_LOPART(guid));
_BroadcastEvent(GE_REMOVED, 0, name.c_str(), player->GetName().c_str());
+ SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_COMMAND_SUCCESS, name);
}
}
}
}
-void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote)
+void Guild::HandleUpdateMemberRank(WorldSession* session, uint64 guid, bool demote)
{
Player* player = session->GetPlayer();
GuildCommandType type = demote ? GUILD_COMMAND_DEMOTE : GUILD_COMMAND_PROMOTE;
@@ -1638,8 +1894,9 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE))
SendCommandResult(session, type, ERR_GUILD_PERMISSIONS);
// Promoted player must be a member of guild
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
+ std::string name = member->GetName();
// Player cannot promote himself
if (member->IsSamePlayer(player->GetGUID()))
{
@@ -1682,6 +1939,36 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
}
}
+void Guild::HandleSetMemberRank(WorldSession* session, uint64 targetGuid, uint64 setterGuid, uint32 rank)
+{
+ Player* player = session->GetPlayer();
+ Member* member = GetMember(targetGuid);
+ GuildRankRights rights = GR_RIGHT_PROMOTE;
+ GuildCommandType type = GUILD_COMMAND_PROMOTE;
+
+ if (rank > member->GetRankId())
+ {
+ rights = GR_RIGHT_DEMOTE;
+ type = GUILD_COMMAND_DEMOTE;
+ }
+
+ // Promoted player must be a member of guild
+ if (!_HasRankRight(player, rights))
+ {
+ SendCommandResult(session, type, ERR_GUILD_PERMISSIONS);
+ return;
+ }
+
+ // Player cannot promote himself
+ if (member->IsSamePlayer(player->GetGUID()))
+ {
+ SendCommandResult(session, type, ERR_GUILD_NAME_INVALID);
+ return;
+ }
+
+ SendGuildRanksUpdate(setterGuid, targetGuid, rank);
+}
+
void Guild::HandleAddNewRank(WorldSession* session, std::string const& name)
{
uint8 size = _GetRanksSize();
@@ -1691,16 +1978,7 @@ void Guild::HandleAddNewRank(WorldSession* session, std::string const& name)
// Only leader can add new rank
if (_IsLeader(session->GetPlayer()))
if (_CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK))
- {
- char aux[2];
- sprintf(aux, "%u", size);
- _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str());
- }
-}
-
-void Guild::HandleRemoveLowestRank(WorldSession* session)
-{
- HandleRemoveRank(session, _GetLowestRankId());
+ _BroadcastEvent(GE_RANK_CREATED, 0);
}
void Guild::HandleRemoveRank(WorldSession* session, uint8 rankId)
@@ -1715,17 +1993,17 @@ void Guild::HandleRemoveRank(WorldSession* session, uint8 rankId)
stmt->setUInt8(1, rankId);
CharacterDatabase.Execute(stmt);
// Delete rank
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_LOWEST_RANK);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANK);
stmt->setUInt32(0, m_id);
stmt->setUInt8(1, rankId);
CharacterDatabase.Execute(stmt);
- m_ranks.pop_back();
+ m_ranks.erase(m_ranks.begin() + rankId);
- _BroadcastEvent(GE_RANK_DELETED, 0);
+ _BroadcastEvent(GE_RANK_DELETED, rankId);
}
-void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
+void Guild::HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool cashFlow /*=false*/)
{
Player* player = session->GetPlayer();
@@ -1734,11 +2012,13 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_ModifyBankMoney(trans, amount, true);
+ if (!cashFlow)
+ {
+ player->ModifyMoney(-int64(amount));
+ player->SaveGoldToDB(trans);
+ }
- player->ModifyMoney(-int32(amount));
- player->SaveGoldToDB(trans);
- _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
-
+ _LogBankEvent(trans, cashFlow ? GUILD_BANK_LOG_CASH_FLOW_DEPOSIT : GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
CharacterDatabase.CommitTransaction(trans);
std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&amount), 8, true);
@@ -1747,12 +2027,12 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
if (player->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE))
{
sLog->outCommand(player->GetSession()->GetAccountId(),
- "GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)",
+ "GM %s (Account: %u) deposit money (Amount: " UI64FMTD ") to guild bank (Guild ID %u)",
player->GetName().c_str(), player->GetSession()->GetAccountId(), amount, m_id);
}
}
-bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair)
+bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint64 amount, bool repair)
{
if (m_bankMoney < amount) // Not enough money in bank
return false;
@@ -1763,7 +2043,7 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool
if (!member)
return false;
- if (uint32(_GetMemberRemainingMoney(member)) < amount) // Check if we have enough slot/money today
+ if (uint64(_GetMemberRemainingMoney(member)) < amount) // Check if we have enough slot/money today
return false;
// Call script after validation and before money transfer.
@@ -1803,6 +2083,8 @@ void Guild::HandleMemberLogout(WorldSession* session)
member->ResetFlags();
}
_BroadcastEvent(GE_SIGNED_OFF, player->GetGUID(), player->GetName().c_str());
+
+ SaveToDB();
}
void Guild::HandleDisband(WorldSession* session)
@@ -1815,50 +2097,104 @@ void Guild::HandleDisband(WorldSession* session)
}
}
-// Send data to client
-void Guild::SendInfo(WorldSession* session) const
+void Guild::HandleGuildPartyRequest(WorldSession* session)
{
- WorldPacket data(SMSG_GUILD_INFO, m_name.size() + 4 + 4 + 4);
- data << m_name;
- data.AppendPackedTime(m_createdDate); // 3.x (prev. year + month + day)
- data << uint32(m_members.size()); // Number of members
- data << m_accountsNumber; // Number of accounts
+ Player* player = session->GetPlayer();
+ Group* group = player->GetGroup();
+
+ // Make sure player is a member of the guild and that he is in a group.
+ if (!IsMember(player->GetGUID()) || !group)
+ return;
+
+ WorldPacket data(SMSG_GUILD_PARTY_STATE_RESPONSE, 13);
+ data.WriteBit(player->GetMap()->GetOwnerGuildId(player->GetTeam()) == GetId()); // Is guild group
+ data.FlushBits();
+ data << float(0.f); // Guild XP multiplier
+ data << uint32(0); // Current guild members
+ data << uint32(0); // Needed guild members
session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_INFO [%s]", session->GetPlayerInfo().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_PARTY_STATE_RESPONSE [%s]", session->GetPlayerInfo().c_str());
}
void Guild::SendEventLog(WorldSession* session) const
{
- WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 1 + m_eventLog->GetSize() * (1 + 8 + 4));
+ WorldPacket data(SMSG_GUILD_EVENT_LOG_QUERY_RESULT, 1 + m_eventLog->GetSize() * (1 + 8 + 4));
m_eventLog->WritePacket(data);
session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_EVENT_LOG_QUERY [%s]", session->GetPlayerInfo().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_EVENT_LOG_QUERY_RESULT [%s]", session->GetPlayerInfo().c_str());
}
-void Guild::SendBankLog(WorldSession* session, uint8 tabId) const
+void Guild::SendNewsUpdate(WorldSession* session)
{
- // GUILD_BANK_MAX_TABS send by client for money log
- if (tabId < _GetPurchasedTabsSize() || tabId == GUILD_BANK_MAX_TABS)
+ uint32 size = m_newsLog->GetSize();
+ GuildLog* logs = m_newsLog->GetGuildLog();
+
+ if (!logs)
+ return;
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, (21 + size * (26 + 8)) / 8 + (8 + 6 * 4) * size);
+ data.WriteBits(size, 21);
+
+ for (GuildLog::const_iterator itr = logs->begin(); itr != logs->end(); ++itr)
{
- const LogHolder* pLog = m_bankEventLog[tabId];
- WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, pLog->GetSize() * (4 * 4 + 1) + 1 + 1);
- data << uint8(tabId);
- pLog->WritePacket(data);
- session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_BANK_LOG_QUERY [%s]", session->GetPlayerInfo().c_str());
+ data.WriteBits(0, 26); // Not yet implemented used for guild achievements
+ ObjectGuid guid = ((NewsLogEntry*)(*itr))->GetPlayerGuid();
+
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
}
-}
-void Guild::SendBankTabData(WorldSession* session, uint8 tabId) const
-{
- if (tabId < _GetPurchasedTabsSize())
- _SendBankContent(session, tabId);
+ data.FlushBits();
+
+ for (GuildLog::const_iterator itr = logs->begin(); itr != logs->end(); ++itr)
+ {
+ NewsLogEntry* news = (NewsLogEntry*)(*itr);
+ ObjectGuid guid = news->GetPlayerGuid();
+ data.WriteByteSeq(guid[5]);
+
+ data << uint32(news->GetFlags()); // 1 sticky
+ data << uint32(news->GetValue());
+ data << uint32(0);
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(news->GetGUID());
+ data << uint32(news->GetType());
+ data.AppendPackedTime(news->GetTimestamp());
+ }
+
+ session->SendPacket(&data);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_NEWS_UPDATE [%s]", session->GetPlayerInfo().c_str());
}
-void Guild::SendBankTabsInfo(WorldSession* session, bool sendAllSlots /*= false*/) const
+void Guild::SendBankLog(WorldSession* session, uint8 tabId) const
{
- _SendBankList(session, 0, sendAllSlots);
+ // GUILD_BANK_MAX_TABS send by client for money log
+ if (tabId < _GetPurchasedTabsSize() || tabId == GUILD_BANK_MAX_TABS)
+ {
+ LogHolder const* log = m_bankEventLog[tabId];
+ WorldPacket data(SMSG_GUILD_BANK_LOG_QUERY_RESULT, log->GetSize() * (4 * 4 + 1) + 1 + 1);
+ data.WriteBit(GetLevel() >= 5 && tabId == GUILD_BANK_MAX_TABS); // has Cash Flow perk
+ log->WritePacket(data);
+ data << uint32(tabId);
+ //if (tabId == GUILD_BANK_MAX_TABS && hasCashFlow)
+ // data << uint64(cashFlowContribution);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_LOG_QUERY_RESULT [%s] TabId: %u", session->GetPlayerInfo().c_str(), tabId);
+ }
}
void Guild::SendBankTabText(WorldSession* session, uint8 tabId) const
@@ -1875,11 +2211,12 @@ void Guild::SendPermissions(WorldSession* session) const
uint8 rankId = member->GetRankId();
- WorldPacket data(MSG_GUILD_PERMISSIONS, 4 * 15 + 1);
+ WorldPacket data(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, 4 * 15 + 1);
data << uint32(rankId);
+ data << uint32(_GetPurchasedTabsSize());
data << uint32(_GetRankRights(rankId));
data << uint32(_GetMemberRemainingMoney(member));
- data << uint8(_GetPurchasedTabsSize());
+ data.WriteBits(GUILD_BANK_MAX_TABS, 23);
for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
{
data << uint32(_GetRankBankTabRights(rankId, tabId));
@@ -1887,7 +2224,7 @@ void Guild::SendPermissions(WorldSession* session) const
}
session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_PERMISSIONS [%s] Rank: %u", session->GetPlayerInfo().c_str(), rankId);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_PERMISSIONS_QUERY_RESULTS [%s] Rank: %u", session->GetPlayerInfo().c_str(), rankId);
}
void Guild::SendMoneyInfo(WorldSession* session) const
@@ -1897,14 +2234,30 @@ void Guild::SendMoneyInfo(WorldSession* session) const
return;
int32 amount = _GetMemberRemainingMoney(member);
- WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4);
- data << int32(amount);
+ WorldPacket data(SMSG_GUILD_BANK_MONEY_WITHDRAWN, 8);
+ data << int64(amount);
session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_BANK_MONEY_WITHDRAWN [%s] Money: %u", session->GetPlayerInfo().c_str(), amount);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_MONEY_WITHDRAWN [%s] Money: %u", session->GetPlayerInfo().c_str(), amount);
}
void Guild::SendLoginInfo(WorldSession* session)
{
+ Player* player = session->GetPlayer();
+ Member* member = GetMember(player->GetGUID());
+ if (!member)
+ return;
+
+ /*
+ Login sequence:
+ SMSG_GUILD_EVENT - GE_MOTD
+ SMSG_GUILD_RANK
+ SMSG_GUILD_EVENT - GE_SIGNED_ON
+ -- learn perks
+ SMSG_GUILD_REPUTATION_WEEKLY_CAP
+ SMSG_GUILD_ACHIEVEMENT_DATA
+ SMSG_GUILD_MEMBER_DAILY_RESET // bank withdrawal reset
+ */
+
WorldPacket data(SMSG_GUILD_EVENT, 1 + 1 + m_motd.size() + 1);
data << uint8(GE_MOTD);
data << uint8(1);
@@ -1913,18 +2266,34 @@ void Guild::SendLoginInfo(WorldSession* session)
TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_EVENT [%s] MOTD", session->GetPlayerInfo().c_str());
- SendBankTabsInfo(session);
+ SendGuildRankInfo(session);
+ _BroadcastEvent(GE_SIGNED_ON, player->GetGUID(), player->GetName().c_str());
- Player* player = session->GetPlayer();
+ // Send to self separately, player is not in world yet and is not found by _BroadcastEvent
+ data.Initialize(SMSG_GUILD_EVENT, 1 + 1 + player->GetName().size() + 8);
+ data << uint8(GE_SIGNED_ON);
+ data << uint8(1);
+ data << player->GetName();
+ data << uint64(player->GetGUID());
+ session->SendPacket(&data);
- HandleRoster(session);
- _BroadcastEvent(GE_SIGNED_ON, player->GetGUID(), player->GetName().c_str());
+ data.Initialize(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit
+ session->SendPacket(&data);
- if (Member* member = GetMember(player->GetGUID()))
- {
- member->SetStats(player);
- member->AddFlag(GUILDMEMBER_STATUS_ONLINE);
- }
+ if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level <= GetLevel())
+ player->learnSpell(entry->SpellId, true);
+
+ SendGuildReputationWeeklyCap(session, member->GetWeekReputation());
+
+ m_achievementMgr.SendAllAchievementData(player);
+
+ member->SetStats(player);
+ member->AddFlag(GUILDMEMBER_STATUS_ONLINE);
}
// Loading methods
@@ -1938,8 +2307,11 @@ bool Guild::LoadFromDB(Field* fields)
m_motd = fields[9].GetString();
m_createdDate = time_t(fields[10].GetUInt32());
m_bankMoney = fields[11].GetUInt64();
+ _level = fields[12].GetUInt32();
+ _experience = fields[13].GetUInt64();
+ _todayExperience = fields[14].GetUInt64();
- uint8 purchasedTabs = uint8(fields[12].GetUInt64());
+ uint8 purchasedTabs = uint8(fields[15].GetUInt64());
if (purchasedTabs > GUILD_BANK_MAX_TABS)
purchasedTabs = GUILD_BANK_MAX_TABS;
@@ -2039,6 +2411,21 @@ bool Guild::LoadBankEventLogFromDB(Field* fields)
return true;
}
+void Guild::LoadGuildNewsLogFromDB(Field* fields)
+{
+ if (!m_newsLog->CanInsert())
+ return;
+
+ m_newsLog->LoadEvent(new NewsLogEntry(
+ m_id, // guild id
+ fields[1].GetUInt32(), // guid
+ fields[6].GetUInt32(), // timestamp //64 bits?
+ GuildNews(fields[2].GetUInt8()), // type
+ fields[3].GetUInt32(), // player guid
+ fields[4].GetUInt32(), // Flags
+ fields[5].GetUInt32())); // value
+}
+
void Guild::LoadBankTabFromDB(Field* fields)
{
uint8 tabId = fields[1].GetUInt8();
@@ -2067,7 +2454,7 @@ bool Guild::Validate()
// GUILD RANKS represent a sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges).
// The lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++
// Between ranks in sequence cannot be gaps - so 0, 1, 2, 4 is impossible
- // Min ranks count is 5 and max is 10.
+ // Min ranks count is 2 and max is 10.
bool broken_ranks = false;
uint8 ranks = _GetRanksSize();
if (ranks < GUILD_RANKS_MIN_COUNT || ranks > GUILD_RANKS_MAX_COUNT)
@@ -2147,6 +2534,21 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
}
}
+void Guild::BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::string const& msg, std::string const& prefix) const
+{
+ if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
+ {
+ WorldPacket data;
+ ChatHandler::FillMessageData(&data, session, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, uint32(CHAT_MSG_ADDON), NULL, 0, msg.c_str(), NULL, prefix.c_str());
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (Player* player = itr->second->FindPlayer())
+ if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) &&
+ !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()) &&
+ player->GetSession()->IsAddonRegistered(prefix))
+ player->GetSession()->SendPacket(&data);
+ }
+}
+
void Guild::BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const
{
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
@@ -2226,7 +2628,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
player->SetInGuild(m_id);
player->SetGuildIdInvited(0);
player->SetRank(rankId);
- member->SetStats(player);
+ player->SetGuildLevel(GetLevel());
SendLoginInfo(player->GetSession());
name = player->GetName();
}
@@ -2247,10 +2649,12 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
fields[1].GetUInt8(),
fields[2].GetUInt8(),
fields[3].GetUInt16(),
- fields[4].GetUInt32());
+ fields[4].GetUInt32(),
+ 0);
ok = member->CheckStats();
}
+
if (!ok)
{
delete member;
@@ -2265,6 +2669,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
_UpdateAccountsNumber();
_LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, lowguid);
_BroadcastEvent(GE_JOINED, guid, name.c_str());
+ sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(lowguid);
// Call scripts if member was succesfully added (and stored to database)
sScriptMgr->OnGuildAddMember(this, player, rankId);
@@ -2322,6 +2727,12 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked)
{
player->SetInGuild(0);
player->SetRank(0);
+ player->SetGuildLevel(0);
+
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level <= GetLevel())
+ player->removeSpell(entry->SpellId, false, false);
}
_DeleteMemberFromDB(lowguid);
@@ -2340,6 +2751,12 @@ bool Guild::ChangeMemberRank(uint64 guid, uint8 newRank)
return false;
}
+bool Guild::IsMember(uint64 guid) const
+{
+ Members::const_iterator itr = m_members.find(GUID_LOPART(guid));
+ return itr != m_members.end();
+}
+
// Bank (items move)
void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount)
{
@@ -2382,6 +2799,7 @@ void Guild::SetBankTabText(uint8 tabId, std::string const& text)
void Guild::_CreateLogHolders()
{
m_eventLog = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
+ m_newsLog = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT));
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
m_bankEventLog[tabId] = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
}
@@ -2772,20 +3190,6 @@ bool Guild::_DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError
return true;
}
-void Guild::_SendBankContent(WorldSession* session, uint8 tabId) const
-{
- uint64 guid = session->GetPlayer()->GetGUID();
- if (!_MemberHasTabRights(guid, tabId, GUILD_BANK_RIGHT_VIEW_TAB))
- return;
-
- _SendBankList(session, tabId, true);
-}
-
-void Guild::_SendBankMoneyUpdate(WorldSession* session) const
-{
- _SendBankList(session);
-}
-
void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const
{
ASSERT(pSrc->IsBank() || pDest->IsBank());
@@ -2820,7 +3224,68 @@ void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) cons
void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const
{
- _SendBankList(NULL, tabId, false, &slots);
+ if (BankTab const* tab = GetBankTab(tabId))
+ {
+ ByteBuffer tabData;
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
+ data.WriteBit(0);
+ data.WriteBits(slots.size(), 20); // Item count
+ data.WriteBits(0, 22); // Tab count
+
+ for (SlotIds::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
+ {
+ data.WriteBit(0);
+
+ Item const* tabItem = tab->GetItem(*itr);
+ uint32 enchantCount = 0;
+ if (tabItem)
+ {
+ for (uint32 enchSlot = 0; enchSlot < MAX_ENCHANTMENT_SLOT; ++enchSlot)
+ {
+ if (uint32 enchantId = tabItem->GetEnchantmentId(EnchantmentSlot(enchSlot)))
+ {
+ tabData << uint32(enchantId);
+ tabData << uint32(enchSlot);
+ ++enchantCount;
+ }
+ }
+ }
+
+ data.WriteBits(enchantCount, 23); // enchantment count
+
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(tabItem ? tabItem->GetCount() : 0); // ITEM_FIELD_STACK_COUNT
+ tabData << uint32(*itr);
+ tabData << uint32(0);
+ tabData << uint32(tabItem ? tabItem->GetEntry() : 0);
+ tabData << uint32(tabItem ? tabItem->GetItemRandomPropertyId() : 0);
+ tabData << uint32(tabItem ? abs(tabItem->GetSpellCharges()) : 0); // Spell charges
+ tabData << uint32(tabItem ? tabItem->GetItemSuffixFactor() : 0); // SuffixFactor
+ }
+
+ data.FlushBits();
+
+ data << uint64(m_bankMoney);
+ if (!tabData.empty())
+ data.append(tabData);
+
+ data << uint32(tabId);
+
+ size_t rempos = data.wpos();
+ data << uint32(0); // Item withdraw amount, will be filled later
+
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (Player* player = itr->second->FindPlayer())
+ {
+ data.put<uint32>(rempos, uint32(_GetMemberRemainingSlots(itr->second, tabId)));
+ player->GetSession()->SendPacket(&data);
+ }
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ }
}
void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* param1, const char* param2, const char* param3) const
@@ -2847,70 +3312,293 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* par
TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_EVENT [Broadcast] Event: %s (%u)", _GetGuildEventString(guildEvent).c_str(), guildEvent);
}
-void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= NULL*/) const
+void Guild::SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const
{
+ Member const* member = GetMember(session->GetPlayer()->GetGUID());
+ if (!member) // Shouldn't happen, just in case
+ return;
+
+ ByteBuffer tabData;
WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
- data << uint64(m_bankMoney);
- data << uint8(tabId);
- size_t rempos = data.wpos();
- data << uint32(0);
- data << uint8(sendAllSlots);
+ data.WriteBit(0);
+ uint32 itemCount = 0;
+ if (withContent && _MemberHasTabRights(session->GetPlayer()->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (BankTab const* tab = GetBankTab(tabId))
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ if (tab->GetItem(slotId))
+ ++itemCount;
+
+ data.WriteBits(itemCount, 20);
+ data.WriteBits(withTabInfo ? _GetPurchasedTabsSize() : 0, 22);
+ if (withContent && _MemberHasTabRights(session->GetPlayer()->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ {
+ if (BankTab const* tab = GetBankTab(tabId))
+ {
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ {
+ if (Item* tabItem = tab->GetItem(slotId))
+ {
+ data.WriteBit(0);
+
+ uint32 enchants = 0;
+ for (uint32 ench = 0; ench < MAX_ENCHANTMENT_SLOT; ++ench)
+ {
+ if (uint32 enchantId = tabItem->GetEnchantmentId(EnchantmentSlot(ench)))
+ {
+ tabData << uint32(enchantId);
+ tabData << uint32(ench);
+ ++enchants;
+ }
+ }
+
+ data.WriteBits(enchants, 23);
+
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(tabItem->GetCount()); // ITEM_FIELD_STACK_COUNT
+ tabData << uint32(slotId);
+ tabData << uint32(0);
+ tabData << uint32(tabItem->GetEntry());
+ tabData << uint32(tabItem->GetItemRandomPropertyId());
+ tabData << uint32(abs(tabItem->GetSpellCharges())); // Spell charges
+ tabData << uint32(tabItem->GetItemSuffixFactor()); // SuffixFactor
+ }
+ }
+ }
+ }
- if (sendAllSlots && !tabId)
+ if (withTabInfo)
{
- data << uint8(_GetPurchasedTabsSize()); // Number of tabs
for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
- m_bankTabs[i]->WriteInfoPacket(data);
+ {
+ data.WriteBits(m_bankTabs[i]->GetIcon().length(), 9);
+ data.WriteBits(m_bankTabs[i]->GetName().length(), 7);
+ }
}
- BankTab const* tab = GetBankTab(tabId);
- if (!tab)
- data << uint8(0);
- else if (sendAllSlots)
- tab->WritePacket(data);
- else if (slots && !slots->empty())
+ data.FlushBits();
+
+ if (withTabInfo)
{
- data << uint8(slots->size());
- for (SlotIds::const_iterator itr = slots->begin(); itr != slots->end(); ++itr)
- tab->WriteSlotPacket(data, *itr, false);
+ for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
+ {
+ data.WriteString(m_bankTabs[i]->GetIcon());
+ data << uint32(i);
+ data.WriteString(m_bankTabs[i]->GetName());
+ }
}
- else
- data << uint8(0);
- if (session)
+ data << uint64(m_bankMoney);
+ if (!tabData.empty())
+ data.append(tabData);
+
+ data << uint32(tabId);
+ data << uint32(_GetMemberRemainingSlots(member, tabId));
+
+ session->SendPacket(&data);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+}
+
+void Guild::SendGuildRanksUpdate(uint64 setterGuid, uint64 targetGuid, uint32 rank)
+{
+ ObjectGuid tarGuid = targetGuid;
+ ObjectGuid setGuid = setterGuid;
+
+ Member* member = GetMember(targetGuid);
+ ASSERT(member);
+
+ WorldPacket data(SMSG_GUILD_RANKS_UPDATE, 100);
+ data.WriteBit(setGuid[7]);
+ data.WriteBit(setGuid[2]);
+ data.WriteBit(tarGuid[2]);
+ data.WriteBit(setGuid[1]);
+ data.WriteBit(tarGuid[1]);
+ data.WriteBit(tarGuid[7]);
+ data.WriteBit(tarGuid[0]);
+ data.WriteBit(tarGuid[5]);
+ data.WriteBit(tarGuid[4]);
+ data.WriteBit(rank < member->GetRankId()); // 1 == higher, 0 = lower?
+ data.WriteBit(setGuid[5]);
+ data.WriteBit(setGuid[0]);
+ data.WriteBit(tarGuid[6]);
+ data.WriteBit(setGuid[3]);
+ data.WriteBit(setGuid[6]);
+ data.WriteBit(tarGuid[3]);
+ data.WriteBit(setGuid[4]);
+
+ data.FlushBits();
+
+ data << uint32(rank);
+ data.WriteByteSeq(setGuid[3]);
+ data.WriteByteSeq(tarGuid[7]);
+ data.WriteByteSeq(setGuid[6]);
+ data.WriteByteSeq(setGuid[2]);
+ data.WriteByteSeq(tarGuid[5]);
+ data.WriteByteSeq(tarGuid[0]);
+ data.WriteByteSeq(setGuid[7]);
+ data.WriteByteSeq(setGuid[5]);
+ data.WriteByteSeq(tarGuid[2]);
+ data.WriteByteSeq(tarGuid[1]);
+ data.WriteByteSeq(setGuid[0]);
+ data.WriteByteSeq(setGuid[4]);
+ data.WriteByteSeq(setGuid[1]);
+ data.WriteByteSeq(tarGuid[3]);
+ data.WriteByteSeq(tarGuid[6]);
+ data.WriteByteSeq(tarGuid[4]);
+ BroadcastPacket(&data);
+
+ member->ChangeRank(rank);
+
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "SMSG_GUILD_RANKS_UPDATE [Broadcast] Target: %u, Issuer: %u, RankId: %u",
+ GUID_LOPART(targetGuid), GUID_LOPART(setterGuid), rank);
+}
+
+void Guild::GiveXP(uint32 xp, Player* source)
+{
+ if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ /// @todo: Award reputation and count activity for player
+
+ if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
+ xp = 0; // SMSG_GUILD_XP_GAIN is always sent, even for no gains
+
+ if (GetLevel() < GUILD_EXPERIENCE_UNCAPPED_LEVEL)
+ xp = std::min(xp, sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP) - uint32(_todayExperience));
+
+ WorldPacket data(SMSG_GUILD_XP_GAIN, 8);
+ data << uint64(xp);
+ source->GetSession()->SendPacket(&data);
+
+ _experience += xp;
+ _todayExperience += xp;
+
+ if (!xp)
+ return;
+
+ uint32 oldLevel = GetLevel();
+
+ // Ding, mon!
+ while (GetExperience() >= sGuildMgr->GetXPForGuildLevel(GetLevel()) && GetLevel() < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
{
- int32 numSlots = 0;
- if (Member const* member = GetMember(session->GetPlayer()->GetGUID()))
- numSlots = _GetMemberRemainingSlots(member, tabId);
- data.put<uint32>(rempos, numSlots);
- session->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %d",
- session->GetPlayerInfo().c_str(), tabId, sendAllSlots, numSlots);
+ _experience -= sGuildMgr->GetXPForGuildLevel(GetLevel());
+ ++_level;
+
+ // Find all guild perks to learn
+ std::vector<uint32> perksToLearn;
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level > oldLevel && entry->Level <= GetLevel())
+ perksToLearn.push_back(entry->SpellId);
+
+ // Notify all online players that guild level changed and learn perks
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ {
+ if (Player* player = itr->second->FindPlayer())
+ {
+ player->SetGuildLevel(GetLevel());
+ for (size_t i = 0; i < perksToLearn.size(); ++i)
+ player->learnSpell(perksToLearn[i], true);
+ }
+ }
+
+ AddGuildNews(GUILD_NEWS_LEVEL_UP, 0, 0, _level);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL, GetLevel(), 0, 0, NULL, source);
+
+ ++oldLevel;
}
- else /// @todo - Probably this is just sent to session + those that have sent CMSG_GUILD_BANKER_ACTIVATE
+}
+
+void Guild::SendGuildXP(WorldSession* session /* = NULL */) const
+{
+ //Member const* member = GetMember(session->GetGuidLow());
+
+ WorldPacket data(SMSG_GUILD_XP, 40);
+ data << uint64(/*member ? member->GetTotalActivity() :*/ 0);
+ data << uint64(sGuildMgr->GetXPForGuildLevel(GetLevel()) - GetExperience()); // XP missing for next level
+ data << uint64(GetTodayExperience());
+ data << uint64(/*member ? member->GetWeeklyActivity() :*/ 0);
+ data << uint64(GetExperience());
+ session->SendPacket(&data);
+}
+
+void Guild::SendGuildReputationWeeklyCap(WorldSession* session, uint32 reputation) const
+{
+ uint32 cap = sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - reputation;
+ WorldPacket data(SMSG_GUILD_REPUTATION_WEEKLY_CAP, 4);
+ data << uint32(cap);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_REPUTATION_WEEKLY_CAP [%s]: Left: %u",
+ session->GetPlayerInfo().c_str(), cap);
+}
+
+void Guild::ResetTimes(bool weekly)
+{
+ _todayExperience = 0;
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ itr->second->ResetValues(weekly);
+ if (Player* player = itr->second->FindPlayer())
{
- if (!_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
- continue;
- Player* player = itr->second->FindPlayer();
- if (!player)
- continue;
-
- uint32 numSlots = _GetMemberRemainingSlots(itr->second, tabId);
- data.put<uint32>(rempos, numSlots);
+ //SendGuildXP(player->GetSession());
+ WorldPacket data(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit
player->GetSession()->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %u"
- , player->GetName().c_str(), tabId, sendAllSlots, numSlots);
}
}
}
-void Guild::ResetTimes()
+void Guild::AddGuildNews(uint8 type, uint64 guid, uint32 flags, uint32 value)
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- itr->second->ResetValues();
+ uint32 lowGuid = GUID_LOPART(guid);
+ NewsLogEntry* news = new NewsLogEntry(m_id, m_newsLog->GetNextGUID(), GuildNews(type), lowGuid, flags, value);
- // Hack... way to force client to ask for money/slots
- _BroadcastEvent(GE_RANK_UPDATED, 0, "0", GetRankInfo(0)->GetName().c_str());
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ m_newsLog->AddEvent(trans, news);
+ CharacterDatabase.CommitTransaction(trans);
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, 7 + 32);
+ data.WriteBits(1, 21); // size, we are only sending 1 news here
+ ByteBuffer buffer;
+ news->WritePacket(data, buffer);
+
+ BroadcastPacket(&data);
+}
+
+bool Guild::HasAchieved(uint32 achievementId) const
+{
+ return m_achievementMgr.HasAchieved(achievementId);
+}
+
+void Guild::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player)
+{
+ m_achievementMgr.UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, player);
+}
+
+void Guild::HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool sticky)
+{
+ GuildLog* logs = m_newsLog->GetGuildLog();
+ GuildLog::iterator itr = logs->begin();
+ while (itr != logs->end() && (*itr)->GetGUID() != newsId)
+ ++itr;
+
+ if (itr == logs->end())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "HandleNewsSetSticky: [%s] requested unknown newsId %u - Sticky: %u",
+ session->GetPlayerInfo().c_str(), newsId, sticky);
+ return;
+ }
+
+ NewsLogEntry* news = (NewsLogEntry*)(*itr);
+ news->SetSticky(sticky);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "HandleNewsSetSticky: [%s] chenged newsId %u sticky to %u",
+ session->GetPlayerInfo().c_str(), newsId, sticky);
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, 7 + 32);
+ data.WriteBits(1, 21);
+ ByteBuffer buffer;
+ news->WritePacket(data, buffer);
+ session->SendPacket(&data);
}
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index f6a3e095957..cf03cb58748 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -19,31 +19,35 @@
#ifndef TRINITYCORE_GUILD_H
#define TRINITYCORE_GUILD_H
+#include "AchievementMgr.h"
#include "World.h"
#include "Item.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "DBCStore.h"
class Item;
enum GuildMisc
{
- GUILD_BANK_MAX_TABS = 6, // send by client for money log also
+ GUILD_BANK_MAX_TABS = 8, // send by client for money log also
GUILD_BANK_MAX_SLOTS = 98,
GUILD_BANK_MONEY_LOGS_TAB = 100, // used for money log in DB
- GUILD_RANKS_MIN_COUNT = 5,
+ GUILD_RANKS_MIN_COUNT = 2,
GUILD_RANKS_MAX_COUNT = 10,
GUILD_RANK_NONE = 0xFF,
GUILD_WITHDRAW_MONEY_UNLIMITED = 0xFFFFFFFF,
GUILD_WITHDRAW_SLOT_UNLIMITED = 0xFFFFFFFF,
GUILD_EVENT_LOG_GUID_UNDEFINED = 0xFFFFFFFF,
+ GUILD_EXPERIENCE_UNCAPPED_LEVEL = 20, ///> Hardcoded in client, starting from this level, guild daily experience gain is unlimited.
TAB_UNDEFINED = 0xFF,
};
enum GuildMemberData
{
GUILD_MEMBER_DATA_ZONEID,
+ GUILD_MEMBER_DATA_ACHIEVEMENT_POINTS,
GUILD_MEMBER_DATA_LEVEL,
};
@@ -79,7 +83,7 @@ enum GuildRankRights
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
- GR_RIGHT_ALL = 0x001DF1FF
+ GR_RIGHT_ALL = 0x00DDFFBF
};
enum GuildCommandType
@@ -128,37 +132,53 @@ enum GuildCommandError
ERR_GUILD_NOT_ENOUGH_MONEY = 26,
ERR_GUILD_BANK_FULL = 28,
ERR_GUILD_ITEM_NOT_FOUND = 29,
+ ERR_GUILD_TOO_MUCH_MONEY = 31,
+ ERR_GUILD_BANK_WRONG_TAB = 32,
+ ERR_RANK_REQUIRES_AUTHENTICATOR = 34,
+ ERR_GUILD_BANK_VOUCHER_FAILED = 35,
+ ERR_GUILD_TRIAL_ACCOUNT = 36,
+ ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL = 37,
+ ERR_GUILD_MOVE_STARTING = 38,
+ ERR_GUILD_REP_TOO_LOW = 39
};
enum GuildEvents
{
- GE_PROMOTION = 0,
- GE_DEMOTION = 1,
- GE_MOTD = 2,
- GE_JOINED = 3,
- GE_LEFT = 4,
- GE_REMOVED = 5,
- GE_LEADER_IS = 6,
- GE_LEADER_CHANGED = 7,
- GE_DISBANDED = 8,
- GE_TABARDCHANGE = 9,
- GE_RANK_UPDATED = 10,
- GE_RANK_DELETED = 11,
- GE_SIGNED_ON = 12,
- GE_SIGNED_OFF = 13,
- GE_GUILDBANKBAGSLOTS_CHANGED = 14,
- GE_BANK_TAB_PURCHASED = 15,
- GE_BANK_TAB_UPDATED = 16,
- GE_BANK_MONEY_SET = 17,
- GE_BANK_MONEY_CHANGED = 18,
- GE_BANK_TEXT_CHANGED = 19,
+ GE_PROMOTION = 1,
+ GE_DEMOTION = 2,
+ GE_MOTD = 3,
+ GE_JOINED = 4,
+ GE_LEFT = 5,
+ GE_REMOVED = 6,
+ GE_LEADER_IS = 7,
+ GE_LEADER_CHANGED = 8,
+ GE_DISBANDED = 9,
+ GE_TABARDCHANGE = 10,
+ GE_RANK_UPDATED = 11,
+ GE_RANK_CREATED = 12,
+ GE_RANK_DELETED = 13,
+ GE_RANK_ORDER_CHANGED = 14,
+ GE_FOUNDER = 15,
+ GE_SIGNED_ON = 16,
+ GE_SIGNED_OFF = 17,
+ GE_GUILDBANKBAGSLOTS_CHANGED = 18,
+ GE_BANK_TAB_PURCHASED = 19,
+ GE_BANK_TAB_UPDATED = 20,
+ GE_BANK_MONEY_SET = 21,
+ GE_BANK_MONEY_CHANGED = 22,
+ GE_BANK_TEXT_CHANGED = 23,
+ // 24 - error 795
+ GE_SIGNED_ON_MOBILE = 25,
+ GE_SIGNED_Off_MOBILE = 26,
};
enum PetitionTurns
{
PETITION_TURN_OK = 0,
PETITION_TURN_ALREADY_IN_GUILD = 2,
- PETITION_TURN_NEED_MORE_SIGNATURES = 4
+ PETITION_TURN_NEED_MORE_SIGNATURES = 4,
+ PETITION_TURN_GUILD_PERMISSIONS = 11,
+ PETITION_TURN_GUILD_NAME_INVALID = 12
};
enum PetitionSigns
@@ -167,7 +187,10 @@ enum PetitionSigns
PETITION_SIGN_ALREADY_SIGNED = 1,
PETITION_SIGN_ALREADY_IN_GUILD = 2,
PETITION_SIGN_CANT_SIGN_OWN = 3,
- PETITION_SIGN_NOT_SERVER = 4
+ PETITION_SIGN_NOT_SERVER = 4,
+ PETITION_SIGN_FULL = 5,
+ PETITION_SIGN_ALREADY_SIGNED_OTHER = 6,
+ PETITION_SIGN_RESTRICTED_ACCOUNT = 7
};
enum GuildBankRights
@@ -190,7 +213,8 @@ enum GuildBankEventLogTypes
GUILD_BANK_LOG_REPAIR_MONEY = 6,
GUILD_BANK_LOG_MOVE_ITEM2 = 7,
GUILD_BANK_LOG_UNK1 = 8,
- GUILD_BANK_LOG_BUY_SLOT = 9
+ GUILD_BANK_LOG_BUY_SLOT = 9,
+ GUILD_BANK_LOG_CASH_FLOW_DEPOSIT = 10
};
enum GuildEventLogTypes
@@ -222,6 +246,28 @@ enum GuildMemberFlags
GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app
};
+enum GuildNews
+{
+ GUILD_NEWS_GUILD_ACHIEVEMENT = 0,
+ GUILD_NEWS_PLAYER_ACHIEVEMENT = 1,
+ GUILD_NEWS_DUNGEON_ENCOUNTER = 2, // @todo Implement
+ GUILD_NEWS_ITEM_LOOTED = 3,
+ GUILD_NEWS_ITEM_CRAFTED = 4,
+ GUILD_NEWS_ITEM_PURCHASED = 5,
+ GUILD_NEWS_LEVEL_UP = 6,
+};
+
+struct GuildReward
+{
+ uint32 Entry;
+ int32 Racemask;
+ uint64 Price;
+ uint32 AchievementId;
+ uint8 Standing;
+};
+
+uint32 const MinNewsItemLevel[MAX_CONTENT] = { 61, 90, 200, 353 };
+
// Emblem info
class EmblemInfo
{
@@ -292,21 +338,30 @@ private:
m_zoneId(0),
m_level(0),
m_class(0),
+ m_flags(GUILDMEMBER_STATUS_NONE),
m_logoutTime(::time(NULL)),
m_accountId(0),
- m_rankId(rankId)
+ m_rankId(rankId),
+ m_achievementPoints(0),
+ m_totalActivity(0),
+ m_weekActivity(0),
+ m_totalReputation(0),
+ m_weekReputation(0)
{
memset(m_bankWithdraw, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(int32));
}
void SetStats(Player* player);
- void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
+ void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId, uint32 reputation);
bool CheckStats() const;
void SetPublicNote(std::string const& publicNote);
void SetOfficerNote(std::string const& officerNote);
- void SetZoneID(uint32 id) { m_zoneId = id; }
+ void SetZoneId(uint32 id) { m_zoneId = id; }
+ void SetAchievementPoints(uint32 val) { m_achievementPoints = val; }
void SetLevel(uint8 var) { m_level = var; }
+ void AddReputation(uint32& reputation);
+ void AddActivity(uint64 activity);
void AddFlag(uint8 var) { m_flags |= var; }
void RemFlag(uint8 var) { m_flags &= ~var; }
@@ -314,7 +369,6 @@ private:
bool LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
uint64 GetGUID() const { return m_guid; }
std::string const& GetName() const { return m_name; }
@@ -327,6 +381,12 @@ private:
uint8 GetLevel() const { return m_level; }
uint8 GetFlags() const { return m_flags; }
uint32 GetZoneId() const { return m_zoneId; }
+ uint32 GetAchievementPoints() const { return m_achievementPoints; }
+ uint64 GetTotalActivity() const { return m_totalActivity; }
+ uint64 GetWeekActivity() const { return m_weekActivity; }
+ uint32 GetTotalReputation() const { return m_totalReputation; }
+ uint32 GetWeekReputation() const { return m_weekReputation; }
+
bool IsOnline() { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
void ChangeRank(uint8 newRank);
@@ -338,7 +398,7 @@ private:
void UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
int32 GetBankWithdrawValue(uint8 tabId) const;
- void ResetValues();
+ void ResetValues(bool weekly = false);
inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); }
@@ -359,6 +419,11 @@ private:
std::string m_officerNote;
int32 m_bankWithdraw[GUILD_BANK_MAX_TABS + 1];
+ uint32 m_achievementPoints;
+ uint64 m_totalActivity;
+ uint64 m_weekActivity;
+ uint32 m_totalReputation;
+ uint32 m_weekReputation;
};
// Base class for event entries
@@ -373,7 +438,7 @@ private:
uint64 GetTimestamp() const { return m_timestamp; }
virtual void SaveToDB(SQLTransaction& trans) const = 0;
- virtual void WritePacket(WorldPacket& data) const = 0;
+ virtual void WritePacket(WorldPacket& data, ByteBuffer& content) const = 0;
protected:
uint32 m_guildId;
@@ -394,7 +459,7 @@ private:
~EventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
private:
GuildEventLogTypes m_eventType;
@@ -412,31 +477,71 @@ private:
return
eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
- eventType == GUILD_BANK_LOG_REPAIR_MONEY;
+ eventType == GUILD_BANK_LOG_REPAIR_MONEY ||
+ eventType == GUILD_BANK_LOG_CASH_FLOW_DEPOSIT;
}
- BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ bool IsMoneyEvent() const
+ {
+ return IsMoneyEvent(m_eventType);
+ }
+
+ BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint64 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
- BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint64 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
~BankEventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
private:
GuildBankEventLogTypes m_eventType;
uint8 m_bankTabId;
uint32 m_playerGuid;
- uint32 m_itemOrMoney;
+ uint64 m_itemOrMoney;
uint16 m_itemStackCount;
uint8 m_destTabId;
};
+ // News log entry
+ class NewsLogEntry : public LogEntry
+ {
+ public:
+ NewsLogEntry(uint32 guildId, uint32 guid, GuildNews type, uint32 playerGuid, uint32 flags, uint32 value) :
+ LogEntry(guildId, guid), m_type(type), m_playerGuid(playerGuid), m_flags(flags), m_value(value) { }
+
+ NewsLogEntry(uint32 guildId, uint32 guid, time_t timestamp, GuildNews type, uint32 playerGuid, uint32 flags, uint32 value) :
+ LogEntry(guildId, guid, timestamp), m_type(type), m_playerGuid(playerGuid), m_flags(flags), m_value(value) { }
+
+ ~NewsLogEntry() { }
+
+ GuildNews GetType() const { return m_type; }
+ uint64 GetPlayerGuid() const { return m_playerGuid ? MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER) : 0; }
+ uint32 GetValue() const { return m_value; }
+ uint32 GetFlags() const { return m_flags; }
+ void SetSticky(bool sticky)
+ {
+ if (sticky)
+ m_flags |= 1;
+ else
+ m_flags &= ~1;
+ }
+
+ void SaveToDB(SQLTransaction& trans) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
+
+ private:
+ GuildNews m_type;
+ uint32 m_playerGuid;
+ uint32 m_flags;
+ uint32 m_value;
+ };
+
// Class encapsulating work with events collection
typedef std::list<LogEntry*> GuildLog;
@@ -456,6 +561,7 @@ private:
// Writes information about all events to packet
void WritePacket(WorldPacket& data) const;
uint32 GetNextGUID();
+ GuildLog* GetGuildLog() { return &m_log; } // Hack needed for news as WritePacket can't be used
private:
GuildLog m_log;
@@ -475,7 +581,6 @@ private:
void LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
uint8 GetId() const { return m_rankId; }
@@ -504,7 +609,6 @@ private:
private:
uint32 m_guildId;
-
uint8 m_rankId;
std::string m_name;
uint32 m_rights;
@@ -534,10 +638,14 @@ private:
void SetInfo(std::string const& name, std::string const& icon);
void SetText(std::string const& text);
- void SendText(const Guild* guild, WorldSession* session) const;
+ void SendText(Guild const* guild, WorldSession* session) const;
+
+ std::string const& GetName() const { return m_name; }
+ std::string const& GetIcon() const { return m_icon; }
+ std::string const& GetText() const { return m_text; }
inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
- bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
+ bool SetItem(SQLTransaction& trans, uint8 slotId, Item* item);
private:
uint32 m_guildId;
@@ -650,8 +758,11 @@ public:
bool Create(Player* pLeader, std::string const& name);
void Disband();
+ void SaveToDB();
+
// Getters
uint32 GetId() const { return m_id; }
+ uint64 GetGUID() const { return MAKE_NEW_GUID(m_id, 0, HIGHGUID_GUILD); }
uint64 GetLeaderGUID() const { return m_leaderGuid; }
std::string const& GetName() const { return m_name; }
std::string const& GetMOTD() const { return m_motd; }
@@ -660,45 +771,49 @@ public:
bool SetName(std::string const& name);
// Handle client commands
- void HandleRoster(WorldSession* session = NULL); // NULL = broadcast
+ void HandleRoster(WorldSession* session = NULL);
void HandleQuery(WorldSession* session);
void HandleSetMOTD(WorldSession* session, std::string const& motd);
void HandleSetInfo(WorldSession* session, std::string const& info);
void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo);
- void HandleSetLeader(WorldSession* session, std::string const& name);
+ void HandleSetNewGuildMaster(WorldSession* session, std::string const& name);
void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon);
- void HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer);
+ void HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic);
void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots);
void HandleBuyBankTab(WorldSession* session, uint8 tabId);
void HandleInviteMember(WorldSession* session, std::string const& name);
void HandleAcceptMember(WorldSession* session);
void HandleLeaveMember(WorldSession* session);
- void HandleRemoveMember(WorldSession* session, std::string const& name);
- void HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote);
+ void HandleRemoveMember(WorldSession* session, uint64 guid);
+ void HandleUpdateMemberRank(WorldSession* session, uint64 guid, bool demote);
+ void HandleSetMemberRank(WorldSession* session, uint64 guid, uint64 setterGuid, uint32 rank);
void HandleAddNewRank(WorldSession* session, std::string const& name);
void HandleRemoveRank(WorldSession* session, uint8 rankId);
- void HandleRemoveLowestRank(WorldSession* session);
- void HandleMemberDepositMoney(WorldSession* session, uint32 amount);
- bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false);
+ void HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool cashFlow = false);
+ bool HandleMemberWithdrawMoney(WorldSession* session, uint64 amount, bool repair = false);
void HandleMemberLogout(WorldSession* session);
void HandleDisband(WorldSession* session);
+ void HandleGuildPartyRequest(WorldSession* session);
+ void HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool sticky);
void UpdateMemberData(Player* player, uint8 dataid, uint32 value);
void OnPlayerStatusChange(Player* player, uint32 flag, bool state);
// Send info to client
- void SendInfo(WorldSession* session) const;
+ void SendGuildRankInfo(WorldSession* session) const;
void SendEventLog(WorldSession* session) const;
void SendBankLog(WorldSession* session, uint8 tabId) const;
- void SendBankTabsInfo(WorldSession* session, bool showTabs = false) const;
- void SendBankTabData(WorldSession* session, uint8 tabId) const;
+ void SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const;
+ void SendGuildXP(WorldSession* session = NULL) const;
void SendBankTabText(WorldSession* session, uint8 tabId) const;
void SendPermissions(WorldSession* session) const;
void SendMoneyInfo(WorldSession* session) const;
void SendLoginInfo(WorldSession* session);
+ void SendNewsUpdate(WorldSession* session);
// Load from DB
bool LoadFromDB(Field* fields);
+ void LoadGuildNewsLogFromDB(Field* fields);
void LoadRankFromDB(Field* fields);
bool LoadMemberFromDB(Field* fields);
bool LoadEventLogFromDB(Field* fields);
@@ -710,6 +825,7 @@ public:
// Broadcasts
void BroadcastToGuild(WorldSession* session, bool officerOnly, std::string const& msg, uint32 language = LANG_UNIVERSAL) const;
+ void BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::string const& msg, std::string const& prefix) const;
void BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const;
void BroadcastPacket(WorldPacket* packet) const;
@@ -729,6 +845,8 @@ public:
bool AddMember(uint64 guid, uint8 rankId = GUILD_RANK_NONE);
void DeleteMember(uint64 guid, bool isDisbanding = false, bool isKicked = false);
bool ChangeMemberRank(uint64 guid, uint8 newRank);
+ bool IsMember(uint64 guid) const;
+ uint32 GetMembersCount() { return m_members.size(); }
// Bank
void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
@@ -737,7 +855,22 @@ public:
// Bank tabs
void SetBankTabText(uint8 tabId, std::string const& text);
- void ResetTimes();
+ AchievementMgr<Guild>& GetAchievementMgr() { return m_achievementMgr; }
+ AchievementMgr<Guild> const& GetAchievementMgr() const { return m_achievementMgr; }
+
+ // Guild leveling
+ uint8 GetLevel() const { return _level; }
+ void GiveXP(uint32 xp, Player* source);
+ uint64 GetExperience() const { return _experience; }
+ uint64 GetTodayExperience() const { return _todayExperience; }
+
+ void AddGuildNews(uint8 type, uint64 guid, uint32 flags, uint32 value);
+
+ EmblemInfo const& GetEmblemInfo() const { return m_emblemInfo; }
+ void ResetTimes(bool weekly);
+
+ bool HasAchieved(uint32 achievementId) const;
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player);
protected:
uint32 m_id;
@@ -758,12 +891,18 @@ protected:
// These are actually ordered lists. The first element is the oldest entry.
LogHolder* m_eventLog;
LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
+ LogHolder* m_newsLog;
+ AchievementMgr<Guild> m_achievementMgr;
+
+ uint8 _level;
+ uint64 _experience;
+ uint64 _todayExperience;
private:
inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
inline const RankInfo* GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
inline RankInfo* GetRankInfo(uint8 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
- inline bool _HasRankRight(Player* player, uint32 right) const
+ inline bool _HasRankRight(Player const* player, uint32 right) const
{
if (player)
if (Member const* member = GetMember(player->GetGUID()))
@@ -841,11 +980,10 @@ private:
void _MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount);
bool _DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount = 0);
- void _SendBankContent(WorldSession* session, uint8 tabId) const;
- void _SendBankMoneyUpdate(WorldSession* session) const;
void _SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const;
void _SendBankContentUpdate(uint8 tabId, SlotIds slots) const;
- void _SendBankList(WorldSession* session = NULL, uint8 tabId = 0, bool sendFullSlots = false, SlotIds *slots = NULL) const;
+ void SendGuildReputationWeeklyCap(WorldSession* session, uint32 reputation) const;
+ void SendGuildRanksUpdate(uint64 setterGuid, uint64 targetGuid, uint32 rank);
void _BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* param1 = NULL, const char* param2 = NULL, const char* param3 = NULL) const;
};
diff --git a/src/server/game/Guilds/GuildFinderMgr.cpp b/src/server/game/Guilds/GuildFinderMgr.cpp
new file mode 100644
index 00000000000..6125b62ebdf
--- /dev/null
+++ b/src/server/game/Guilds/GuildFinderMgr.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "GuildFinderMgr.h"
+#include "GuildMgr.h"
+#include "World.h"
+
+GuildFinderMgr::GuildFinderMgr()
+{
+}
+
+GuildFinderMgr::~GuildFinderMgr()
+{
+}
+
+void GuildFinderMgr::LoadFromDB()
+{
+ LoadGuildSettings();
+ LoadMembershipRequests();
+}
+
+void GuildFinderMgr::LoadGuildSettings()
+{
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading guild finder guild-related settings...");
+ // 0 1 2 3 4 5 6 7
+ QueryResult result = CharacterDatabase.Query("SELECT gfgs.guildId, gfgs.availability, gfgs.classRoles, gfgs.interests, gfgs.level, gfgs.listed, gfgs.comment, c.race "
+ "FROM guild_finder_guild_settings gfgs "
+ "LEFT JOIN guild_member gm ON gm.guildid=gfgs.guildId "
+ "LEFT JOIN characters c ON c.guid = gm.guid LIMIT 1");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild finder guild-related settings. Table `guild_finder_guild_settings` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ uint32 oldMSTime = getMSTime();
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ uint8 availability = fields[1].GetUInt8();
+ uint8 classRoles = fields[2].GetUInt8();
+ uint8 interests = fields[3].GetUInt8();
+ uint8 level = fields[4].GetUInt8();
+ bool listed = (fields[5].GetUInt8() != 0);
+ std::string comment = fields[6].GetString();
+
+ TeamId guildTeam = TEAM_ALLIANCE;
+ if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(fields[7].GetUInt8()))
+ if (raceEntry->TeamID == 1)
+ guildTeam = TEAM_HORDE;
+
+ LFGuildSettings settings(listed, guildTeam, guildId, classRoles, availability, interests, level, comment);
+ _guildSettings[guildId] = settings;
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild finder guild-related settings in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildFinderMgr::LoadMembershipRequests()
+{
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading guild finder membership requests...");
+ // 0 1 2 3 4 5 6
+ QueryResult result = CharacterDatabase.Query("SELECT guildId, playerGuid, availability, classRole, interests, comment, submitTime "
+ "FROM guild_finder_applicant");
+
+ if (!result)
+ {
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild finder membership requests. Table `guild_finder_applicant` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ uint32 oldMSTime = getMSTime();
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ uint32 playerId = fields[1].GetUInt32();
+ uint8 availability = fields[2].GetUInt8();
+ uint8 classRoles = fields[3].GetUInt8();
+ uint8 interests = fields[4].GetUInt8();
+ std::string comment = fields[5].GetString();
+ uint32 submitTime = fields[6].GetUInt32();
+
+ MembershipRequest request(playerId, guildId, availability, classRoles, interests, comment, time_t(submitTime));
+
+ _membershipRequests[guildId].push_back(request);
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild finder membership requests in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildFinderMgr::AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request)
+{
+ _membershipRequests[guildGuid].push_back(request);
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, request.GetGuildId());
+ stmt->setUInt32(1, request.GetPlayerGUID());
+ stmt->setUInt8(2, request.GetAvailability());
+ stmt->setUInt8(3, request.GetClassRoles());
+ stmt->setUInt8(4, request.GetInterests());
+ stmt->setString(5, request.GetComment());
+ stmt->setUInt32(6, request.GetSubmitTime());
+ trans->Append(stmt);
+ CharacterDatabase.CommitTransaction(trans);
+
+ // Notify the applicant his submittion has been added
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(guildGuid))
+ SendApplicantListUpdate(*guild);
+}
+
+void GuildFinderMgr::RemoveAllMembershipRequestsFromPlayer(uint32 playerId)
+{
+ for (MembershipRequestStore::iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ std::vector<MembershipRequest>::iterator itr2 = itr->second.begin();
+ for (; itr2 != itr->second.end(); ++itr2)
+ if (itr2->GetPlayerGUID() == playerId)
+ break;
+
+ if (itr2 == itr->second.end())
+ continue;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr2->GetGuildId());
+ stmt->setUInt32(1, itr2->GetPlayerGUID());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+ itr->second.erase(itr2);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(itr->first))
+ SendApplicantListUpdate(*guild);
+ }
+}
+
+void GuildFinderMgr::RemoveMembershipRequest(uint32 playerId, uint32 guildId)
+{
+ std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin();
+ for (; itr != _membershipRequests[guildId].end(); ++itr)
+ if (itr->GetPlayerGUID() == playerId)
+ break;
+
+ if (itr == _membershipRequests[guildId].end())
+ return;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr->GetGuildId());
+ stmt->setUInt32(1, itr->GetPlayerGUID());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ _membershipRequests[guildId].erase(itr);
+
+ // Notify the applicant his submittion has been removed
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(playerId, 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ SendApplicantListUpdate(*guild);
+}
+
+std::list<MembershipRequest> GuildFinderMgr::GetAllMembershipRequestsForPlayer(uint32 playerGuid)
+{
+ std::list<MembershipRequest> resultSet;
+ for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ std::vector<MembershipRequest> const& guildReqs = itr->second;
+ for (std::vector<MembershipRequest>::const_iterator itr2 = guildReqs.begin(); itr2 != guildReqs.end(); ++itr2)
+ {
+ if (itr2->GetPlayerGUID() == playerGuid)
+ {
+ resultSet.push_back(*itr2);
+ break;
+ }
+ }
+ }
+ return resultSet;
+}
+
+uint8 GuildFinderMgr::CountRequestsFromPlayer(uint32 playerId)
+{
+ uint8 result = 0;
+ for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ for (std::vector<MembershipRequest>::const_iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
+ {
+ if (itr2->GetPlayerGUID() != playerId)
+ continue;
+ ++result;
+ break;
+ }
+ }
+ return result;
+}
+
+LFGuildStore GuildFinderMgr::GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction)
+{
+ LFGuildStore resultSet;
+ for (LFGuildStore::const_iterator itr = _guildSettings.begin(); itr != _guildSettings.end(); ++itr)
+ {
+ LFGuildSettings const& guildSettings = itr->second;
+
+ if (guildSettings.GetTeam() != faction)
+ continue;
+
+ if (!(guildSettings.GetAvailability() & settings.GetAvailability()))
+ continue;
+
+ if (!(guildSettings.GetClassRoles() & settings.GetClassRoles()))
+ continue;
+
+ if (!(guildSettings.GetInterests() & settings.GetInterests()))
+ continue;
+
+ if (!(guildSettings.GetLevel() & settings.GetLevel()))
+ continue;
+
+ resultSet.insert(std::make_pair(itr->first, guildSettings));
+ }
+
+ return resultSet;
+}
+
+bool GuildFinderMgr::HasRequest(uint32 playerId, uint32 guildId)
+{
+ for (std::vector<MembershipRequest>::const_iterator itr = _membershipRequests[guildId].begin(); itr != _membershipRequests[guildId].end(); ++itr)
+ if (itr->GetPlayerGUID() == playerId)
+ return true;
+ return false;
+}
+
+void GuildFinderMgr::SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings)
+{
+ _guildSettings[guildGuid] = settings;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS);
+ stmt->setUInt32(0, settings.GetGUID());
+ stmt->setUInt8(1, settings.GetAvailability());
+ stmt->setUInt8(2, settings.GetClassRoles());
+ stmt->setUInt8(3, settings.GetInterests());
+ stmt->setUInt8(4, settings.GetLevel());
+ stmt->setUInt8(5, settings.IsListed());
+ stmt->setString(6, settings.GetComment());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void GuildFinderMgr::DeleteGuild(uint32 guildId)
+{
+ std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin();
+ while (itr != _membershipRequests[guildId].end())
+ {
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ uint32 applicant = itr->GetPlayerGUID();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr->GetGuildId());
+ stmt->setUInt32(1, applicant);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS);
+ stmt->setUInt32(0, itr->GetGuildId());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ // Notify the applicant his submition has been removed
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(applicant, 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ ++itr;
+ }
+
+ _membershipRequests.erase(guildId);
+ _guildSettings.erase(guildId);
+
+ // Notify the guild master the list changed (even if he's not a GM any more, not sure if needed)
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ SendApplicantListUpdate(*guild);
+}
+
+void GuildFinderMgr::SendApplicantListUpdate(Guild& guild)
+{
+ WorldPacket data(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, 0);
+ if (Player* player = ObjectAccessor::FindPlayer(guild.GetLeaderGUID()))
+ player->SendDirectMessage(&data);
+ guild.BroadcastPacketToRank(&data, GR_OFFICER);
+}
+
+void GuildFinderMgr::SendMembershipRequestListUpdate(Player& player)
+{
+ WorldPacket data(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, 0);
+ player.SendDirectMessage(&data);
+}
diff --git a/src/server/game/Guilds/GuildFinderMgr.h b/src/server/game/Guilds/GuildFinderMgr.h
new file mode 100644
index 00000000000..d101c91e97c
--- /dev/null
+++ b/src/server/game/Guilds/GuildFinderMgr.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TRINITY_GUILDFINDER_H
+#define __TRINITY_GUILDFINDER_H
+
+#include <ace/Singleton.h>
+#include "Common.h"
+#include "World.h"
+#include "GuildMgr.h"
+
+enum GuildFinderOptionsInterest
+{
+ INTEREST_QUESTING = 0x01,
+ INTEREST_DUNGEONS = 0x02,
+ INTEREST_RAIDS = 0x04,
+ INTEREST_PVP = 0x08,
+ INTEREST_ROLE_PLAYING = 0x10,
+ ALL_INTERESTS = INTEREST_QUESTING | INTEREST_DUNGEONS | INTEREST_RAIDS | INTEREST_PVP | INTEREST_ROLE_PLAYING
+};
+
+enum GuildFinderOptionsAvailability
+{
+ AVAILABILITY_WEEKDAYS = 0x1,
+ AVAILABILITY_WEEKENDS = 0x2,
+ AVAILABILITY_ALWAYS = AVAILABILITY_WEEKDAYS | AVAILABILITY_WEEKENDS
+};
+
+enum GuildFinderOptionsRoles
+{
+ GUILDFINDER_ROLE_TANK = 0x1,
+ GUILDFINDER_ROLE_HEALER = 0x2,
+ GUILDFINDER_ROLE_DPS = 0x4,
+ GUILDFINDER_ALL_ROLES = GUILDFINDER_ROLE_TANK | GUILDFINDER_ROLE_HEALER | GUILDFINDER_ROLE_DPS
+};
+
+enum GuildFinderOptionsLevel
+{
+ ANY_FINDER_LEVEL = 0x1,
+ MAX_FINDER_LEVEL = 0x2,
+ ALL_GUILDFINDER_LEVELS = ANY_FINDER_LEVEL | MAX_FINDER_LEVEL
+};
+
+/// Holds all required informations about a membership request
+struct MembershipRequest
+{
+ public:
+ MembershipRequest(MembershipRequest const& settings) : _comment(settings.GetComment())
+ {
+ _availability = settings.GetAvailability();
+ _classRoles = settings.GetClassRoles();
+ _interests = settings.GetInterests();
+ _guildId = settings.GetGuildId();
+ _playerGUID = settings.GetPlayerGUID();
+ _time = settings.GetSubmitTime();
+ }
+
+ MembershipRequest(uint32 playerGUID, uint32 guildId, uint32 availability, uint32 classRoles, uint32 interests, std::string& comment, time_t submitTime) :
+ _comment(comment), _guildId(guildId), _playerGUID(playerGUID), _availability(availability),
+ _classRoles(classRoles), _interests(interests), _time(submitTime) {}
+
+ MembershipRequest() : _guildId(0), _playerGUID(0), _availability(0), _classRoles(0),
+ _interests(0), _time(time(NULL)) {}
+
+ uint32 GetGuildId() const { return _guildId; }
+ uint32 GetPlayerGUID() const { return _playerGUID; }
+ uint8 GetAvailability() const { return _availability; }
+ uint8 GetClassRoles() const { return _classRoles; }
+ uint8 GetInterests() const { return _interests; }
+ uint8 GetClass() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_class; }
+ uint8 GetLevel() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_level; }
+ time_t GetSubmitTime() const { return _time; }
+ time_t GetExpiryTime() const { return time_t(_time + 30 * 24 * 3600); } // Adding 30 days
+ std::string const& GetComment() const { return _comment; }
+ std::string const& GetName() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_name; }
+ private:
+ std::string _comment;
+
+ uint32 _guildId;
+ uint32 _playerGUID;
+
+ uint8 _availability;
+ uint8 _classRoles;
+ uint8 _interests;
+
+ time_t _time;
+};
+
+/// Holds all informations about a player's finder settings. _NOT_ stored in database.
+struct LFGuildPlayer
+{
+ public:
+ LFGuildPlayer()
+ {
+ _guid = 0;
+ _roles = 0;
+ _availability = 0;
+ _interests = 0;
+ _level = 0;
+ }
+
+ LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level)
+ {
+ _guid = guid;
+ _roles = role;
+ _availability = availability;
+ _interests = interests;
+ _level = level;
+ }
+
+ LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) : _comment(comment)
+ {
+ _guid = guid;
+ _roles = role;
+ _availability = availability;
+ _interests = interests;
+ _level = level;
+ }
+
+ LFGuildPlayer(LFGuildPlayer const& settings) : _comment(settings.GetComment())
+ {
+ _guid = settings.GetGUID();
+ _roles = settings.GetClassRoles();
+ _availability = settings.GetAvailability();
+ _interests = settings.GetInterests();
+ _level = settings.GetLevel();
+ }
+
+ uint32 GetGUID() const { return _guid; }
+ uint8 GetClassRoles() const { return _roles; }
+ uint8 GetAvailability() const { return _availability; }
+ uint8 GetInterests() const { return _interests; }
+ uint8 GetLevel() const { return _level; }
+ std::string const& GetComment() const { return _comment; }
+
+ private:
+ std::string _comment;
+ uint32 _guid;
+ uint8 _roles;
+ uint8 _availability;
+ uint8 _interests;
+ uint8 _level;
+};
+
+/// Holds settings for a guild in the finder system. Saved to database.
+struct LFGuildSettings : public LFGuildPlayer
+{
+ public:
+ LFGuildSettings() : LFGuildPlayer(), _listed(false), _team(TEAM_ALLIANCE) {}
+
+ LFGuildSettings(bool listed, TeamId team) : LFGuildPlayer(), _listed(listed), _team(team) {}
+
+ LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level) :
+ LFGuildPlayer(guid, role, availability, interests, level), _listed(listed), _team(team) {}
+
+ LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) :
+ LFGuildPlayer(guid, role, availability, interests, level, comment), _listed(listed), _team(team) {}
+
+ LFGuildSettings(LFGuildSettings const& settings) :
+ LFGuildPlayer(settings), _listed(settings.IsListed()), _team(settings.GetTeam()) {}
+
+
+ bool IsListed() const { return _listed; }
+ void SetListed(bool state) { _listed = state; }
+
+ TeamId GetTeam() const { return _team; }
+ private:
+ bool _listed;
+ TeamId _team;
+};
+
+typedef std::map<uint32 /* guildGuid */, LFGuildSettings> LFGuildStore;
+typedef std::map<uint32 /* guildGuid */, std::vector<MembershipRequest> > MembershipRequestStore;
+
+class GuildFinderMgr
+{
+ friend class ACE_Singleton<GuildFinderMgr, ACE_Null_Mutex>;
+
+ private:
+ GuildFinderMgr();
+ ~GuildFinderMgr();
+
+ LFGuildStore _guildSettings;
+
+ MembershipRequestStore _membershipRequests;
+
+ void LoadGuildSettings();
+ void LoadMembershipRequests();
+
+ public:
+ void LoadFromDB();
+
+ /**
+ * @brief Stores guild settings and begins an asynchronous database insert
+ * @param guildGuid The guild's database guid.
+ * @param LFGuildSettings The guild's settings storage.
+ */
+ void SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings);
+
+ /**
+ * @brief Returns settings for a guild.
+ * @param guildGuid The guild's database guid.
+ */
+ LFGuildSettings GetGuildSettings(uint32 guildGuid) { return _guildSettings[guildGuid]; }
+
+ /**
+ * @brief Files a membership request to a guild
+ * @param guildGuid The guild's database GUID.
+ * @param MembershipRequest An object storing all data related to the request.
+ */
+ void AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request);
+
+ /**
+ * @brief Removes all membership request from a player.
+ * @param playerId The player's database guid whose application shall be deleted.
+ */
+ void RemoveAllMembershipRequestsFromPlayer(uint32 playerId);
+
+ /**
+ * @brief Removes a membership request to a guild.
+ * @param playerId The player's database guid whose application shall be deleted.
+ * @param guildId The guild's database guid
+ */
+ void RemoveMembershipRequest(uint32 playerId, uint32 guildId);
+
+ /// Wipes everything related to a guild. Used when that guild is disbanded
+ void DeleteGuild(uint32 guildId);
+
+ /**
+ * @brief Returns a set of membership requests for a guild
+ * @param guildGuid The guild's database guid.
+ */
+ std::vector<MembershipRequest> GetAllMembershipRequestsForGuild(uint32 guildGuid) { return _membershipRequests[guildGuid]; }
+
+ /**
+ * @brief Returns a list of membership requests for a player.
+ * @param playerGuid The player's database guid.
+ */
+ std::list<MembershipRequest> GetAllMembershipRequestsForPlayer(uint32 playerGuid);
+
+ /**
+ * @brief Returns a store of guilds matching the settings provided, using bitmask operators.
+ * @param settings The player's finder settings
+ * @param teamId The player's faction (TEAM_ALLIANCE or TEAM_HORDE)
+ */
+ LFGuildStore GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction);
+
+ /// Provided a player DB guid and a guild DB guid, determines if a pending request is filed with these keys.
+ bool HasRequest(uint32 playerId, uint32 guildId);
+
+ /// Counts the amount of pending membership requests, given the player's db guid.
+ uint8 CountRequestsFromPlayer(uint32 playerId);
+
+ void SendApplicantListUpdate(Guild& guild);
+ void SendMembershipRequestListUpdate(Player& player);
+};
+
+#define sGuildFinderMgr ACE_Singleton<GuildFinderMgr, ACE_Null_Mutex>::instance()
+
+#endif // __TRINITY_GUILDFINDER_H
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 583cfa11be9..d1646705395 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -37,6 +37,12 @@ void GuildMgr::RemoveGuild(uint32 guildId)
GuildStore.erase(guildId);
}
+void GuildMgr::SaveGuilds()
+{
+ for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
+ itr->second->SaveToDB();
+}
+
uint32 GuildMgr::GenerateGuildId()
{
if (NextGuildId >= 0xFFFFFFFE)
@@ -57,6 +63,17 @@ Guild* GuildMgr::GetGuildById(uint32 guildId) const
return NULL;
}
+Guild* GuildMgr::GetGuildByGuid(uint64 guid) const
+{
+ // Full guids are only used when receiving/sending data to client
+ // everywhere else guild id is used
+ if (IS_GUILD_GUID(guid))
+ if (uint32 guildId = GUID_LOPART(guid))
+ return GetGuildById(guildId);
+
+ return NULL;
+}
+
Guild* GuildMgr::GetGuildByName(const std::string& guildName) const
{
std::string search = guildName;
@@ -88,6 +105,13 @@ Guild* GuildMgr::GetGuildByLeader(uint64 guid) const
return NULL;
}
+uint32 GuildMgr::GetXPForGuildLevel(uint8 level) const
+{
+ if (level < GuildXPperLevel.size())
+ return GuildXPperLevel[level];
+ return 0;
+}
+
void GuildMgr::LoadGuilds()
{
// 1. Load all guilds
@@ -97,8 +121,8 @@ void GuildMgr::LoadGuilds()
// 0 1 2 3 4 5 6
QueryResult result = CharacterDatabase.Query("SELECT g.guildid, g.name, g.leaderguid, g.EmblemStyle, g.EmblemColor, g.BorderStyle, g.BorderColor, "
- // 7 8 9 10 11 12
- "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, COUNT(gbt.guildid) "
+ // 7 8 9 10 11 12 13 14 15
+ "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, g.level, g.experience, g.todayExperience, COUNT(gbt.guildid) "
"FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC");
if (!result)
@@ -173,13 +197,13 @@ void GuildMgr::LoadGuilds()
CharacterDatabase.DirectExecute("DELETE gm FROM guild_member gm LEFT JOIN guild g ON gm.guildId = g.guildId WHERE g.guildId IS NULL");
CharacterDatabase.DirectExecute("DELETE gm FROM guild_member_withdraw gm LEFT JOIN guild_member g ON gm.guid = g.guid WHERE g.guid IS NULL");
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = CharacterDatabase.Query("SELECT guildid, gm.guid, rank, pnote, offnote, w.tab0, w.tab1, w.tab2, w.tab3, w.tab4, w.tab5, "
- // 11 12 13 14 15 16 17
- "w.money, c.name, c.level, c.class, c.zone, c.account, c.logout_time "
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult result = CharacterDatabase.Query("SELECT gm.guildid, gm.guid, rank, pnote, offnote, w.tab0, w.tab1, w.tab2, w.tab3, w.tab4, w.tab5, "
+ // 11 12 13 14 15 16 17 18 19
+ "w.tab6, w.tab7, w.money, c.name, c.level, c.class, c.zone, c.account, c.logout_time "
"FROM guild_member gm "
"LEFT JOIN guild_member_withdraw w ON gm.guid = w.guid "
- "LEFT JOIN characters c ON c.guid = gm.guid ORDER BY guildid ASC");
+ "LEFT JOIN characters c ON c.guid = gm.guid ORDER BY gm.guildid ASC");
if (!result)
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild members. DB table `guild_member` is empty.");
@@ -304,7 +328,39 @@ void GuildMgr::LoadGuilds()
}
}
- // 7. Load all guild bank tabs
+ // 7. Load all news event logs
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Guild News...");
+ {
+ uint32 oldMSTime = getMSTime();
+
+ CharacterDatabase.DirectPExecute("DELETE FROM guild_newslog WHERE LogGuid > %u", sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT));
+
+ // 0 1 2 3 4 5 6
+ QueryResult result = CharacterDatabase.Query("SELECT guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp FROM guild_newslog ORDER BY TimeStamp DESC, LogGuid DESC");
+
+ if (!result)
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild event logs. DB table `guild_newslog` is empty.");
+ else
+ {
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+
+ if (Guild* guild = GetGuildById(guildId))
+ guild->LoadGuildNewsLogFromDB(fields);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild new logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ }
+ }
+
+
+ // 8. Load all guild bank tabs
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading guild bank tabs...");
{
uint32 oldMSTime = getMSTime();
@@ -338,7 +394,7 @@ void GuildMgr::LoadGuilds()
}
}
- // 8. Fill all guild bank tabs
+ // 9. Fill all guild bank tabs
TC_LOG_INFO(LOG_FILTER_GUILD, "Filling bank tabs with items...");
{
uint32 oldMSTime = getMSTime();
@@ -374,8 +430,25 @@ void GuildMgr::LoadGuilds()
}
}
- // 9. Validate loaded guild data
- TC_LOG_INFO(LOG_FILTER_GUILD, "Validating data of loaded guilds...");
+ // 10. Load guild achievements
+ {
+ PreparedQueryResult achievementResult;
+ PreparedQueryResult criteriaResult;
+ for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, itr->first);
+ achievementResult = CharacterDatabase.Query(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, itr->first);
+ criteriaResult = CharacterDatabase.Query(stmt);
+
+ itr->second->GetAchievementMgr().LoadFromDB(achievementResult, criteriaResult);
+ }
+ }
+
+ // 11. Validate loaded guild data
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Validating data of loaded guilds...");
{
uint32 oldMSTime = getMSTime();
std::set<Guild*> rm; // temporary storage to avoid modifying GuildStore with RemoveGuild() while iterating
@@ -398,11 +471,112 @@ void GuildMgr::LoadGuilds()
}
}
-void GuildMgr::ResetTimes()
+void GuildMgr::LoadGuildXpForLevel()
{
+ uint32 oldMSTime = getMSTime();
+
+ GuildXPperLevel.resize(sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL));
+ for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level)
+ GuildXPperLevel[level] = 0;
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM guild_xp_for_level");
+
+ if (!result)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 xp for guild level definitions. DB table `guild_xp_for_level` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 level = fields[0].GetUInt8();
+ uint32 requiredXP = fields[1].GetUInt64();
+
+ if (level >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
+ {
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Unused (> Guild.MaxLevel in worldserver.conf) level %u in `guild_xp_for_level` table, ignoring.", uint32(level));
+ continue;
+ }
+
+ GuildXPperLevel[level] = requiredXP;
+ ++count;
+
+ } while (result->NextRow());
+
+ // fill level gaps
+ for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level)
+ {
+ if (!GuildXPperLevel[level])
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Level %i does not have XP for guild level data. Using data of level [%i] + 1660000.", level+1, level);
+ GuildXPperLevel[level] = GuildXPperLevel[level - 1] + 1660000;
+ }
+ }
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u xp for guild level definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildMgr::LoadGuildRewards()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT entry, standing, racemask, price, achievement FROM guild_rewards");
+
+ if (!result)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild reward definitions. DB table `guild_rewards` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ GuildReward reward;
+ Field* fields = result->Fetch();
+ reward.Entry = fields[0].GetUInt32();
+ reward.Standing = fields[1].GetUInt8();
+ reward.Racemask = fields[2].GetInt32();
+ reward.Price = fields[3].GetUInt64();
+ reward.AchievementId = fields[4].GetUInt32();
+
+ if (!sObjectMgr->GetItemTemplate(reward.Entry))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Guild rewards constains not existing item entry %u", reward.Entry);
+ continue;
+ }
+
+ if (reward.AchievementId != 0 && (!sAchievementMgr->GetAchievement(reward.AchievementId)))
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Guild rewards constains not existing achievement entry %u", reward.AchievementId);
+ continue;
+ }
+
+ if (reward.Standing >= MAX_REPUTATION_RANK)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Guild rewards contains wrong reputation standing %u, max is %u", uint32(reward.Standing), MAX_REPUTATION_RANK - 1);
+ continue;
+ }
+
+ GuildRewards.push_back(reward);
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild reward definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildMgr::ResetTimes(bool week)
+{
+ CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE));
+ CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER_WITHDRAW));
+
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
if (Guild* guild = itr->second)
- guild->ResetTimes();
-
- CharacterDatabase.DirectExecute("TRUNCATE guild_member_withdraw");
-} \ No newline at end of file
+ guild->ResetTimes(week);
+}
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index 0c99fde2ecc..f10f84fb90f 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -31,21 +31,34 @@ private:
public:
Guild* GetGuildByLeader(uint64 guid) const;
Guild* GetGuildById(uint32 guildId) const;
+ Guild* GetGuildByGuid(uint64 guid) const;
Guild* GetGuildByName(std::string const& guildName) const;
std::string GetGuildNameById(uint32 guildId) const;
+ void LoadGuildXpForLevel();
+ void LoadGuildRewards();
+
void LoadGuilds();
void AddGuild(Guild* guild);
void RemoveGuild(uint32 guildId);
+ void SaveGuilds();
+
+ void ResetReputationCaps();
+
uint32 GenerateGuildId();
void SetNextGuildId(uint32 Id) { NextGuildId = Id; }
- void ResetTimes();
+ uint32 GetXPForGuildLevel(uint8 level) const;
+ std::vector<GuildReward> const& GetGuildRewards() const { return GuildRewards; }
+
+ void ResetTimes(bool week);
protected:
typedef UNORDERED_MAP<uint32, Guild*> GuildContainer;
uint32 NextGuildId;
GuildContainer GuildStore;
+ std::vector<uint64> GuildXPperLevel;
+ std::vector<GuildReward> GuildRewards;
};
#define sGuildMgr ACE_Singleton<GuildMgr, ACE_Null_Mutex>::instance()
diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp
index b2fa49233c3..6f48176db60 100644
--- a/src/server/game/Handlers/ArenaTeamHandler.cpp
+++ b/src/server/game/Handlers/ArenaTeamHandler.cpp
@@ -75,6 +75,54 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket& recvData)
arenaTeam->Roster(this);
}
+void WorldSession::HandleArenaTeamCreateOpcode(WorldPacket & recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ARENA_TEAM_CREATE");
+
+ uint32 slot, icon, iconcolor, border, bordercolor, background;
+ std::string name;
+
+ recvData >> slot;
+ recvData >> iconcolor;
+ recvData >> bordercolor;
+ recvData >> icon;
+ recvData >> background;
+ recvData >> border;
+ name = recvData.ReadString(recvData.ReadBits(8));
+
+ uint8 type = ArenaTeam::GetTypeBySlot(slot);
+
+ if (_player->GetArenaTeamId(slot))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
+ return;
+ }
+
+ if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
+ return;
+ }
+
+ if (sArenaTeamMgr->GetArenaTeamByName(name))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
+ return;
+ }
+
+ ArenaTeam* arenaTeam = new ArenaTeam;
+ if (!arenaTeam->Create(GUID_LOPART(_player->GetGUID()), type, name, background, icon, iconcolor, border, bordercolor))
+ {
+ TC_LOG_ERROR(LOG_FILTER_ARENAS, "Arena team create failed.");
+ delete arenaTeam;
+ return;
+ }
+
+ sArenaTeamMgr->AddArenaTeam(arenaTeam);
+
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_CREATED);
+}
+
void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_INVITE");
@@ -113,6 +161,12 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
return;
}
+ if (arenaTeam->GetCaptain() != _player->GetGUID())
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
+ return;
+ }
+
// OK result but don't send invite
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
return;
@@ -349,20 +403,25 @@ void WorldSession::HandleArenaTeamLeaderOpcode(WorldPacket& recvData)
void WorldSession::SendArenaTeamCommandResult(uint32 teamAction, const std::string& team, const std::string& player, uint32 errorId)
{
- WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4);
+ WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 2 + team.length() + player.length() + 4 + 4);
+
+ data.WriteBits(player.length(), 7);
+ data.WriteBits(team.length(), 8);
+ data.FlushBits();
+
+ data.WriteString(player);
data << uint32(teamAction);
- data << team;
- data << player;
data << uint32(errorId);
+ data.WriteString(team);
SendPacket(&data);
}
void WorldSession::SendNotInArenaTeamPacket(uint8 type)
{
- WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team
- uint32 unk = 0;
- data << uint32(unk); // unk(0)
- if (!unk)
+ WorldPacket data(SMSG_ARENA_ERROR, 4+1);
+ uint32 error = 0;
+ data << uint32(error); // 0 = ERR_ARENA_NO_TEAM_II, 1 = ERR_ARENA_EXPIRED_CAIS, 2 = ERR_LFG_CANT_USE_BATTLEGROUND
+ if (!error)
data << uint8(type); // team type (2=2v2, 3=3v3, 5=5v5), can be used for custom types...
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index d193852eb1c..4ebe9a2b90d 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -71,14 +71,29 @@ void WorldSession::SendAuctionHello(uint64 guid, Creature* unit)
}
//call this method when player bids, creates, or deletes auction
-void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError)
+void WorldSession::SendAuctionCommandResult(AuctionEntry* auction, uint32 action, uint32 errorCode, uint32 bidError)
{
- WorldPacket data(SMSG_AUCTION_COMMAND_RESULT, 16);
- data << auctionId;
- data << Action;
- data << ErrorCode;
- if (!ErrorCode && Action)
- data << bidError; //when bid, then send 0, once...
+ WorldPacket data(SMSG_AUCTION_COMMAND_RESULT);
+ data << uint32(auction ? auction->Id : 0);
+ data << uint32(action);
+ data << uint32(errorCode);
+
+ switch (errorCode)
+ {
+ case ERR_AUCTION_OK:
+ if (action == AUCTION_PLACE_BID)
+ data << uint64(auction->bid ? auction->GetAuctionOutBid() : 0);
+ break;
+ case ERR_AUCTION_INVENTORY:
+ data << uint32(bidError);
+ break;
+ case ERR_AUCTION_HIGHER_BID:
+ data << uint64(auction->bidder);
+ data << uint64(auction->bid);
+ data << uint64(auction->bid ? auction->GetAuctionOutBid() : 0);
+ break;
+ }
+
SendPacket(&data);
}
@@ -89,32 +104,41 @@ void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auction
data << uint32(location);
data << uint32(auctionId);
data << uint64(bidder);
- data << uint32(bidSum);
- data << uint32(diff);
+ data << uint64(bidSum);
+ data << uint64(diff);
data << uint32(itemEntry);
data << uint32(0);
SendPacket(&data);
}
-//this void causes on client to display: "Your auction sold"
+// this void causes on client to display: "Your auction sold"
void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction)
{
- WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (8*4));
+ WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, 40);
data << uint32(auction->Id);
- data << uint32(auction->bid);
- data << uint32(0); //unk
- data << uint64(0); //unk (bidder guid?)
+ data << uint64(auction->bid);
+ data << uint64(0); //unk
+ data << uint64(0); //unk
data << uint32(auction->itemEntry);
- data << uint32(0); //unk
- data << float(0); //unk (time?)
+ data << uint32(0); //unk
+ data << float(0); //unk
+ SendPacket(&data);
+}
+
+void WorldSession::SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId)
+{
+ WorldPacket data(SMSG_AUCTION_REMOVED_NOTIFICATION, (4+4+4));
+ data << uint32(auctionId);
+ data << uint32(itemEntry);
+ data << uint32(randomPropertyId);
SendPacket(&data);
}
//this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
{
- uint64 auctioneer;
- uint32 itemsCount, etime, bid, buyout;
+ uint64 auctioneer, bid, buyout;
+ uint32 itemsCount, etime;
recvData >> auctioneer;
recvData >> itemsCount;
@@ -123,7 +147,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (itemsCount > MAX_AUCTION_ITEMS)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
recvData.rfinish();
return;
}
@@ -150,7 +174,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUIDLow());
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -194,7 +218,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!item)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND);
return;
}
@@ -202,7 +226,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
item->GetCount() < count[i])
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -212,7 +236,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!finalCount)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -222,7 +246,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (item->GetMaxStackCount() < finalCount)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
}
@@ -233,9 +257,9 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount);
- if (!_player->HasEnoughMoney(deposit))
+ if (!_player->HasEnoughMoney((uint64)deposit))
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY);
return;
}
@@ -268,7 +292,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) "
+ "to auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(),
+ AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(item);
auctionHouse->AddAuction(AH);
@@ -281,7 +308,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
- SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
+ SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
}
@@ -291,7 +318,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!newItem)
{
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry());
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
delete AH;
return;
}
@@ -315,7 +342,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to "
+ "auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(),
+ newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(newItem);
auctionHouse->AddAuction(AH);
@@ -352,7 +382,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
- SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
+ SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
}
@@ -360,19 +390,20 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->ModifyMoney(-int32(deposit));
}
-//this function is called when client bids or buys out auction
+// this function is called when client bids or buys out auction
void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID");
uint64 auctioneer;
uint32 auctionId;
- uint32 price;
+ uint64 price;
recvData >> auctioneer;
- recvData >> auctionId >> price;
+ recvData >> auctionId;
+ recvData >> price;
if (!auctionId || !price)
- return; //check for cheaters
+ return; // check for cheaters
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -393,18 +424,18 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if (!auction || auction->owner == player->GetGUIDLow())
{
//you cannot bid your own auction:
- SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
+ SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
return;
}
// impossible have online own another character (use this for speedup check in case online owner)
- Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER));
+ /*Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER));
if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == player->GetSession()->GetAccountId())
{
//you cannot bid your another character auction:
- SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
+ SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
return;
- }
+ }*/
// cheating
if (price <= auction->bid || price < auction->startbid)
@@ -414,14 +445,15 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if ((price < auction->buyout || auction->buyout == 0) &&
price < auction->bid + auction->GetAuctionOutBid())
{
- //auction has already higher bid, client tests it!
+ // client already test it but just in case ...
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_HIGHER_BID);
return;
}
if (!player->HasEnoughMoney(price))
{
- //you don't have enought money!, client tests!
- //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
+ // client already test it but just in case ...
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_NOT_ENOUGHT_MONEY);
return;
}
@@ -432,16 +464,16 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if (auction->bidder > 0)
{
if (auction->bidder == player->GetGUIDLow())
- player->ModifyMoney(-int32(price - auction->bid));
+ player->ModifyMoney(-int64(price - auction->bid));
else
{
// mail to last bidder and return money
sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans);
- player->ModifyMoney(-int32(price));
+ player->ModifyMoney(-int64(price));
}
}
else
- player->ModifyMoney(-int32(price));
+ player->ModifyMoney(-int64(price));
auction->bidder = player->GetGUIDLow();
auction->bid = price;
@@ -453,16 +485,16 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
stmt->setUInt32(2, auction->Id);
trans->Append(stmt);
- SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK, 0);
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK);
}
else
{
//buyout:
if (player->GetGUIDLow() == auction->bidder)
- player->ModifyMoney(-int32(auction->buyout - auction->bid));
+ player->ModifyMoney(-int64(auction->buyout - auction->bid));
else
{
- player->ModifyMoney(-int32(auction->buyout));
+ player->ModifyMoney(-int64(auction->buyout));
if (auction->bidder) //buyout for bidded auction ..
sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans);
}
@@ -475,7 +507,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
sAuctionMgr->SendAuctionSuccessfulMail(auction, trans);
sAuctionMgr->SendAuctionWonMail(auction, trans);
- SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK);
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK);
auction->DeleteFromDB(trans);
@@ -496,7 +528,6 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
uint32 auctionId;
recvData >> auctioneer;
recvData >> auctionId;
- //TC_LOG_DEBUG("Cancel AUCTION AuctionID: %u", auctionId);
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -523,11 +554,10 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid
{
uint32 auctionCut = auction->GetAuctionCut();
- if (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed
+ if (!player->HasEnoughMoney((uint64)auctionCut)) //player doesn't have enough money, maybe message needed
return;
- //some auctionBidderNotification would be needed, but don't know that parts..
- sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans);
- player->ModifyMoney(-int32(auctionCut));
+ sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans, pItem);
+ player->ModifyMoney(-int64(auctionCut));
}
// item will deleted or added to received mail list
@@ -537,21 +567,21 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
}
else
{
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->itemGUIDLow);
- SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Auction id: %u got non existing item (item guid : %u)!", auction->Id, auction->itemGUIDLow);
+ SendAuctionCommandResult(NULL, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
return;
}
}
else
{
- SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
//this code isn't possible ... maybe there should be assert
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUIDLow(), auctionId);
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "CHEATER: %u tried to cancel auction (id: %u) of another player or auction is NULL", player->GetGUIDLow(), auctionId);
return;
}
//inform player, that auction is removed
- SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, ERR_AUCTION_OK);
+ SendAuctionCommandResult(auction, AUCTION_CANCEL, ERR_AUCTION_OK);
// Now remove the auction
@@ -598,7 +628,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket& recvData)
WorldPacket data(SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4));
Player* player = GetPlayer();
- data << (uint32) 0; //add 0 as count
+ data << uint32(0); //add 0 as count
uint32 count = 0;
uint32 totalcount = 0;
while (outbiddedCount > 0) //add all data, which client requires
@@ -617,7 +647,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket& recvData)
auctionHouse->BuildListBidderItems(data, player, count, totalcount);
data.put<uint32>(0, count); // add count to placeholder
data << totalcount;
- data << (uint32)300; //unk 2.3.0
+ data << uint32(300); //unk 2.3.0
SendPacket(&data);
}
@@ -646,15 +676,15 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4));
- data << (uint32) 0; // amount place holder
+ data << uint32(0); // amount place holder
uint32 count = 0;
uint32 totalcount = 0;
auctionHouse->BuildListOwnerItems(data, _player, count, totalcount);
data.put<uint32>(0, count);
- data << (uint32) totalcount;
- data << (uint32) 0;
+ data << uint32(totalcount);
+ data << uint32(0);
SendPacket(&data);
}
@@ -677,15 +707,11 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
recvData >> quality >> usable;
recvData.read_skip<uint8>(); // unk
+ recvData.read_skip<uint8>(); // unk
// this block looks like it uses some lame byte packing or similar...
- uint8 unkCnt;
- recvData >> unkCnt;
- for (uint8 i = 0; i < unkCnt; i++)
- {
- recvData.read_skip<uint8>();
+ for (uint8 i = 0; i < 15; i++)
recvData.read_skip<uint8>();
- }
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -700,13 +726,13 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
- //TC_LOG_DEBUG("Auctionhouse search (GUID: %u TypeId: %u)",, list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u",
+ //TC_LOG_DEBUG(LOG_FILTER_GENERAL, "Auctionhouse search (GUID: %u TypeId: %u)",, list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u",
// GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)), listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable);
WorldPacket data(SMSG_AUCTION_LIST_RESULT, (4+4+4));
uint32 count = 0;
uint32 totalcount = 0;
- data << (uint32) 0;
+ data << uint32(0);
// converting string that we try to find to lower case
std::wstring wsearchedname;
@@ -721,8 +747,8 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
count, totalcount);
data.put<uint32>(0, count);
- data << (uint32) totalcount;
- data << (uint32) 300; // unk 2.3.0 const?
+ data << uint32(totalcount);
+ data << uint32(300); //unk 2.3.0
SendPacket(&data);
}
@@ -740,7 +766,7 @@ void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
{
data << ""; // string
data << ""; // string
- data << uint32(0);
+ data << uint64(0);
data << uint32(0);
data << float(0);
}*/
diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp
index 880937c2c39..7e1c12afe89 100644
--- a/src/server/game/Handlers/AuthHandler.cpp
+++ b/src/server/game/Handlers/AuthHandler.cpp
@@ -19,20 +19,28 @@
#include "WorldSession.h"
#include "WorldPacket.h"
-void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos)
+void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos)
{
- WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + (shortForm ? 0 : (4 + 1)));
- packet << uint8(code);
+ WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0));
+ packet.WriteBit(queued);
+ if (queued)
+ packet.WriteBit(0);
+
+ packet.WriteBit(1); // has account info
+
+ packet.FlushBits();
+
+ // account info
packet << uint32(0); // BillingTimeRemaining
- packet << uint8(0); // BillingPlanFlags
+ packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account
+ packet << uint32(0);
+ packet << uint8(Expansion()); // Unknown, these two show the same
packet << uint32(0); // BillingTimeRested
- packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account
+ packet << uint8(0); // BillingPlanFlags
- if (!shortForm)
- {
+ packet << uint8(code);
+ if (queued)
packet << uint32(queuePos); // Queue position
- packet << uint8(0); // Realm has a free character migration - bool
- }
SendPacket(&packet);
}
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 61197cb10b0..c4855cd2fd5 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -66,23 +66,41 @@ void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket& recvData)
void WorldSession::SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId)
{
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId, 0);
+ sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId);
SendPacket(&data);
}
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
- uint64 guid;
uint32 bgTypeId_;
uint32 instanceId;
- uint8 joinAsGroup;
+ uint8 asGroup;
bool isPremade = false;
Group* grp = NULL;
-
- recvData >> guid; // battlemaster guid
- recvData >> bgTypeId_; // battleground type id (DBC id)
- recvData >> instanceId; // instance id, 0 if First Available selected
- recvData >> joinAsGroup; // join as group
+ ObjectGuid guid;
+
+ recvData >> instanceId; // Instance Id
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ asGroup = recvData.ReadBit(); // As Group
+ guid[4] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+
+ //extract from guid
+ bgTypeId_ = GUID_LOPART(guid);
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
@@ -95,10 +113,9 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
return;
}
-
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
+ //TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID:"UI64FMTD" TypeId:%u)", guid, bgTypeId_);
// can do this, since it's battleground, not arena
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0);
@@ -123,16 +140,15 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!bracketEntry)
return;
- GroupJoinBattlegroundResult err;
+ GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE;
// check queue conditions
- if (!joinAsGroup)
+ if (!asGroup)
{
if (GetPlayer()->isUsingLfg())
{
- // player is using dungeon finder or raid finder
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_LFG_CANT_USE_BATTLEGROUND);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_LFG_CANT_USE_BATTLEGROUND);
GetPlayer()->GetSession()->SendPacket(&data);
return;
}
@@ -141,7 +157,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!_player->CanJoinToBattleground(bg))
{
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -150,7 +166,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
// player is already in random queue
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -159,7 +175,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
// player is already in queue, can't start random queue
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_NON_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -173,33 +189,37 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!_player->HasFreeBattlegroundQueueId())
{
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
_player->GetSession()->SendPacket(&data);
return;
}
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
-
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
+
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
- // already checked if queueSlot is valid, now just get it
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
- WorldPacket data;
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0);
+ // add joined time data
+ _player->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
+
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType);
SendPacket(&data);
+
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
}
else
{
grp = _player->GetGroup();
- // no group found, error
+
if (!grp)
return;
+
if (grp->GetLeaderGUID() != _player->GetGUID())
return;
+
err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
@@ -207,7 +227,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
GroupQueueInfo* ginfo = NULL;
uint32 avgTime = 0;
- if (err > 0)
+ if (!err)
{
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: the following players are joining as group:");
ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
@@ -220,11 +240,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!member)
continue; // this should never happen
- WorldPacket data;
-
- if (err <= 0)
+ if (err)
{
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
+ WorldPacket data;
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err);
member->GetSession()->SendPacket(&data);
continue;
}
@@ -232,65 +251,107 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// add to queue
uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0);
- member->GetSession()->SendPacket(&data);
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
+ // add joined time data
+ member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
+
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType);
member->GetSession()->SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
}
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: group end");
}
+
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
}
void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEGROUND_PLAYER_POSITIONS Message");
Battleground* bg = _player->GetBattleground();
if (!bg) // can't be received if player not in battleground
return;
- uint32 flagCarrierCount = 0;
- Player* allianceFlagCarrier = NULL;
- Player* hordeFlagCarrier = NULL;
+ uint32 acount = 0;
+ uint32 hcount = 0;
+ Player* aplr = NULL;
+ Player* hplr = NULL;
if (uint64 guid = bg->GetFlagPickerGUID(TEAM_ALLIANCE))
{
- allianceFlagCarrier = ObjectAccessor::FindPlayer(guid);
- if (allianceFlagCarrier)
- ++flagCarrierCount;
+ aplr = ObjectAccessor::FindPlayer(guid);
+ if (aplr)
+ ++acount;
}
if (uint64 guid = bg->GetFlagPickerGUID(TEAM_HORDE))
{
- hordeFlagCarrier = ObjectAccessor::FindPlayer(guid);
- if (hordeFlagCarrier)
- ++flagCarrierCount;
+ hplr = ObjectAccessor::FindPlayer(guid);
+ if (hplr)
+ ++hcount;
}
- WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4 + 16 * flagCarrierCount);
- // Used to send several player positions (found used in AV)
- data << 0; // CGBattlefieldInfo__m_numPlayerPositions
- /*
- for (CGBattlefieldInfo__m_numPlayerPositions)
- data << guid << posx << posy;
- */
- data << flagCarrierCount;
- if (allianceFlagCarrier)
+ ObjectGuid aguid = aplr ? aplr->GetGUID() : 0;
+ ObjectGuid hguid = hplr ? hplr->GetGUID() : 0;
+
+ WorldPacket data(SMSG_BATTLEFIELD_PLAYER_POSITIONS);
+
+ data.WriteBits(acount, 22);
+ for (uint8 i = 0; i < acount; i++)
+ {
+ data.WriteBit(aguid[3]);
+ data.WriteBit(aguid[5]);
+ data.WriteBit(aguid[1]);
+ data.WriteBit(aguid[6]);
+ data.WriteBit(aguid[7]);
+ data.WriteBit(aguid[0]);
+ data.WriteBit(aguid[2]);
+ data.WriteBit(aguid[4]);
+ }
+
+ data.WriteBits(hcount, 22);
+ for (uint8 i = 0; i < hcount; i++)
+ {
+ data.WriteBit(hguid[6]);
+ data.WriteBit(hguid[5]);
+ data.WriteBit(hguid[4]);
+ data.WriteBit(hguid[7]);
+ data.WriteBit(hguid[2]);
+ data.WriteBit(hguid[1]);
+ data.WriteBit(hguid[0]);
+ data.WriteBit(hguid[3]);
+ }
+
+ data.FlushBits();
+
+ for (uint8 i = 0; i < hcount; i++)
{
- data << uint64(allianceFlagCarrier->GetGUID());
- data << float(allianceFlagCarrier->GetPositionX());
- data << float(allianceFlagCarrier->GetPositionY());
+ data.WriteByteSeq(hguid[2]);
+ data.WriteByteSeq(hguid[1]);
+ data << float(hplr->GetPositionY());
+ data.WriteByteSeq(hguid[5]);
+ data.WriteByteSeq(hguid[4]);
+ data.WriteByteSeq(hguid[7]);
+ data.WriteByteSeq(hguid[0]);
+ data.WriteByteSeq(hguid[6]);
+ data.WriteByteSeq(hguid[3]);
+ data << float(hplr->GetPositionX());
}
- if (hordeFlagCarrier)
+ for (uint8 i = 0; i < acount; i++)
{
- data << uint64(hordeFlagCarrier->GetGUID());
- data << float(hordeFlagCarrier->GetPositionX());
- data << float(hordeFlagCarrier->GetPositionY());
+ data.WriteByteSeq(aguid[6]);
+ data << float(aplr->GetPositionX());
+ data.WriteByteSeq(aguid[5]);
+ data.WriteByteSeq(aguid[3]);
+ data << float(aplr->GetPositionY());
+ data.WriteByteSeq(aguid[1]);
+ data.WriteByteSeq(aguid[7]);
+ data.WriteByteSeq(aguid[0]);
+ data.WriteByteSeq(aguid[2]);
+ data.WriteByteSeq(aguid[4]);
}
SendPacket(&data);
@@ -298,7 +359,7 @@ void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvDa
void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_PVP_LOG_DATA Message");
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_PVP_LOG_DATA Message");
Battleground* bg = _player->GetBattleground();
if (!bg)
@@ -312,22 +373,16 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/)
sBattlegroundMgr->BuildPvpLogDataPacket(&data, bg);
SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent MSG_PVP_LOG_DATA Message");
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_PVP_LOG_DATA Message");
}
-void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
+void WorldSession::HandleBattlefieldListOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
uint32 bgTypeId;
recvData >> bgTypeId; // id from DBC
- uint8 fromWhere;
- recvData >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
-
- uint8 canGainXP;
- recvData >> canGainXP; // players with locked xp have their own bg queue on retail
-
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (!bl)
{
@@ -336,60 +391,87 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
}
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId), fromWhere);
+ sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId));
SendPacket(&data);
}
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
{
- uint8 type; // arenatype if arena
- uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
- uint32 bgTypeId_; // type id from dbc
- uint16 unk; // 0x1F90 constant?
- uint8 action; // enter battle 0x1, leave queue 0x0
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
+
+ uint32 time;
+ uint32 queueSlot;
+ uint32 unk;
+ uint8 action; // enter battle 0x1, leave queue 0x0
+ ObjectGuid guid;
+
+ recvData >> time;
+ recvData >> queueSlot;
+ recvData >> unk;
+
+ guid[0] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+
+ action = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
- recvData >> type >> unk2 >> bgTypeId_ >> unk >> action;
- if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
+ if (!_player->InBattlegroundQueue())
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Invalid BgType!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- if (!_player->InBattlegroundQueue())
+ BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(queueSlot);
+ if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Invalid queueSlot!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- //get GroupQueueInfo from BattlegroundQueue
- BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
- BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, type);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
+
//we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function
GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue (No player Group Info)!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue (No player Group Info)!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
// if action == 1, then instanceId is required
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player is not invited to any bg!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player is not invited to any bg!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
+ BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(bgQueueTypeId);
+ // BGTemplateId returns BATTLEGROUND_AA when it is arena queue.
+ // Do instance id search as there is no AA bg instances.
+ Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BATTLEGROUND_AA ? BATTLEGROUND_TYPE_NONE : bgTypeId);
if (!bg)
{
if (action)
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Cant find BG with id %u!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action, ginfo.IsInvitedToBGInstanceGUID);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Cant find BG with id %u!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action, ginfo.IsInvitedToBGInstanceGUID);
return;
}
@@ -401,8 +483,11 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
}
}
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u.",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u.",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
+
+ // get real bg type
+ bgTypeId = bg->GetTypeID();
// expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
@@ -417,7 +502,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
{
//send bg command result to show nice message
WorldPacket data2;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data2, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data2);
action = 0;
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUIDLow());
@@ -425,12 +510,12 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
if (_player->getLevel() > bg->GetMaxLevel())
{
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
_player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
action = 0;
}
}
- uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
+
WorldPacket data;
if (action)
{
@@ -453,7 +538,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
_player->CleanupAfterTaxiFlight();
}
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.Team);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), bg->GetArenaType());
_player->GetSession()->SendPacket(&data);
// remove battleground queue status from BGmgr
@@ -476,9 +561,6 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
}
else // leave queue
{
- if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE)
- return;
-
// if player leaves rated arena match before match start, it is counted as he played but he lost
if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
{
@@ -490,25 +572,22 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
at->SaveToDB();
}
}
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_NONE, _player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0);
+ SendPacket(&data);
+
_player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
bgQueue.RemovePlayer(_player->GetGUID(), true);
// player left queue, we should update it - do not update Arena Queue
if (!ginfo.ArenaType)
sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
- SendPacket(&data);
+
TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
}
}
-void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData)
+void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
-
- recvData.read_skip<uint8>(); // unk1
- recvData.read_skip<uint8>(); // unk2
- recvData.read_skip<uint32>(); // BattlegroundTypeId
- recvData.read_skip<uint16>(); // unk3
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_LEAVE Message");
// not allow leave battleground in combat
if (_player->isInCombat())
@@ -522,7 +601,7 @@ void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData)
void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
{
// empty opcode
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Battleground status");
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_STATUS Message");
WorldPacket data;
// we must update all queues here
@@ -541,13 +620,14 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
//so i must use bg pointer to get that information
if (bg && bg->GetArenaType() == arenaType)
{
- // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
+ // this line is checked, i only don't know if GetElapsedTime() is changing itself after bg end!
// send status in Battleground
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), arenaType);
SendPacket(&data);
continue;
}
}
+
//we are sending update to player about queue - he can be invited there!
//get GroupQueueInfo for queue status
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
@@ -559,9 +639,9 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
if (!bg)
continue;
- uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime);
+
// send status invited to Battleground
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_WAIT_JOIN, getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime), _player->GetBattlegroundQueueJoinTime(bgTypeId), arenaType);
SendPacket(&data);
}
else
@@ -577,7 +657,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId());
// send status in Battleground Queue
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_WAIT_QUEUE, avgTime, _player->GetBattlegroundQueueJoinTime(bgTypeId), arenaType);
SendPacket(&data);
}
}
@@ -587,44 +667,18 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
- uint64 guid; // arena Battlemaster guid
uint8 arenaslot; // 2v2, 3v3 or 5v5
- uint8 asGroup; // asGroup
- uint8 isRated; // isRated
- Group* grp = NULL;
- recvData >> guid >> arenaslot >> asGroup >> isRated;
+ recvData >> arenaslot;
// ignore if we already in BG or BG queue
if (_player->InBattleground())
return;
- Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
- if (!unit)
- return;
-
- if (!unit->isBattleMaster()) // it's not battle master
- return;
-
- uint8 arenatype = 0;
uint32 arenaRating = 0;
uint32 matchmakerRating = 0;
- switch (arenaslot)
- {
- case 0:
- arenatype = ARENA_TYPE_2v2;
- break;
- case 1:
- arenatype = ARENA_TYPE_3v3;
- break;
- case 2:
- arenatype = ARENA_TYPE_5v5;
- break;
- default:
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot);
- return;
- }
+ uint8 arenatype = ArenaTeam::GetTypeBySlot(arenaslot);
//check existance
Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
@@ -646,108 +700,73 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
if (!bracketEntry)
return;
- GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
+ GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE;
- if (!asGroup)
- {
- // check if already in queue
- if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
- //player is already in this queue
- return;
- // check if has free queue slots
- if (!_player->HasFreeBattlegroundQueueId())
- return;
- }
- else
+ Group* grp = _player->GetGroup();
+ // no group found, error
+ if (!grp)
+ return;
+ if (grp->GetLeaderGUID() != _player->GetGUID())
+ return;
+
+ uint32 ateamId = _player->GetArenaTeamId(arenaslot);
+ // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
+ ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
+ if (!at)
{
- grp = _player->GetGroup();
- // no group found, error
- if (!grp)
- return;
- if (grp->GetLeaderGUID() != _player->GetGUID())
- return;
- err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);
+ _player->GetSession()->SendNotInArenaTeamPacket(arenatype);
+ return;
}
- uint32 ateamId = 0;
+ // get the team rating for queueing
+ arenaRating = at->GetRating();
+ matchmakerRating = at->GetAverageMMR(grp);
+ // the arenateam id must match for everyone in the group
+
+ if (arenaRating <= 0)
+ arenaRating = 1;
+
+ BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
- if (isRated)
+ uint32 avgTime = 0;
+ GroupQueueInfo* ginfo = NULL;
+
+ err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, true, arenaslot);
+ if (!err)
{
- ateamId = _player->GetArenaTeamId(arenaslot);
- // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
- ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
- if (!at)
- {
- _player->GetSession()->SendNotInArenaTeamPacket(arenatype);
- return;
- }
- // get the team rating for queueing
- arenaRating = at->GetRating();
- matchmakerRating = at->GetAverageMMR(grp);
- // the arenateam id must match for everyone in the group
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName().c_str(), matchmakerRating, arenatype);
- if (arenaRating <= 0)
- arenaRating = 1;
+ ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, true, false, arenaRating, matchmakerRating, ateamId);
+ avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
}
- BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
- if (asGroup)
+ for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
- uint32 avgTime = 0;
+ Player* member = itr->getSource();
+ if (!member)
+ continue;
- if (err > 0)
+ if (err)
{
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: arena join as group start");
- if (isRated)
- {
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName().c_str(), matchmakerRating, arenatype);
- bg->SetRated(true);
- }
- else
- bg->SetRated(false);
-
- GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId);
- avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
+ WorldPacket data;
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err);
+ member->GetSession()->SendPacket(&data);
+ continue;
}
- for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* member = itr->getSource();
- if (!member)
- continue;
-
- WorldPacket data;
+ // add to queue
+ uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
- if (err <= 0)
- {
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
- member->GetSession()->SendPacket(&data);
- continue;
- }
+ // add joined time data
+ member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
- // add to queue
- uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, arenatype);
+ member->GetSession()->SendPacket(&data);
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, 0);
- member->GetSession()->SendPacket(&data);
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
- member->GetSession()->SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
- }
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
}
- else
- {
- GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId);
- uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
- uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
- WorldPacket data;
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, 0);
- SendPacket(&data);
- TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
- }
sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
}
@@ -767,3 +786,78 @@ void WorldSession::HandleReportPvPAFK(WorldPacket& recvData)
reportedPlayer->ReportedAfkBy(_player);
}
+
+void WorldSession::HandleRequestRatedBgInfo(WorldPacket & recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REQUEST_RATED_BG_INFO");
+
+ uint8 unk;
+ recvData >> unk;
+
+ TC_LOG_DEBUG(LOG_FILTER_BATTLEGROUND, "WorldSession::HandleRequestRatedBgInfo: unk = %u", unk);
+
+ /// @Todo: perfome research in this case
+ /// The unk fields are related to arenas
+ WorldPacket data(SMSG_RATED_BG_STATS, 72);
+ data << uint32(0); // BgWeeklyWins20vs20
+ data << uint32(0); // BgWeeklyPlayed20vs20
+ data << uint32(0); // BgWeeklyPlayed15vs15
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyWins10vs10
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyWins15vs15
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyPlayed10vs10
+ data << uint32(0);
+ data << uint32(0);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleRequestPvpOptions(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REQUEST_PVP_OPTIONS_ENABLED");
+
+ /// @Todo: perfome research in this case
+ WorldPacket data(SMSG_PVP_OPTIONS_ENABLED, 1);
+ data.WriteBit(1);
+ data.WriteBit(1); // WargamesEnabled
+ data.WriteBit(1);
+ data.WriteBit(1); // RatedBGsEnabled
+ data.WriteBit(1); // RatedArenasEnabled
+
+ data.FlushBits();
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleRequestPvpReward(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REQUEST_PVP_REWARDS");
+
+ _player->SendPvpRewards();
+}
+
+void WorldSession::HandleRequestRatedBgStats(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REQUEST_RATED_BG_STATS");
+
+ WorldPacket data(SMSG_BATTLEFIELD_RATED_INFO, 29);
+ data << uint32(0); // Reward
+ data << uint8(3); // unk
+ data << uint32(0); // unk
+ data << uint32(0); // unk
+ data << _player->GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ data << uint32(0); // unk
+ data << uint32(0); // unk
+ data << _player->GetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, true);
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/BattlefieldHandler.cpp b/src/server/game/Handlers/BattlefieldHandler.cpp
index 11e7789f275..9cf9e59427e 100644
--- a/src/server/game/Handlers/BattlefieldHandler.cpp
+++ b/src/server/game/Handlers/BattlefieldHandler.cpp
@@ -20,6 +20,7 @@
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "Object.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
@@ -27,124 +28,291 @@
#include "Player.h"
//This send to player windows for invite player to join the war
-//Param1:(BattleId) the BattleId of Bf
+//Param1:(guid) the guid of Bf
//Param2:(ZoneId) the zone where the battle is (4197 for wg)
//Param3:(time) Time in second that the player have for accept
-void WorldSession::SendBfInvitePlayerToWar(uint32 BattleId, uint32 ZoneId, uint32 p_time)
+void WorldSession::SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 pTime)
{
- //Send packet
- WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12);
- data << uint32(BattleId);
- data << uint32(ZoneId);
- data << uint32((time(NULL) + p_time));
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 16);
+
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[0]);
+
+ data.WriteByteSeq(guidBytes[6]);
+ data << uint32(zoneId); // Zone Id
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[0]);
+ data << uint32(time(NULL) + pTime); // Invite lasts until
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[5]);
//Sending the packet to player
SendPacket(&data);
}
//This send invitation to player to join the queue
-//Param1:(BattleId) the BattleId of Bf
-void WorldSession::SendBfInvitePlayerToQueue(uint32 BattleId)
+void WorldSession::SendBfInvitePlayerToQueue(uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, 5);
- data << uint32(BattleId);
- data << uint8(1); //warmup ? used ?
+ data.WriteBit(1); // unk
+ data.WriteBit(0); // Has Warmup
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(1); // unk
+ data.WriteBit(0); // unk
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[6]);
+ data << uint8(1); // Warmup
+ data.WriteByteSeq(guidBytes[5]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
//Sending packet to player
SendPacket(&data);
}
//This send packet for inform player that he join queue
-//Param1:(BattleId) the BattleId of Bf
+//Param1:(guid) the guid of Bf
//Param2:(ZoneId) the zone where the battle is (4197 for wg)
//Param3:(CanQueue) if able to queue
//Param4:(Full) on log in is full
-void WorldSession::SendBfQueueInviteResponse(uint32 BattleId, uint32 ZoneId, bool CanQueue, bool Full)
+void WorldSession::SendBfQueueInviteResponse(uint64 guid, uint32 ZoneId, bool CanQueue, bool Full)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11);
- data << uint32(BattleId);
+ const bool hasSecondGuid = false;
+ const bool warmup = true;
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 16);
+
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(Full); // Logging In, VERIFYME
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(!hasSecondGuid);
+ data.WriteBit(guidBytes[4]);
+
+ // if (hasSecondGuid) 7 3 0 4 2 6 1 5
+
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[2]);
+
+ // if (hasSecondGuid) 2 5 3 0 4 6 1 7
+
+ data.FlushBits();
+
+ data << uint8(CanQueue); // Accepted
+
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[6]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[0]);
+
+ data << uint8(warmup);
+
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[5]);
+
data << uint32(ZoneId);
- data << uint8((CanQueue ? 1 : 0)); //Accepted //0 you cannot queue wg //1 you are queued
- data << uint8((Full ? 0 : 1)); //Logging In //0 wg full //1 queue for upcoming
- data << uint8(1); //Warmup
+
SendPacket(&data);
}
//This is call when player accept to join war
-//Param1:(BattleId) the BattleId of Bf
-void WorldSession::SendBfEntered(uint32 BattleId)
+void WorldSession::SendBfEntered(uint64 guid)
{
-// m_PlayerInWar[player->GetTeamId()].insert(player->GetGUID());
- WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 7);
- data << uint32(BattleId);
- data << uint8(1); //unk
- data << uint8(1); //unk
- data << uint8(_player->isAFK() ? 1 : 0); //Clear AFK
+ uint8 isAFK = _player->isAFK() ? 1 : 0;
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 11);
+
+ data.WriteBit(0); // unk
+ data.WriteBit(isAFK); // Clear AFK
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(0); // unk
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[2]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guidBytes[5]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[6]);
+
SendPacket(&data);
}
-void WorldSession::SendBfLeaveMessage(uint32 BattleId, BFLeaveReason reason)
+void WorldSession::SendBfLeaveMessage(uint64 guid, BFLeaveReason reason)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 7);
- data << uint32(BattleId);
- data << uint8(reason);//byte Reason
- data << uint8(2);//byte BattleStatus
- data << uint8(0);//bool Relocated
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 11);
+
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(0); // Relocated
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[4]);
+
+ data.FlushBits();
+
+ data << uint8(2); // BattleStatus
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[3]);
+ data << uint8(reason); // Reason
+ data.WriteByteSeq(guidBytes[6]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[5]);
+
SendPacket(&data);
}
//Send by client when he click on accept for queue
-void WorldSession::HandleBfQueueInviteResponse(WorldPacket & recvData)
+void WorldSession::HandleBfQueueInviteResponse(WorldPacket& recvData)
{
- uint32 BattleId;
- uint8 Accepted;
+ uint8 accepted;
+ ObjectGuid guid;
- recvData >> BattleId >> Accepted;
- TC_LOG_DEBUG(LOG_FILTER_GENERAL, "HandleQueueInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
- Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
- if (!Bf)
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ accepted = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "HandleQueueInviteResponse: GUID:"UI64FMTD" Accepted:%u", (uint64)guid, accepted);
+
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid);
+ if (!bf)
return;
- if (Accepted)
- {
- Bf->PlayerAcceptInviteToQueue(_player);
- }
+ if (accepted)
+ bf->PlayerAcceptInviteToQueue(_player);
}
//Send by client on clicking in accept or refuse of invitation windows for join game
-void WorldSession::HandleBfEntryInviteResponse(WorldPacket & recvData)
+void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData)
{
- uint32 BattleId;
- uint8 Accepted;
+ uint8 accepted;
+ ObjectGuid guid;
+
+ guid[6] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ accepted = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[5]);
- recvData >> BattleId >> Accepted;
- TC_LOG_DEBUG(LOG_FILTER_GENERAL, "HandleBattlefieldInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
- Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
- if (!Bf)
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "HandleBattlefieldInviteResponse: GUID:"UI64FMTD" Accepted:%u", (uint64)guid, accepted);
+
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid);
+ if (!bf)
return;
- //If player accept invitation
- if (Accepted)
- {
- Bf->PlayerAcceptInviteToWar(_player);
- }
+ if (accepted)
+ bf->PlayerAcceptInviteToWar(_player);
else
- {
- if (_player->GetZoneId() == Bf->GetZoneId())
- Bf->KickPlayerFromBattlefield(_player->GetGUID());
- }
+ if (_player->GetZoneId() == bf->GetZoneId())
+ bf->KickPlayerFromBattlefield(_player->GetGUID());
}
-void WorldSession::HandleBfExitRequest(WorldPacket & recvData)
+void WorldSession::HandleBfExitRequest(WorldPacket& recvData)
{
- uint32 BattleId;
+ ObjectGuid guid;
- recvData >> BattleId;
- TC_LOG_DEBUG(LOG_FILTER_GENERAL, "HandleBfExitRequest: BattleID:%u ", BattleId);
- Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
- if (!Bf)
- return;
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[6]);
+
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "HandleBfExitRequest: GUID:"UI64FMTD" ", (uint64)guid);
- Bf->AskToLeaveQueue(_player);
+ if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid))
+ bf->AskToLeaveQueue(_player);
}
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index b47e085ab6c..3c28a32af93 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -90,6 +90,10 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
data.AppendPackedTime(calendarEvent->GetEventTime());
data << uint32(calendarEvent->GetFlags());
data << int32(calendarEvent->GetDungeonId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent->GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
+
data.appendPackGUID(calendarEvent->GetCreatorGUID());
}
@@ -613,10 +617,11 @@ void WorldSession::HandleCalendarComplain(WorldPacket& recvData)
uint64 guid = _player->GetGUID();
uint64 eventId;
uint64 complainGUID;
+ uint64 inviteId;
- recvData >> eventId >> complainGUID;
+ recvData >> complainGUID >> eventId >> inviteId;
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_CALENDAR_COMPLAIN [" UI64FMTD "] EventId ["
- UI64FMTD "] guid [" UI64FMTD "]", guid, eventId, complainGUID);
+ UI64FMTD "] guid [" UI64FMTD "] InviteId [" UI64FMTD "]", guid, eventId, complainGUID, inviteId);
// what to do with complains?
}
diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp
index 1ac1e5c78ac..c5a3638e1f0 100644
--- a/src/server/game/Handlers/ChannelHandler.cpp
+++ b/src/server/game/Handlers/ChannelHandler.cpp
@@ -19,14 +19,21 @@
#include "ObjectMgr.h" // for normalizePlayerName
#include "ChannelMgr.h"
#include "Player.h"
+#include "WorldSession.h"
void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
{
uint32 channelId;
- uint8 unknown1, unknown2;
+ uint32 channelLength, passLength;
std::string channelName, password;
- recvPacket >> channelId >> unknown1 >> unknown2 >> channelName >> password;
+ recvPacket >> channelId;
+ uint8 unknown1 = recvPacket.ReadBit(); // unknowns
+ uint8 unknown2 = recvPacket.ReadBit();
+ channelLength = recvPacket.ReadBits(8);
+ passLength = recvPacket.ReadBits(8);
+ channelName = recvPacket.ReadString(channelLength);
+ password = recvPacket.ReadString(passLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_JOIN_CHANNEL %s Channel: %u, unk1: %u, unk2: %u, channel: %s, password: %s",
GetPlayerInfo().c_str(), channelId, unknown1, unknown2, channelName.c_str(), password.c_str());
@@ -57,7 +64,9 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
{
uint32 unk;
std::string channelName;
- recvPacket >> unk >> channelName;
+ recvPacket >> unk; // channel id?
+ uint32 length = recvPacket.ReadBits(8);
+ channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_LEAVE_CHANNEL %s Channel: %s, unk1: %u",
GetPlayerInfo().c_str(), channelName.c_str(), unk);
@@ -75,8 +84,8 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
void WorldSession::HandleChannelList(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "%s %s Channel: %s",
recvPacket.GetOpcode() == CMSG_CHANNEL_DISPLAY_LIST ? "CMSG_CHANNEL_DISPLAY_LIST" : "CMSG_CHANNEL_LIST",
@@ -89,8 +98,11 @@ void WorldSession::HandleChannelList(WorldPacket& recvPacket)
void WorldSession::HandleChannelPassword(WorldPacket& recvPacket)
{
- std::string channelName, password;
- recvPacket >> channelName >> password;
+ uint32 nameLength = recvPacket.ReadBits(8);
+ uint32 passLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(nameLength);
+ std::string password = recvPacket.ReadString(passLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_PASSWORD %s Channel: %s, Password: %s",
GetPlayerInfo().c_str(), channelName.c_str(), password.c_str());
@@ -102,8 +114,11 @@ void WorldSession::HandleChannelPassword(WorldPacket& recvPacket)
void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_SET_OWNER %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -118,8 +133,8 @@ void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket)
void WorldSession::HandleChannelOwner(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_OWNER %s Channel: %s",
GetPlayerInfo().c_str(), channelName.c_str());
@@ -131,8 +146,11 @@ void WorldSession::HandleChannelOwner(WorldPacket& recvPacket)
void WorldSession::HandleChannelModerator(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_MODERATOR %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -147,8 +165,11 @@ void WorldSession::HandleChannelModerator(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ uint32 channelLength = recvPacket.ReadBits(8);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_UNMODERATOR %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -163,8 +184,11 @@ void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket)
void WorldSession::HandleChannelMute(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_MUTE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -179,8 +203,11 @@ void WorldSession::HandleChannelMute(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(8);
+ uint32 channelLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_UNMUTE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -195,8 +222,11 @@ void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket)
void WorldSession::HandleChannelInvite(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ uint32 channelLength = recvPacket.ReadBits(8);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_INVITE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -211,8 +241,11 @@ void WorldSession::HandleChannelInvite(WorldPacket& recvPacket)
void WorldSession::HandleChannelKick(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_KICK %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -227,8 +260,14 @@ void WorldSession::HandleChannelKick(WorldPacket& recvPacket)
void WorldSession::HandleChannelBan(WorldPacket& recvPacket)
{
+ uint32 channelLength, nameLength;
std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+
+ channelLength = recvPacket.ReadBits(8);
+ nameLength = recvPacket.ReadBits(7);
+
+ targetName = recvPacket.ReadString(nameLength);
+ channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_BAN %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -243,8 +282,11 @@ void WorldSession::HandleChannelBan(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnban(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(7);
+ uint32 nameLength = recvPacket.ReadBits(8);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_UNBAN %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -259,8 +301,8 @@ void WorldSession::HandleChannelUnban(WorldPacket& recvPacket)
void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_ANNOUNCEMENTS %s Channel: %s",
GetPlayerInfo().c_str(), channelName.c_str());
@@ -300,7 +342,7 @@ void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket)
}
}
-void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket)
+void WorldSession::HandleSetChannelWatch(WorldPacket& recvPacket)
{
std::string channelName;
recvPacket >> channelName;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index e3f5893a871..85a76760c7e 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -26,6 +26,7 @@
#include "DatabaseEnv.h"
#include "Group.h"
#include "Guild.h"
+#include "GuildFinderMgr.h"
#include "GuildMgr.h"
#include "Language.h"
#include "LFGMgr.h"
@@ -47,7 +48,6 @@
#include "WorldPacket.h"
#include "WorldSession.h"
-
class LoginQueryHolder : public SQLQueryHolder
{
private:
@@ -116,6 +116,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INVENTORY, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_VOID_STORAGE);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS);
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_ACTIONS, stmt);
@@ -168,6 +172,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA);
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_BG_DATA, stmt);
@@ -204,36 +212,53 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, m_accountId);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_CURRENCY);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt);
+
return res;
}
void WorldSession::HandleCharEnum(PreparedQueryResult result)
{
- WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
+ uint32 charCount = 0;
+ ByteBuffer bitBuffer;
+ ByteBuffer dataBuffer;
- uint8 num = 0;
-
- data << num;
-
- _legitCharacters.clear();
+ bitBuffer.WriteBits(0, 23);
+ bitBuffer.WriteBit(1);
if (result)
{
+ _legitCharacters.clear();
+
+ charCount = uint32(result->GetRowCount());
+ bitBuffer.reserve(24 * charCount / 8);
+ dataBuffer.reserve(charCount * 381);
+
+ bitBuffer.WriteBits(charCount, 17);
+
do
{
- uint32 guidlow = (*result)[0].GetUInt32();
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidlow, GetAccountId());
- if (Player::BuildEnumData(result, &data))
- {
- _legitCharacters.insert(guidlow);
- if (!sWorld->HasCharacterNameData(guidlow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
- sWorld->AddCharacterNameData(guidlow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
- ++num;
- }
- }
- while (result->NextRow());
+ uint32 guidLow = (*result)[0].GetUInt32();
+
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidLow, GetAccountId());
+
+ Player::BuildEnumData(result, &dataBuffer, &bitBuffer);
+
+ _legitCharacters.insert(guidLow);
+ if (!sWorld->HasCharacterNameData(guidLow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
+ sWorld->AddCharacterNameData(guidLow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
+ } while (result->NextRow());
+
+ bitBuffer.FlushBits();
}
+ else
+ bitBuffer.WriteBits(0, 17);
- data.put<uint8>(0, num);
+ WorldPacket data(SMSG_CHAR_ENUM, 7 + bitBuffer.size() + dataBuffer.size());
+ data.append(bitBuffer);
+ if (charCount)
+ data.append(dataBuffer);
SendPacket(&data);
}
@@ -746,6 +771,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
sLog->outCharDump(dump.c_str(), accountId, GUID_LOPART(guid), name.c_str());
}
+ sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid);
sCalendarMgr->RemoveAllPlayerEventsAndInvites(guid);
Player::DeleteFromDB(guid, accountId);
@@ -758,16 +784,33 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
{
if (PlayerLoading() || GetPlayer() != NULL)
{
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player tryes to login again, AccountId = %d", GetAccountId());
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player tries to login again, AccountId = %d", GetAccountId());
return;
}
m_playerLoading = true;
- uint64 playerGuid = 0;
+ ObjectGuid playerGuid;
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd Player Logon Message");
-
- recvData >> playerGuid;
+ playerGuid[2] = recvData.ReadBit();
+ playerGuid[3] = recvData.ReadBit();
+ playerGuid[0] = recvData.ReadBit();
+ playerGuid[6] = recvData.ReadBit();
+ playerGuid[4] = recvData.ReadBit();
+ playerGuid[5] = recvData.ReadBit();
+ playerGuid[1] = recvData.ReadBit();
+ playerGuid[7] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(playerGuid[2]);
+ recvData.ReadByteSeq(playerGuid[7]);
+ recvData.ReadByteSeq(playerGuid[0]);
+ recvData.ReadByteSeq(playerGuid[3]);
+ recvData.ReadByteSeq(playerGuid[5]);
+ recvData.ReadByteSeq(playerGuid[6]);
+ recvData.ReadByteSeq(playerGuid[1]);
+ recvData.ReadByteSeq(playerGuid[4]);
+
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Character (Guid: %u) logging in", GUID_LOPART(playerGuid));
if (!IsLegitCharacterForAccount(GUID_LOPART(playerGuid)))
{
@@ -787,6 +830,17 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
}
+void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "WORLD: Recvd CMSG_LOAD_SCREEN");
+ uint32 mapID;
+
+ recvPacket >> mapID;
+ recvPacket.ReadBit();
+
+ // TODO: Do something with this packet
+}
+
void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
uint64 playerGuid = holder->GetGuid();
@@ -821,9 +875,34 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA), PER_CHARACTER_CACHE_MASK);
SendAccountDataTimes(PER_CHARACTER_CACHE_MASK);
- data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0
+ bool featureBit4 = true;
+ data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 7); // checked in 4.2.2
data << uint8(2); // unknown value
- data << uint8(0); // enable(1)/disable(0) voice chat interface in client
+ data << uint32(1);
+ data << uint32(1);
+ data << uint32(2);
+ data << uint32(0);
+ data.WriteBit(1);
+ data.WriteBit(1);
+ data.WriteBit(0);
+ data.WriteBit(featureBit4);
+ data.WriteBit(0);
+ data.WriteBit(0);
+ data.FlushBits();
+ if (featureBit4)
+ {
+ data << uint32(1);
+ data << uint32(0);
+ data << uint32(10);
+ data << uint32(60);
+ }
+
+ //if (featureBit5)
+ //{
+ // data << uint32(0);
+ // data << uint32(0);
+ // data << uint32(0);
+ //}
SendPacket(&data);
// Send MOTD
@@ -870,28 +949,30 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
Field* fields = resultGuild->Fetch();
pCurrChar->SetInGuild(fields[0].GetUInt32());
pCurrChar->SetRank(fields[1].GetUInt8());
+ if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
+ pCurrChar->SetGuildLevel(guild->GetLevel());
}
else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
{
pCurrChar->SetInGuild(0);
pCurrChar->SetRank(0);
+ pCurrChar->SetGuildLevel(0);
}
- if (pCurrChar->GetGuildId() != 0)
+ data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
+ data << uint64(0);
+ SendPacket(&data);
+
+ data.Initialize(SMSG_HOTFIX_INFO);
+ HotfixData const& hotfix = sObjectMgr->GetHotfixData();
+ data.WriteBits(hotfix.size(), 22);
+ data.FlushBits();
+ for (uint32 i = 0; i < hotfix.size(); ++i)
{
- if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
- guild->SendLoginInfo(this);
- else
- {
- // remove wrong guild data
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
- pCurrChar->SetInGuild(0);
- }
+ data << uint32(hotfix[i].Type);
+ data << uint32(hotfix[i].Timestamp);
+ data << uint32(hotfix[i].Entry);
}
-
- data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
- data << uint32(0);
- data << uint32(0);
SendPacket(&data);
pCurrChar->SendInitialPacketsBeforeAddToMap();
@@ -916,7 +997,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid())
{
- AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
+ AreaTriggerStruct const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
if (at)
pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());
else
@@ -926,18 +1007,26 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
sObjectAccessor->AddObject(pCurrChar);
//TC_LOG_DEBUG("Player %s added to Map.", pCurrChar->GetName().c_str());
+ if (pCurrChar->GetGuildId() != 0)
+ {
+ if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
+ guild->SendLoginInfo(this);
+ else
+ {
+ // remove wrong guild data
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
+ pCurrChar->SetInGuild(0);
+ }
+ }
+
pCurrChar->SendInitialPacketsAfterAddToMap();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);
-
stmt->setUInt32(0, pCurrChar->GetGUIDLow());
-
CharacterDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
-
stmt->setUInt32(0, GetAccountId());
-
LoginDatabase.Execute(stmt);
pCurrChar->SetInGameTime(getMSTime());
@@ -964,7 +1053,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form)
pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
- pCurrChar->SetMovement(MOVE_WATER_WALK);
+ pCurrChar->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ pCurrChar->SendMovementWaterWalking();
}
pCurrChar->ContinueTaxiFlight();
@@ -992,14 +1082,37 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS))
{
- pCurrChar->resetTalents(true);
+ pCurrChar->ResetTalents(true);
pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
SendNotification(LANG_RESET_TALENTS);
}
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
+ {
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
+ if (pCurrChar->getClass() == CLASS_HUNTER)
+ {
+ static uint32 const HunterCreatePetSpells[MAX_RACES] =
+ {
+ 0, /* None */ 79597, /* Human - Young Wolf */
+ 79598, /* Orc - Young Boar */ 79593, /* Dwarf - Young Bear */
+ 79602, /* Night Elf - Young Cat */ 79600, /* Undead - Young Widow */
+ 79603, /* Tauren - Young Tallstrider */ 0, /* Gnome */
+ 79599, /* Troll - Young Raptor */ 79595, /* Goblin - Young Crab */
+ 79594, /* Blood Elf - Young Dragonhawk */ 79601, /* Draenei - Young Moth */
+ 0, /* Fel Orc */ 0, /* Naga */
+ 0, /* Broken */ 0, /* Skeleton */
+ 0, /* Vrykul */ 0, /* Tuskarr */
+ 0, /* Forest Troll */ 0, /* Taunka */
+ 0, /* Northrend Skeleton */ 0, /* Ice Troll */
+ 79596, /* Worgen - Young Mastiff */
+ };
+
+ pCurrChar->CastSpell(pCurrChar, HunterCreatePetSpells[pCurrChar->getRace()], true);
+ }
+ }
+
// show time before shutdown if shutdown planned.
if (sWorld->IsShuttingDown())
sWorld->ShutdownMsg(true, pCurrChar);
@@ -1059,13 +1172,13 @@ void WorldSession::HandleTutorialFlag(WorldPacket& recvData)
SetTutorialInt(index, flag);
}
-void WorldSession::HandleTutorialClear(WorldPacket & /*recvData*/)
+void WorldSession::HandleTutorialClear(WorldPacket& /*recvData*/)
{
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
SetTutorialInt(i, 0xFFFFFFFF);
}
-void WorldSession::HandleTutorialReset(WorldPacket & /*recvData*/)
+void WorldSession::HandleTutorialReset(WorldPacket& /*recvData*/)
{
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
SetTutorialInt(i, 0x00000000);
@@ -1339,8 +1452,8 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
// 0 - ok
// 1, 3 - not enough money
- // 2 - you have to seat on barber chair
- if (!_player->HasEnoughMoney(cost))
+ // 2 - you have to sit on barber chair
+ if (!_player->HasEnoughMoney((uint64)cost))
{
WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
data << uint32(1); // no money
@@ -1354,7 +1467,7 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
SendPacket(&data);
}
- _player->ModifyMoney(-int32(cost)); // it isn't free
+ _player->ModifyMoney(-int64(cost)); // it isn't free
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost);
_player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
@@ -1379,7 +1492,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
return;
}
- if (uint32 glyph = _player->GetGlyph(slot))
+ if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -1411,9 +1524,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN);
-
stmt->setUInt32(0, GUID_LOPART(guid));
- // TODO: Make async with callback
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
@@ -1515,7 +1626,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
SendPacket(&data);
}
-void WorldSession::HandleEquipmentSetSave(WorldPacket &recvData)
+void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_SAVE");
@@ -1577,7 +1688,7 @@ void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData)
_player->DeleteEquipmentSet(setGuid);
}
-void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData)
+void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
{
if (_player->isInCombat())
return;
@@ -1780,6 +1891,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_UNDEAD_PLAYER:
case RACE_TROLL:
case RACE_BLOODELF:
+ case RACE_GOBLIN:
team = TEAM_HORDE;
break;
default:
@@ -1824,6 +1936,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_NIGHTELF:
stmt->setUInt16(1, 113);
break;
+ case RACE_WORGEN:
+ stmt->setUInt16(1, 791);
+ break;
case RACE_UNDEAD_PLAYER:
stmt->setUInt16(1, 673);
break;
@@ -1836,6 +1951,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_BLOODELF:
stmt->setUInt16(1, 137);
break;
+ case RACE_GOBLIN:
+ stmt->setUInt16(1, 792);
+ break;
}
trans->Append(stmt);
@@ -2178,3 +2296,88 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
data << uint8(race);
SendPacket(&data);
}
+
+void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recvData)
+{
+ uint8 gender, race;
+
+ recvData >> race;
+ recvData >> gender;
+
+ if (!Player::IsValidRace(race))
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Invalid race (%u) sent by accountId: %u", race, GetAccountId());
+ return;
+ }
+
+ if (!Player::IsValidGender(gender))
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Invalid gender (%u) sent by accountId: %u", gender, GetAccountId());
+ return;
+ }
+
+ std::string const* name = GetRandomCharacterName(race, gender);
+ WorldPacket data(SMSG_RANDOMIZE_CHAR_NAME, 10);
+ data.WriteBit(0); // unk
+ data.WriteBits(name->size(), 7);
+ data.WriteString(*name);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleReorderCharacters(WorldPacket& recvData)
+{
+ uint32 charactersCount = recvData.ReadBits(10);
+
+ std::vector<ObjectGuid> guids(charactersCount);
+ uint8 position;
+
+ for (uint8 i = 0; i < charactersCount; ++i)
+ {
+ guids[i][1] = recvData.ReadBit();
+ guids[i][4] = recvData.ReadBit();
+ guids[i][5] = recvData.ReadBit();
+ guids[i][3] = recvData.ReadBit();
+ guids[i][0] = recvData.ReadBit();
+ guids[i][7] = recvData.ReadBit();
+ guids[i][6] = recvData.ReadBit();
+ guids[i][2] = recvData.ReadBit();
+ }
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (uint8 i = 0; i < charactersCount; ++i)
+ {
+ recvData.ReadByteSeq(guids[i][6]);
+ recvData.ReadByteSeq(guids[i][5]);
+ recvData.ReadByteSeq(guids[i][1]);
+ recvData.ReadByteSeq(guids[i][4]);
+ recvData.ReadByteSeq(guids[i][0]);
+ recvData.ReadByteSeq(guids[i][3]);
+
+ recvData >> position;
+
+ recvData.ReadByteSeq(guids[i][2]);
+ recvData.ReadByteSeq(guids[i][7]);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_LIST_SLOT);
+ stmt->setUInt8(0, position);
+ stmt->setUInt32(1, GUID_LOPART(guids[i]));
+ trans->Append(stmt);
+ }
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void WorldSession::HandleOpeningCinematic(WorldPacket& /*recvData*/)
+{
+ // Only players that has not yet gained any experience can use this
+ if (_player->GetUInt32Value(PLAYER_XP))
+ return;
+
+ if (ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(_player->getClass()))
+ {
+ if (classEntry->CinematicSequence)
+ _player->SendCinematicStart(classEntry->CinematicSequence);
+ else if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(_player->getRace()))
+ _player->SendCinematicStart(raceEntry->CinematicSequence);
+ }
+}
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index 9d4eae0f1b0..9ec018aaf78 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -42,11 +42,55 @@
void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
{
- uint32 type;
+ uint32 type = 0;
uint32 lang;
- recvData >> type;
- recvData >> lang;
+ switch (recvData.GetOpcode())
+ {
+ case CMSG_MESSAGECHAT_SAY:
+ type = CHAT_MSG_SAY;
+ break;
+ case CMSG_MESSAGECHAT_YELL:
+ type = CHAT_MSG_YELL;
+ break;
+ case CMSG_MESSAGECHAT_CHANNEL:
+ type = CHAT_MSG_CHANNEL;
+ break;
+ case CMSG_MESSAGECHAT_WHISPER:
+ type = CHAT_MSG_WHISPER;
+ break;
+ case CMSG_MESSAGECHAT_GUILD:
+ type = CHAT_MSG_GUILD;
+ break;
+ case CMSG_MESSAGECHAT_OFFICER:
+ type = CHAT_MSG_OFFICER;
+ break;
+ case CMSG_MESSAGECHAT_AFK:
+ type = CHAT_MSG_AFK;
+ break;
+ case CMSG_MESSAGECHAT_DND:
+ type = CHAT_MSG_DND;
+ break;
+ case CMSG_MESSAGECHAT_EMOTE:
+ type = CHAT_MSG_EMOTE;
+ break;
+ case CMSG_MESSAGECHAT_PARTY:
+ type = CHAT_MSG_PARTY;
+ break;
+ case CMSG_MESSAGECHAT_RAID:
+ type = CHAT_MSG_RAID;
+ break;
+ case CMSG_MESSAGECHAT_BATTLEGROUND:
+ type = CHAT_MSG_BATTLEGROUND;
+ break;
+ case CMSG_MESSAGECHAT_RAID_WARNING:
+ type = CHAT_MSG_RAID_WARNING;
+ break;
+ default:
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleMessagechatOpcode : Unknown chat opcode (%u)", recvData.GetOpcode());
+ recvData.hexlike();
+ return;
+ }
if (type >= MAX_CHAT_MSG_TYPE)
{
@@ -57,117 +101,125 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
Player* sender = GetPlayer();
- //TC_LOG_DEBUG("CHAT: packet received. type %u, lang %u", type, lang);
+ //TC_LOG_DEBUG(LOG_FILTER_GENERAL, "CHAT: packet received. type %u, lang %u", type, lang);
- // prevent talking at unknown language (cheating)
- LanguageDesc const* langDesc = GetLanguageDescByID(lang);
- if (!langDesc)
+ // no language sent with emote packet.
+ if (type != CHAT_MSG_EMOTE && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
{
- SendNotification(LANG_UNKNOWN_LANGUAGE);
- recvData.rfinish();
- return;
- }
- if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id))
- {
- // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
- Unit::AuraEffectList const& langAuras = sender->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE);
- bool foundAura = false;
- for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i)
- {
- if ((*i)->GetMiscValue() == int32(lang))
- {
- foundAura = true;
- break;
- }
- }
- if (!foundAura)
+ recvData >> lang;
+
+ // prevent talking at unknown language (cheating)
+ LanguageDesc const* langDesc = GetLanguageDescByID(lang);
+ if (!langDesc)
{
- SendNotification(LANG_NOT_LEARNED_LANGUAGE);
+ SendNotification(LANG_UNKNOWN_LANGUAGE);
recvData.rfinish();
return;
}
- }
-
- if (lang == LANG_ADDON)
- {
- // LANG_ADDON is only valid for the following message types
- switch (type)
+ if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id))
{
- case CHAT_MSG_PARTY:
- case CHAT_MSG_RAID:
- case CHAT_MSG_GUILD:
- case CHAT_MSG_BATTLEGROUND:
- case CHAT_MSG_WHISPER:
- if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON))
+ // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
+ Unit::AuraEffectList const& langAuras = sender->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE);
+ bool foundAura = false;
+ for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i)
+ {
+ if ((*i)->GetMiscValue() == int32(lang))
{
- std::string msg = "";
- recvData >> msg;
+ foundAura = true;
+ break;
+ }
+ }
+ if (!foundAura)
+ {
+ SendNotification(LANG_NOT_LEARNED_LANGUAGE);
+ recvData.rfinish();
+ return;
+ }
+ }
- if (msg.empty())
+ if (lang == LANG_ADDON)
+ {
+ // LANG_ADDON is only valid for the following message types
+ switch (type)
+ {
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_BATTLEGROUND:
+ case CHAT_MSG_WHISPER:
+ if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON))
+ {
+ std::string msg = "";
+ recvData >> msg;
+
+ if (msg.empty())
+ return;
+
+ sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), lang, msg);
+ }
+
+ // Disabled addon channel?
+ if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
return;
+ break;
+ default:
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination",
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
- sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), lang, msg);
- }
-
- // Disabled addon channel?
- if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
+ recvData.rfinish();
return;
- break;
- default:
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
-
- recvData.rfinish();
- return;
+ }
}
- }
- // LANG_ADDON should not be changed nor be affected by flood control
- else
- {
- // send in universal language if player in .gmon mode (ignore spell effects)
- if (sender->isGameMaster())
- lang = LANG_UNIVERSAL;
+ // LANG_ADDON should not be changed nor be affected by flood control
else
{
- Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE);
- if (!ModLangAuras.empty())
- lang = ModLangAuras.front()->GetMiscValue();
- else if (HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHAT))
+ // send in universal language if player in .gm on mode (ignore spell effects)
+ if (sender->isGameMaster())
lang = LANG_UNIVERSAL;
else
{
- switch (type)
+ // send in universal language in two side iteration allowed mode
+ if (HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHAT))
+ lang = LANG_UNIVERSAL;
+ else
{
- case CHAT_MSG_PARTY:
- case CHAT_MSG_PARTY_LEADER:
- case CHAT_MSG_RAID:
- case CHAT_MSG_RAID_LEADER:
- case CHAT_MSG_RAID_WARNING:
- // allow two side chat at group channel if two side group allowed
- if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
- lang = LANG_UNIVERSAL;
- break;
- case CHAT_MSG_GUILD:
- case CHAT_MSG_OFFICER:
- // allow two side chat at guild channel if two side guild allowed
- if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
- lang = LANG_UNIVERSAL;
- break;
+ switch (type)
+ {
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_PARTY_LEADER:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_RAID_LEADER:
+ case CHAT_MSG_RAID_WARNING:
+ // allow two side chat at group channel if two side group allowed
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
+ lang = LANG_UNIVERSAL;
+ break;
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_OFFICER:
+ // allow two side chat at guild channel if two side guild allowed
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
+ lang = LANG_UNIVERSAL;
+ break;
+ }
}
+
+ // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used)
+ Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE);
+ if (!ModLangAuras.empty())
+ lang = ModLangAuras.front()->GetMiscValue();
}
- }
- if (!sender->CanSpeak())
- {
- std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
- SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
- recvData.rfinish(); // Prevent warnings
- return;
+ if (!sender->CanSpeak())
+ {
+ std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
+ SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
+ recvData.rfinish(); // Prevent warnings
+ return;
+ }
}
-
- if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
- sender->UpdateSpeakTime();
}
+ else
+ lang = LANG_UNIVERSAL;
if (sender->HasAura(1852) && type != CHAT_MSG_WHISPER)
{
@@ -176,6 +228,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
+ uint32 textLength = 0;
+ uint32 receiverLength = 0;
std::string to, channel, msg;
bool ignoreChecks = false;
switch (type)
@@ -184,27 +238,30 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
case CHAT_MSG_EMOTE:
case CHAT_MSG_YELL:
case CHAT_MSG_PARTY:
- case CHAT_MSG_PARTY_LEADER:
case CHAT_MSG_GUILD:
case CHAT_MSG_OFFICER:
case CHAT_MSG_RAID:
- case CHAT_MSG_RAID_LEADER:
case CHAT_MSG_RAID_WARNING:
case CHAT_MSG_BATTLEGROUND:
- case CHAT_MSG_BATTLEGROUND_LEADER:
- recvData >> msg;
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
break;
case CHAT_MSG_WHISPER:
- recvData >> to;
- recvData >> msg;
+ receiverLength = recvData.ReadBits(10);
+ textLength = recvData.ReadBits(9);
+ to = recvData.ReadString(receiverLength);
+ msg = recvData.ReadString(textLength);
break;
case CHAT_MSG_CHANNEL:
- recvData >> channel;
- recvData >> msg;
+ receiverLength = recvData.ReadBits(10);
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
+ channel = recvData.ReadString(receiverLength);
break;
case CHAT_MSG_AFK:
case CHAT_MSG_DND:
- recvData >> msg;
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
ignoreChecks = true;
break;
}
@@ -307,8 +364,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
- if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(_player->GetGUID()))
- return;
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_PARTY_LEADER;
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
@@ -341,6 +398,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
} break;
case CHAT_MSG_RAID:
+ case CHAT_MSG_RAID_LEADER:
{
// if player is in battleground, he cannot say to battleground members by /ra
Group* group = GetPlayer()->GetOriginalGroup();
@@ -351,27 +409,13 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
- sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
-
- WorldPacket data;
- ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL);
- group->BroadcastPacket(&data, false);
- } break;
- case CHAT_MSG_RAID_LEADER:
- {
- // if player is in battleground, he cannot say to battleground members by /ra
- Group* group = GetPlayer()->GetOriginalGroup();
- if (!group)
- {
- group = GetPlayer()->GetGroup();
- if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID()))
- return;
- }
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_RAID_LEADER;
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data;
- ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL);
+ ChatHandler::FillMessageData(&data, this, uint8(type), lang, "", 0, msg.c_str(), NULL);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_RAID_WARNING:
@@ -388,29 +432,20 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_BATTLEGROUND:
- {
- //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
- Group* group = GetPlayer()->GetGroup();
- if (!group || !group->isBGGroup())
- return;
-
- sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
-
- WorldPacket data;
- ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL);
- group->BroadcastPacket(&data, false);
- } break;
case CHAT_MSG_BATTLEGROUND_LEADER:
{
// battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group* group = GetPlayer()->GetGroup();
- if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
+ if (!group || !group->isBGGroup())
return;
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_BATTLEGROUND_LEADER;
+
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data;
- ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL);
+ ChatHandler::FillMessageData(&data, this, uint8(type), lang, "", 0, msg.c_str(), NULL);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_CHANNEL:
@@ -486,6 +521,144 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
}
+void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recvData)
+{
+ Player* sender = GetPlayer();
+ ChatMsg type;
+
+ switch (recvData.GetOpcode())
+ {
+ case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND:
+ type = CHAT_MSG_BATTLEGROUND;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_GUILD:
+ type = CHAT_MSG_GUILD;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_OFFICER:
+ type = CHAT_MSG_OFFICER;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_PARTY:
+ type = CHAT_MSG_PARTY;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_RAID:
+ type = CHAT_MSG_RAID;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_WHISPER:
+ type = CHAT_MSG_WHISPER;
+ break;
+ default:
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleAddonMessagechatOpcode: Unknown addon chat opcode (%u)", recvData.GetOpcode());
+ recvData.hexlike();
+ return;
+ }
+
+ std::string message;
+ std::string prefix;
+ std::string targetName;
+
+ switch (type)
+ {
+ case CHAT_MSG_WHISPER:
+ {
+ uint32 msgLen = recvData.ReadBits(9);
+ uint32 prefixLen = recvData.ReadBits(5);
+ uint32 targetLen = recvData.ReadBits(10);
+ message = recvData.ReadString(msgLen);
+ prefix = recvData.ReadString(prefixLen);
+ targetName = recvData.ReadString(targetLen);
+ break;
+ }
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_OFFICER:
+ {
+ uint32 prefixLen = recvData.ReadBits(5);
+ uint32 msgLen = recvData.ReadBits(9);
+ prefix = recvData.ReadString(prefixLen);
+ message = recvData.ReadString(msgLen);
+ break;
+ }
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_BATTLEGROUND:
+ {
+ uint32 msgLen = recvData.ReadBits(9);
+ uint32 prefixLen = recvData.ReadBits(5);
+ message = recvData.ReadString(msgLen);
+ prefix = recvData.ReadString(prefixLen);
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Logging enabled?
+ if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON))
+ {
+ if (message.empty())
+ return;
+
+ // Weird way to log stuff...
+ sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), uint32(LANG_ADDON), message);
+ }
+
+ // Disabled addon channel?
+ if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
+ return;
+
+ switch (type)
+ {
+ case CHAT_MSG_BATTLEGROUND:
+ {
+ Group* group = sender->GetGroup();
+ if (!group || !group->isBGGroup())
+ return;
+
+ WorldPacket data;
+ ChatHandler::FillMessageData(&data, this, type, uint32(LANG_ADDON), "", 0, message.c_str(), NULL);
+ group->BroadcastAddonMessagePacket(&data, prefix, false);
+ break;
+ }
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_OFFICER:
+ {
+ if (sender->GetGuildId())
+ if (Guild* guild = sGuildMgr->GetGuildById(sender->GetGuildId()))
+ guild->BroadcastAddonToGuild(this, type == CHAT_MSG_OFFICER, message, prefix);
+ break;
+ }
+ case CHAT_MSG_WHISPER:
+ {
+ if (!normalizePlayerName(targetName))
+ break;
+ Player* receiver = sObjectAccessor->FindPlayerByName(targetName.c_str());
+ if (!receiver)
+ break;
+
+ sender->WhisperAddon(message, prefix, receiver);
+ break;
+ }
+ // Messages sent to "RAID" while in a party will get delivered to "PARTY"
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ {
+
+ Group* group = sender->GetGroup();
+ if (!group || group->isBGGroup())
+ break;
+
+ WorldPacket data;
+ ChatHandler::FillMessageData(&data, this, type, uint32(LANG_ADDON), "", 0, message.c_str(), NULL, prefix.c_str());
+ group->BroadcastAddonMessagePacket(&data, prefix, true, -1, group->GetMemberGroup(sender->GetGUID()));
+ break;
+ }
+ default:
+ {
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "HandleAddonMessagechatOpcode: unknown addon message type %u", type);
+ break;
+ }
+ }
+}
+
void WorldSession::HandleEmoteOpcode(WorldPacket& recvData)
{
if (!GetPlayer()->isAlive() || GetPlayer()->HasUnitState(UNIT_STATE_DIED))
@@ -584,7 +757,7 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker);
cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
+ GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, 0, unit);
//Send scripted event call
if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI())
@@ -593,14 +766,30 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData)
{
- uint64 iguid;
+ ObjectGuid guid;
uint8 unk;
//TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_CHAT_IGNORED");
- recvData >> iguid;
recvData >> unk; // probably related to spam reporting
-
- Player* player = ObjectAccessor::FindPlayer(iguid);
+ guid[5] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[2]);
+
+ Player* player = ObjectAccessor::FindPlayer(guid);
if (!player || !player->GetSession())
return;
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 0bf76555567..27cc50dacc5 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -48,11 +48,12 @@ class Aura;
void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
{
- WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4);
+ WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4 + 8);
data << uint32(operation);
data << member;
data << uint32(res);
data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
+ data << uint64(0); // player who caused error (in some cases).
SendPacket(&data);
}
@@ -61,59 +62,91 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE");
- std::string membername;
- recvData >> membername;
- recvData.read_skip<uint32>();
+ ObjectGuid crossRealmGuid; // unused
+
+ recvData.read_skip<uint32>(); // Non-zero in cross realm invites
+ recvData.read_skip<uint32>(); // Always 0
+
+ crossRealmGuid[2] = recvData.ReadBit();
+ crossRealmGuid[7] = recvData.ReadBit();
+
+ uint8 realmLen = recvData.ReadBits(9);
+
+ crossRealmGuid[3] = recvData.ReadBit();
+
+ uint8 nameLen = recvData.ReadBits(10);
+
+ crossRealmGuid[5] = recvData.ReadBit();
+ crossRealmGuid[4] = recvData.ReadBit();
+ crossRealmGuid[6] = recvData.ReadBit();
+ crossRealmGuid[0] = recvData.ReadBit();
+ crossRealmGuid[1] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(crossRealmGuid[4]);
+ recvData.ReadByteSeq(crossRealmGuid[7]);
+ recvData.ReadByteSeq(crossRealmGuid[6]);
+
+ std::string memberName, realmName;
+ memberName = recvData.ReadString(nameLen);
+ realmName = recvData.ReadString(realmLen); // unused
+
+ recvData.ReadByteSeq(crossRealmGuid[1]);
+ recvData.ReadByteSeq(crossRealmGuid[0]);
+ recvData.ReadByteSeq(crossRealmGuid[5]);
+ recvData.ReadByteSeq(crossRealmGuid[3]);
+ recvData.ReadByteSeq(crossRealmGuid[2]);
// attempt add selected player
// cheating
- if (!normalizePlayerName(membername))
+ if (!normalizePlayerName(memberName))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
- Player* player = sObjectAccessor->FindPlayerByName(membername);
+ Player* player = sObjectAccessor->FindPlayerByName(memberName);
// no player
if (!player)
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
// restrict invite to GMs
if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
// can't group with
if (!GetPlayer()->isGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION);
return;
}
if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
// just ignore us
if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
+ ObjectGuid invitedGuid = player->GetGUID();
+
Group* group = GetPlayer()->GetGroup();
if (group && group->isBGGroup())
group = GetPlayer()->GetOriginalGroup();
@@ -124,17 +157,63 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
// player already in another group or invited
if (group2 || player->GetGroupInvite())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S);
if (group2)
{
// tell the player that they were invited but it failed as they were already in a group
- WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
- data << uint8(0); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_INVITE, 45);
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[0]);
+ data.WriteBit(invitedGuid[3]);
+ data.WriteBit(invitedGuid[2]);
+
+ data.WriteBit(0); // Inverse already in group
+
+ data.WriteBit(invitedGuid[6]);
+ data.WriteBit(invitedGuid[5]);
+
+ data.WriteBits(0, 9); // Realm name
+
+ data.WriteBit(invitedGuid[4]);
+
+ data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
+
+ data.WriteBits(0, 24); // Count 2
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[1]);
+ data.WriteBit(invitedGuid[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(invitedGuid[1]);
+ data.WriteByteSeq(invitedGuid[4]);
+
+ data << int32(getMSTime());
+ data << int32(0);
+ data << int32(0);
+
+ data.WriteByteSeq(invitedGuid[6]);
+ data.WriteByteSeq(invitedGuid[0]);
+ data.WriteByteSeq(invitedGuid[2]);
+ data.WriteByteSeq(invitedGuid[3]);
+
+ // for count2 { int32(0) }
+
+ data.WriteByteSeq(invitedGuid[5]);
+
+ // data.append(realm name);
+
+ data.WriteByteSeq(invitedGuid[7]);
+
+ data.WriteString(GetPlayer()->GetName()); // inviter name
+
+ data << int32(0);
+
player->GetSession()->SendPacket(&data);
}
@@ -185,90 +264,138 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
// ok, we do it
- WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
- data << uint8(1); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_INVITE, 45);
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[0]);
+ data.WriteBit(invitedGuid[3]);
+ data.WriteBit(invitedGuid[2]);
+
+ data.WriteBit(1); // Inverse already in group
+
+ data.WriteBit(invitedGuid[6]);
+ data.WriteBit(invitedGuid[5]);
+
+ data.WriteBits(0, 9); // Realm name
+
+ data.WriteBit(invitedGuid[4]);
+
+ data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
+
+ data.WriteBits(0, 24); // Count 2
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[1]);
+ data.WriteBit(invitedGuid[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(invitedGuid[1]);
+ data.WriteByteSeq(invitedGuid[4]);
+
+ data << int32(getMSTime());
+ data << int32(0);
+ data << int32(0);
+
+ data.WriteByteSeq(invitedGuid[6]);
+ data.WriteByteSeq(invitedGuid[0]);
+ data.WriteByteSeq(invitedGuid[2]);
+ data.WriteByteSeq(invitedGuid[3]);
+
+ // for count2 { int32(0) }
+
+ data.WriteByteSeq(invitedGuid[5]);
+
+ // data.append(realm name);
+
+ data.WriteByteSeq(invitedGuid[7]);
+
+ data.WriteString(GetPlayer()->GetName());
+
+ data << int32(0);
+
player->GetSession()->SendPacket(&data);
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK);
}
-void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData)
+void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ACCEPT");
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE_RESPONSE");
- recvData.read_skip<uint32>();
- Group* group = GetPlayer()->GetGroupInvite();
+ recvData.ReadBit(); // unk always 0
+ bool accept = recvData.ReadBit();
- if (!group)
- return;
+ // Never actually received?
+ /*if (accept)
+ recvData.read_skip<uint32>(); // unk*/
- // Remove player from invitees in any case
- group->RemoveInvite(GetPlayer());
+ Group* group = GetPlayer()->GetGroupInvite();
- if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
- {
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ if (!group)
return;
- }
- // Group is full
- if (group->IsFull())
+ if (accept)
{
- SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
- return;
- }
-
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
+ // Remove player from invitees in any case
+ group->RemoveInvite(GetPlayer());
- // Forming a new group, create it
- if (!group->IsCreated())
- {
- // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
- if (!leader)
+ if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
{
- group->RemoveAllInvites();
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
return;
}
- // If we're about to create a group there really should be a leader present
- ASSERT(leader);
- group->RemoveInvite(leader);
- group->Create(leader);
- sGroupMgr->AddGroup(group);
- }
+ // Group is full
+ if (group->IsFull())
+ {
+ SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
+ return;
+ }
- // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
- if (!group->AddMember(GetPlayer()))
- return;
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- group->BroadcastGroupUpdate();
-}
+ // Forming a new group, create it
+ if (!group->IsCreated())
+ {
+ // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
+ if (!leader)
+ {
+ group->RemoveAllInvites();
+ return;
+ }
-void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recvData*/)
-{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DECLINE");
+ // If we're about to create a group there really should be a leader present
+ ASSERT(leader);
+ group->RemoveInvite(leader);
+ group->Create(leader);
+ sGroupMgr->AddGroup(group);
+ }
- Group* group = GetPlayer()->GetGroupInvite();
- if (!group)
- return;
+ // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
+ if (!group->AddMember(GetPlayer()))
+ return;
- // Remember leader if online (group pointer will be invalid if group gets disbanded)
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
+ group->BroadcastGroupUpdate();
+ }
+ else
+ {
+ // Remember leader if online (group pointer will be invalid if group gets disbanded)
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- // uninvite, group can be deleted
- GetPlayer()->UninviteFromGroup();
+ // uninvite, group can be deleted
+ GetPlayer()->UninviteFromGroup();
- if (!leader || !leader->GetSession())
- return;
+ if (!leader || !leader->GetSession())
+ return;
- // report
- WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().length());
- data << GetPlayer()->GetName();
- leader->GetSession()->SendPacket(&data);
+ // report
+ WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().size());
+ data << GetPlayer()->GetName();
+ leader->GetSession()->SendPacket(&data);
+ }
}
void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData)
@@ -386,7 +513,81 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
group->SendUpdate();
}
-void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SET_ROLES");
+
+ uint32 newRole;
+ ObjectGuid guid1; // Assigner GUID
+ ObjectGuid guid2; // Target GUID
+
+ guid1 = GetPlayer()->GetGUID();
+
+ recvData >> newRole;
+
+ guid2[2] = recvData.ReadBit();
+ guid2[6] = recvData.ReadBit();
+ guid2[3] = recvData.ReadBit();
+ guid2[7] = recvData.ReadBit();
+ guid2[5] = recvData.ReadBit();
+ guid2[1] = recvData.ReadBit();
+ guid2[0] = recvData.ReadBit();
+ guid2[4] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid2[6]);
+ recvData.ReadByteSeq(guid2[4]);
+ recvData.ReadByteSeq(guid2[1]);
+ recvData.ReadByteSeq(guid2[3]);
+ recvData.ReadByteSeq(guid2[0]);
+ recvData.ReadByteSeq(guid2[5]);
+ recvData.ReadByteSeq(guid2[2]);
+ recvData.ReadByteSeq(guid2[7]);
+
+ WorldPacket data(SMSG_GROUP_SET_ROLE, 24);
+
+ data.WriteBit(guid1[1]);
+ data.WriteBit(guid2[0]);
+ data.WriteBit(guid2[2]);
+ data.WriteBit(guid2[4]);
+ data.WriteBit(guid2[7]);
+ data.WriteBit(guid2[3]);
+ data.WriteBit(guid1[7]);
+ data.WriteBit(guid2[5]);
+ data.WriteBit(guid1[5]);
+ data.WriteBit(guid1[4]);
+ data.WriteBit(guid1[3]);
+ data.WriteBit(guid2[6]);
+ data.WriteBit(guid1[2]);
+ data.WriteBit(guid1[6]);
+ data.WriteBit(guid2[1]);
+ data.WriteBit(guid1[0]);
+
+ data.WriteByteSeq(guid1[7]);
+ data.WriteByteSeq(guid2[3]);
+ data.WriteByteSeq(guid1[6]);
+ data.WriteByteSeq(guid2[4]);
+ data.WriteByteSeq(guid2[0]);
+ data << uint32(newRole); // New Role
+ data.WriteByteSeq(guid2[6]);
+ data.WriteByteSeq(guid2[2]);
+ data.WriteByteSeq(guid1[0]);
+ data.WriteByteSeq(guid1[4]);
+ data.WriteByteSeq(guid2[1]);
+ data.WriteByteSeq(guid1[3]);
+ data.WriteByteSeq(guid1[5]);
+ data.WriteByteSeq(guid1[2]);
+ data.WriteByteSeq(guid2[5]);
+ data.WriteByteSeq(guid2[7]);
+ data.WriteByteSeq(guid1[1]);
+ data << uint32(0); // Old Role
+
+ if (GetPlayer()->GetGroup())
+ GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
+ else
+ SendPacket(&data);
+}
+
+void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DISBAND");
@@ -471,7 +672,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
recvData >> x;
recvData >> y;
- //TC_LOG_DEBUG("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
+ //TC_LOG_DEBUG(LOG_FILTER_GENERAL, "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
/** error handling **/
/********************/
@@ -500,7 +701,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData)
// everything's fine, do it
roll = urand(minimum, maximum);
- //TC_LOG_DEBUG("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
+ //TC_LOG_DEBUG(LOG_FILTER_GENERAL, "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8);
data << uint32(minimum);
@@ -521,7 +722,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
if (!group)
return;
- uint8 x;
+ uint8 x;
recvData >> x;
/** error handling **/
@@ -529,9 +730,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
// everything's fine, do it
if (x == 0xFF) // target icon request
- {
group->SendTargetIconList(this);
- }
else // target icon update
{
if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
@@ -543,7 +742,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_RAID_CONVERT");
@@ -554,14 +753,22 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
if (_player->InBattleground())
return;
- /** error handling **/
+ // error handling
if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2)
return;
- /********************/
// everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code)
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
- group->ConvertToRaid();
+
+ // New 4.x: it is now possible to convert a raid to a group if member count is 5 or less
+
+ bool toRaid;
+ recvData >> toRaid;
+
+ if (toRaid)
+ group->ConvertToRaid();
+ else
+ group->ConvertToGroup();
}
void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
@@ -590,10 +797,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
Player* movedPlayer = sObjectAccessor->FindPlayerByName(name);
uint64 guid;
+
if (movedPlayer)
- {
guid = movedPlayer->GetGUID();
- }
else
{
CharacterDatabase.EscapeString(name);
@@ -603,6 +809,16 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
group->ChangeMembersGroup(guid, groupNr);
}
+void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SWAP_SUB_GROUP");
+ std::string unk1;
+ std::string unk2;
+
+ recvData >> unk1;
+ recvData >> unk2;
+}
+
void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER");
@@ -693,7 +909,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/)
{
//Group* group = GetPlayer()->GetGroup();
//if (!group)
@@ -718,12 +934,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
- uint32 byteCount = 0;
- for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
- if (mask & (1 << i))
- byteCount += GroupUpdateLength[i];
-
- data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
+ data->Initialize(SMSG_PARTY_MEMBER_STATS, 80); // average value
data->append(player->GetPackGUID());
*data << uint32(mask);
@@ -780,23 +991,47 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_ZONE)
*data << uint16(player->GetZoneId());
+ if (mask & GROUP_UPDATE_FLAG_UNK100)
+ *data << uint16(0);
+
if (mask & GROUP_UPDATE_FLAG_POSITION)
{
*data << uint16(player->GetPositionX());
*data << uint16(player->GetPositionY());
+ *data << uint16(player->GetPositionZ());
}
if (mask & GROUP_UPDATE_FLAG_AURAS)
{
+ *data << uint8(0);
uint64 auramask = player->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
+ *data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = player->GetVisibleAura(i);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(1);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ *data << int32(eff->GetAmount());
+ else
+ *data << int32(0);
+ }
+ }
}
}
}
@@ -805,9 +1040,9 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_GUID)
{
if (pet)
- *data << (uint64) pet->GetGUID();
+ *data << uint64(pet->GetGUID());
else
- *data << (uint64) 0;
+ *data << uint64(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_NAME)
@@ -870,20 +1105,50 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
{
if (pet)
{
+ *data << uint8(0);
uint64 auramask = pet->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
+ *data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = pet->GetVisibleAura(i);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(aurApp ? aurApp->GetFlags() : 0);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ *data << int32(eff->GetAmount());
+ else
+ *data << int32(0);
+ }
+ }
}
}
}
else
+ {
+ *data << uint8(0);
*data << uint64(0);
+ }
+ }
+
+ if (mask & GROUP_UPDATE_FLAG_PHASE)
+ {
+ *data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT
+ *data << uint32(0); // count
+ // for (count) *data << uint16(phaseId)
}
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
@@ -892,22 +1157,23 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
*data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]);
else
*data << uint32(0);
+
}
}
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
-void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
+void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
- uint64 Guid;
- recvData >> Guid;
+ uint64 guid;
+ recvData >> guid;
- Player* player = HashMapHolder<Player>::Find(Guid);
+ Player* player = HashMapHolder<Player>::Find(guid);
if (!player)
{
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data.appendPackGUID(Guid);
+ data.appendPackGUID(guid);
data << uint32(GROUP_UPDATE_FLAG_STATUS);
data << uint16(MEMBER_STATUS_OFFLINE);
SendPacket(&data);
@@ -970,21 +1236,37 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
+ data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION
- uint64 auraMask = 0;
+ // GROUP_UPDATE_FLAG_AURAS
+ data << uint8(1);
+ uint64 auramask = 0;
size_t maskPos = data.wpos();
- data << uint64(auraMask); // placeholder
+ data << uint64(auramask); // placeholder
+ data << uint32(MAX_AURAS); // count
+
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = player->GetVisibleAura(i))
{
- auraMask |= uint64(1) << i;
+ auramask |= (uint64(1) << i);
+
data << uint32(aurApp->GetBase()->GetId());
- data << uint8(aurApp->GetFlags());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ data << int32(eff->GetAmount());
+ else
+ data << int32(0);
+ }
+ }
}
}
-
- data.put<uint64>(maskPos, auraMask); // GROUP_UPDATE_FLAG_AURAS
+ data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
data << uint64(pet->GetGUID());
@@ -1012,16 +1294,43 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
data << uint64(petAuraMask); // placeholder
if (pet)
{
+ // GROUP_UPDATE_FLAG_PET_AURAS
+ data << uint8(1);
+ uint64 petauramask = 0;
+ size_t petMaskPos = data.wpos();
+ data << uint64(petauramask); // placeholder
+ data << uint32(MAX_AURAS); // count
+
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
{
- petAuraMask |= uint64(1) << i;
+ petauramask |= (uint64(1) << i);
+
data << uint32(aurApp->GetBase()->GetId());
- data << uint8(aurApp->GetFlags());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ data << int32(eff->GetAmount());
+ else
+ data << int32(0);
+ }
+ }
}
}
+
+ data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS
}
+ // else not needed, flags do not include any PET_ update
+
+ // GROUP_UPDATE_FLAG_PHASE
+ data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT
+ data << uint32(0); // count
+ // for (count) *data << uint16(phaseId)
data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS
@@ -1031,28 +1340,23 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
SendPacket(&data);
}
-/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)
{
// every time the player checks the character screen
_player->SendRaidInfo();
}
-/*void WorldSession::HandleGroupCancelOpcode(WorldPacket& recvData)
-{
- TC_LOG_DEBUG("WORLD: got CMSG_GROUP_CANCEL.");
-}*/
-
void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_OPT_OUT_OF_LOOT");
- uint32 passOnLoot;
+ bool passOnLoot;
recvData >> passOnLoot; // 1 always pass, 0 do not pass
// ignore if player not loaded
if (!GetPlayer()) // needed because STATUS_AUTHED
{
- if (passOnLoot != 0)
+ if (passOnLoot)
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
return;
}
diff --git a/src/server/game/Handlers/GuildFinderHandler.cpp b/src/server/game/Handlers/GuildFinderHandler.cpp
new file mode 100644
index 00000000000..6855dac43fa
--- /dev/null
+++ b/src/server/game/Handlers/GuildFinderHandler.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WorldSession.h"
+#include "WorldPacket.h"
+#include "Object.h"
+#include "SharedDefines.h"
+#include "GuildFinderMgr.h"
+#include "GuildMgr.h"
+
+void WorldSession::HandleGuildFinderAddRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_ADD_RECRUIT");
+
+ if (sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow()).size() == 10)
+ return;
+
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+
+ recvPacket >> classRoles >> guildInterests >> availability;
+
+ ObjectGuid guid;
+ guid[3] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ uint16 commentLength = recvPacket.ReadBits(11);
+ guid[5] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ uint8 nameLength = recvPacket.ReadBits(7);
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[5]);
+ std::string comment = recvPacket.ReadString(commentLength);
+ std::string playerName = recvPacket.ReadString(nameLength);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[3]);
+
+ uint32 guildLowGuid = GUID_LOPART(uint64(guid));
+
+ if (!IS_GUILD_GUID(guid))
+ return;
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+
+ MembershipRequest request = MembershipRequest(GetPlayer()->GetGUIDLow(), guildLowGuid, availability, classRoles, guildInterests, comment, time(NULL));
+ sGuildFinderMgr->AddMembershipRequest(guildLowGuid, request);
+}
+
+void WorldSession::HandleGuildFinderBrowse(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_BROWSE");
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+ uint32 playerLevel = 0; // Raw player level (1-85), do they use MAX_FINDER_LEVEL when on level 85 ?
+
+ recvPacket >> classRoles >> availability >> guildInterests >> playerLevel;
+
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+ if (playerLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || playerLevel < 1)
+ return;
+
+ Player* player = GetPlayer();
+
+ LFGuildPlayer settings(player->GetGUIDLow(), classRoles, availability, guildInterests, ANY_FINDER_LEVEL);
+ LFGuildStore guildList = sGuildFinderMgr->GetGuildsMatchingSetting(settings, player->GetTeamId());
+ uint32 guildCount = guildList.size();
+
+ if (guildCount == 0)
+ {
+ WorldPacket packet(SMSG_LF_GUILD_BROWSE_UPDATED, 0);
+ player->SendDirectMessage(&packet);
+ return;
+ }
+
+ ByteBuffer bufferData(65 * guildCount);
+ WorldPacket data(SMSG_LF_GUILD_BROWSE_UPDATED, 3 + guildCount * 65); // Estimated size
+ data.WriteBits(guildCount, 19);
+
+ for (LFGuildStore::const_iterator itr = guildList.begin(); itr != guildList.end(); ++itr)
+ {
+ LFGuildSettings guildSettings = itr->second;
+ Guild* guild = sGuildMgr->GetGuildById(itr->first);
+
+ ObjectGuid guildGUID = ObjectGuid(guild->GetGUID());
+
+ data.WriteBit(guildGUID[7]);
+ data.WriteBit(guildGUID[5]);
+ data.WriteBits(guild->GetName().size(), 8);
+ data.WriteBit(guildGUID[0]);
+ data.WriteBits(guildSettings.GetComment().size(), 11);
+ data.WriteBit(guildGUID[4]);
+ data.WriteBit(guildGUID[1]);
+ data.WriteBit(guildGUID[2]);
+ data.WriteBit(guildGUID[6]);
+ data.WriteBit(guildGUID[3]);
+
+ bufferData << uint32(guild->GetEmblemInfo().GetColor());
+ bufferData << uint32(guild->GetEmblemInfo().GetBorderStyle()); // Guessed
+ bufferData << uint32(guild->GetEmblemInfo().GetStyle());
+
+ bufferData.WriteString(guildSettings.GetComment());
+
+ bufferData << uint8(0); // Unk
+
+ bufferData.WriteByteSeq(guildGUID[5]);
+
+ bufferData << uint32(guildSettings.GetInterests());
+
+ bufferData.WriteByteSeq(guildGUID[6]);
+ bufferData.WriteByteSeq(guildGUID[4]);
+
+ bufferData << uint32(guild->GetLevel());
+
+ bufferData.WriteString(guild->GetName());
+
+ bufferData << uint32(guild->GetAchievementMgr().GetAchievementPoints());
+
+ bufferData.WriteByteSeq(guildGUID[7]);
+
+ bufferData << uint8(sGuildFinderMgr->HasRequest(player->GetGUIDLow(), guild->GetGUID())); // Request pending
+
+ bufferData.WriteByteSeq(guildGUID[2]);
+ bufferData.WriteByteSeq(guildGUID[0]);
+
+ bufferData << uint32(guildSettings.GetAvailability());
+
+ bufferData.WriteByteSeq(guildGUID[1]);
+
+ bufferData << uint32(guild->GetEmblemInfo().GetBackgroundColor());
+ bufferData << uint32(0); // Unk Int 2 (+ 128) // Always 0 or 1
+ bufferData << uint32(guild->GetEmblemInfo().GetBorderColor());
+ bufferData << uint32(guildSettings.GetClassRoles());
+
+ bufferData.WriteByteSeq(guildGUID[3]);
+ bufferData << uint32(guild->GetMembersCount());
+ }
+
+ data.FlushBits();
+ data.append(bufferData);
+
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_DECLINE_RECRUIT");
+
+ ObjectGuid playerGuid;
+
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[2] = recvPacket.ReadBit();
+ playerGuid[6] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ recvPacket.ReadByteSeq(playerGuid[2]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+
+ if (!IS_PLAYER_GUID(playerGuid))
+ return;
+
+ sGuildFinderMgr->RemoveMembershipRequest(GUID_LOPART(playerGuid), GetPlayer()->GetGuildId());
+}
+
+void WorldSession::HandleGuildFinderGetApplications(WorldPacket& /*recvPacket*/)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_GET_APPLICATIONS"); // Empty opcode
+
+ std::list<MembershipRequest> applicatedGuilds = sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow());
+ uint32 applicationsCount = applicatedGuilds.size();
+ WorldPacket data(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, 7 + 54 * applicationsCount);
+ data.WriteBits(applicationsCount, 20);
+
+ if (applicationsCount > 0)
+ {
+ ByteBuffer bufferData(54 * applicationsCount);
+ for (std::list<MembershipRequest>::const_iterator itr = applicatedGuilds.begin(); itr != applicatedGuilds.end(); ++itr)
+ {
+ Guild* guild = sGuildMgr->GetGuildById(itr->GetGuildId());
+ LFGuildSettings guildSettings = sGuildFinderMgr->GetGuildSettings(itr->GetGuildId());
+ MembershipRequest request = *itr;
+
+ ObjectGuid guildGuid = ObjectGuid(guild->GetGUID());
+
+ data.WriteBit(guildGuid[1]);
+ data.WriteBit(guildGuid[0]);
+ data.WriteBit(guildGuid[5]);
+ data.WriteBits(request.GetComment().size(), 11);
+ data.WriteBit(guildGuid[3]);
+ data.WriteBit(guildGuid[7]);
+ data.WriteBit(guildGuid[4]);
+ data.WriteBit(guildGuid[6]);
+ data.WriteBit(guildGuid[2]);
+ data.WriteBits(guild->GetName().size(), 8);
+
+ bufferData.WriteByteSeq(guildGuid[2]);
+ bufferData.WriteString(request.GetComment());
+ bufferData.WriteByteSeq(guildGuid[5]);
+ bufferData.WriteString(guild->GetName());
+
+ bufferData << uint32(guildSettings.GetAvailability());
+ bufferData << uint32(request.GetExpiryTime() - time(NULL)); // Time left to application expiry (seconds)
+
+ bufferData.WriteByteSeq(guildGuid[0]);
+ bufferData.WriteByteSeq(guildGuid[6]);
+ bufferData.WriteByteSeq(guildGuid[3]);
+ bufferData.WriteByteSeq(guildGuid[7]);
+
+ bufferData << uint32(guildSettings.GetClassRoles());
+
+ bufferData.WriteByteSeq(guildGuid[4]);
+ bufferData.WriteByteSeq(guildGuid[1]);
+
+ bufferData << uint32(time(NULL) - request.GetSubmitTime()); // Time since application (seconds)
+ bufferData << uint32(guildSettings.GetInterests());
+ }
+
+ data.FlushBits();
+ data.append(bufferData);
+ }
+ data << uint32(10 - sGuildFinderMgr->CountRequestsFromPlayer(GetPlayer()->GetGUIDLow())); // Applications count left
+
+ GetPlayer()->SendDirectMessage(&data);
+}
+
+// Lists all recruits for a guild - Misses times
+void WorldSession::HandleGuildFinderGetRecruits(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_GET_RECRUITS");
+
+ uint32 unkTime = 0;
+ recvPacket >> unkTime;
+
+ Player* player = GetPlayer();
+ if (!player->GetGuildId())
+ return;
+
+ std::vector<MembershipRequest> recruitsList = sGuildFinderMgr->GetAllMembershipRequestsForGuild(player->GetGuildId());
+ uint32 recruitCount = recruitsList.size();
+
+ ByteBuffer dataBuffer(53 * recruitCount);
+ WorldPacket data(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, 7 + 26 * recruitCount + 53 * recruitCount);
+ data.WriteBits(recruitCount, 20);
+
+ for (std::vector<MembershipRequest>::const_iterator itr = recruitsList.begin(); itr != recruitsList.end(); ++itr)
+ {
+ MembershipRequest request = *itr;
+ ObjectGuid playerGuid(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER));
+
+ data.WriteBits(request.GetComment().size(), 11);
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBits(request.GetName().size(), 7);
+ data.WriteBit(playerGuid[5]);
+ data.WriteBit(playerGuid[1]);
+ data.WriteBit(playerGuid[6]);
+
+ dataBuffer.WriteByteSeq(playerGuid[4]);
+
+ dataBuffer << int32(time(NULL) <= request.GetExpiryTime());
+
+ dataBuffer.WriteByteSeq(playerGuid[3]);
+ dataBuffer.WriteByteSeq(playerGuid[0]);
+ dataBuffer.WriteByteSeq(playerGuid[1]);
+
+ dataBuffer << int32(request.GetLevel());
+
+ dataBuffer.WriteByteSeq(playerGuid[6]);
+ dataBuffer.WriteByteSeq(playerGuid[7]);
+ dataBuffer.WriteByteSeq(playerGuid[2]);
+
+ dataBuffer << int32(time(NULL) - request.GetSubmitTime()); // Time in seconds since application submitted.
+ dataBuffer << int32(request.GetAvailability());
+ dataBuffer << int32(request.GetClassRoles());
+ dataBuffer << int32(request.GetInterests());
+ dataBuffer << int32(request.GetExpiryTime() - time(NULL)); // TIme in seconds until application expires.
+
+ dataBuffer.WriteString(request.GetName());
+ dataBuffer.WriteString(request.GetComment());
+
+ dataBuffer << int32(request.GetClass());
+
+ dataBuffer.WriteByteSeq(playerGuid[5]);
+ }
+
+ data.FlushBits();
+ data.append(dataBuffer);
+ data << uint32(time(NULL)); // Unk time
+
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderPostRequest(WorldPacket& /*recvPacket*/)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_POST_REQUEST"); // Empty opcode
+
+ Player* player = GetPlayer();
+
+ if (!player->GetGuildId()) // Player must be in guild
+ return;
+
+ bool isGuildMaster = true;
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (guild->GetLeaderGUID() != player->GetGUID())
+ isGuildMaster = false;
+
+ LFGuildSettings settings = sGuildFinderMgr->GetGuildSettings(player->GetGuildId());
+
+ WorldPacket data(SMSG_LF_GUILD_POST_UPDATED, 35);
+ data.WriteBit(isGuildMaster); // Guessed
+
+ if (isGuildMaster)
+ {
+ data.WriteBit(settings.IsListed());
+ data.WriteBits(settings.GetComment().size(), 11);
+ data << uint32(settings.GetLevel());
+ data.WriteString(settings.GetComment());
+ data << uint32(0); // Unk Int32
+ data << uint32(settings.GetAvailability());
+ data << uint32(settings.GetClassRoles());
+ data << uint32(settings.GetInterests());
+ }
+ else
+ data.FlushBits();
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_REMOVE_RECRUIT");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[4]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+
+ if (!IS_GUILD_GUID(guildGuid))
+ return;
+
+ sGuildFinderMgr->RemoveMembershipRequest(GetPlayer()->GetGUIDLow(), GUID_LOPART(guildGuid));
+}
+
+// Sent any time a guild master sets an option in the interface and when listing / unlisting his guild
+void WorldSession::HandleGuildFinderSetGuildPost(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_SET_GUILD_POST");
+
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+ uint32 level = 0;
+
+ recvPacket >> level >> availability >> guildInterests >> classRoles;
+ // Level sent is zero if untouched, force to any (from interface). Idk why
+ if (!level)
+ level = ANY_FINDER_LEVEL;
+
+ uint16 length = recvPacket.ReadBits(11);
+ bool listed = recvPacket.ReadBit();
+ std::string comment = recvPacket.ReadString(length);
+
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+ if (!(level & ALL_GUILDFINDER_LEVELS) || level > ALL_GUILDFINDER_LEVELS)
+ return;
+
+ Player* player = GetPlayer();
+
+ if (!player->GetGuildId()) // Player must be in guild
+ return;
+
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) // Player must be guild master
+ if (guild->GetLeaderGUID() != player->GetGUID())
+ return;
+
+ LFGuildSettings settings(listed, player->GetTeamId(), player->GetGuildId(), classRoles, availability, guildInterests, level, comment);
+ sGuildFinderMgr->SetGuildSettings(player->GetGuildId(), settings);
+}
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index aa7c4b0b34a..b21b0a90c3d 100644
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -30,38 +30,21 @@
void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket)
{
- uint32 guildId;
- recvPacket >> guildId;
+ uint64 guildGuid, playerGuid;
+ recvPacket >> guildGuid >> playerGuid;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_QUERY [%s]: Guild: %u", GetPlayerInfo().c_str(), guildId);
- if (!guildId)
- return;
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_QUERY [%s]: Guild: %u Target: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(guildGuid), GUID_LOPART(playerGuid));
- if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->HandleQuery(this);
-}
-
-void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
-{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_CREATE");
-
- std::string name;
- recvPacket >> name;
-
- if (!GetPlayer()->GetGuildId()) // Player cannot be in guild
- {
- Guild* guild = new Guild();
- if (guild->Create(GetPlayer(), name))
- sGuildMgr->AddGuild(guild);
- else
- delete guild;
- }
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(playerGuid))
+ guild->HandleQuery(this);
}
void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
{
- std::string invitedName;
- recvPacket >> invitedName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ std::string invitedName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_INVITE [%s]: Invited: %s", GetPlayerInfo().c_str(), invitedName.c_str());
if (normalizePlayerName(invitedName))
@@ -71,19 +54,35 @@ void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid playerGuid;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_REMOVE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ playerGuid[6] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ playerGuid[2] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleRemoveMember(this, playerName);
+ recvPacket.ReadByteSeq(playerGuid[2]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_REMOVE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(playerGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleRemoveMember(this, playerGuid);
}
void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_ACCEPT [%s]", GetPlayer()->GetName().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_ACCEPT [%s]", GetPlayerInfo().c_str());
if (!GetPlayer()->GetGuildId())
if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildIdInvited()))
@@ -98,17 +97,10 @@ void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
GetPlayer()->SetInGuild(0);
}
-void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/)
-{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_INFO [%s]", GetPlayerInfo().c_str());
-
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->SendInfo(this);
-}
-
-void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
+void WorldSession::HandleGuildRosterOpcode(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_ROSTER [%s]", GetPlayerInfo().c_str());
+ recvPacket.rfinish();
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleRoster(this);
@@ -118,26 +110,107 @@ void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid targetGuid;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_PROMOTE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ targetGuid[7] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleUpdateMemberRank(this, playerName, false);
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_PROMOTE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(targetGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleUpdateMemberRank(this, targetGuid, false);
}
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid targetGuid;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_DEMOTE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ targetGuid[7] = recvPacket.ReadBit();
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleUpdateMemberRank(this, playerName, true);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_DEMOTE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(targetGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleUpdateMemberRank(this, targetGuid, true);
+}
+
+void WorldSession::HandleGuildAssignRankOpcode(WorldPacket& recvPacket)
+{
+ ObjectGuid targetGuid;
+ ObjectGuid setterGuid;
+
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[7] = recvPacket.ReadBit();
+ setterGuid[4] = recvPacket.ReadBit();
+ setterGuid[2] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ setterGuid[1] = recvPacket.ReadBit();
+ setterGuid[7] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ setterGuid[6] = recvPacket.ReadBit();
+ setterGuid[3] = recvPacket.ReadBit();
+ setterGuid[0] = recvPacket.ReadBit();
+ setterGuid[5] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(setterGuid[1]);
+ recvPacket.ReadByteSeq(setterGuid[3]);
+ recvPacket.ReadByteSeq(setterGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+ recvPacket.ReadByteSeq(setterGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(setterGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(setterGuid[2]);
+ recvPacket.ReadByteSeq(setterGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(setterGuid[7]);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_ASSIGN_MEMBER_RANK [%s]: Target: %u Rank: %u, Issuer: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(targetGuid), rankId, GUID_LOPART(setterGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetMemberRank(this, targetGuid, setterGuid, rankId);
}
void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
@@ -156,100 +229,85 @@ void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
guild->HandleDisband(this);
}
-void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
-{
- std::string name;
- recvPacket >> name;
-
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_LEADER [%s]: Target: %s", GetPlayerInfo().c_str(), name.c_str());
-
- if (normalizePlayerName(name))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetLeader(this, name);
-}
-
void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
{
- std::string motd;
- recvPacket >> motd;
-
+ uint32 motdLength = recvPacket.ReadBits(11);
+ std::string motd = recvPacket.ReadString(motdLength);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_MOTD [%s]: MOTD: %s", GetPlayerInfo().c_str(), motd.c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetMOTD(this, motd);
}
-void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleGuildSetNoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- std::string note;
- recvPacket >> playerName >> note;
-
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_SET_PUBLIC_NOTE [%s]: Target: %s, Note: %s",
- GetPlayerInfo().c_str(), playerName.c_str(), note.c_str());
+ ObjectGuid playerGuid;
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetMemberNote(this, playerName, note, true);
-}
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ bool ispublic = recvPacket.ReadBit(); // 0 == Officer, 1 == Public
+ playerGuid[6] = recvPacket.ReadBit();
+ uint32 noteLength = recvPacket.ReadBits(8);
+ playerGuid[2] = recvPacket.ReadBit();
-void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
-{
- std::string playerName;
- std::string note;
- recvPacket >> playerName >> note;
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ std::string note = recvPacket.ReadString(noteLength);
+ recvPacket.ReadByteSeq(playerGuid[2]);
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_SET_OFFICER_NOTE [%s]: Target: %s, Note: %s",
- GetPlayerInfo().c_str(), playerName.c_str(), note.c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_SET_NOTE [%s]: Target: %u, Note: %s, Public: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(playerGuid), note.c_str(), ispublic);
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetMemberNote(this, playerName, note, false);
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetMemberNote(this, note, playerGuid, ispublic);
}
-void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleGuildQueryRanksOpcode(WorldPacket& recvPacket)
{
- uint32 rankId;
- recvPacket >> rankId;
+ ObjectGuid guildGuid;
- uint32 rights;
- recvPacket >> rights;
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
- std::string rankName;
- recvPacket >> rankName;
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
- uint32 money;
- recvPacket >> money;
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_QUERY_RANKS [%s]: Guild: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(guildGuid));
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_RANK [%s]: Rank: %s (%u)", GetPlayerInfo().c_str(), rankName.c_str(), rankId);
-
- Guild* guild = GetPlayer()->GetGuild();
- if (!guild)
- {
- recvPacket.rpos(recvPacket.wpos());
- return;
- }
-
- GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS);
-
- for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
- {
- uint32 bankRights;
- uint32 slots;
-
- recvPacket >> bankRights;
- recvPacket >> slots;
-
- rightsAndSlots[tabId] = GuildBankRightsAndSlots(tabId, bankRights, slots);
- }
-
- guild->HandleSetRankInfo(this, rankId, rankName, rights, money, rightsAndSlots);
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(_player->GetGUID()))
+ guild->SendGuildRankInfo(this);
}
void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
{
- std::string rankName;
- recvPacket >> rankName;
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ uint32 length = recvPacket.ReadBits(7);
+ std::string rankName = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_ADD_RANK [%s]: Rank: %s", GetPlayerInfo().c_str(), rankName.c_str());
@@ -257,18 +315,21 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
guild->HandleAddNewRank(this, rankName);
}
-void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/)
+void WorldSession::HandleGuildDelRankOpcode(WorldPacket& recvPacket)
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_DEL_RANK [%s]", GetPlayerInfo().c_str());
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_DEL_RANK [%s]: Rank: %u", GetPlayerInfo().c_str(), rankId);
if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleRemoveLowestRank(this);
+ guild->HandleRemoveRank(this, rankId);
}
void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket)
{
- std::string info;
- recvPacket >> info;
+ uint32 length = recvPacket.ReadBits(12);
+ std::string info = recvPacket.ReadString(length);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_INFO_TEXT [%s]: %s", GetPlayerInfo().c_str(), info.c_str());
@@ -313,32 +374,36 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
guild->SendEventLog(this);
}
-void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recvData */)
+void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket& /* recvPacket */)
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_BANK_MONEY_WITHDRAWN [%s]", GetPlayerInfo().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_MONEY_WITHDRAWN [%s]", GetPlayerInfo().c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendMoneyInfo(this);
}
-void WorldSession::HandleGuildPermissions(WorldPacket& /* recvData */)
+void WorldSession::HandleGuildPermissions(WorldPacket& /* recvPacket */)
{
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_PERMISSIONS [%s]", GetPlayerInfo().c_str());
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_PERMISSIONS [%s]", GetPlayerInfo().c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendPermissions(this);
}
// Called when clicking on Guild bank gameobject
-void WorldSession::HandleGuildBankerActivate(WorldPacket& recvData)
+void WorldSession::HandleGuildBankerActivate(WorldPacket& recvPacket)
{
uint64 guid;
bool sendAllSlots;
- recvData >> guid >> sendAllSlots;
+ recvPacket >> guid >> sendAllSlots;
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANKER_ACTIVATE [%s]: Go: [" UI64FMTD "] AllSlots: %u"
, GetPlayerInfo().c_str(), guid, sendAllSlots);
+ GameObject const* const go = GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK);
+ if (!go)
+ return;
+
Guild* const guild = GetPlayer()->GetGuild();
if (!guild)
{
@@ -346,33 +411,33 @@ void WorldSession::HandleGuildBankerActivate(WorldPacket& recvData)
return;
}
- guild->SendBankTabsInfo(this, sendAllSlots);
+ guild->SendBankList(this, 0, true, true);
}
// Called when opening guild bank tab only (first one)
-void WorldSession::HandleGuildBankQueryTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankQueryTab(WorldPacket& recvPacket)
{
uint64 guid;
uint8 tabId;
- bool full;
+ bool sendAllSlots;
- recvData >> guid >> tabId >> full;
+ recvPacket >> guid >> tabId >> sendAllSlots;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_QUERY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, ShowTabs: %u"
- , GetPlayerInfo().c_str(), guid, tabId, full);
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_QUERY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, AllSlots: %u"
+ , GetPlayerInfo().c_str(), guid, tabId, sendAllSlots);
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
- guild->SendBankTabData(this, tabId);
+ guild->SendBankList(this, tabId, true, false);
}
-void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvData)
+void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvPacket)
{
uint64 guid;
- uint32 money;
- recvData >> guid >> money;
+ uint64 money;
+ recvPacket >> guid >> money;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_DEPOSIT_MONEY [%s]: Go: [" UI64FMTD "], money: %u",
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_DEPOSIT_MONEY [%s]: Go: [" UI64FMTD "], money: " UI64FMTD,
GetPlayerInfo().c_str(), guid, money);
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
@@ -381,13 +446,13 @@ void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvData)
guild->HandleMemberDepositMoney(this, money);
}
-void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvData)
+void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvPacket)
{
uint64 guid;
- uint32 money;
- recvData >> guid >> money;
+ uint64 money;
+ recvPacket >> guid >> money;
- TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_WITHDRAW_MONEY [%s]: Go: [" UI64FMTD "], money: %u",
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_WITHDRAW_MONEY [%s]: Go: [" UI64FMTD "], money: " UI64FMTD,
GetPlayerInfo().c_str(), guid, money);
if (money && GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
@@ -395,28 +460,28 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvData)
guild->HandleMemberWithdrawMoney(this, money);
}
-void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
+void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_SWAP_ITEMS [%s]", GetPlayerInfo().c_str());
uint64 GoGuid;
- recvData >> GoGuid;
+ recvPacket >> GoGuid;
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
{
- recvData.rfinish(); // Prevent additional spam at rejected packet
+ recvPacket.rfinish(); // Prevent additional spam at rejected packet
return;
}
Guild* guild = GetPlayer()->GetGuild();
if (!guild)
{
- recvData.rfinish(); // Prevent additional spam at rejected packet
+ recvPacket.rfinish(); // Prevent additional spam at rejected packet
return;
}
uint8 bankToBank;
- recvData >> bankToBank;
+ recvPacket >> bankToBank;
uint8 tabId;
uint8 slotId;
@@ -426,18 +491,19 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
if (bankToBank)
{
uint8 destTabId;
- recvData >> destTabId;
+ recvPacket >> destTabId;
uint8 destSlotId;
- recvData >> destSlotId;
- recvData.read_skip<uint32>(); // Always 0
+ recvPacket >> destSlotId;
- recvData >> tabId;
- recvData >> slotId;
- recvData >> itemEntry;
- recvData.read_skip<uint8>(); // Always 0
+ uint32 destItemEntry;
+ recvPacket >> destItemEntry;
- recvData >> splitedAmount;
+ recvPacket >> tabId;
+ recvPacket >> slotId;
+ recvPacket >> itemEntry;
+ recvPacket.read_skip<uint8>(); // Always 0
+ recvPacket >> splitedAmount;
guild->SwapItems(GetPlayer(), tabId, slotId, destTabId, destSlotId, splitedAmount);
}
@@ -447,71 +513,70 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
uint8 playerSlotId = NULL_SLOT;
uint8 toChar = 1;
- recvData >> tabId;
- recvData >> slotId;
- recvData >> itemEntry;
+ recvPacket >> tabId;
+ recvPacket >> slotId;
+ recvPacket >> itemEntry;
uint8 autoStore;
- recvData >> autoStore;
+ recvPacket >> autoStore;
if (autoStore)
{
- recvData.read_skip<uint32>(); // autoStoreCount
- recvData.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char)
- recvData.read_skip<uint32>(); // Always 0
+ recvPacket.read_skip<uint32>(); // autoStoreCount
+ recvPacket.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char)
+ recvPacket.read_skip<uint32>(); // Always 0
}
else
{
- recvData >> playerBag;
- recvData >> playerSlotId;
- recvData >> toChar;
- recvData >> splitedAmount;
+ recvPacket >> playerBag;
+ recvPacket >> playerSlotId;
+ recvPacket >> toChar;
+ recvPacket >> splitedAmount;
}
// Player <-> Bank
// Allow to work with inventory only
if (!Player::IsInventoryPos(playerBag, playerSlotId) && !(playerBag == NULL_BAG && playerSlotId == NULL_SLOT))
- GetPlayer()->SendEquipError(EQUIP_ERR_NONE, NULL);
+ GetPlayer()->SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, NULL);
else
guild->SwapItemsWithInventory(GetPlayer(), toChar, tabId, slotId, playerBag, playerSlotId, splitedAmount);
}
}
-void WorldSession::HandleGuildBankBuyTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankBuyTab(WorldPacket& recvPacket)
{
uint64 guid;
- uint8 tabId;
+ recvPacket >> guid;
- recvData >> guid >> tabId;
+ uint8 tabId;
+ recvPacket >> tabId;
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_BUY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u", GetPlayerInfo().c_str(), guid, tabId);
-
- if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (!guid || GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleBuyBankTab(this, tabId);
}
-void WorldSession::HandleGuildBankUpdateTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankUpdateTab(WorldPacket& recvPacket)
{
uint64 guid;
uint8 tabId;
std::string name, icon;
- recvData >> guid >> tabId >> name >> icon;
+ recvPacket >> guid >> tabId >> name >> icon;
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_BANK_UPDATE_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, Name: %s, Icon: %s"
, GetPlayerInfo().c_str(), guid, tabId, name.c_str(), icon.c_str());
-
if (!name.empty() && !icon.empty())
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetBankTabInfo(this, tabId, name, icon);
}
-void WorldSession::HandleGuildBankLogQuery(WorldPacket& recvData)
+void WorldSession::HandleGuildBankLogQuery(WorldPacket& recvPacket)
{
- uint8 tabId;
- recvData >> tabId;
+ uint32 tabId;
+ recvPacket >> tabId;
TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_GUILD_BANK_LOG_QUERY [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
@@ -519,10 +584,10 @@ void WorldSession::HandleGuildBankLogQuery(WorldPacket& recvData)
guild->SendBankLog(this, tabId);
}
-void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvData)
+void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvPacket)
{
uint8 tabId;
- recvData >> tabId;
+ recvPacket >> tabId;
TC_LOG_DEBUG(LOG_FILTER_GUILD, "MSG_QUERY_GUILD_BANK_TEXT [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
@@ -530,14 +595,231 @@ void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvData)
guild->SendBankTabText(this, tabId);
}
-void WorldSession::HandleSetGuildBankTabText(WorldPacket &recvData)
+void WorldSession::HandleSetGuildBankTabText(WorldPacket& recvPacket)
{
- uint8 tabId;
- std::string text;
- recvData >> tabId >> text;
+ uint32 tabId;
+ recvPacket >> tabId;
+
+ uint32 textLen = recvPacket.ReadBits(14);
+ std::string text = recvPacket.ReadString(textLen);
TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_SET_GUILD_BANK_TEXT [%s]: TabId: %u, Text: %s", GetPlayerInfo().c_str(), tabId, text.c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SetBankTabText(tabId, text);
}
+
+void WorldSession::HandleGuildQueryXPOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUERY_GUILD_XP");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_QUERY_GUILD_XP [%s]: Guild: %u", GetPlayerInfo().c_str(), GUID_LOPART(guildGuid));
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(_player->GetGUID()))
+ guild->SendGuildXP(this);
+}
+
+void WorldSession::HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket)
+{
+ Guild* guild = GetPlayer()->GetGuild();
+ if (!guild)
+ {
+ recvPacket.rfinish();
+ return;
+ }
+
+ uint32 oldRankId;
+ uint32 newRankId;
+ uint32 oldRights;
+ uint32 newRights;
+ uint32 moneyPerDay;
+
+ recvPacket >> oldRankId;
+ recvPacket >> oldRights;
+ recvPacket >> newRights;
+
+ GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS);
+ for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
+ {
+ uint32 bankRights;
+ uint32 slots;
+
+ recvPacket >> bankRights;
+ recvPacket >> slots;
+
+ rightsAndSlots[tabId] = GuildBankRightsAndSlots(tabId, uint8(bankRights), slots);
+ }
+
+ recvPacket >> moneyPerDay;
+ recvPacket >> newRankId;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ std::string rankName = recvPacket.ReadString(nameLength);
+
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_SET_RANK_PERMISSIONS [%s]: Rank: %s (%u)", GetPlayerInfo().c_str(), rankName.c_str(), newRankId);
+
+ guild->HandleSetRankInfo(this, newRankId, rankName, newRights, moneyPerDay, rightsAndSlots);
+}
+
+void WorldSession::HandleGuildRequestPartyState(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_REQUEST_PARTY_STATE");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ guild->HandleGuildPartyRequest(this);
+}
+
+void WorldSession::HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[0] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[0]);
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guid))
+ {
+ if (guild->IsMember(_player->GetGUID()))
+ {
+ WorldPacket data(SMSG_GUILD_MAX_DAILY_XP, 8);
+ data << uint64(sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP));
+ SendPacket(&data);
+ }
+ }
+}
+
+void WorldSession::HandleAutoDeclineGuildInvites(WorldPacket& recvPacket)
+{
+ uint8 enable;
+ recvPacket >> enable;
+
+ GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_AUTO_DECLINE_GUILD, enable);
+}
+
+void WorldSession::HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket)
+{
+ recvPacket.read_skip<uint32>(); // Unk
+
+ if (sGuildMgr->GetGuildById(_player->GetGuildId()))
+ {
+ std::vector<GuildReward> const& rewards = sGuildMgr->GetGuildRewards();
+
+ WorldPacket data(SMSG_GUILD_REWARDS_LIST, 3 + rewards.size() * (4 + 4 + 4 + 8 + 4 + 4));
+ data.WriteBits(rewards.size(), 21);
+ data.FlushBits();
+
+ for (uint32 i = 0; i < rewards.size(); i++)
+ {
+ data << uint32(rewards[i].Standing);
+ data << int32(rewards[i].Racemask);
+ data << uint32(rewards[i].Entry);
+ data << uint64(rewards[i].Price);
+ data << uint32(0); // Unused
+ data << uint32(rewards[i].AchievementId);
+ }
+ data << uint32(time(NULL));
+ SendPacket(&data);
+ }
+}
+
+void WorldSession::HandleGuildQueryNewsOpcode(WorldPacket& recvPacket)
+{
+ recvPacket.read_skip<uint32>();
+ TC_LOG_DEBUG(LOG_FILTER_GUILD, "CMSG_GUILD_QUERY_NEWS [%s]", GetPlayerInfo().c_str());
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->SendNewsUpdate(this);
+}
+
+void WorldSession::HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket)
+{
+ uint32 newsId;
+ bool sticky;
+ ObjectGuid guid;
+
+ recvPacket >> newsId;
+
+ guid[2] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ sticky = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleNewsSetSticky(this, newsId, sticky);
+}
+
+void WorldSession::HandleGuildSetGuildMaster(WorldPacket& recvPacket)
+{
+ uint8 nameLength = recvPacket.ReadBits(7);
+ // This is related to guild master inactivity.
+ /*bool isDethrone = */recvPacket.ReadBit();
+ std::string playerName = recvPacket.ReadString(nameLength);
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetNewGuildMaster(this, playerName);
+}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 13f1988f050..f23a1c9632f 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -27,6 +27,8 @@
#include "UpdateData.h"
#include "ObjectAccessor.h"
#include "SpellInfo.h"
+#include "DB2Stores.h"
+#include <vector>
void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
{
@@ -54,7 +56,7 @@ void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, dstslot, false)) // can be autostore pos
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -81,7 +83,7 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, true))
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -133,7 +135,7 @@ void WorldSession::HandleSwapItem(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, dstslot, true))
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -236,7 +238,7 @@ void WorldSession::HandleAutoEquipItemOpcode(WorldPacket& recvData)
void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
{
- //TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: CMSG_DESTROYITEM");
+ //TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: CMSG_DESTROY_ITEM");
uint8 bag, slot, count, data1, data2, data3;
recvData >> bag >> slot >> count >> data1 >> data2 >> data3;
@@ -264,7 +266,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
if (pItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_INDESTRUCTIBLE)
{
- _player->SendEquipError(EQUIP_ERR_CANT_DROP_SOULBOUND, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL);
return;
}
@@ -277,174 +279,11 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
_player->DestroyItem(bag, slot, true);
}
-// Only _static_ data send in this packet !!!
-void WorldSession::HandleItemQuerySingleOpcode(WorldPacket& recvData)
-{
- //TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: CMSG_ITEM_QUERY_SINGLE");
- uint32 item;
- recvData >> item;
-
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "STORAGE: Item Query = %u", item);
-
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
- if (pProto)
- {
- std::string Name = pProto->Name1;
- std::string Description = pProto->Description;
-
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
- {
- if (ItemLocale const* il = sObjectMgr->GetItemLocale(pProto->ItemId))
- {
- ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
- }
- }
- // guess size
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
- data << pProto->ItemId;
- data << pProto->Class;
- data << pProto->SubClass;
- data << pProto->SoundOverrideSubclass;
- data << Name;
- data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
- data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
- data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
- data << pProto->DisplayInfoID;
- data << pProto->Quality;
- data << pProto->Flags;
- data << pProto->Flags2;
- data << pProto->BuyPrice;
- data << pProto->SellPrice;
- data << pProto->InventoryType;
- data << pProto->AllowableClass;
- data << pProto->AllowableRace;
- data << pProto->ItemLevel;
- data << pProto->RequiredLevel;
- data << pProto->RequiredSkill;
- data << pProto->RequiredSkillRank;
- data << pProto->RequiredSpell;
- data << pProto->RequiredHonorRank;
- data << pProto->RequiredCityRank;
- data << pProto->RequiredReputationFaction;
- data << pProto->RequiredReputationRank;
- data << int32(pProto->MaxCount);
- data << int32(pProto->Stackable);
- data << pProto->ContainerSlots;
- data << pProto->StatsCount; // item stats count
- for (uint32 i = 0; i < pProto->StatsCount; ++i)
- {
- data << pProto->ItemStat[i].ItemStatType;
- data << pProto->ItemStat[i].ItemStatValue;
- }
- data << pProto->ScalingStatDistribution; // scaling stats distribution
- data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- data << pProto->Damage[i].DamageMin;
- data << pProto->Damage[i].DamageMax;
- data << pProto->Damage[i].DamageType;
- }
-
- // resistances (7)
- data << pProto->Armor;
- data << pProto->HolyRes;
- data << pProto->FireRes;
- data << pProto->NatureRes;
- data << pProto->FrostRes;
- data << pProto->ShadowRes;
- data << pProto->ArcaneRes;
-
- data << pProto->Delay;
- data << pProto->AmmoType;
- data << pProto->RangedModRange;
-
- for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
- {
- // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
- // use `item_template` or if not set then only use spell cooldowns
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(pProto->Spells[s].SpellId);
- if (spell)
- {
- bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
-
- data << pProto->Spells[s].SpellId;
- data << pProto->Spells[s].SpellTrigger;
- data << uint32(-abs(pProto->Spells[s].SpellCharges));
-
- if (db_data)
- {
- data << uint32(pProto->Spells[s].SpellCooldown);
- data << uint32(pProto->Spells[s].SpellCategory);
- data << uint32(pProto->Spells[s].SpellCategoryCooldown);
- }
- else
- {
- data << uint32(spell->RecoveryTime);
- data << uint32(spell->Category);
- data << uint32(spell->CategoryRecoveryTime);
- }
- }
- else
- {
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(-1);
- data << uint32(0);
- data << uint32(-1);
- }
- }
- data << pProto->Bonding;
- data << Description;
- data << pProto->PageText;
- data << pProto->LanguageID;
- data << pProto->PageMaterial;
- data << pProto->StartQuest;
- data << pProto->LockID;
- data << int32(pProto->Material);
- data << pProto->Sheath;
- data << pProto->RandomProperty;
- data << pProto->RandomSuffix;
- data << pProto->Block;
- data << pProto->ItemSet;
- data << pProto->MaxDurability;
- data << pProto->Area;
- data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch
- data << pProto->BagFamily;
- data << pProto->TotemCategory;
- for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
- {
- data << pProto->Socket[s].Color;
- data << pProto->Socket[s].Content;
- }
- data << pProto->socketBonus;
- data << pProto->GemProperties;
- data << pProto->RequiredDisenchantSkill;
- data << pProto->ArmorDamageModifier;
- data << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
- data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
- data << pProto->HolidayId; // Holiday.dbc?
- SendPacket(&data);
- }
- else
- {
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item);
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
- data << uint32(item | 0x80000000);
- SendPacket(&data);
- }
-}
-
void WorldSession::HandleReadItem(WorldPacket& recvData)
{
- //TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: CMSG_READ_ITEM");
-
uint8 bag, slot;
recvData >> bag >> slot;
- //TC_LOG_INFO(LOG_FILTER_NETWORKIO, "STORAGE: Read bag = %u, slot = %u", bag, slot);
Item* pItem = _player->GetItemByPos(bag, slot);
if (pItem && pItem->GetTemplate()->PageText)
@@ -454,7 +293,7 @@ void WorldSession::HandleReadItem(WorldPacket& recvData)
InventoryResult msg = _player->CanUseItem(pItem);
if (msg == EQUIP_ERR_OK)
{
- data.Initialize (SMSG_READ_ITEM_OK, 8);
+ data.Initialize(SMSG_READ_ITEM_OK, 8);
TC_LOG_INFO(LOG_FILTER_NETWORKIO, "STORAGE: Item page sent");
}
else
@@ -470,19 +309,6 @@ void WorldSession::HandleReadItem(WorldPacket& recvData)
_player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
}
-void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket& recvData)
-{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY");
-
- uint32 itemid;
- uint64 guid;
-
- recvData >> itemid >> guid;
-
- TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u",
- itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid));
-}
-
void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SELL_ITEM");
@@ -498,7 +324,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
if (!creature)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid);
return;
}
@@ -512,21 +338,21 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
// prevent sell not owner item
if (_player->GetGUID() != pItem->GetOwnerGUID())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
// prevent sell non empty bag by drag-and-drop at vendor's item list
if (pItem->IsNotEmptyBag())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
// prevent sell currently looted item
if (_player->GetLootGUID() == pItem->GetGUID())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
@@ -544,7 +370,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
// prevent sell more items that exist in stack (possible only not from client)
if (count > pItem->GetCount())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
}
@@ -560,7 +386,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
if (!pNewItem)
{
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
@@ -587,11 +413,11 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
}
else
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
}
- _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid);
return;
}
@@ -607,7 +433,7 @@ void WorldSession::HandleBuybackItem(WorldPacket& recvData)
if (!creature)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0);
return;
}
@@ -619,7 +445,7 @@ void WorldSession::HandleBuybackItem(WorldPacket& recvData)
if (pItem)
{
uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START);
- if (!_player->HasEnoughMoney(price))
+ if (!_player->HasEnoughMoney(uint64(price)))
{
_player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, pItem->GetEntry(), 0);
return;
@@ -659,24 +485,15 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData)
return; // cheating
uint8 bag = NULL_BAG; // init for case invalid bagGUID
-
+ Item* bagItem = NULL;
// find bag slot by bag guid
if (bagguid == _player->GetGUID())
bag = INVENTORY_SLOT_BAG_0;
else
- {
- for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
- {
- if (Bag* pBag = _player->GetBagByPos(i))
- {
- if (bagguid == pBag->GetGUID())
- {
- bag = i;
- break;
- }
- }
- }
- }
+ bagItem = _player->GetItemByGuid(bagguid);
+
+ if (bagItem && bagItem->IsBag())
+ bag = bagItem->GetSlot();
// bag not found, cheating?
if (bag == NULL_BAG)
@@ -688,11 +505,12 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData)
void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUY_ITEM");
- uint64 vendorguid;
+ uint64 vendorguid, bagGuid;
uint32 item, slot, count;
- uint8 unk1;
+ uint8 itemType; // 1 = item, 2 = currency
+ uint8 bagSlot;
- recvData >> vendorguid >> item >> slot >> count >> unk1;
+ recvData >> vendorguid >> itemType >> item >> slot >> count >> bagGuid >> bagSlot;
// client expects count starting at 1, and we send vendorslot+1 to client already
if (slot > 0)
@@ -700,7 +518,22 @@ void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData)
else
return; // cheating
- GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, NULL_BAG, NULL_SLOT);
+ if (itemType == ITEM_VENDOR_TYPE_ITEM)
+ {
+ Item* bagItem = _player->GetItemByGuid(bagGuid);
+
+ uint8 bag = NULL_BAG;
+ if (bagItem && bagItem->IsBag())
+ bag = bagItem->GetSlot();
+ else if (bagGuid == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack
+ bag = INVENTORY_SLOT_BAG_0;
+
+ GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagSlot);
+ }
+ else if (itemType == ITEM_VENDOR_TYPE_CURRENCY)
+ GetPlayer()->BuyCurrencyFromVendorSlot(vendorguid, slot, item, count);
+ else
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", itemType);
}
void WorldSession::HandleListInventoryOpcode(WorldPacket& recvData)
@@ -725,7 +558,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
if (!vendor)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0);
return;
}
@@ -737,78 +570,148 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
if (vendor->HasUnitState(UNIT_STATE_MOVING))
vendor->StopMoving();
- VendorItemData const* items = vendor->GetVendorItems();
- if (!items)
- {
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1);
- data << uint64(vendorGuid);
- data << uint8(0); // count == 0, next will be error code
- data << uint8(0); // "Vendor has no inventory"
- SendPacket(&data);
- return;
- }
-
- uint8 itemCount = items->GetItemCount();
- uint8 count = 0;
+ VendorItemData const* vendorItems = vendor->GetVendorItems();
+ uint8 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4);
- data << uint64(vendorGuid);
+ //if (rawItemCount > 300),
+ // rawItemCount = 300; // client cap but uint8 max value is 255
- size_t countPos = data.wpos();
- data << uint8(count);
+ ByteBuffer itemsData(32 * rawItemCount);
+ std::vector<bool> enablers;
+ enablers.reserve(2 * rawItemCount);
- float discountMod = _player->GetReputationPriceDiscount(vendor);
-
- for (uint8 slot = 0; slot < itemCount; ++slot)
+ const float discountMod = _player->GetReputationPriceDiscount(vendor);
+ uint8 count = 0;
+ for (uint8 slot = 0; slot < rawItemCount; ++slot)
{
- if (VendorItem const* item = items->GetItem(slot))
+ VendorItem const* vendorItem = vendorItems->GetItem(slot);
+ if (!vendorItem) continue;
+
+ if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM)
{
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item->item))
+ ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
+ if (!itemTemplate)
+ continue;
+
+ uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem);
+ if (!_player->isGameMaster()) // ignore conditions if GM on
{
- if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster())
+ // Respect allowed class
+ if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP)
continue;
- // Only display items in vendor lists for the team the
- // player is on. If GM on, display all items.
- if (!_player->isGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)))
+
+ // Only display items in vendor lists for the team the player is on
+ if ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
+ (itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
continue;
// Items sold out are not displayed in list
- uint32 leftInStock = !item->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(item);
- if (!_player->isGameMaster() && !leftInStock)
+ if (leftInStock == 0)
continue;
+ }
- ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), item->item);
- if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
- {
- TC_LOG_DEBUG(LOG_FILTER_CONDITIONSYS, "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), item->item);
- continue;
- }
+ ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), vendorItem->item);
+ if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
+ {
+ TC_LOG_DEBUG(LOG_FILTER_CONDITIONSYS, "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item);
+ continue;
+ }
+
+ int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
- ++count;
+ if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
+ price -= CalculatePct(price, priceMod);
- // reputation discount
- int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
+ ++count;
+ itemsData << uint32(slot + 1); // client expects counting to start at 1
+ itemsData << uint32(itemTemplate->MaxDurability);
- data << uint32(slot + 1); // client expects counting to start at 1
- data << uint32(item->item);
- data << uint32(itemTemplate->DisplayInfoID);
- data << int32(leftInStock);
- data << uint32(price);
- data << uint32(itemTemplate->MaxDurability);
- data << uint32(itemTemplate->BuyCount);
- data << uint32(item->ExtendedCost);
+ if (vendorItem->ExtendedCost != 0)
+ {
+ enablers.push_back(0);
+ itemsData << uint32(vendorItem->ExtendedCost);
}
+ else
+ enablers.push_back(1);
+ enablers.push_back(1); // unk bit
+
+ itemsData << uint32(vendorItem->item);
+ itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
+ itemsData << uint32(price);
+ itemsData << uint32(itemTemplate->DisplayInfoID);
+ // if (!unk "enabler") data << uint32(something);
+ itemsData << int32(leftInStock);
+ itemsData << uint32(itemTemplate->BuyCount);
}
- }
+ else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY)
+ {
+ CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item);
+ if (!currencyTemplate)
+ continue;
- if (count == 0)
- {
- data << uint8(0);
- SendPacket(&data);
- return;
+ if (vendorItem->ExtendedCost == 0)
+ continue; // there's no price defined for currencies, only extendedcost is used
+
+ ++count;
+ itemsData << uint32(slot + 1); // client expects counting to start at 1
+ itemsData << uint32(0); // max durability
+
+ if (vendorItem->ExtendedCost != 0)
+ {
+ enablers.push_back(0);
+ itemsData << uint32(vendorItem->ExtendedCost);
+ }
+ else
+ enablers.push_back(1);
+
+ enablers.push_back(1); // unk bit
+
+ itemsData << uint32(vendorItem->item);
+ itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
+ itemsData << uint32(0); // price, only seen currency types that have Extended cost
+ itemsData << uint32(0); // displayId
+ // if (!unk "enabler") data << uint32(something);
+ itemsData << int32(-1);
+ itemsData << uint32(vendorItem->maxcount);
+ }
+ // else error
}
- data.put<uint8>(countPos, count);
+ ObjectGuid guid = vendorGuid;
+
+ WorldPacket data(SMSG_LIST_INVENTORY, 12 + itemsData.size());
+
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[0]);
+
+ data.WriteBits(count, 21); // item count
+
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[7]);
+
+ for (std::vector<bool>::const_iterator itr = enablers.begin(); itr != enablers.end(); ++itr)
+ data.WriteBit(*itr);
+
+ data.WriteBit(guid[4]);
+
+ data.FlushBits();
+ data.append(itemsData);
+
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ data << uint8(count == 0); // unk byte, item count 0: 1, item count != 0: 0 or some "random" value below 300
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[7]);
+
SendPacket(&data);
}
@@ -826,7 +729,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, NULL_SLOT, false)) // can be autostore pos
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -855,7 +758,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket& recvData)
if (dest.size() == 1 && dest[0].pos == src)
{
// just remove grey item state
- _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+ _player->SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, pItem, NULL);
return;
}
@@ -900,7 +803,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
uint32 price = slotEntry->price;
- if (!_player->HasEnoughMoney(price))
+ if (!_player->HasEnoughMoney(uint64(price)))
{
data << uint32(ERR_BANKSLOT_INSUFFICIENT_FUNDS);
SendPacket(&data);
@@ -908,7 +811,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
}
_player->SetBankBagSlotCount(slot);
- _player->ModifyMoney(-int32(price));
+ _player->ModifyMoney(-int64(price));
data << uint32(ERR_BANKSLOT_OK);
SendPacket(&data);
@@ -938,7 +841,7 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
if (dest.size() == 1 && dest[0].pos == pItem->GetPos())
{
- _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_SWAP, pItem, NULL);
return;
}
@@ -988,28 +891,9 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
}
}
-void WorldSession::HandleSetAmmoOpcode(WorldPacket& recvData)
-{
- if (!GetPlayer()->isAlive())
- {
- GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL);
- return;
- }
-
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_AMMO");
- uint32 item;
-
- recvData >> item;
-
- if (!item)
- GetPlayer()->RemoveAmmo();
- else
- GetPlayer()->SetAmmo(item);
-}
-
void WorldSession::SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId)
{
- WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4)); // last check 2.0.10
+ WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4));
data.appendPackGUID(target);
data.appendPackGUID(caster);
data << uint32(itemId);
@@ -1028,30 +912,6 @@ void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,
SendPacket(&data);
}
-void WorldSession::HandleItemNameQueryOpcode(WorldPacket& recvData)
-{
- uint32 itemid;
- recvData >> itemid;
- recvData.read_skip<uint64>(); // guid
-
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
- ItemSetNameEntry const* pName = sObjectMgr->GetItemSetNameEntry(itemid);
- if (pName)
- {
- std::string Name = pName->name;
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
- if (ItemSetNameLocale const* isnl = sObjectMgr->GetItemSetNameLocale(itemid))
- ObjectMgr::GetLocaleString(isnl->Name, loc_idx, Name);
-
- WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+Name.size()+1+4));
- data << uint32(itemid);
- data << Name;
- data << uint32(pName->InventoryType);
- SendPacket(&data);
- }
-}
-
void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Received opcode CMSG_WRAP_ITEM");
@@ -1086,44 +946,44 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData)
if (item == gift) // not possable with pacjket from real client
{
- _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
return;
}
if (item->IsEquipped())
{
- _player->SendEquipError(EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_EQUIPPED, item, NULL);
return;
}
if (item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
{
- _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
return;
}
if (item->IsBag())
{
- _player->SendEquipError(EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BAGS, item, NULL);
return;
}
if (item->IsSoulBound())
{
- _player->SendEquipError(EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BOUND, item, NULL);
return;
}
if (item->GetMaxStackCount() != 1)
{
- _player->SendEquipError(EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_STACKABLE, item, NULL);
return;
}
// maybe not correct check (it is better than nothing)
- if (item->GetTemplate()->MaxCount>0)
+ if (item->GetTemplate()->MaxCount > 0)
{
- _player->SendEquipError(EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_UNIQUE, item, NULL);
return;
}
@@ -1227,6 +1087,14 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
// tried to put meta gem in normal socket
if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
return;
+
+ // tried to put normal gem in cogwheel socket
+ if (itemProto->Socket[i].Color == SOCKET_COLOR_COGWHEEL && GemProps[i]->color != SOCKET_COLOR_COGWHEEL)
+ return;
+
+ // tried to put cogwheel gem in normal socket
+ if (itemProto->Socket[i].Color != SOCKET_COLOR_COGWHEEL && GemProps[i]->color == SOCKET_COLOR_COGWHEEL)
+ return;
}
uint32 GemEnchants[MAX_GEM_SOCKETS];
@@ -1335,7 +1203,10 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
{
itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0, _player->GetGUID());
if (Item* guidItem = _player->GetItemByGuid(gem_guids[i]))
- _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true);
+ {
+ uint32 gemCount = 1;
+ _player->DestroyItemCount(guidItem, gemCount, true);
+ }
}
}
@@ -1363,15 +1234,15 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
- uint32 eslot;
+ uint32 slot;
- recvData >> eslot;
+ recvData >> slot;
// apply only to equipped item
- if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, eslot))
+ if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
return;
- Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);
+ Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (!item)
return;
@@ -1428,7 +1299,7 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData )
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid));
- WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10)); // guess size
+ WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, 14); // guess size
if (Item* item = _player->GetItemByGuid(itemGuid))
{
@@ -1443,3 +1314,266 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData )
SendPacket(&data);
}
+
+void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS");
+ Player* player = GetPlayer();
+
+ // Read data
+ uint32 count = recvData.ReadBits(22);
+
+ if (count >= EQUIPMENT_SLOT_END)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), count);
+ recvData.rfinish();
+ return;
+ }
+
+ std::vector<ObjectGuid> itemGuids(count, ObjectGuid(0));
+ std::vector<uint32> newEntries(count, 0);
+ std::vector<uint32> slots(count, 0);
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ itemGuids[i][0] = recvData.ReadBit();
+ itemGuids[i][5] = recvData.ReadBit();
+ itemGuids[i][6] = recvData.ReadBit();
+ itemGuids[i][2] = recvData.ReadBit();
+ itemGuids[i][3] = recvData.ReadBit();
+ itemGuids[i][7] = recvData.ReadBit();
+ itemGuids[i][4] = recvData.ReadBit();
+ itemGuids[i][1] = recvData.ReadBit();
+ }
+
+ ObjectGuid npcGuid;
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+
+ recvData.FlushBits();
+
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvData >> newEntries[i];
+
+ recvData.ReadByteSeq(itemGuids[i][1]);
+ recvData.ReadByteSeq(itemGuids[i][5]);
+ recvData.ReadByteSeq(itemGuids[i][0]);
+ recvData.ReadByteSeq(itemGuids[i][4]);
+ recvData.ReadByteSeq(itemGuids[i][6]);
+ recvData.ReadByteSeq(itemGuids[i][7]);
+ recvData.ReadByteSeq(itemGuids[i][3]);
+ recvData.ReadByteSeq(itemGuids[i][2]);
+
+ recvData >> slots[i];
+ }
+
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[0]);
+
+ // Validate
+
+ if (!player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_TRANSMOGRIFIER))
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ int32 cost = 0;
+ for (uint8 i = 0; i < count; ++i)
+ {
+ // slot of the transmogrified item
+ if (slots[i] >= EQUIPMENT_SLOT_END)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an item (lowguid: %u) with a wrong slot (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]), slots[i]);
+ return;
+ }
+
+ // entry of the transmogrifier item, if it's not 0
+ if (newEntries[i])
+ {
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(newEntries[i]);
+ if (!proto)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), newEntries[i]);
+ return;
+ }
+ }
+
+ Item* itemTransmogrifier = NULL;
+ // guid of the transmogrifier item, if it's not 0
+ if (itemGuids[i])
+ {
+ itemTransmogrifier = player->GetItemByGuid(itemGuids[i]);
+ if (!itemTransmogrifier)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (lowguid: %u).", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]));
+ return;
+ }
+ }
+
+ // transmogrified item
+ Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]);
+ if (!itemTransmogrified)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i]);
+ return;
+ }
+
+ // uint16 tempDest;
+ //// has to be able to equip item transmogrified item
+ //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrified, true, true))
+ //{
+ // TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the item to be transmogrified (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrified->GetEntry());
+ // return;
+ //}
+ //
+ //// has to be able to equip item transmogrifier item
+ //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrifier, true, true))
+ //{
+ // TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the transmogrifier item (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrifier->GetEntry());
+ // return;
+ //}
+
+ if (!newEntries[i]) // reset look
+ {
+ itemTransmogrified->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT);
+ player->SetVisibleItemSlot(slots[i], itemTransmogrified);
+ }
+ else
+ {
+ if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier))
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUIDLow(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry());
+ return;
+ }
+
+ // All okay, proceed
+ itemTransmogrified->SetEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT, newEntries[i], 0, 0);
+ player->SetVisibleItemSlot(slots[i], itemTransmogrified);
+
+ itemTransmogrified->UpdatePlayedTime(player);
+
+ itemTransmogrified->SetOwnerGUID(player->GetGUID());
+ itemTransmogrified->SetNotRefundable(player);
+ itemTransmogrified->ClearSoulboundTradeable(player);
+
+ if (itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_EQUIPED || itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_USE)
+ itemTransmogrifier->SetBinding(true);
+
+ itemTransmogrifier->SetOwnerGUID(player->GetGUID());
+ itemTransmogrifier->SetNotRefundable(player);
+ itemTransmogrifier->ClearSoulboundTradeable(player);
+
+ cost += itemTransmogrified->GetSpecialPrice();
+ }
+ }
+
+ // trusting the client, if it got here it has to have enough money
+ // ... unless client was modified
+ if (cost) // 0 cost if reverting look
+ player->ModifyMoney(-cost);
+}
+
+void WorldSession::SendReforgeResult(bool success)
+{
+ WorldPacket data(SMSG_REFORGE_RESULT, 1);
+ data.WriteBit(success);
+ data.FlushBits();
+ SendPacket(&data);
+}
+
+void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData)
+{
+ uint32 slot, reforgeEntry;
+ ObjectGuid guid;
+ uint32 bag;
+ Player* player = GetPlayer();
+
+ recvData >> reforgeEntry >> slot >> bag;
+
+ guid[2] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[5]);
+
+ if (!player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_REFORGER))
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleReforgeItemOpcode - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(guid));
+ SendReforgeResult(false);
+ return;
+ }
+
+ Item* item = player->GetItemByPos(bag, slot);
+
+ if (!item)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an invalid/non-existant item.", player->GetGUIDLow(), player->GetName().c_str());
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!reforgeEntry)
+ {
+ // Reset the item
+ if (item->IsEquipped())
+ player->ApplyReforgeEnchantment(item, false);
+ item->ClearEnchantment(REFORGE_ENCHANTMENT_SLOT);
+ SendReforgeResult(true);
+ return;
+ }
+
+ ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry);
+ if (!stats)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an item with invalid reforge entry (%u).", player->GetGUIDLow(), player->GetName().c_str(), reforgeEntry);
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!item->GetReforgableStat(ItemModType(stats->SourceStat)) || item->GetReforgableStat(ItemModType(stats->FinalStat))) // Cheating, you cant reforge to a stat that the item already has, nor reforge from a stat that the item does not have
+ {
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!player->HasEnoughMoney(uint64(item->GetSpecialPrice()))) // cheating
+ {
+ SendReforgeResult(false);
+ return;
+ }
+
+ player->ModifyMoney(-int64(item->GetSpecialPrice()));
+
+ item->SetEnchantment(REFORGE_ENCHANTMENT_SLOT, reforgeEntry, 0, 0);
+
+ SendReforgeResult(true);
+
+ if (item->IsEquipped())
+ player->ApplyReforgeEnchantment(item, true);
+}
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index 4885fa38bb5..653caf23453 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -30,6 +30,8 @@ void BuildPlayerLockDungeonBlock(WorldPacket& data, lfg::LfgLockMap const& lock)
{
data << uint32(it->first); // Dungeon entry (id + type)
data << uint32(it->second); // Lock status
+ data << uint32(0); // Unknown 4.2.2
+ data << uint32(0); // Unknown 4.2.2
}
}
@@ -257,7 +259,7 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recvData*
uint32 size = 0;
for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it)
- size += 8 + 4 + uint32(it->second.size()) * (4 + 4);
+ size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4);
TC_LOG_DEBUG(LOG_FILTER_LFG, "SMSG_LFG_PARTY_INFO %s", GetPlayerInfo().c_str());
WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size);
@@ -448,7 +450,7 @@ void WorldSession::SendLfgJoinResult(lfg::LfgJoinResultData const& joinData)
{
uint32 size = 0;
for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it)
- size += 8 + 4 + uint32(it->second.size()) * (4 + 4);
+ size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4);
TC_LOG_DEBUG(LOG_FILTER_LFG, "SMSG_LFG_JOIN_RESULT %s checkResult: %u checkValue: %u",
GetPlayerInfo().c_str(), joinData.result, joinData.state);
@@ -540,10 +542,11 @@ void WorldSession::SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot)
GetPlayerInfo().c_str(), uint8(boot.inProgress), uint8(playerVote != lfg::LFG_ANSWER_PENDING),
uint8(playerVote == lfg::LFG_ANSWER_AGREE), GUID_LOPART(boot.victim), votesNum, agreeNum,
secsleft, lfg::LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str());
- WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length());
+ WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length());
data << uint8(boot.inProgress); // Vote in progress
- data << uint8(playerVote != lfg::LFG_ANSWER_PENDING); // Did Vote
- data << uint8(playerVote == lfg::LFG_ANSWER_AGREE); // Agree
+ data << uint8(playerVote != lfg::LFG_ANSWER_PENDING); // Did Vote
+ data << uint8(playerVote == lfg::LFG_ANSWER_AGREE); // Agree
+ data << uint8(0); // Unknown 4.2.2
data << uint64(boot.victim); // Victim GUID
data << uint32(votesNum); // Total Votes
data << uint32(agreeNum); // Agree Count
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 6c87b9486f2..caf9d7a65e2 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -22,6 +22,7 @@
#include "Creature.h"
#include "GameObject.h"
#include "Group.h"
+#include "GuildMgr.h"
#include "LootMgr.h"
#include "ObjectAccessor.h"
#include "Object.h"
@@ -186,6 +187,10 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
(*i)->ModifyMoney(goldPerPlayer);
(*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer);
+ if (Guild* guild = sGuildMgr->GetGuildById((*i)->GetGuildId()))
+ if (uint32 guildGold = CalculatePct(goldPerPlayer, (*i)->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
+ guild->HandleMemberDepositMoney(this, guildGold, true);
+
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1);
data << uint32(goldPerPlayer);
data << uint8(playersNear.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..."
@@ -197,6 +202,10 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
player->ModifyMoney(loot->gold);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold);
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (uint32 guildGold = CalculatePct(loot->gold, player->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
+ guild->HandleMemberDepositMoney(this, guildGold, true);
+
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1);
data << uint32(loot->gold);
data << uint8(1); // "You loot..."
@@ -453,7 +462,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
ItemPosCountVec dest;
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
if (item.follow_loot_rules && !item.AllowedForPlayer(target))
- msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ msg = EQUIP_ERR_CANT_EQUIP_EVER;
if (msg != EQUIP_ERR_OK)
{
target->SendEquipError(msg, NULL, NULL, item.itemid);
@@ -469,7 +478,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, looters);
target->SendNewItem(newitem, uint32(item.count), false, false, true);
target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item.count);
+ target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item.itemid, item.count, loot->loot_type);
target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count);
// mark as looted
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 6005174748f..d34ea534753 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -31,15 +31,20 @@
void WorldSession::HandleSendMail(WorldPacket& recvData)
{
- uint64 mailbox, unk3;
+ ObjectGuid mailbox;
+ uint64 money, COD;
std::string receiverName, subject, body;
- uint32 unk1, unk2, money, COD;
- uint8 unk4;
- uint8 items_count;
- recvData >> mailbox >> receiverName >> subject >> body
- >> unk1 // stationery?
- >> unk2 // 0x00000000
- >> items_count; // attached items count
+ uint32 bodyLength, subjectLength, receiverLength;
+ uint32 unk1, unk2;
+
+ recvData >> unk1;
+ recvData >> unk2; // Stationery?
+
+ recvData >> COD >> money; // money and cod
+ bodyLength = recvData.ReadBits(12);
+ subjectLength = recvData.ReadBits(9);
+
+ uint8 items_count = recvData.ReadBits(5); // attached items count
if (items_count > MAX_MAIL_ITEMS) // client limit
{
@@ -48,17 +53,60 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
- uint64 itemGUIDs[MAX_MAIL_ITEMS];
+ mailbox[0] = recvData.ReadBit();
+
+ ObjectGuid itemGUIDs[MAX_MAIL_ITEMS];
for (uint8 i = 0; i < items_count; ++i)
{
- recvData.read_skip<uint8>(); // item slot in mail, not used
- recvData >> itemGUIDs[i];
+ itemGUIDs[i][2] = recvData.ReadBit();
+ itemGUIDs[i][6] = recvData.ReadBit();
+ itemGUIDs[i][3] = recvData.ReadBit();
+ itemGUIDs[i][7] = recvData.ReadBit();
+ itemGUIDs[i][1] = recvData.ReadBit();
+ itemGUIDs[i][0] = recvData.ReadBit();
+ itemGUIDs[i][4] = recvData.ReadBit();
+ itemGUIDs[i][5] = recvData.ReadBit();
}
- recvData >> money >> COD; // money and cod
- recvData >> unk3; // const 0
- recvData >> unk4; // const 0
+ mailbox[3] = recvData.ReadBit();
+ mailbox[4] = recvData.ReadBit();
+ receiverLength = recvData.ReadBits(7);
+ mailbox[2] = recvData.ReadBit();
+ mailbox[6] = recvData.ReadBit();
+ mailbox[1] = recvData.ReadBit();
+ mailbox[7] = recvData.ReadBit();
+ mailbox[5] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(mailbox[4]);
+
+ for (uint8 i = 0; i < items_count; ++i)
+ {
+ recvData.ReadByteSeq(itemGUIDs[i][6]);
+ recvData.ReadByteSeq(itemGUIDs[i][1]);
+ recvData.ReadByteSeq(itemGUIDs[i][7]);
+ recvData.ReadByteSeq(itemGUIDs[i][2]);
+ recvData.read_skip<uint8>(); // item slot in mail, not used
+ recvData.ReadByteSeq(itemGUIDs[i][3]);
+ recvData.ReadByteSeq(itemGUIDs[i][0]);
+ recvData.ReadByteSeq(itemGUIDs[i][4]);
+ recvData.ReadByteSeq(itemGUIDs[i][5]);
+ }
+
+ recvData.ReadByteSeq(mailbox[7]);
+ recvData.ReadByteSeq(mailbox[3]);
+ recvData.ReadByteSeq(mailbox[6]);
+ recvData.ReadByteSeq(mailbox[5]);
+
+ subject = recvData.ReadString(subjectLength);
+ receiverName = recvData.ReadString(receiverLength);
+
+ recvData.ReadByteSeq(mailbox[2]);
+ recvData.ReadByteSeq(mailbox[0]);
+
+ body = recvData.ReadString(bodyLength);
+
+ recvData.ReadByteSeq(mailbox[1]);
// packet read complete, now do check
@@ -83,7 +131,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (!receiverGuid)
{
TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s "
- "and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
+ "and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(),
items_count, money, COD, unk1, unk2);
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND);
@@ -91,7 +139,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
TC_LOG_INFO(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s "
- "includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
+ "includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(),
body.c_str(), items_count, money, COD, unk1, unk2);
@@ -103,7 +151,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client
- uint32 reqmoney = cost + money;
+ uint64 reqmoney = cost + money;
if (!player->HasEnoughMoney(reqmoney) && !player->isGameMaster())
{
@@ -213,7 +261,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS);
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT);
return;
}
@@ -231,7 +279,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (item->IsNotEmptyBag())
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG);
return;
}
@@ -240,7 +288,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
player->SendMailResult(0, MAIL_SEND, MAIL_OK);
- player->ModifyMoney(-int32(reqmoney));
+ player->ModifyMoney(-int64(reqmoney));
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
bool needItemDelay = false;
@@ -281,7 +329,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (log && money > 0)
{
- sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: %u to player: %s (GUID: %u) (Account: %u)",
+ sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: " UI64FMTD " to player: %s (GUID: %u) (Account: %u)",
GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId);
}
}
@@ -369,8 +417,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR);
return;
}
- //we can return mail now
- //so firstly delete the old one
+ //we can return mail now, so firstly delete the old one
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
@@ -394,14 +441,8 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
{
for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2)
{
- Item* item = player->GetMItem(itr2->item_guid);
- if (item)
+ if (Item* const item = player->GetMItem(itr2->item_guid))
draft.AddItem(item);
- else
- {
- //WTF?
- }
-
player->RemoveMItem(itr2->item_guid);
}
}
@@ -437,7 +478,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
}
// prevent cheating with skip client money check
- if (!player->HasEnoughMoney(m->COD))
+ if (!player->HasEnoughMoney(uint64(m->COD)))
{
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY);
return;
@@ -476,7 +517,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name))
sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
}
- sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)",
+ sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)",
GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId);
}
else if (!receiver)
@@ -514,9 +555,12 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
{
uint64 mailbox;
+ uint64 money;
uint32 mailId;
+
recvData >> mailbox;
recvData >> mailId;
+ recvData >> money;
if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
@@ -524,7 +568,8 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
Player* player = _player;
Mail* m = player->GetMail(mailId);
- if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
+ if ((!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) ||
+ (money > 0 && m->money != money))
{
player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR);
return;
@@ -570,7 +615,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
uint32 mailsCount = 0; // real send to client mails amount
uint32 realCount = 0; // real mails amount
- WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size
+ WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size
data << uint32(0); // real mail's count
data << uint8(0); // mail's count
time_t cur_time = time(NULL);
@@ -611,14 +656,14 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
case MAIL_GAMEOBJECT:
case MAIL_AUCTION:
case MAIL_CALENDAR:
- data << uint32((*itr)->sender); // creature/gameobject entry, auction id, calendar event id?
+ data << uint32((*itr)->sender); // creature/gameobject entry, auction id, calendar event id?
break;
}
- data << uint32((*itr)->COD); // COD
- data << uint32(0); // package (Package.dbc)
+ data << uint64((*itr)->COD); // COD
+ data << uint32(0); // Package.dbc ID ?
data << uint32((*itr)->stationery); // stationery (Stationery.dbc)
- data << uint32((*itr)->money); // Gold
+ data << uint64((*itr)->money); // Gold
data << uint32((*itr)->checked); // flags
data << float(float((*itr)->expire_time-time(NULL))/DAY); // Time
data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc)
@@ -641,6 +686,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
data << uint32((item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0));
data << uint32((item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0));
}
+
// can be negative
data << int32((item ? item->GetItemRandomPropertyId() : 0));
// unk
@@ -707,7 +753,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
return;
}
- bodyItem->SetText(mailTemplateEntry->content[GetSessionDbcLocale()]);
+ bodyItem->SetText(mailTemplateEntry->content);
}
else
bodyItem->SetText(m->body);
@@ -736,7 +782,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
}
/// @todo Fix me! ... this void has probably bad condition, but good data are sent
-void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recvData*/)
+void WorldSession::HandleQueryNextMailTime(WorldPacket& /*recvData*/)
{
WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 8);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 088a13cd7c6..5a630a0bfe0 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -55,6 +55,7 @@
#include "BattlegroundMgr.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "DB2Stores.h"
void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
{
@@ -397,7 +398,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
return;
}
- //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
+ // instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
if (instantLogout)
{
LogoutPlayer(true);
@@ -408,11 +409,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
if (GetPlayer()->CanFreeMove())
{
GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT);
-
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, (8+4)); // guess size
- data.append(GetPlayer()->GetPackGUID());
- data << (uint32)2;
- SendPacket(&data);
+ GetPlayer()->SetRooted(true);
GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
@@ -441,10 +438,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket& /*recvData*/)
if (GetPlayer()->CanFreeMove())
{
//!we can move again
- data.Initialize(SMSG_FORCE_MOVE_UNROOT, 8); // guess size
- data.append(GetPlayer()->GetPackGUID());
- data << uint32(0);
- SendPacket(&data);
+ GetPlayer()->SetRooted(false);
//! Stand Up
GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
@@ -501,6 +495,13 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData)
//GetPlayer()->SendInitWorldStates(true, newZone);
}
+void WorldSession::HandleReturnToGraveyard(WorldPacket& /*recvPacket*/)
+{
+ if (GetPlayer()->isAlive() || !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
+ return;
+ GetPlayer()->RepopAtGraveyard();
+}
+
void WorldSession::HandleSetSelectionOpcode(WorldPacket& recvData)
{
uint64 guid;
@@ -520,9 +521,8 @@ void WorldSession::HandleStandStateChangeOpcode(WorldPacket& recvData)
void WorldSession::HandleContactListOpcode(WorldPacket& recvData)
{
- uint32 unk;
- recvData >> unk;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk);
+ recvData.read_skip<uint32>(); // always 1
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST");
_player->GetSocial()->SendSocialList(_player);
}
@@ -707,9 +707,11 @@ void WorldSession::HandleBugOpcode(WorldPacket& recvData)
uint32 suggestion, contentlen, typelen;
std::string content, type;
- recvData >> suggestion >> contentlen >> content;
+ recvData >> suggestion >> contentlen;
+ content = recvData.ReadString(contentlen);
- recvData >> typelen >> type;
+ recvData >> typelen;
+ type = recvData.ReadString(typelen);
if (suggestion == 0)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUG [Bug Report]");
@@ -778,11 +780,11 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData)
if (status == 0)
{
- GetPlayer()->clearResurrectRequestData(); // reject
+ GetPlayer()->ClearResurrectRequestData(); // reject
return;
}
- if (!GetPlayer()->isRessurectRequestedBy(guid))
+ if (!GetPlayer()->IsRessurectRequestedBy(guid))
return;
GetPlayer()->ResurectUsingRequestData();
@@ -916,7 +918,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
if (pvp->HandleAreaTrigger(_player, triggerId))
return;
- AreaTrigger const* at = sObjectMgr->GetAreaTrigger(triggerId);
+ AreaTriggerStruct const* at = sObjectMgr->GetAreaTrigger(triggerId);
if (!at)
return;
@@ -1028,6 +1030,13 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recvData)
SendPacket(&data);
}
+int32 WorldSession::HandleEnableNagleAlgorithm()
+{
+ // Instructs the server we wish to receive few amounts of large packets (SMSG_MULTIPLE_PACKETS?)
+ // instead of large amount of small packets
+ return 0;
+}
+
void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData)
{
uint8 button;
@@ -1053,12 +1062,32 @@ void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/)
void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
{
- /* WorldSession::Update(getMSTime());*/
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_TIME_SKIPPED");
- uint64 guid;
- recvData.readPackGUID(guid);
- recvData.read_skip<uint32>();
+ ObjectGuid guid;
+ uint32 time;
+ recvData >> time;
+
+ guid[5] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+
+ //TODO!
+
/*
uint64 guid;
uint32 time_skipped;
@@ -1176,10 +1205,9 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
return;
}
- uint32 talent_points = 0x47;
- uint32 guid_size = player->GetPackGUID().wpos();
- WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points);
- data.append(player->GetPackGUID());
+ uint32 talent_points = 41;
+ WorldPacket data(SMSG_INSPECT_TALENT, 8 + 4 + 1 + 1 + talent_points + 8 + 4 + 8 + 4);
+ data << player->GetGUID();
if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster())
player->BuildPlayerTalentsInfoData(&data);
@@ -1191,29 +1219,66 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
}
player->BuildEnchantmentsInfoData(&data);
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ {
+ data << uint64(guild->GetGUID());
+ data << uint32(guild->GetLevel());
+ data << uint64(0/*guild->GetXP()*/);
+ data << uint32(guild->GetMembersCount());
+ }
SendPacket(&data);
}
void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recvData)
{
- uint64 guid;
- recvData >> guid;
-
+ ObjectGuid guid;
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[3]);
Player* player = ObjectAccessor::FindPlayer(guid);
if (!player)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "MSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, guid);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, (uint64)guid);
return;
}
- WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4);
- data << uint64(player->GetGUID());
- data << uint8(player->GetHonorPoints());
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS));
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
+ ObjectGuid playerGuid = player->GetGUID();
+ WorldPacket data(SMSG_INSPECT_HONOR_STATS, 8+1+4+4);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[6]);
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[5]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[1]);
+ data << uint8(0); // rank
+ data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 1)); // yesterday kills
+ data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 0)); // today kills
+ data.WriteByteSeq(playerGuid[2]);
+ data.WriteByteSeq(playerGuid[0]);
+ data.WriteByteSeq(playerGuid[6]);
+ data.WriteByteSeq(playerGuid[3]);
+ data.WriteByteSeq(playerGuid[4]);
+ data.WriteByteSeq(playerGuid[1]);
+ data.WriteByteSeq(playerGuid[5]);
data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
+ data.WriteByteSeq(playerGuid[7]);
SendPacket(&data);
}
@@ -1345,8 +1410,9 @@ void WorldSession::HandleComplainOpcode(WorldPacket& recvData)
// if it's mail spam - ALL mails from this spammer automatically removed by client
// Complaint Received message
- WorldPacket data(SMSG_COMPLAIN_RESULT, 1);
- data << uint8(0);
+ WorldPacket data(SMSG_COMPLAIN_RESULT, 2);
+ data << uint8(0); // value 1 resets CGChat::m_complaintsSystemStatus in client. (unused?)
+ data << uint8(0); // value 0xC generates a "CalendarError" in client.
SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str());
@@ -1422,8 +1488,8 @@ void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
uint32 counter, clientTicks;
recvData >> counter >> clientTicks;
- if (counter != _player->m_timeSyncCounter - 1)
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
+ if (counter != _player->m_timeSyncCounter)
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient);
@@ -1596,7 +1662,7 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
MovementInfo movementInfo;
movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
+ _player->ReadMovementInfo(recvData, &movementInfo);
recvData.read_skip<float>(); // unk2
@@ -1632,6 +1698,15 @@ void WorldSession::HandleQueryInspectAchievements(WorldPacket& recvData)
player->SendRespondInspectAchievements(_player);
}
+void WorldSession::HandleGuildAchievementProgressQuery(WorldPacket& recvData)
+{
+ uint32 achievementId;
+ recvData >> achievementId;
+
+ if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId()))
+ guild->GetAchievementMgr().SendAchievementInfo(_player, achievementId);
+}
+
void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recvData*/)
{
// empty opcode
@@ -1650,12 +1725,54 @@ void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/)
SendAccountDataTimes(GLOBAL_CACHE_MASK);
}
-void WorldSession::SendSetPhaseShift(uint32 PhaseShift)
+void WorldSession::SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps)
{
- WorldPacket data(SMSG_SET_PHASE_SHIFT, 4);
- data << uint32(PhaseShift);
+ ObjectGuid guid = _player->GetGUID();
+
+ WorldPacket data(SMSG_SET_PHASE_SHIFT, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+
+ data << uint32(0);
+ //for (uint8 i = 0; i < worldMapAreaCount; ++i)
+ // data << uint16(0); // WorldMapArea.dbc id (controls map display)
+
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(phaseIds.size() ? 0 : 8); // flags (not phasemask)
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[6]);
+
+ data << uint32(0); // Inactive terrain swaps
+ //for (uint8 i = 0; i < inactiveSwapsCount; ++i)
+ // data << uint16(0);
+
+ data << uint32(phaseIds.size()) * 2; // Phase.dbc ids
+ for (std::set<uint32>::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+
+ data << uint32(terrainswaps.size()) * 2; // Active terrain swaps
+ for (std::set<uint32>::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[5]);
+
SendPacket(&data);
}
+
// Battlefield and Battleground
void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData)
{
@@ -1743,6 +1860,74 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket)
_player->SetPendingBind(0, 0);
}
+void WorldSession::HandleRequestHotfix(WorldPacket& recvPacket)
+{
+ uint32 type, count;
+ recvPacket >> type;
+
+ DB2StorageBase const* store = GetDB2Storage(type);
+ if (!store)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "CMSG_REQUEST_HOTFIX: Received unknown hotfix type: %u", type);
+ recvPacket.rfinish();
+ return;
+ }
+
+ count = recvPacket.ReadBits(23);
+
+ ObjectGuid* guids = new ObjectGuid[count];
+ for (uint32 i = 0; i < count; ++i)
+ {
+ guids[i][0] = recvPacket.ReadBit();
+ guids[i][4] = recvPacket.ReadBit();
+ guids[i][7] = recvPacket.ReadBit();
+ guids[i][2] = recvPacket.ReadBit();
+ guids[i][5] = recvPacket.ReadBit();
+ guids[i][3] = recvPacket.ReadBit();
+ guids[i][6] = recvPacket.ReadBit();
+ guids[i][1] = recvPacket.ReadBit();
+ }
+
+ uint32 entry;
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvPacket.ReadByteSeq(guids[i][5]);
+ recvPacket.ReadByteSeq(guids[i][6]);
+ recvPacket.ReadByteSeq(guids[i][7]);
+ recvPacket.ReadByteSeq(guids[i][0]);
+ recvPacket.ReadByteSeq(guids[i][1]);
+ recvPacket.ReadByteSeq(guids[i][3]);
+ recvPacket.ReadByteSeq(guids[i][4]);
+ recvPacket >> entry;
+ recvPacket.ReadByteSeq(guids[i][2]);
+
+ if (!store->HasRecord(entry))
+ {
+ WorldPacket data(SMSG_DB_REPLY, 4 * 4);
+ data << -int32(entry);
+ data << uint32(store->GetHash());
+ data << uint32(time(NULL));
+ data << uint32(0);
+ SendPacket(&data);
+ continue;
+ }
+
+ WorldPacket data(SMSG_DB_REPLY);
+ data << int32(entry);
+ data << uint32(store->GetHash());
+ data << uint32(sObjectMgr->GetHotfixDate(entry, store->GetHash()));
+
+ size_t sizePos = data.wpos();
+ data << uint32(0); // size of next block
+ store->WriteRecord(entry, uint32(GetSessionDbcLocale()), data);
+ data.put<uint32>(sizePos, data.wpos() - sizePos - 4);
+
+ SendPacket(&data);
+ }
+
+ delete[] guids;
+}
+
void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY");
@@ -1782,7 +1967,169 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
uint32 opcode;
recvPacket >> opcode;
- recvPacket.SetOpcode(opcode);
+ recvPacket.SetOpcode(MSG_MOVE_STOP); // always set to MSG_MOVE_STOP in client SetOpcode
HandleMovementOpcodes(recvPacket);
}
}
+
+void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket)
+{
+ uint8 violenceLevel;
+ recvPacket >> violenceLevel;
+
+ // do something?
+}
+
+void WorldSession::HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+
+ WorldObject* obj = ObjectAccessor::GetWorldObject(*GetPlayer(), guid);
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Object update failed for object " UI64FMTD " (%s) for player %s (%u)", uint64(guid), obj ? obj->GetName().c_str() : "object-not-found", GetPlayerName().c_str(), GetGuidLow());
+}
+
+void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SAVE_CUF_PROFILES");
+
+ uint8 count = (uint8)recvPacket.ReadBits(20);
+
+ if (count > MAX_CUF_PROFILES)
+ {
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "HandleSaveCUFProfiles - %s tried to save more than %i CUF profiles. Hacking attempt?", GetPlayerName().c_str(), MAX_CUF_PROFILES);
+ recvPacket.rfinish();
+ return;
+ }
+
+ CUFProfile* profiles[MAX_CUF_PROFILES];
+ uint8 strlens[MAX_CUF_PROFILES];
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ profiles[i] = new CUFProfile;
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_2 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_10_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_157 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HEAL_PREDICTION , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_1 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVP , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_POWER_BAR , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_15_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_40_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_PETS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_5_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS, recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_2_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_156 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_NON_BOSS_DEBUFFS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_MAIN_TANK_AND_ASSIST , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_AGGRO_HIGHLIGHT , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_3_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_BORDER , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_USE_CLASS_COLORS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_145 , recvPacket.ReadBit());
+ strlens[i] = (uint8)recvPacket.ReadBits(8);
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVE , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HORIZONTAL_GROUPS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_25_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_KEEP_GROUPS_TOGETHER , recvPacket.ReadBit());
+ }
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ recvPacket >> profiles[i]->Unk146;
+ profiles[i]->ProfileName = recvPacket.ReadString(strlens[i]);
+ recvPacket >> profiles[i]->Unk152;
+ recvPacket >> profiles[i]->FrameHeight;
+ recvPacket >> profiles[i]->FrameWidth;
+ recvPacket >> profiles[i]->Unk150;
+ recvPacket >> profiles[i]->HealthText;
+ recvPacket >> profiles[i]->Unk147;
+ recvPacket >> profiles[i]->SortBy;
+ recvPacket >> profiles[i]->Unk154;
+ recvPacket >> profiles[i]->Unk148;
+
+ GetPlayer()->SaveCUFProfile(i, profiles[i]);
+ }
+
+ for (uint8 i = count; i < MAX_CUF_PROFILES; ++i)
+ GetPlayer()->SaveCUFProfile(i, NULL);
+}
+
+void WorldSession::SendLoadCUFProfiles()
+{
+ Player* player = GetPlayer();
+
+ uint8 count = player->GetCUFProfilesCount();
+
+ ByteBuffer byteBuffer(25 * count);
+ WorldPacket data(SMSG_LOAD_CUF_PROFILES, 5 * count + 25 * count);
+
+ data.WriteBits(count, 20);
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ CUFProfile* profile = player->GetCUFProfile(i);
+ if (!profile)
+ continue;
+
+ data.WriteBit(profile->BoolOptions[CUF_UNK_157]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_10_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_5_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_25_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HEAL_PREDICTION]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVE]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HORIZONTAL_GROUPS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_40_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_3_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_AGGRO_HIGHLIGHT]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_BORDER]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_2_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_NON_BOSS_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_MAIN_TANK_AND_ASSIST]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_156]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_2]);
+ data.WriteBit(profile->BoolOptions[CUF_USE_CLASS_COLORS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_POWER_BAR]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_1]);
+ data.WriteBits(profile->ProfileName.size(), 8);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_KEEP_GROUPS_TOGETHER]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_145]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_15_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_PETS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVP]);
+
+ byteBuffer << uint16(profile->Unk154);
+ byteBuffer << uint16(profile->FrameHeight);
+ byteBuffer << uint16(profile->Unk152);
+ byteBuffer << uint8(profile->Unk147);
+ byteBuffer << uint16(profile->Unk150);
+ byteBuffer << uint8(profile->Unk146);
+ byteBuffer << uint8(profile->HealthText);
+ byteBuffer << uint8(profile->SortBy);
+ byteBuffer << uint16(profile->FrameWidth);
+ byteBuffer << uint8(profile->Unk148);
+ byteBuffer.WriteString(profile->ProfileName);
+ }
+
+ data.FlushBits();
+ data.append(byteBuffer);
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 3270b19fd48..2739e53b818 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -30,8 +30,9 @@
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
#include "ObjectMgr.h"
+#include "MovementStructures.h"
-void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket& /*recvPacket*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: got MSG_MOVE_WORLDPORT_ACK.");
HandleMoveWorldportAckOpcode();
@@ -189,16 +190,33 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->ProcessDelayedOperations();
}
-void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
+void WorldSession::HandleMoveTeleportAck(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "MSG_MOVE_TELEPORT_ACK");
- uint64 guid;
-
- recvData.readPackGUID(guid);
+ ObjectGuid guid;
uint32 flags, time;
- recvData >> flags >> time;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Guid " UI64FMTD, guid);
+ recvPacket >> flags >> time;
+
+ guid[5] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[0]);
+
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Guid " UI64FMTD, uint64(guid));
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Flags %u, time %u", flags, time/IN_MILLISECONDS);
Player* plMover = _player->m_mover->ToPlayer();
@@ -240,9 +258,9 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
GetPlayer()->ProcessDelayedOperations();
}
-void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
+void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
{
- uint16 opcode = recvData.GetOpcode();
+ uint16 opcode = recvPacket.GetOpcode();
Unit* mover = _player->m_mover;
@@ -253,46 +271,41 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if (plrMover && plrMover->IsBeingTeleported())
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
/* extract packet */
- uint64 guid;
-
- recvData.readPackGUID(guid);
-
MovementInfo movementInfo;
- movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData.rfinish(); // prevent warnings spam
+ GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo);
// prevent tampered movement data
- if (guid != mover->GetGUID())
+ if (movementInfo.guid != mover->GetGUID())
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleMovementOpcodes: guid error");
return;
-
+ }
if (!movementInfo.pos.IsPositionValid())
{
- recvData.rfinish(); // prevent warnings spam
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleMovementOpcodes: Invalid Position");
return;
}
/* handle special cases */
- if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
+ if (movementInfo.t_guid)
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50)
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(),
movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation()))
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
@@ -341,7 +354,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
- movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
+ movementInfo.t_guid = 0;
}
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
@@ -361,17 +374,12 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
- /*----------------------*/
-
- /* process position-change */
- WorldPacket data(opcode, recvData.size());
movementInfo.time = getMSTime();
movementInfo.guid = mover->GetGUID();
- WriteMovementInfo(&data, &movementInfo);
- mover->SendMessageToSet(&data, _player);
-
mover->m_movementInfo = movementInfo;
+ /*----------------------*/
+ /* process position-change */
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
if (mover->GetVehicle())
{
@@ -381,11 +389,17 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
mover->UpdatePosition(movementInfo.pos);
+ WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
+ mover->WriteMovementInfo(data);
+ mover->SendMessageToSet(&data, _player);
+
if (plrMover) // nothing is charmed, or player charmed
{
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
- if (movementInfo.pos.GetPositionZ() < -500.0f)
+ AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
+ float depth = zone ? zone->MaxDepth : -500.0f;
+ if (movementInfo.pos.GetPositionZ() < depth)
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
@@ -409,62 +423,62 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
{
uint32 opcode = recvData.GetOpcode();
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
/* extract packet */
- uint64 guid;
- uint32 unk1;
- float newspeed;
-
- recvData.readPackGUID(guid);
+ MovementInfo movementInfo;
+ static MovementStatusElements const speedElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extras(&speedElement);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo, &extras);
// now can skip not our packet
- if (_player->GetGUID() != guid)
+ if (_player->GetGUID() != movementInfo.guid)
{
recvData.rfinish(); // prevent warnings spam
return;
}
- // continue parse packet
-
- recvData >> unk1; // counter or moveEvent
-
- MovementInfo movementInfo;
- movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData >> newspeed;
+ float newspeed = extras.Data.floatData;
/*----------------*/
// client ACK send one packet for mounted/run case and need skip all except last from its
// in other cases anti-cheat check can be fail in false case
UnitMoveType move_type;
- UnitMoveType force_move_type;
- static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
+ static char const* const move_type_name[MAX_MOVE_TYPE] =
+ {
+ "Walk",
+ "Run",
+ "RunBack",
+ "Swim",
+ "SwimBack",
+ "TurnRate",
+ "Flight",
+ "FlightBack",
+ "PitchRate"
+ };
switch (opcode)
{
- case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
- case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break;
- case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break;
- case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break;
- case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break;
- case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
- case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
- case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
- case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
+ case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
+ case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
+ case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; break;
+ case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
+ case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; break;
+ case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break;
+ case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break;
+ case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; break;
+ case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break;
default:
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
return;
}
// skip all forced speed changes except last and unexpected
- // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
- if (_player->m_forced_speed_changes[force_move_type] > 0)
+ // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both.
+ if (_player->m_forced_speed_changes[move_type] > 0)
{
- --_player->m_forced_speed_changes[force_move_type];
- if (_player->m_forced_speed_changes[force_move_type] > 0)
+ --_player->m_forced_speed_changes[move_type];
+ if (_player->m_forced_speed_changes[move_type] > 0)
return;
}
@@ -485,17 +499,34 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
}
}
-void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recvData)
+void WorldSession::HandleSetActiveMoverOpcode(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
- uint64 guid;
- recvData >> guid;
+ ObjectGuid guid;
+
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[7]);
if (GetPlayer()->IsInWorld())
{
if (_player->m_mover->GetGUID() != guid)
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID());
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, uint64(guid), GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID());
}
}
@@ -503,14 +534,8 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
- uint64 old_mover_guid;
- recvData.readPackGUID(old_mover_guid);
-
MovementInfo mi;
- ReadMovementInfo(recvData, &mi);
-
- mi.guid = old_mover_guid;
-
+ GetPlayer()->ReadMovementInfo(recvData, &mi);
_player->m_movementInfo = mi;
}
@@ -526,29 +551,16 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_MOVE_KNOCK_BACK_ACK");
- uint64 guid;
- recvData.readPackGUID(guid);
+ MovementInfo movementInfo;
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
- if (_player->m_mover->GetGUID() != guid)
+ if (_player->m_mover->GetGUID() != movementInfo.guid)
return;
- recvData.read_skip<uint32>(); // unk
-
- MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
-
_player->m_movementInfo = movementInfo;
- WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
- data.appendPackGUID(guid);
- _player->BuildMovementPacket(&data);
-
- // knockback specific info
- data << movementInfo.j_sinAngle;
- data << movementInfo.j_cosAngle;
- data << movementInfo.j_xyspeed;
- data << movementInfo.j_zspeed;
-
+ WorldPacket data(SMSG_MOVE_UPDATE_KNOCK_BACK, 66);
+ _player->WriteMovementInfo(data);
_player->SendMessageToSet(&data, false);
}
@@ -562,7 +574,7 @@ void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
recvData.read_skip<uint32>(); // unk2
}
@@ -577,7 +589,7 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
recvData.read_skip<uint32>(); // unk2
}
@@ -587,10 +599,20 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData)
if (!_player->isAlive() || _player->isInCombat())
return;
- uint64 summoner_guid;
+ uint64 summonerGuid;
bool agree;
- recvData >> summoner_guid;
+ recvData >> summonerGuid;
recvData >> agree;
_player->SummonIfPossible(agree);
}
+
+void WorldSession::HandleSetCollisionHeightAck(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_MOVE_SET_COLLISION_HEIGHT_ACK");
+
+ static MovementStatusElements const heightElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&heightElement);
+ MovementInfo movementInfo;
+ GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo, &extra);
+}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 18023ae519c..51533ad8a9f 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -151,6 +151,7 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
data << guid;
data << uint32(trainer_spells->trainerType);
+ data << uint32(1); // different value for each trainer, also found in CMSG_TRAINER_BUY_SPELL
size_t count_pos = data.wpos();
data << uint32(trainer_spells->spellList.size());
@@ -188,9 +189,6 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state);
data << uint32(floor(tSpell->spellCost * fDiscountMod));
- data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
- // primary prof. learn confirmation dialog
- data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
data << uint8(tSpell->reqLevel);
data << uint32(tSpell->reqSkill);
data << uint32(tSpell->reqSkillValue);
@@ -205,7 +203,7 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint32(prevSpellId);
++maxReq;
}
- if (maxReq == 3)
+ if (maxReq == 2)
break;
SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]);
for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2)
@@ -213,15 +211,19 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint32(itr2->second);
++maxReq;
}
- if (maxReq == 3)
+ if (maxReq == 2)
break;
}
- while (maxReq < 3)
+ while (maxReq < 2)
{
data << uint32(0);
++maxReq;
}
+ data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
+ // primary prof. learn confirmation dialog
+ data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
+
++count;
}
@@ -234,9 +236,10 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
{
uint64 guid;
- uint32 spellId = 0;
+ uint32 spellId;
+ uint32 trainerId;
- recvData >> guid >> spellId;
+ recvData >> guid >> trainerId >> spellId;
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u", uint32(GUID_LOPART(guid)), spellId);
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
@@ -253,28 +256,40 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
// check present spell in trainer spell list
TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
if (!trainer_spells)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// not found, cheat?
TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
if (!trainer_spell)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// can't be learn, cheat? Or double learn with lags...
if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// apply reputation discount
uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
// check money requirement
- if (!_player->HasEnoughMoney(nSpellCost))
+ if (!_player->HasEnoughMoney(uint64(nSpellCost)))
+ {
+ SendTrainerBuyFailed(guid, spellId, 1);
return;
+ }
- _player->ModifyMoney(-int32(nSpellCost));
+ _player->ModifyMoney(-int64(nSpellCost));
- unit->SendPlaySpellVisual(179); // 53 SpellCastDirected
- unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute
+ unit->SendPlaySpellVisualKit(179, 0); // 53 SpellCastDirected
+ _player->SendPlaySpellVisualKit(362, 1); // 113 EmoteSalute
// learn explicitly or cast explicitly
if (trainer_spell->IsCastable())
@@ -284,7 +299,16 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(guid);
- data << uint32(spellId); // should be same as in packet from client
+ data << uint32(spellId);
+ SendPacket(&data);
+}
+
+void WorldSession::SendTrainerBuyFailed(uint64 guid, uint32 spellId, uint32 reason)
+{
+ WorldPacket data(SMSG_TRAINER_BUY_FAILED, 16);
+ data << uint64(guid);
+ data << uint32(spellId); // should be same as in packet from client
+ data << uint32(reason); // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable."
SendPacket(&data);
}
@@ -312,9 +336,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
// GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
if (unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider() || unit->isGuard())
- {
unit->StopMoving();
- }
// If spiritguide, no need for gossip menu, just put player into resurrect queue
if (unit->isSpiritGuide())
@@ -466,7 +488,7 @@ void WorldSession::SendBindPoint(Creature* npc)
// send spell for homebinding (3286)
npc->CastSpell(_player, bindspell, true);
- WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
+ WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(npc->GetGUID());
data << uint32(bindspell);
SendPacket(&data);
@@ -530,6 +552,7 @@ void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid
// not let move dead pet in slot
if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET)
{
+ data << uint32(0); // 4.x unknown, some kind of order?
data << uint32(pet->GetCharmInfo()->GetPetNumber());
data << uint32(pet->GetEntry());
data << uint32(pet->getLevel());
@@ -742,7 +765,7 @@ void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
if (GetPlayer()->m_stableSlots < MAX_PET_STABLES)
{
- StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
+ /*StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
if (_player->HasEnoughMoney(SlotPrice->Price))
{
++GetPlayer()->m_stableSlots;
@@ -750,7 +773,7 @@ void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
SendStableResult(STABLE_SUCCESS_BUY_SLOT);
}
else
- SendStableResult(STABLE_ERR_MONEY);
+ SendStableResult(STABLE_ERR_MONEY);*/
}
else
SendStableResult(STABLE_ERR_STABLE);
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index a8046f2f441..c26c0ce7c01 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -61,9 +61,14 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
uint64 guid1;
uint32 data;
uint64 guid2;
+ float x, y, z;
recvData >> guid1; //pet guid
recvData >> data;
recvData >> guid2; //tag guid
+ // Position
+ recvData >> x;
+ recvData >> y;
+ recvData >> z;
uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); //delete = 0x07 CastSpell = C1
@@ -98,7 +103,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
return;
if (GetPlayer()->m_Controlled.size() == 1)
- HandlePetActionHelper(pet, guid1, spellid, flag, guid2);
+ HandlePetActionHelper(pet, guid1, spellid, flag, guid2, x, y, z);
else
{
//If a pet is dismissed, m_Controlled will change
@@ -107,7 +112,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
if ((*itr)->GetEntry() == pet->GetEntry() && (*itr)->isAlive())
controlled.push_back(*itr);
for (std::vector<Unit*>::iterator itr = controlled.begin(); itr != controlled.end(); ++itr)
- HandlePetActionHelper(*itr, guid1, spellid, flag, guid2);
+ HandlePetActionHelper(*itr, guid1, spellid, flag, guid2, x, y, z);
}
}
@@ -139,7 +144,7 @@ void WorldSession::HandlePetStopAttack(WorldPacket &recvData)
pet->AttackStop();
}
-void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2)
+void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2, float x, float y, float z)
{
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
@@ -261,6 +266,18 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid
}
}
break;
+ case COMMAND_MOVE_TO:
+ pet->StopMoving();
+ pet->GetMotionMaster()->Clear(false);
+ pet->GetMotionMaster()->MovePoint(0, x, y, z);
+ charmInfo->SetCommandState(COMMAND_MOVE_TO);
+
+ charmInfo->SetIsCommandAttack(false);
+ charmInfo->SetIsAtStay(true);
+ charmInfo->SetIsFollowing(false);
+ charmInfo->SetIsReturning(false);
+ charmInfo->SaveStayPosition();
+ break;
default:
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
}
@@ -683,15 +700,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
if (pet)
{
if (pet->isPet())
- {
- if (pet->GetGUID() == _player->GetPetGUID())
- {
- uint32 feelty = pet->GetPower(POWER_HAPPINESS);
- pet->SetPower(POWER_HAPPINESS, feelty > 50000 ? (feelty-50000) : 0);
- }
-
_player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED);
- }
else if (pet->GetGUID() == _player->GetCharmGUID())
_player->StopCastingCharm();
}
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index cabdf657120..2d551d03f45 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -182,7 +182,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
return;
}
- if (!_player->HasEnoughMoney(cost))
+ if (!_player->HasEnoughMoney(uint64(cost)))
{ //player hasn't got enough money
_player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, charterid, 0);
return;
@@ -382,7 +382,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData)
{
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_RENAME"); // ok
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_RENAME");
uint64 petitionGuid;
uint32 type;
@@ -550,14 +550,10 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
data << uint64(petitionGuid);
data << uint64(_player->GetGUID());
- data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
+ data << uint32(PETITION_SIGN_ALREADY_SIGNED);
// close at signer side
SendPacket(&data);
-
- // update for owner if online
- if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid))
- owner->GetSession()->SendPacket(&data);
return;
}
@@ -779,7 +775,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
if (_player->GetGuildId())
{
data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
- data << (uint32)PETITION_TURN_ALREADY_IN_GUILD;
+ data << uint32(PETITION_TURN_ALREADY_IN_GUILD);
_player->GetSession()->SendPacket(&data);
return;
}
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index 5a94d5b391b..01c50b46b21 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -118,10 +118,14 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100);
data << uint32(entry); // creature entry
data << Name;
- data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
+
+ for (int i = 0; i < 7; i++)
+ data << uint8(0); // name2, ..., name8
+
data << SubName;
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
data << uint32(ci->type_flags); // flags
+ data << uint32(ci->type_flags2); // unknown meaning
data << uint32(ci->type); // CreatureType.dbc
data << uint32(ci->family); // CreatureFamily.dbc
data << uint32(ci->rank); // Creature Rank (elite, boss, etc)
@@ -137,6 +141,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
data << uint32(ci->questItems[i]); // itemId[6], quest drop
data << uint32(ci->movementId); // CreatureMovementInfo.dbc
+ data << uint32(ci->expansionUnknown); // unknown meaning
SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
}
@@ -192,7 +197,8 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
data.append(info->raw.data, MAX_GAMEOBJECT_DATA);
data << float(info->size); // go size
for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
- data << uint32(info->questItems[i]); // itemId[6], quest drop
+ data << uint32(info->questItems[i]); // itemId[6], quest drop
+ data << int32(info->unkInt32); // 4.x, unknown
SendPacket(&data);
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
}
@@ -207,7 +213,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleCorpseQueryOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_CORPSE_QUERY");
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index a63192f64b6..279c1392e17 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -37,8 +37,8 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData)
{
uint64 guid;
recvData >> guid;
- uint8 questStatus = DIALOG_STATUS_NONE;
- uint8 defstatus = DIALOG_STATUS_NONE;
+ uint32 questStatus = DIALOG_STATUS_NONE;
+ uint32 defstatus = DIALOG_STATUS_NONE;
Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
if (!questgiver)
@@ -295,74 +295,87 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u", uint32(GUID_LOPART(guid)), questId, reward);
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
- if (!object || !object->hasInvolvedQuest(questId))
+ Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
+ if (!quest)
return;
- // some kind of WPE protection
- if (!_player->CanInteractWithQuestGiver(object))
- return;
+ Object* object = _player;
- if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
+ if (!quest->HasFlag(QUEST_FLAGS_AUTO_SUBMIT))
{
- if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) ||
- (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
- {
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
- _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
+ if (!object || !object->hasInvolvedQuest(questId))
return;
- }
- if (_player->CanRewardQuest(quest, reward, true))
- {
- _player->RewardQuest(quest, reward, object);
- switch (object->GetTypeId())
+ // some kind of WPE protection
+ if (!_player->CanInteractWithQuestGiver(object))
+ return;
+ }
+
+ if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) ||
+ (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
+ _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ return;
+ }
+
+ if (_player->CanRewardQuest(quest, reward, true))
+ {
+ _player->RewardQuest(quest, reward, object);
+
+ switch (object->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
{
- case TYPEID_UNIT:
- if (!(sScriptMgr->OnQuestReward(_player, (object->ToCreature()), quest, reward)))
+ //For AutoSubmition was added plr case there as it almost same exclute AI script cases.
+ Creature* creatureQGiver = object->ToCreature();
+ if (!creatureQGiver || !(sScriptMgr->OnQuestReward(_player, creatureQGiver, quest, reward)))
+ {
+ // Send next quest
+ if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
{
- // Send next quest
- if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
+ if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
{
- if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
- {
- _player->AddQuest(nextQuest, object);
- if (_player->CanCompleteQuest(nextQuest->GetQuestId()))
- _player->CompleteQuest(nextQuest->GetQuestId());
- }
-
- _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
+ _player->AddQuest(nextQuest, object);
+ if (_player->CanCompleteQuest(nextQuest->GetQuestId()))
+ _player->CompleteQuest(nextQuest->GetQuestId());
}
- (object->ToCreature())->AI()->sQuestReward(_player, quest, reward);
+ _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- break;
- case TYPEID_GAMEOBJECT:
- if (!sScriptMgr->OnQuestReward(_player, ((GameObject*)object), quest, reward))
+
+ if (creatureQGiver)
+ creatureQGiver->AI()->sQuestReward(_player, quest, reward);
+ }
+ break;
+ }
+ case TYPEID_GAMEOBJECT:
+ if (!sScriptMgr->OnQuestReward(_player, ((GameObject*)object), quest, reward))
+ {
+ // Send next quest
+ if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
{
- // Send next quest
- if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
+ if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
{
- if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
- {
- _player->AddQuest(nextQuest, object);
- if (_player->CanCompleteQuest(nextQuest->GetQuestId()))
- _player->CompleteQuest(nextQuest->GetQuestId());
- }
-
- _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
+ _player->AddQuest(nextQuest, object);
+ if (_player->CanCompleteQuest(nextQuest->GetQuestId()))
+ _player->CompleteQuest(nextQuest->GetQuestId());
}
- object->ToGameObject()->AI()->QuestReward(_player, quest, reward);
+ _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- break;
- default:
- break;
- }
+
+ object->ToGameObject()->AI()->QuestReward(_player, quest, reward);
+ }
+ break;
+ default:
+ break;
}
- else
- _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
}
+ else
+ _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
}
void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket& recvData)
@@ -427,7 +440,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData)
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
- if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED))
+ if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
_player->RemoveTimedQuest(questId);
if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
@@ -455,7 +468,7 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
uint32 questId;
recvData >> questId;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", questId);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = %u", questId);
if (const Quest* quest = sObjectMgr->GetQuestTemplate(questId))
{
@@ -480,25 +493,35 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
{
uint32 questId;
- uint64 guid;
-
- recvData >> guid >> questId;
+ uint64 playerGuid;
+ bool autoCompleteMode; // 0 - standart complete quest mode with npc, 1 - auto-complete mode
+ recvData >> playerGuid >> questId >> autoCompleteMode;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId);
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
+ Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
if (!object || !object->hasInvolvedQuest(questId))
return;
- // some kind of WPE protection
- if (!_player->CanInteractWithQuestGiver(object))
- return;
+ if (autoCompleteMode == 0)
+ {
+ // some kind of WPE protection
+ if (!_player->CanInteractWithQuestGiver(object))
+ return;
+ }
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
+ if (autoCompleteMode && !quest->HasFlag(QUEST_FLAGS_AUTO_SUBMIT))
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [playerGuid: %u] tried to complete questId [entry: %u] by auto-submit flag for quest witch not suport it.",
+ _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ return;
+ }
+
if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE)
{
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!",
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [playerGuid: %u] tried to complete questId [entry: %u] without being in possession of the questId!",
_player->GetName().c_str(), _player->GetGUIDLow(), questId);
return;
}
@@ -511,16 +534,16 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE)
{
if (quest->IsRepeatable())
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanCompleteRepeatableQuest(quest), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanCompleteRepeatableQuest(quest), false);
else
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
}
else
{
if (quest->GetReqItemsCount()) // some items required
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
else // no items required
- _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
+ _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, !autoCompleteMode);
}
if (Creature* creature = object->ToCreature())
@@ -538,7 +561,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
uint32 questId;
recvPacket >> questId;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", questId);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId);
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
@@ -716,13 +739,13 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
uint32 count = 0;
- WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
+ WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4 + 8 + 4);
data << uint32(count); // placeholder
for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
{
- uint8 questStatus = DIALOG_STATUS_NONE;
- uint8 defstatus = DIALOG_STATUS_NONE;
+ uint32 questStatus = DIALOG_STATUS_NONE;
+ uint32 defstatus = DIALOG_STATUS_NONE;
if (IS_CRE_OR_VEH_OR_PET_GUID(*itr))
{
@@ -737,7 +760,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
questStatus = getDialogStatus(_player, questgiver, defstatus);
data << uint64(questgiver->GetGUID());
- data << uint8(questStatus);
+ data << uint32(questStatus);
++count;
}
else if (IS_GAMEOBJECT_GUID(*itr))
@@ -752,7 +775,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
questStatus = getDialogStatus(_player, questgiver, defstatus);
data << uint64(questgiver->GetGUID());
- data << uint8(questStatus);
+ data << uint32(questStatus);
++count;
}
}
@@ -761,7 +784,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
SendPacket(&data);
}
-void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recvData*/)
+void WorldSession::HandleQueryQuestsCompleted(WorldPacket& /*recvData*/)
{
size_t rew_count = _player->GetRewardedQuestCount();
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index 04cc468f216..82f569ebb1e 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -29,18 +29,34 @@
void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData)
{
- uint32 talent_id, requested_rank;
- recvData >> talent_id >> requested_rank;
+ uint32 talentId, requestedRank;
+ recvData >> talentId >> requestedRank;
- _player->LearnTalent(talent_id, requested_rank);
- _player->SendTalentsInfoData(false);
+ if (_player->LearnTalent(talentId, requestedRank))
+ _player->SendTalentsInfoData(false);
}
void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_LEARN_PREVIEW_TALENTS");
+ int32 tabPage;
uint32 talentsCount;
+ recvPacket >> tabPage; // talent tree
+
+ // prevent cheating (selecting new tree with points already in another)
+ if (tabPage >= 0) // -1 if player already has specialization
+ {
+ if (TalentTabEntry const* talentTabEntry = sTalentTabStore.LookupEntry(_player->GetPrimaryTalentTree(_player->GetActiveSpec())))
+ {
+ if (talentTabEntry->tabpage != uint32(tabPage))
+ {
+ recvPacket.rfinish();
+ return;
+ }
+ }
+ }
+
recvPacket >> talentsCount;
uint32 talentId, talentRank;
@@ -49,7 +65,11 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
{
recvPacket >> talentId >> talentRank;
- _player->LearnTalent(talentId, talentRank);
+ if (!_player->LearnTalent(talentId, talentRank))
+ {
+ recvPacket.rfinish();
+ break;
+ }
}
_player->SendTalentsInfoData(false);
@@ -72,7 +92,7 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- if (!(_player->resetTalents()))
+ if (!_player->ResetTalents())
{
WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent
data << uint64(0);
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index f7c2bf0f87d..69e643eb00b 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -21,6 +21,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "ObjectMgr.h"
+#include "GuildMgr.h"
#include "SpellMgr.h"
#include "Log.h"
#include "Opcodes.h"
@@ -50,9 +51,27 @@ void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlag
uint8 hasMovementData;
recvPacket >> hasMovementData;
if (hasMovementData)
- {
- recvPacket.SetOpcode(recvPacket.read<uint32>());
HandleMovementOpcodes(recvPacket);
+ }
+ else if (castFlags & 0x8) // Archaeology
+ {
+ uint32 count, entry, usedCount;
+ uint8 type;
+ recvPacket >> count;
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvPacket >> type;
+ switch (type)
+ {
+ case 2: // Keystones
+ recvPacket >> entry; // Item id
+ recvPacket >> usedCount; // Item count
+ break;
+ case 1: // Fragments
+ recvPacket >> entry; // Currency id
+ recvPacket >> usedCount; // Currency count
+ break;
+ }
}
}
}
@@ -200,7 +219,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
// Verify that the bag is an actual bag or wrapped item that can be used "normally"
if (!(proto->Flags & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
{
- pUser->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ pUser->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!",
pUser->GetName().c_str(), pUser->GetGUIDLow(), item->GetGUIDLow(), proto->ItemId);
return;
@@ -308,9 +327,13 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
- uint32 spellId;
+ uint32 spellId, glyphIndex;
uint8 castCount, castFlags;
- recvPacket >> castCount >> spellId >> castFlags;
+
+ recvPacket >> castCount;
+ recvPacket >> spellId;
+ recvPacket >> glyphIndex;
+ recvPacket >> castFlags;
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size());
@@ -357,6 +380,27 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
+ Unit::AuraEffectList swaps = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS);
+ Unit::AuraEffectList const& swaps2 = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2);
+ if (!swaps2.empty())
+ swaps.insert(swaps.end(), swaps2.begin(), swaps2.end());
+
+ if (!swaps.empty())
+ {
+ for (Unit::AuraEffectList::const_iterator itr = swaps.begin(); itr != swaps.end(); ++itr)
+ {
+ if ((*itr)->IsAffectingSpell(spellInfo))
+ {
+ if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo((*itr)->GetAmount()))
+ {
+ spellInfo = newInfo;
+ spellId = newInfo->Id;
+ }
+ break;
+ }
+ }
+ }
+
// Client is resending autoshot cast opcode when other spell is casted during shoot rotation
// Skip it to prevent "interrupt" message
if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
@@ -390,6 +434,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false);
spell->m_cast_count = castCount; // set count of casts
+ spell->m_glyphIndex = glyphIndex;
spell->prepare(&targets);
}
@@ -506,8 +551,9 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket)
return;
uint8 slotId;
-
+ uint64 guid;
recvPacket >> slotId;
+ recvPacket >> guid;
++slotId;
if (slotId >= MAX_TOTEM_SLOT)
@@ -517,12 +563,11 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket)
return;
Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_SummonSlot[slotId]);
-
- if (totem && totem->isTotem())
+ if (totem && totem->isTotem() && totem->GetGUID() == guid)
totem->ToTotem()->UnSummon();
}
-void WorldSession::HandleSelfResOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleSelfResOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SELF_RES"); // empty opcode
@@ -562,6 +607,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GET_MIRRORIMAGE_DATA");
uint64 guid;
recvData >> guid;
+ recvData.read_skip<uint32>(); // DisplayId ?
// Get unit for which data is needed by client
Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL);
@@ -586,12 +632,17 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
if (creator->GetTypeId() == TYPEID_PLAYER)
{
Player* player = creator->ToPlayer();
+ Guild* guild = NULL;
+
+ if (uint32 guildId = player->GetGuildId())
+ guild = sGuildMgr->GetGuildById(guildId);
+
data << uint8(player->GetByteValue(PLAYER_BYTES, 0)); // skin
data << uint8(player->GetByteValue(PLAYER_BYTES, 1)); // face
data << uint8(player->GetByteValue(PLAYER_BYTES, 2)); // hair
data << uint8(player->GetByteValue(PLAYER_BYTES, 3)); // haircolor
data << uint8(player->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair
- data << uint32(player->GetGuildId()); // unk
+ data << uint64(guild ? guild->GetGUID() : 0);
static EquipmentSlots const itemSlots[] =
{
@@ -680,3 +731,27 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket)
data << float(z);
caster->SendMessageToSet(&data, true);
}
+
+void WorldSession::HandleRequestCategoryCooldowns(WorldPacket& /*recvPacket*/)
+{
+ std::map<uint32, int32> categoryMods;
+ Unit::AuraEffectList const& categoryCooldownAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN);
+ for (Unit::AuraEffectList::const_iterator itr = categoryCooldownAuras.begin(); itr != categoryCooldownAuras.end(); ++itr)
+ {
+ std::map<uint32, int32>::iterator cItr = categoryMods.find((*itr)->GetMiscValue());
+ if (cItr == categoryMods.end())
+ categoryMods[(*itr)->GetMiscValue()] = (*itr)->GetAmount();
+ else
+ cItr->second += (*itr)->GetAmount();
+ }
+
+ WorldPacket data(SMSG_SPELL_CATEGORY_COOLDOWN, 11);
+ data.WriteBits(categoryMods.size(), 23);
+ for (std::map<uint32, int32>::const_iterator itr = categoryMods.begin(); itr != categoryMods.end(); ++itr)
+ {
+ data << uint32(itr->first);
+ data << int32(-itr->second);
+ }
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index ae25d9f4750..2c159f4ab0d 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -94,12 +94,12 @@ void WorldSession::SendTaxiMenu(Creature* unit)
{
// find current node
uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
-
- if (curloc == 0)
+ if (!curloc)
return;
bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater();
- if (unit->GetEntry() == 29480) GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.
+ if (unit->GetEntry() == 29480)
+ GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ", curloc);
@@ -199,13 +199,10 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_SPLINE_DONE");
- uint64 guid; // used only for proper packet read
- recvData.readPackGUID(guid);
+ recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo; // used only for proper packet read
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData.read_skip<uint32>(); // unk
+ _player->ReadMovementInfo(recvData, &movementInfo);
// in taxi flight packet received in 2 case:
// 1) end taxi path in far (multi-node) flight
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 6983585878b..82804fe40fc 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -34,34 +34,38 @@ void WorldSession::SendTradeStatus(TradeStatus status)
{
WorldPacket data;
+ data.Initialize(SMSG_TRADE_STATUS, 1+4+4);
+ data.WriteBit(0); // unk bit, usually 0
+ data.WriteBits(status, 5);
+
switch (status)
{
case TRADE_STATUS_BEGIN_TRADE:
- data.Initialize(SMSG_TRADE_STATUS, 4+8);
- data << uint32(status);
- data << uint64(0);
+ data.WriteBits(0, 8); // zero guid
+ data.FlushBits();
break;
case TRADE_STATUS_OPEN_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4);
- data << uint32(status);
- data << uint32(0); // added in 2.4.0
+ data.FlushBits();
+ data << uint32(0); // unk
break;
case TRADE_STATUS_CLOSE_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4);
- data << uint32(status);
- data << uint32(0);
- data << uint8(0);
- data << uint32(0);
+ data.WriteBit(0); // unk
+ data.FlushBits();
+ data << uint32(0); // unk
+ data << uint32(0); // unk
break;
case TRADE_STATUS_ONLY_CONJURED:
case TRADE_STATUS_NOT_ELIGIBLE:
- data.Initialize(SMSG_TRADE_STATUS, 4+1);
- data << uint32(status);
- data << uint8(0);
+ data.FlushBits();
+ data << uint8(0); // unk
break;
+ case TRADE_STATUS_CURRENCY: // Not implemented
+ case TRADE_STATUS_CURRENCY_NOT_TRADABLE: // Not implemented
+ data.FlushBits();
+ data << uint32(0); // unk
+ data << uint32(0); // unk
default:
- data.Initialize(SMSG_TRADE_STATUS, 4);
- data << uint32(status);
+ data.FlushBits();
break;
}
@@ -71,60 +75,117 @@ void WorldSession::SendTradeStatus(TradeStatus status)
void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Ignore Trade %u", _player->GetGUIDLow());
- // recvPacket.print_storage();
}
void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Busy Trade %u", _player->GetGUIDLow());
- // recvPacket.print_storage();
}
void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
{
TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();
- WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 1+4+4+4+4+4+7*(1+4+4+4+4+8+4+4+4+4+8+4+4+4+4+4+4));
- data << uint8(trader_data); // 1 means traders data, 0 means own
- data << uint32(0); // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
+ ByteBuffer itemData(7*2 + 7*4 + 3*4 + 3*4 + 1);
+
+ uint8 count = 0;
+ for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
+ if (view_trade->GetItem(TradeSlots(i)))
+ ++count;
+
+ WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 4*6 + 8 + 1 + 3 + count * 70);
+ data << uint32(0); // this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
+ data << uint32(0); // unk 2
+ data << uint64(view_trade->GetMoney()); // trader gold
+ data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases
+ data << uint32(0); // unk 5
+ data << uint8(trader_data); // 1 means traders data, 0 means own
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases
- data << uint32(view_trade->GetMoney()); // trader gold
- data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item
+ data.WriteBits(count, 22);
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
{
- data << uint8(i); // trade slot number, if not specified, then end of packet
+ Item* item = view_trade->GetItem(TradeSlots(i));
+ if (!item)
+ continue;
- if (Item* item = view_trade->GetItem(TradeSlots(i)))
- {
- data << uint32(item->GetTemplate()->ItemId); // entry
- data << uint32(item->GetTemplate()->DisplayInfoID);// display id
- data << uint32(item->GetCount()); // stack count
- // wrapped: hide stats but show giftcreator name
- data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED) ? 1 : 0);
- data << uint64(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR));
- // perm. enchantment and gems
- data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
- for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
- data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
- // creator
- data << uint64(item->GetUInt64Value(ITEM_FIELD_CREATOR));
- data << uint32(item->GetSpellCharges()); // charges
- data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
- data << uint32(item->GetItemRandomPropertyId());// random properties id
- data << uint32(item->GetTemplate()->LockID); // lock id
- // max durability
- data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
- // durability
- data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
- }
- else
+ ObjectGuid giftCreatorGuid = item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
+ ObjectGuid creatorGuid = item->GetUInt64Value(ITEM_FIELD_CREATOR);
+
+ data.WriteBit(giftCreatorGuid[7]);
+ data.WriteBit(giftCreatorGuid[1]);
+ bool notWrapped = data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED));
+ data.WriteBit(giftCreatorGuid[3]);
+
+ if (notWrapped)
{
- for (uint8 j = 0; j < 18; ++j)
- data << uint32(0);
+ data.WriteBit(creatorGuid[7]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(item->GetTemplate()->LockID != 0);
+ data.WriteBit(creatorGuid[0]);
+
+ itemData.WriteByteSeq(creatorGuid[1]);
+
+ itemData << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
+ for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS /*3*/; ++enchant_slot)
+ itemData << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
+ itemData << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
+
+ itemData.WriteByteSeq(creatorGuid[6]);
+ itemData.WriteByteSeq(creatorGuid[2]);
+ itemData.WriteByteSeq(creatorGuid[7]);
+ itemData.WriteByteSeq(creatorGuid[4]);
+
+ itemData << uint32(0); // reforge id, FIXME: not implemented
+ itemData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
+ itemData << uint32(item->GetItemRandomPropertyId());
+
+ itemData.WriteByteSeq(creatorGuid[3]);
+
+ itemData << uint32(0); // unk7
+
+ itemData.WriteByteSeq(creatorGuid[0]);
+
+ itemData << uint32(item->GetSpellCharges());
+ itemData << uint32(item->GetItemSuffixFactor());
+
+ itemData.WriteByteSeq(creatorGuid[5]);
}
+
+ data.WriteBit(giftCreatorGuid[6]);
+ data.WriteBit(giftCreatorGuid[4]);
+ data.WriteBit(giftCreatorGuid[2]);
+ data.WriteBit(giftCreatorGuid[0]);
+ data.WriteBit(giftCreatorGuid[5]);
+
+ itemData.WriteByteSeq(giftCreatorGuid[6]);
+ itemData.WriteByteSeq(giftCreatorGuid[1]);
+ itemData.WriteByteSeq(giftCreatorGuid[7]);
+ itemData.WriteByteSeq(giftCreatorGuid[4]);
+
+ itemData << uint32(item->GetTemplate()->ItemId);
+
+ itemData.WriteByteSeq(giftCreatorGuid[0]);
+
+ itemData << uint32(item->GetCount());
+
+ itemData.WriteByteSeq(giftCreatorGuid[5]);
+
+ itemData << uint8(i);
+
+ itemData.WriteByteSeq(giftCreatorGuid[2]);
+ itemData.WriteByteSeq(giftCreatorGuid[3]);
}
+
+ data.FlushBits();
+ data.append(itemData);
+
SendPacket(&data);
}
@@ -292,14 +353,14 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
return;
}
- if (_player->GetMoney() >= uint32(MAX_MONEY_AMOUNT) - his_trade->GetMoney())
+ if (_player->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - his_trade->GetMoney())
{
_player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
my_trade->SetAccepted(false, true);
return;
}
- if (trader->GetMoney() >= uint32(MAX_MONEY_AMOUNT) - my_trade->GetMoney())
+ if (trader->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - my_trade->GetMoney())
{
trader->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
his_trade->SetAccepted(false, true);
@@ -477,7 +538,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
if (my_trade->GetMoney() > 0)
{
- sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
+ sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
_player->GetName().c_str(), _player->GetSession()->GetAccountId(),
my_trade->GetMoney(),
trader->GetName().c_str(), trader->GetSession()->GetAccountId());
@@ -485,7 +546,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
if (his_trade->GetMoney() > 0)
{
- sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
+ sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
trader->GetName().c_str(), trader->GetSession()->GetAccountId(),
his_trade->GetMoney(),
_player->GetName().c_str(), _player->GetSession()->GetAccountId());
@@ -493,9 +554,9 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
}
// update money
- _player->ModifyMoney(-int32(my_trade->GetMoney()));
+ _player->ModifyMoney(-int64(my_trade->GetMoney()));
_player->ModifyMoney(his_trade->GetMoney());
- trader->ModifyMoney(-int32(his_trade->GetMoney()));
+ trader->ModifyMoney(-int64(his_trade->GetMoney()));
trader->ModifyMoney(my_trade->GetMoney());
if (my_spell)
@@ -555,15 +616,32 @@ void WorldSession::SendCancelTrade()
void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
{
- // sended also after LOGOUT COMPLETE
+ // sent also after LOGOUT COMPLETE
if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT
_player->TradeCancel(true);
}
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
{
- uint64 ID;
- recvPacket >> ID;
+ ObjectGuid guid;
+
+ guid[0] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[0]);
if (GetPlayer()->m_trade)
return;
@@ -598,7 +676,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
- Player* pOther = ObjectAccessor::FindPlayer(ID);
+ Player* pOther = ObjectAccessor::FindPlayer(guid);
if (!pOther)
{
@@ -664,15 +742,36 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
_player->m_trade = new TradeData(_player, pOther);
pOther->m_trade = new TradeData(pOther, _player);
- WorldPacket data(SMSG_TRADE_STATUS, 12);
- data << uint32(TRADE_STATUS_BEGIN_TRADE);
- data << uint64(_player->GetGUID());
+ WorldPacket data(SMSG_TRADE_STATUS, 2+7);
+ data.WriteBit(0); // unk bit, usually 0
+ data.WriteBits(TRADE_STATUS_BEGIN_TRADE, 5);
+
+ ObjectGuid playerGuid = _player->GetGUID();
+ // WTB StartBitStream...
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[6]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBit(playerGuid[1]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[5]);
+
+ data.WriteByteSeq(playerGuid[4]);
+ data.WriteByteSeq(playerGuid[1]);
+ data.WriteByteSeq(playerGuid[2]);
+ data.WriteByteSeq(playerGuid[3]);
+ data.WriteByteSeq(playerGuid[0]);
+ data.WriteByteSeq(playerGuid[7]);
+ data.WriteByteSeq(playerGuid[6]);
+ data.WriteByteSeq(playerGuid[5]);
+
pOther->GetSession()->SendPacket(&data);
}
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
{
- uint32 gold;
+ uint64 gold;
recvPacket >> gold;
TradeData* my_trade = _player->GetTradeData();
@@ -690,9 +789,9 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
uint8 bag;
uint8 slot;
+ recvPacket >> slot;
recvPacket >> tradeSlot;
recvPacket >> bag;
- recvPacket >> slot;
TradeData* my_trade = _player->GetTradeData();
if (!my_trade)
diff --git a/src/server/game/Handlers/VehicleHandler.cpp b/src/server/game/Handlers/VehicleHandler.cpp
index c44d8a2d38e..7a5d5ef8f48 100644
--- a/src/server/game/Handlers/VehicleHandler.cpp
+++ b/src/server/game/Handlers/VehicleHandler.cpp
@@ -22,6 +22,7 @@
#include "Player.h"
#include "Log.h"
#include "ObjectAccessor.h"
+#include "MovementStructures.h"
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData)
{
@@ -35,20 +36,15 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData)
return;
}
- uint64 guid;
-
- recvData.readPackGUID(guid);
-
MovementInfo mi;
- mi.guid = guid;
- ReadMovementInfo(recvData, &mi);
+ _player->ReadMovementInfo(recvData, &mi);
_player->m_movementInfo = mi;
_player->ExitVehicle();
}
-void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
+void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvData)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
@@ -78,20 +74,36 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
break;
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
{
- uint64 guid; // current vehicle guid
- recvData.readPackGUID(guid);
-
+ static MovementStatusElements const accessoryGuid[] =
+ {
+ MSEExtraInt8,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ };
+
+ Movement::ExtraMovementStatusElement extra(accessoryGuid);
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo, &extra);
vehicle_base->m_movementInfo = movementInfo;
- uint64 accessory; // accessory guid
- recvData.readPackGUID(accessory);
-
- int8 seatId;
- recvData >> seatId;
+ uint64 accessory = extra.Data.guid;
+ int8 seatId = extra.Data.byteData;
- if (vehicle_base->GetGUID() != guid)
+ if (vehicle_base->GetGUID() != movementInfo.guid)
return;
if (!accessory)
@@ -125,7 +137,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
}
}
-void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
+void WorldSession::HandleEnterPlayerVehicle(WorldPacket& data)
{
// Read guid
uint64 guid;
@@ -144,7 +156,7 @@ void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
}
}
-void WorldSession::HandleEjectPassenger(WorldPacket &data)
+void WorldSession::HandleEjectPassenger(WorldPacket& data)
{
Vehicle* vehicle = _player->GetVehicleKit();
if (!vehicle)
diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp
index 36e9d4e716d..9cff49a6b49 100644
--- a/src/server/game/Handlers/VoiceChatHandler.cpp
+++ b/src/server/game/Handlers/VoiceChatHandler.cpp
@@ -34,6 +34,10 @@ void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CHANNEL_VOICE_ON");
// Enable Voice button in channel context menu
+ /* structure:
+ 8 bits -> channel name length
+ string -> channel name
+ */
}
void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp
new file mode 100644
index 00000000000..7ac4f687509
--- /dev/null
+++ b/src/server/game/Handlers/VoidStorageHandler.cpp
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Common.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "World.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "Log.h"
+#include "Opcodes.h"
+#include "Player.h"
+#include <list>
+#include <vector>
+#include <utility>
+
+void WorldSession::SendVoidStorageTransferResult(VoidTransferError result)
+{
+ WorldPacket data(SMSG_VOID_TRANSFER_RESULT, 4);
+ data << uint32(result);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleVoidStorageUnlock(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_UNLOCK");
+ Player* player = GetPlayer();
+
+ ObjectGuid npcGuid;
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[4]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Player (GUID: %u, name: %s) tried to unlock void storage a 2nd time.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ player->ModifyMoney(-int64(VOID_STORAGE_UNLOCK));
+ player->UnlockVoidStorage();
+}
+
+void WorldSession::HandleVoidStorageQuery(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_QUERY");
+ Player* player = GetPlayer();
+
+ ObjectGuid npcGuid;
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[2]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ uint8 count = 0;
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (player->GetVoidStorageItem(i))
+ ++count;
+
+ WorldPacket data(SMSG_VOID_STORAGE_CONTENTS, 2 * count + (14 + 4 + 4 + 4 + 4) * count);
+
+ data.WriteBits(count, 8);
+
+ ByteBuffer itemData((14 + 4 + 4 + 4 + 4) * count);
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ VoidStorageItem* item = player->GetVoidStorageItem(i);
+ if (!item)
+ continue;
+
+ ObjectGuid itemId = item->ItemId;
+ ObjectGuid creatorGuid = item->CreatorGuid;
+
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(creatorGuid[0]);
+ data.WriteBit(creatorGuid[7]);
+
+ itemData.WriteByteSeq(creatorGuid[3]);
+
+ itemData << uint32(item->ItemSuffixFactor);
+
+ itemData.WriteByteSeq(creatorGuid[4]);
+
+ itemData << uint32(i);
+
+ itemData.WriteByteSeq(itemId[0]);
+ itemData.WriteByteSeq(itemId[6]);
+ itemData.WriteByteSeq(creatorGuid[0]);
+
+ itemData << uint32(item->ItemRandomPropertyId);
+
+ itemData.WriteByteSeq(itemId[4]);
+ itemData.WriteByteSeq(itemId[5]);
+ itemData.WriteByteSeq(itemId[2]);
+ itemData.WriteByteSeq(creatorGuid[2]);
+ itemData.WriteByteSeq(creatorGuid[6]);
+ itemData.WriteByteSeq(itemId[1]);
+ itemData.WriteByteSeq(itemId[3]);
+ itemData.WriteByteSeq(creatorGuid[5]);
+ itemData.WriteByteSeq(creatorGuid[7]);
+
+ itemData << uint32(item->ItemEntry);
+
+ itemData.WriteByteSeq(itemId[7]);
+ }
+
+ data.FlushBits();
+ data.append(itemData);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_TRANSFER");
+ Player* player = GetPlayer();
+
+ // Read everything
+
+ ObjectGuid npcGuid;
+ npcGuid[1] = recvData.ReadBit();
+
+ uint32 countDeposit = recvData.ReadBits(26);
+
+ if (countDeposit > 9)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countDeposit);
+ return;
+ }
+
+ std::vector<ObjectGuid> itemGuids(countDeposit);
+ for (uint32 i = 0; i < countDeposit; ++i)
+ {
+ itemGuids[i][4] = recvData.ReadBit();
+ itemGuids[i][6] = recvData.ReadBit();
+ itemGuids[i][7] = recvData.ReadBit();
+ itemGuids[i][0] = recvData.ReadBit();
+ itemGuids[i][1] = recvData.ReadBit();
+ itemGuids[i][5] = recvData.ReadBit();
+ itemGuids[i][3] = recvData.ReadBit();
+ itemGuids[i][2] = recvData.ReadBit();
+ }
+
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+
+ uint32 countWithdraw = recvData.ReadBits(26);
+
+ if (countWithdraw > 9)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countWithdraw);
+ return;
+ }
+
+ std::vector<ObjectGuid> itemIds(countWithdraw);
+ for (uint32 i = 0; i < countWithdraw; ++i)
+ {
+ itemIds[i][4] = recvData.ReadBit();
+ itemIds[i][7] = recvData.ReadBit();
+ itemIds[i][1] = recvData.ReadBit();
+ itemIds[i][0] = recvData.ReadBit();
+ itemIds[i][2] = recvData.ReadBit();
+ itemIds[i][3] = recvData.ReadBit();
+ itemIds[i][5] = recvData.ReadBit();
+ itemIds[i][6] = recvData.ReadBit();
+ }
+
+ npcGuid[7] = recvData.ReadBit();
+
+ for (uint32 i = 0; i < countDeposit; ++i)
+ {
+ recvData.ReadByteSeq(itemGuids[i][6]);
+ recvData.ReadByteSeq(itemGuids[i][1]);
+ recvData.ReadByteSeq(itemGuids[i][0]);
+ recvData.ReadByteSeq(itemGuids[i][2]);
+ recvData.ReadByteSeq(itemGuids[i][4]);
+ recvData.ReadByteSeq(itemGuids[i][5]);
+ recvData.ReadByteSeq(itemGuids[i][3]);
+ recvData.ReadByteSeq(itemGuids[i][7]);
+ }
+
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+
+ for (uint32 i = 0; i < countWithdraw; ++i)
+ {
+ recvData.ReadByteSeq(itemIds[i][3]);
+ recvData.ReadByteSeq(itemIds[i][0]);
+ recvData.ReadByteSeq(itemIds[i][1]);
+ recvData.ReadByteSeq(itemIds[i][6]);
+ recvData.ReadByteSeq(itemIds[i][2]);
+ recvData.ReadByteSeq(itemIds[i][7]);
+ recvData.ReadByteSeq(itemIds[i][5]);
+ recvData.ReadByteSeq(itemIds[i][4]);
+ }
+
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[0]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots())
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return;
+ }
+
+ uint32 freeBagSlots = 0;
+ if (itemIds.size() != 0)
+ {
+ // make this a Player function
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
+ if (Bag* bag = player->GetBagByPos(i))
+ freeBagSlots += bag->GetFreeSlots();
+ for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
+ if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeBagSlots;
+ }
+
+ if (itemIds.size() > freeBagSlots)
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL);
+ return;
+ }
+
+ if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM)))
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY);
+ return;
+ }
+
+ std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT];
+ uint8 depositCount = 0;
+ for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr)
+ {
+ Item* item = player->GetItemByGuid(*itr);
+ if (!item)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ continue;
+ }
+
+ VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor());
+
+ uint8 slot = player->AddVoidStorageItem(itemVS);
+
+ depositItems[depositCount++] = std::make_pair(itemVS, slot);
+
+ player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
+ }
+
+ int64 cost = depositCount * VOID_STORAGE_STORE_ITEM;
+
+ player->ModifyMoney(-cost);
+
+ VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW];
+ uint8 withdrawCount = 0;
+ for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr)
+ {
+ uint8 slot;
+ VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot);
+ if (!itemVS)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ continue;
+ }
+
+ ItemPosCountVec dest;
+ InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1);
+ if (msg != EQUIP_ERR_OK)
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL);
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ return;
+ }
+
+ Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId);
+ item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid));
+ item->SetBinding(true);
+ player->SendNewItem(item, 1, false, false, false);
+
+ withdrawItems[withdrawCount++] = *itemVS;
+
+ player->DeleteVoidStorageItem(slot);
+ }
+
+ WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount +
+ 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount);
+
+ data.WriteBits(depositCount, 5);
+ data.WriteBits(withdrawCount, 5);
+
+ for (uint8 i = 0; i < depositCount; ++i)
+ {
+ ObjectGuid itemId = depositItems[i].first.ItemId;
+ ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid;
+ data.WriteBit(creatorGuid[7]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(creatorGuid[0]);
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[6]);
+ }
+
+ for (uint8 i = 0; i < withdrawCount; ++i)
+ {
+ ObjectGuid itemId = withdrawItems[i].ItemId;
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[0]);
+ }
+
+ data.FlushBits();
+
+ for (uint8 i = 0; i < withdrawCount; ++i)
+ {
+ ObjectGuid itemId = withdrawItems[i].ItemId;
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(itemId[1]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(itemId[7]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[4]);
+ }
+
+ for (uint8 i = 0; i < depositCount; ++i)
+ {
+ ObjectGuid itemId = depositItems[i].first.ItemId;
+ ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid;
+
+ data << uint32(depositItems[i].first.ItemSuffixFactor);
+
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[4]);
+ data.WriteByteSeq(creatorGuid[4]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(creatorGuid[1]);
+ data.WriteByteSeq(creatorGuid[3]);
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(creatorGuid[0]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(creatorGuid[6]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(creatorGuid[5]);
+ data.WriteByteSeq(creatorGuid[7]);
+
+ data << uint32(depositItems[i].first.ItemEntry);
+
+ data.WriteByteSeq(itemId[1]);
+
+ data << uint32(depositItems[i].second); // slot
+
+ data.WriteByteSeq(creatorGuid[2]);
+ data.WriteByteSeq(itemId[7]);
+
+ data << uint32(depositItems[i].first.ItemRandomPropertyId);
+ }
+
+ SendPacket(&data);
+
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR);
+}
+
+void WorldSession::HandleVoidSwapItem(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_SWAP_ITEM");
+
+ Player* player = GetPlayer();
+ uint32 newSlot;
+ ObjectGuid npcGuid;
+ ObjectGuid itemId;
+
+ recvData >> newSlot;
+
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ itemId[2] = recvData.ReadBit();
+ itemId[6] = recvData.ReadBit();
+ itemId[5] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ itemId[3] = recvData.ReadBit();
+ itemId[7] = recvData.ReadBit();
+ itemId[0] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ itemId[1] = recvData.ReadBit();
+ itemId[4] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(itemId[3]);
+ recvData.ReadByteSeq(itemId[2]);
+ recvData.ReadByteSeq(itemId[4]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(itemId[6]);
+ recvData.ReadByteSeq(itemId[1]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(itemId[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(itemId[0]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(itemId[7]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ uint8 oldSlot;
+ if (!player->GetVoidStorageItem(itemId, oldSlot))
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) requested swapping an invalid item (slot: %u, itemid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), newSlot, uint64(itemId));
+ return;
+ }
+
+ bool usedSrcSlot = player->GetVoidStorageItem(oldSlot) != NULL; // should be always true
+ bool usedDestSlot = player->GetVoidStorageItem(newSlot) != NULL;
+ ObjectGuid itemIdDest;
+ if (usedDestSlot)
+ itemIdDest = player->GetVoidStorageItem(newSlot)->ItemId;
+
+ if (!player->SwapVoidStorageItem(oldSlot, newSlot))
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
+
+ WorldPacket data(SMSG_VOID_ITEM_SWAP_RESPONSE, 1 + (usedSrcSlot + usedDestSlot) * (1 + 7 + 4));
+
+ data.WriteBit(!usedDestSlot);
+ data.WriteBit(!usedSrcSlot);
+
+ if (usedSrcSlot)
+ {
+ data.WriteBit(itemId[5]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[3]);
+ }
+
+ data.WriteBit(!usedDestSlot); // unk
+
+ if (usedDestSlot)
+ {
+ data.WriteBit(itemIdDest[7]);
+ data.WriteBit(itemIdDest[3]);
+ data.WriteBit(itemIdDest[4]);
+ data.WriteBit(itemIdDest[0]);
+ data.WriteBit(itemIdDest[5]);
+ data.WriteBit(itemIdDest[1]);
+ data.WriteBit(itemIdDest[2]);
+ data.WriteBit(itemIdDest[6]);
+ }
+
+ data.WriteBit(!usedSrcSlot); // unk
+
+ data.FlushBits();
+
+ if (usedDestSlot)
+ {
+ data.WriteByteSeq(itemIdDest[4]);
+ data.WriteByteSeq(itemIdDest[6]);
+ data.WriteByteSeq(itemIdDest[5]);
+ data.WriteByteSeq(itemIdDest[2]);
+ data.WriteByteSeq(itemIdDest[3]);
+ data.WriteByteSeq(itemIdDest[1]);
+ data.WriteByteSeq(itemIdDest[7]);
+ data.WriteByteSeq(itemIdDest[0]);
+ }
+
+ if (usedSrcSlot)
+ {
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(itemId[1]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(itemId[4]);
+ data.WriteByteSeq(itemId[7]);
+ }
+
+ if (usedDestSlot)
+ data << uint32(oldSlot);
+
+ if (usedSrcSlot)
+ data << uint32(newSlot);
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index a1b439387ef..46bd523f9f2 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -331,7 +331,7 @@ void InstanceScript::DoUpdateAchievementCriteria(AchievementCriteriaTypes type,
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->getSource())
- player->UpdateAchievementCriteria(type, miscValue1, miscValue2, unit);
+ player->UpdateAchievementCriteria(type, miscValue1, miscValue2, 0, unit);
}
// Start timed achievement for all players in instance
@@ -411,6 +411,7 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8
case ENCOUNTER_FRAME_ADD_TIMER:
case ENCOUNTER_FRAME_ENABLE_OBJECTIVE:
case ENCOUNTER_FRAME_DISABLE_OBJECTIVE:
+ case ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT:
data << uint8(param1);
break;
case ENCOUNTER_FRAME_UPDATE_OBJECTIVE:
@@ -418,6 +419,8 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8
data << uint8(param2);
break;
case ENCOUNTER_FRAME_UNK7:
+ case ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT:
+ case ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT:
default:
break;
}
@@ -442,7 +445,7 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
if (encounter->lastEncounterDungeon)
{
dungeonId = encounter->lastEncounterDungeon;
- TC_LOG_DEBUG(LOG_FILTER_LFG, "UpdateEncounterState: Instance %s (instanceId %u) completed encounter %s. Credit Dungeon: %u", instance->GetMapName(), instance->GetInstanceId(), encounter->dbcEntry->encounterName[0], dungeonId);
+ TC_LOG_DEBUG(LOG_FILTER_LFG, "UpdateEncounterState: Instance %s (instanceId %u) completed encounter %s. Credit Dungeon: %u", instance->GetMapName(), instance->GetInstanceId(), encounter->dbcEntry->encounterName, dungeonId);
break;
}
}
@@ -463,3 +466,14 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
}
}
}
+
+void InstanceScript::UpdatePhasing()
+{
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddConditionType(CONDITION_INSTANCE_INFO);
+
+ Map::PlayerList const& players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->getSource())
+ player->GetPhaseMgr().NotifyConditionChanged(phaseUdateData);
+}
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 1e349207b2f..2d77f6792c6 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -42,14 +42,17 @@ typedef std::set<Creature*> MinionSet;
enum EncounterFrameType
{
- ENCOUNTER_FRAME_ENGAGE = 0,
- ENCOUNTER_FRAME_DISENGAGE = 1,
- ENCOUNTER_FRAME_UPDATE_PRIORITY = 2,
- ENCOUNTER_FRAME_ADD_TIMER = 3,
- ENCOUNTER_FRAME_ENABLE_OBJECTIVE = 4,
- ENCOUNTER_FRAME_UPDATE_OBJECTIVE = 5,
- ENCOUNTER_FRAME_DISABLE_OBJECTIVE = 6,
- ENCOUNTER_FRAME_UNK7 = 7 // Seems to have something to do with sorting the encounter units
+ ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT = 0,
+ ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT = 1,
+ ENCOUNTER_FRAME_ENGAGE = 2,
+ ENCOUNTER_FRAME_DISENGAGE = 3,
+ ENCOUNTER_FRAME_UPDATE_PRIORITY = 4,
+ ENCOUNTER_FRAME_ADD_TIMER = 5,
+ ENCOUNTER_FRAME_ENABLE_OBJECTIVE = 6,
+ ENCOUNTER_FRAME_UPDATE_OBJECTIVE = 7,
+ ENCOUNTER_FRAME_DISABLE_OBJECTIVE = 8,
+ ENCOUNTER_FRAME_UNK7 = 9, // Seems to have something to do with sorting the encounter units
+ ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT = 10
};
enum EncounterState
@@ -216,6 +219,9 @@ class InstanceScript : public ZoneScript
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
+ // ReCheck PhaseTemplate related conditions
+ void UpdatePhasing();
+
protected:
void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadDoorData(DoorData const* data);
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 5765d64ce60..7da7cd975ee 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -863,17 +863,21 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
{
b << uint32(0); // gold
b << uint8(0); // item count
+ b << uint8(0); // currency count
return b;
}
Loot &l = lv.loot;
uint8 itemsShown = 0;
+ uint8 currenciesShown = 0;
b << uint32(l.gold); //gold
size_t count_pos = b.wpos(); // pos of item count byte
b << uint8(0); // item count placeholder
+ size_t currency_count_pos = b.wpos(); // pos of currency count byte
+ b << uint8(0); // currency count placeholder
switch (lv.permission)
{
@@ -1051,8 +1055,9 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
- //update number of items shown
+ //update number of items and currencies shown
b.put<uint8>(count_pos, itemsShown);
+ b.put<uint8>(currency_count_pos, currenciesShown);
return b;
}
@@ -1534,16 +1539,17 @@ void LoadLootTemplates_Disenchant()
LootIdSet lootIdSet, lootIdSetUsed;
uint32 count = LootTemplates_Disenchant.LoadAndCollectLootIds(lootIdSet);
- ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
- for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
{
- if (uint32 lootid = itr->second.DisenchantID)
- {
- if (lootIdSet.find(lootid) == lootIdSet.end())
- LootTemplates_Disenchant.ReportNotExistedId(lootid);
- else
- lootIdSetUsed.insert(lootid);
- }
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
+
+ uint32 lootid = disenchant->Id;
+ if (lootIdSet.find(lootid) == lootIdSet.end())
+ LootTemplates_Disenchant.ReportNotExistedId(lootid);
+ else
+ lootIdSetUsed.insert(lootid);
}
for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h
index 6357d70e4a7..a53694841ee 100644
--- a/src/server/game/Mails/Mail.h
+++ b/src/server/game/Mails/Mail.h
@@ -126,13 +126,13 @@ class MailDraft
public: // Accessors
uint16 GetMailTemplateId() const { return m_mailTemplateId; }
std::string const& GetSubject() const { return m_subject; }
- uint32 GetMoney() const { return m_money; }
- uint32 GetCOD() const { return m_COD; }
+ uint64 GetMoney() const { return m_money; }
+ uint64 GetCOD() const { return m_COD; }
std::string const& GetBody() const { return m_body; }
public: // modifiers
MailDraft& AddItem(Item* item);
- MailDraft& AddMoney(uint32 money) { m_money = money; return *this; }
+ MailDraft& AddMoney(uint64 money) { m_money = money; return *this; }
MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; }
public: // finishers
@@ -150,8 +150,8 @@ class MailDraft
MailItemMap m_items; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid
- uint32 m_money;
- uint32 m_COD;
+ uint64 m_money;
+ uint64 m_COD;
};
struct MailItemInfo
@@ -167,7 +167,7 @@ struct Mail
uint8 messageType;
uint8 stationery;
uint16 mailTemplateId;
- uint32 sender;
+ uint32 sender; // TODO: change to uint64 and store full guids
uint32 receiver;
std::string subject;
std::string body;
@@ -175,8 +175,8 @@ struct Mail
std::vector<uint32> removedItems;
time_t expire_time;
time_t deliver_time;
- uint32 money;
- uint32 COD;
+ uint64 money;
+ uint64 COD;
uint32 checked;
MailState state;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 493ddc662b4..90e072825de 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1963,7 +1963,7 @@ bool Map::CheckGridIntegrity(Creature* c, bool moved) const
char const* Map::GetMapName() const
{
- return i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
+ return i_mapEntry ? i_mapEntry->name : "UNNAMEDMAP\x0";
}
void Map::UpdateObjectVisibility(WorldObject* obj, Cell cell, CellCoord cellpair)
@@ -1992,7 +1992,7 @@ void Map::SendInitSelf(Player* player)
{
TC_LOG_INFO(LOG_FILTER_MAPS, "Creating player data for himself %u", player->GetGUIDLow());
- UpdateData data;
+ UpdateData data(player->GetMapId());
// attach to player data current transport data
if (Transport* transport = player->GetTransport())
@@ -2029,7 +2029,7 @@ void Map::SendInitTransports(Player* player)
if (tmap.find(player->GetMapId()) == tmap.end())
return;
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
MapManager::TransportSet& tset = tmap[player->GetMapId()];
@@ -2056,7 +2056,7 @@ void Map::SendRemoveTransports(Player* player)
if (tmap.find(player->GetMapId()) == tmap.end())
return;
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
MapManager::TransportSet& tset = tmap[player->GetMapId()];
@@ -2155,6 +2155,9 @@ void Map::RemoveAllObjectsInRemoveList()
case TYPEID_DYNAMICOBJECT:
RemoveFromMap((DynamicObject*)obj, true);
break;
+ case TYPEID_AREATRIGGER:
+ RemoveFromMap((AreaTrigger*)obj, true);
+ break;
case TYPEID_GAMEOBJECT:
RemoveFromMap((GameObject*)obj, true);
break;
@@ -2273,11 +2276,13 @@ template bool Map::AddToMap(Corpse*);
template bool Map::AddToMap(Creature*);
template bool Map::AddToMap(GameObject*);
template bool Map::AddToMap(DynamicObject*);
+template bool Map::AddToMap(AreaTrigger*);
template void Map::RemoveFromMap(Corpse*, bool);
template void Map::RemoveFromMap(Creature*, bool);
template void Map::RemoveFromMap(GameObject*, bool);
template void Map::RemoveFromMap(DynamicObject*, bool);
+template void Map::RemoveFromMap(AreaTrigger*, bool);
/* ******* Dungeon Instance Maps ******* */
@@ -2449,10 +2454,11 @@ bool InstanceMap::AddPlayerToMap(Player* player)
// players also become permanently bound when they enter
if (groupBind->perm)
{
- WorldPacket data(SMSG_INSTANCE_LOCK_WARNING_QUERY, 9);
+ WorldPacket data(SMSG_INSTANCE_LOCK_WARNING_QUERY, 10);
data << uint32(60000);
data << uint32(i_data ? i_data->GetCompletedEncounterMask() : 0);
data << uint8(0);
+ data << uint8(0); // events it throws: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
player->GetSession()->SendPacket(&data);
player->SetPendingBind(mapSave->GetInstanceId(), 60000);
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 3deeb4e04b1..4eaec222b95 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -454,6 +454,7 @@ class Map : public GridRefManager<NGridType>
bool ContainsGameObjectModel(const GameObjectModel& model) const { return _dynamicTree.contains(model);}
bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist);
+ virtual uint32 GetOwnerGuildId(uint32 /*team*/ = TEAM_OTHER) const { return 0; }
/*
RESPAWN TIMES
*/
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index e7b0b997f07..538285edd0f 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -186,7 +186,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
if (player->isGameMaster())
return true;
- char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
+ char const* mapName = entry->name;
Group* group = player->GetGroup();
if (entry->IsRaid())
diff --git a/src/server/game/Maps/PhaseMgr.cpp b/src/server/game/Maps/PhaseMgr.cpp
new file mode 100644
index 00000000000..a7393dfba7f
--- /dev/null
+++ b/src/server/game/Maps/PhaseMgr.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PhaseMgr.h"
+#include "Chat.h"
+#include "Language.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+
+//////////////////////////////////////////////////////////////////
+// Updating
+
+PhaseMgr::PhaseMgr(Player* _player) : player(_player), phaseData(_player), _UpdateFlags(0)
+{
+ _PhaseDefinitionStore = sObjectMgr->GetPhaseDefinitionStore();
+ _SpellPhaseStore = sObjectMgr->GetSpellPhaseStore();
+}
+
+void PhaseMgr::Update()
+{
+ if (IsUpdateInProgress())
+ return;
+
+ if (_UpdateFlags & PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED)
+ phaseData.SendPhaseshiftToPlayer();
+
+ if (_UpdateFlags & PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED)
+ phaseData.SendPhaseMaskToPlayer();
+
+ _UpdateFlags = 0;
+}
+
+void PhaseMgr::RemoveUpdateFlag(PhaseUpdateFlag updateFlag)
+{
+ _UpdateFlags &= ~updateFlag;
+
+ if (updateFlag == PHASE_UPDATE_FLAG_ZONE_UPDATE)
+ {
+ // Update zone changes
+ if (phaseData.HasActiveDefinitions())
+ {
+ phaseData.ResetDefinitions();
+ _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ }
+
+ if (_PhaseDefinitionStore->find(player->GetZoneId()) != _PhaseDefinitionStore->end())
+ Recalculate();
+ }
+
+ Update();
+}
+
+/////////////////////////////////////////////////////////////////
+// Notifier
+
+void PhaseMgr::NotifyConditionChanged(PhaseUpdateData const& updateData)
+{
+ if (NeedsPhaseUpdateWithData(updateData))
+ {
+ Recalculate();
+ Update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+// Phasing Definitions
+
+void PhaseMgr::Recalculate()
+{
+ if (phaseData.HasActiveDefinitions())
+ {
+ phaseData.ResetDefinitions();
+ _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ }
+
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr != _PhaseDefinitionStore->end())
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ if (CheckDefinition(&(*phase)))
+ {
+ phaseData.AddPhaseDefinition(&(*phase));
+
+ if (phase->phasemask)
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ if (phase->phaseId || phase->terrainswapmap)
+ _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ if (phase->IsLastDefinition())
+ break;
+ }
+}
+
+inline bool PhaseMgr::CheckDefinition(PhaseDefinition const* phaseDefinition)
+{
+ ConditionList const* conditions = sConditionMgr->GetConditionsForPhaseDefinition(phaseDefinition->zoneId, phaseDefinition->entry);
+ if (!conditions)
+ return true;
+
+ ConditionSourceInfo srcInfo(player);
+ return sConditionMgr->IsObjectMeetToConditions(srcInfo, *conditions);
+}
+
+bool PhaseMgr::NeedsPhaseUpdateWithData(PhaseUpdateData const& updateData) const
+{
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr != _PhaseDefinitionStore->end())
+ {
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ {
+ ConditionList const* conditionList = sConditionMgr->GetConditionsForPhaseDefinition(phase->zoneId, phase->entry);
+ if (!conditionList)
+ continue;
+
+ for (ConditionList::const_iterator condition = conditionList->begin(); condition != conditionList->end(); ++condition)
+ if (updateData.IsConditionRelated(*condition))
+ return true;
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////
+// Auras
+
+void PhaseMgr::RegisterPhasingAuraEffect(AuraEffect const* auraEffect)
+{
+ PhaseInfo phaseInfo;
+
+ if (auraEffect->GetMiscValue())
+ {
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+ phaseInfo.phasemask = auraEffect->GetMiscValue();
+ }
+ else
+ {
+ SpellPhaseStore::const_iterator itr = _SpellPhaseStore->find(auraEffect->GetId());
+ if (itr != _SpellPhaseStore->end())
+ {
+ if (itr->second.phasemask)
+ {
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+ phaseInfo.phasemask = itr->second.phasemask;
+ }
+
+ if (itr->second.terrainswapmap)
+ phaseInfo.terrainswapmap = itr->second.terrainswapmap;
+ }
+ }
+
+ phaseInfo.phaseId = auraEffect->GetMiscValueB();
+
+ if (phaseInfo.NeedsClientSideUpdate())
+ _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ phaseData.AddAuraInfo(auraEffect->GetId(), phaseInfo);
+
+ Update();
+}
+
+void PhaseMgr::UnRegisterPhasingAuraEffect(AuraEffect const* auraEffect)
+{
+ _UpdateFlags |= phaseData.RemoveAuraInfo(auraEffect->GetId());
+
+ Update();
+}
+
+//////////////////////////////////////////////////////////////////
+// Commands
+
+void PhaseMgr::SendDebugReportToPlayer(Player* const debugger)
+{
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_REPORT_STATUS, player->GetName().c_str(), player->GetZoneId(), player->getLevel(), player->GetTeamId(), _UpdateFlags);
+
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr == _PhaseDefinitionStore->end())
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_NO_DEFINITIONS, player->GetZoneId());
+ else
+ {
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ {
+ if (CheckDefinition(&(*phase)))
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_SUCCESS, phase->entry, phase->IsNegatingPhasemask() ? "negated Phase" : "Phase", phase->phasemask);
+ else
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_FAILED, phase->phasemask, phase->entry, phase->zoneId);
+
+ if (phase->IsLastDefinition())
+ {
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_LAST_PHASE, phase->phasemask, phase->entry, phase->zoneId);
+ break;
+ }
+ }
+ }
+
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_LIST, phaseData._PhasemaskThroughDefinitions, phaseData._PhasemaskThroughAuras, phaseData._CustomPhasemask);
+
+ ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_PHASEMASK, phaseData.GetPhaseMaskForSpawn(), player->GetPhaseMask());
+}
+
+void PhaseMgr::SetCustomPhase(uint32 phaseMask)
+{
+ phaseData._CustomPhasemask = phaseMask;
+
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ Update();
+}
+
+//////////////////////////////////////////////////////////////////
+// Phase Data
+
+uint32 PhaseData::GetCurrentPhasemask() const
+{
+ if (player->isGameMaster())
+ return uint32(PHASEMASK_ANYWHERE);
+
+ if (_CustomPhasemask)
+ return _CustomPhasemask;
+
+ return GetPhaseMaskForSpawn();
+}
+
+inline uint32 PhaseData::GetPhaseMaskForSpawn() const
+{
+ uint32 const phase = (_PhasemaskThroughDefinitions | _PhasemaskThroughAuras);
+ return (phase ? phase : PHASEMASK_NORMAL);
+}
+
+void PhaseData::SendPhaseMaskToPlayer()
+{
+ // Server side update
+ uint32 const phasemask = GetCurrentPhasemask();
+ if (player->GetPhaseMask() == phasemask)
+ return;
+
+ player->SetPhaseMask(phasemask, false);
+
+ if (player->IsVisible())
+ player->UpdateObjectVisibility();
+}
+
+void PhaseData::SendPhaseshiftToPlayer()
+{
+ // Client side update
+ std::set<uint32> phaseIds;
+ std::set<uint32> terrainswaps;
+
+ for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr)
+ {
+ if (itr->second.terrainswapmap)
+ terrainswaps.insert(itr->second.terrainswapmap);
+
+ if (itr->second.phaseId)
+ phaseIds.insert(itr->second.phaseId);
+ }
+
+ // Phase Definitions
+ for (std::list<PhaseDefinition const*>::const_iterator itr = activePhaseDefinitions.begin(); itr != activePhaseDefinitions.end(); ++itr)
+ {
+ if ((*itr)->phaseId)
+ phaseIds.insert((*itr)->phaseId);
+
+ if ((*itr)->terrainswapmap)
+ terrainswaps.insert((*itr)->terrainswapmap);
+ }
+
+ player->GetSession()->SendSetPhaseShift(phaseIds, terrainswaps);
+}
+
+void PhaseData::AddPhaseDefinition(PhaseDefinition const* phaseDefinition)
+{
+ if (phaseDefinition->IsOverwritingExistingPhases())
+ {
+ activePhaseDefinitions.clear();
+ _PhasemaskThroughDefinitions = phaseDefinition->phasemask;
+ }
+ else
+ {
+ if (phaseDefinition->IsNegatingPhasemask())
+ _PhasemaskThroughDefinitions &= ~phaseDefinition->phasemask;
+ else
+ _PhasemaskThroughDefinitions |= phaseDefinition->phasemask;
+ }
+
+ activePhaseDefinitions.push_back(phaseDefinition);
+}
+
+void PhaseData::AddAuraInfo(uint32 spellId, PhaseInfo const& phaseInfo)
+{
+ if (phaseInfo.phasemask)
+ _PhasemaskThroughAuras |= phaseInfo.phasemask;
+
+ spellPhaseInfo[spellId] = phaseInfo;
+}
+
+uint32 PhaseData::RemoveAuraInfo(uint32 spellId)
+{
+ PhaseInfoContainer::const_iterator rAura = spellPhaseInfo.find(spellId);
+ if (rAura != spellPhaseInfo.end())
+ {
+ uint32 updateflag = 0;
+
+ if (rAura->second.NeedsClientSideUpdate())
+ updateflag |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ if (rAura->second.NeedsServerSideUpdate())
+ {
+ _PhasemaskThroughAuras = 0;
+
+ updateflag |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ spellPhaseInfo.erase(rAura);
+
+ for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr)
+ _PhasemaskThroughAuras |= itr->second.phasemask;
+ }
+
+ return updateflag;
+ }
+
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////
+// Phase Update Data
+
+void PhaseUpdateData::AddQuestUpdate(uint32 questId)
+{
+ AddConditionType(CONDITION_QUESTREWARDED);
+ AddConditionType(CONDITION_QUESTTAKEN);
+ AddConditionType(CONDITION_QUEST_COMPLETE);
+ AddConditionType(CONDITION_QUEST_NONE);
+
+ _questId = questId;
+}
+
+bool PhaseUpdateData::IsConditionRelated(Condition const* condition) const
+{
+ switch (condition->ConditionType)
+ {
+ case CONDITION_QUESTREWARDED:
+ case CONDITION_QUESTTAKEN:
+ case CONDITION_QUEST_COMPLETE:
+ case CONDITION_QUEST_NONE:
+ return condition->ConditionValue1 == _questId && ((1 << condition->ConditionType) & _conditionTypeFlags);
+ default:
+ return (1 << condition->ConditionType) & _conditionTypeFlags;
+ }
+}
+
+bool PhaseMgr::IsConditionTypeSupported(ConditionTypes conditionType)
+{
+ switch (conditionType)
+ {
+ case CONDITION_QUESTREWARDED:
+ case CONDITION_QUESTTAKEN:
+ case CONDITION_QUEST_COMPLETE:
+ case CONDITION_QUEST_NONE:
+ case CONDITION_TEAM:
+ case CONDITION_CLASS:
+ case CONDITION_RACE:
+ case CONDITION_INSTANCE_INFO:
+ case CONDITION_LEVEL:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/server/game/Maps/PhaseMgr.h b/src/server/game/Maps/PhaseMgr.h
new file mode 100644
index 00000000000..21f67038c3f
--- /dev/null
+++ b/src/server/game/Maps/PhaseMgr.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_PHASEMGR_H
+#define TRINITY_PHASEMGR_H
+
+#include "SharedDefines.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+#include "ConditionMgr.h"
+
+class ObjectMgr;
+class Player;
+
+// Phasing (visibility)
+enum PhasingFlags
+{
+ PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases
+ PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied)
+ PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask
+};
+
+enum PhaseUpdateFlag
+{
+ PHASE_UPDATE_FLAG_ZONE_UPDATE = 0x01,
+ PHASE_UPDATE_FLAG_AREA_UPDATE = 0x02,
+
+ // Internal flags
+ PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED = 0x08,
+ PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED = 0x10,
+};
+
+struct PhaseDefinition
+{
+ uint32 zoneId;
+ uint32 entry;
+ uint32 phasemask;
+ uint32 phaseId;
+ uint32 terrainswapmap;
+ uint8 flags;
+
+ bool IsOverwritingExistingPhases() const { return flags & PHASE_FLAG_OVERWRITE_EXISTING; }
+ bool IsLastDefinition() const { return flags & PHASE_FLAG_NO_MORE_PHASES; }
+ bool IsNegatingPhasemask() const { return flags & PHASE_FLAG_NEGATE_PHASE; }
+};
+
+typedef std::list<PhaseDefinition> PhaseDefinitionContainer;
+typedef UNORDERED_MAP<uint32 /*zoneId*/, PhaseDefinitionContainer> PhaseDefinitionStore;
+
+struct SpellPhaseInfo
+{
+ uint32 spellId;
+ uint32 phasemask;
+ uint32 terrainswapmap;
+};
+
+typedef UNORDERED_MAP<uint32 /*spellId*/, SpellPhaseInfo> SpellPhaseStore;
+
+struct PhaseInfo
+{
+ PhaseInfo() : phasemask(0), terrainswapmap(0), phaseId(0) {}
+
+ uint32 phasemask;
+ uint32 terrainswapmap;
+ uint32 phaseId;
+
+ bool NeedsServerSideUpdate() const { return phasemask; }
+ bool NeedsClientSideUpdate() const { return terrainswapmap || phaseId; }
+};
+
+typedef UNORDERED_MAP<uint32 /*spellId*/, PhaseInfo> PhaseInfoContainer;
+
+struct PhaseData
+{
+ PhaseData(Player* _player) : _PhasemaskThroughDefinitions(0), _PhasemaskThroughAuras(0), _CustomPhasemask(0), player(_player) {}
+
+ uint32 _PhasemaskThroughDefinitions;
+ uint32 _PhasemaskThroughAuras;
+ uint32 _CustomPhasemask;
+
+ uint32 GetCurrentPhasemask() const;
+ inline uint32 GetPhaseMaskForSpawn() const;
+
+ void ResetDefinitions() { _PhasemaskThroughDefinitions = 0; activePhaseDefinitions.clear(); }
+ void AddPhaseDefinition(PhaseDefinition const* phaseDefinition);
+ bool HasActiveDefinitions() const { return !activePhaseDefinitions.empty(); }
+
+ void AddAuraInfo(uint32 spellId, PhaseInfo const& phaseInfo);
+ uint32 RemoveAuraInfo(uint32 spellId);
+
+ void SendPhaseMaskToPlayer();
+ void SendPhaseshiftToPlayer();
+
+private:
+ Player* player;
+ std::list<PhaseDefinition const*> activePhaseDefinitions;
+ PhaseInfoContainer spellPhaseInfo;
+};
+
+struct PhaseUpdateData
+{
+ PhaseUpdateData(): _conditionTypeFlags(0), _questId(0) { }
+ void AddConditionType(ConditionTypes const conditionType) { _conditionTypeFlags |= (1 << conditionType); }
+ void AddQuestUpdate(uint32 const questId);
+
+ bool IsConditionRelated(Condition const* condition) const;
+
+private:
+ uint32 _conditionTypeFlags;
+ uint32 _questId;
+};
+
+class PhaseMgr
+{
+public:
+ PhaseMgr(Player* _player);
+ ~PhaseMgr() {}
+
+ uint32 GetCurrentPhasemask() { return phaseData.GetCurrentPhasemask(); };
+ inline uint32 GetPhaseMaskForSpawn() { return phaseData.GetCurrentPhasemask(); }
+
+ // Phase definitions update handling
+ void NotifyConditionChanged(PhaseUpdateData const& updateData);
+ void NotifyStoresReloaded() { Recalculate(); Update(); }
+
+ void Update();
+
+ // Aura phase effects
+ void RegisterPhasingAuraEffect(AuraEffect const* auraEffect);
+ void UnRegisterPhasingAuraEffect(AuraEffect const* auraEffect);
+
+ // Update flags (delayed phasing)
+ void AddUpdateFlag(PhaseUpdateFlag updateFlag) { _UpdateFlags |= updateFlag; }
+ void RemoveUpdateFlag(PhaseUpdateFlag updateFlag);
+
+ // Needed for modify phase command
+ void SetCustomPhase(uint32 phaseMask);
+
+ // Debug
+ void SendDebugReportToPlayer(Player* const debugger);
+
+ static bool IsConditionTypeSupported(ConditionTypes conditionType);
+
+private:
+ void Recalculate();
+
+ inline bool CheckDefinition(PhaseDefinition const* phaseDefinition);
+
+ bool NeedsPhaseUpdateWithData(PhaseUpdateData const& updateData) const;
+
+ inline bool IsUpdateInProgress() const { return (_UpdateFlags & PHASE_UPDATE_FLAG_ZONE_UPDATE) || (_UpdateFlags & PHASE_UPDATE_FLAG_AREA_UPDATE); }
+
+ PhaseDefinitionStore const* _PhaseDefinitionStore;
+ SpellPhaseStore const* _SpellPhaseStore;
+
+ Player* player;
+ PhaseData phaseData;
+ uint8 _UpdateFlags;
+};
+
+#endif
diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h
index e3e85d45603..39a478f158e 100644
--- a/src/server/game/Miscellaneous/Formulas.h
+++ b/src/server/game/Miscellaneous/Formulas.h
@@ -128,6 +128,9 @@ namespace Trinity
case CONTENT_71_80:
nBaseExp = 580;
break;
+ case CONTENT_81_85:
+ nBaseExp = 1878;
+ break;
default:
TC_LOG_ERROR(LOG_FILTER_GENERAL, "BaseGain: Unsupported content level %u", content);
nBaseExp = 45;
@@ -221,6 +224,26 @@ namespace Trinity
return rate;
}
} // namespace Trinity::XP
+
+ namespace Currency
+ {
+ inline uint32 ConquestRatingCalculator(uint32 rate)
+ {
+ if (rate <= 1500)
+ return 1350; // Default conquest points
+ else if (rate > 3000)
+ rate = 3000;
+
+ // http://www.arenajunkies.com/topic/179536-conquest-point-cap-vs-personal-rating-chart/page__st__60#entry3085246
+ return uint32(1.4326 * ((1511.26 / (1 + 1639.28 / exp(0.00412 * rate))) + 850.15));
+ }
+
+ inline uint32 BgConquestRatingCalculator(uint32 rate)
+ {
+ // WowWiki: Battleground ratings receive a bonus of 22.2% to the cap they generate
+ return uint32((ConquestRatingCalculator(rate) * 1.222f) + 0.5f);
+ }
+ } // namespace Trinity::Currency
} // namespace Trinity
#endif
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 0da63a61b43..0c056d225c7 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -211,7 +211,15 @@ enum TrinityStrings
LANG_LIQUID_STATUS = 175,
LANG_INVALID_GAMEOBJECT_TYPE = 176,
LANG_GAMEOBJECT_DAMAGED = 177,
- // Room for more level 1 178-199 not used
+
+ LANG_PHASING_SUCCESS = 178,
+ LANG_PHASING_FAILED = 179,
+ LANG_PHASING_LAST_PHASE = 180,
+ LANG_PHASING_LIST = 181,
+ LANG_PHASING_PHASEMASK = 182,
+ LANG_PHASING_REPORT_STATUS = 183,
+ LANG_PHASING_NO_DEFINITIONS = 184, // Phasing
+ // Room for more level 1 185-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
@@ -734,12 +742,12 @@ enum TrinityStrings
LANG_DEBUG_ARENA_OFF = 738,
LANG_DEBUG_BG_ON = 739,
LANG_DEBUG_BG_OFF = 740,
- LANG_DIST_ARENA_POINTS_START = 741,
- LANG_DIST_ARENA_POINTS_ONLINE_START = 742,
- LANG_DIST_ARENA_POINTS_ONLINE_END = 743,
- LANG_DIST_ARENA_POINTS_TEAM_START = 744,
- LANG_DIST_ARENA_POINTS_TEAM_END = 745,
- LANG_DIST_ARENA_POINTS_END = 746,
+// LANG_DIST_ARENA_POINTS_START = 741,
+// LANG_DIST_ARENA_POINTS_ONLINE_START = 742,
+// LANG_DIST_ARENA_POINTS_ONLINE_END = 743,
+// LANG_DIST_ARENA_POINTS_TEAM_START = 744,
+// LANG_DIST_ARENA_POINTS_TEAM_END = 745,
+// LANG_DIST_ARENA_POINTS_END = 746,
LANG_BG_DISABLED = 747,
LANG_ARENA_DISABLED = 748,
// = 749, see LANG_PINFO_ACC_OS
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index caf504944c6..57faa5f3ebc 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -23,6 +23,8 @@
#include "Define.h"
#include <cassert>
+#define MAX_CREATURE_BASE_HP 4
+
enum SpellEffIndex
{
EFFECT_0 = 0,
@@ -63,9 +65,9 @@ enum Races
RACE_TAUREN = 6,
RACE_GNOME = 7,
RACE_TROLL = 8,
- //RACE_GOBLIN = 9,
+ RACE_GOBLIN = 9,
RACE_BLOODELF = 10,
- RACE_DRAENEI = 11
+ RACE_DRAENEI = 11,
//RACE_FEL_ORC = 12,
//RACE_NAGA = 13,
//RACE_BROKEN = 14,
@@ -75,21 +77,23 @@ enum Races
//RACE_FOREST_TROLL = 18,
//RACE_TAUNKA = 19,
//RACE_NORTHREND_SKELETON = 20,
- //RACE_ICE_TROLL = 21
+ //RACE_ICE_TROLL = 21,
+ RACE_WORGEN = 22,
+ //RACE_GILNEAN = 23
};
// max+1 for player race
-#define MAX_RACES 12
+#define MAX_RACES 23
#define RACEMASK_ALL_PLAYABLE \
((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \
(1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \
(1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \
- (1<<(RACE_DRAENEI-1)))
+ (1<<(RACE_DRAENEI-1)) |(1<<(RACE_GOBLIN-1)) |(1<<(RACE_WORGEN-1)))
#define RACEMASK_ALLIANCE \
((1<<(RACE_HUMAN-1)) | (1<<(RACE_DWARF-1)) | (1<<(RACE_NIGHTELF-1)) | \
- (1<<(RACE_GNOME-1)) | (1<<(RACE_DRAENEI-1)))
+ (1<<(RACE_GNOME-1)) | (1<<(RACE_DRAENEI-1)) | (1<<(RACE_WORGEN-1)))
#define RACEMASK_HORDE RACEMASK_ALL_PLAYABLE & ~RACEMASK_ALLIANCE
@@ -149,7 +153,7 @@ enum ReputationRank
#define MIN_REPUTATION_RANK (REP_HATED)
#define MAX_REPUTATION_RANK 8
-#define MAX_SPILLOVER_FACTIONS 4
+#define MAX_SPILLOVER_FACTIONS 5
enum MoneyConstants
{
@@ -175,14 +179,20 @@ enum Powers
POWER_RAGE = 1,
POWER_FOCUS = 2,
POWER_ENERGY = 3,
- POWER_HAPPINESS = 4,
- POWER_RUNE = 5,
+ POWER_UNUSED = 4,
+ POWER_RUNES = 5,
POWER_RUNIC_POWER = 6,
- MAX_POWERS = 7,
- POWER_ALL = 127, // default for class?
+ POWER_SOUL_SHARDS = 7,
+ POWER_ECLIPSE = 8,
+ POWER_HOLY_POWER = 9,
+ POWER_ALTERNATE_POWER = 10, // Used in some quests
+ MAX_POWERS = 11,
+ POWER_ALL = 127, // default for class?
POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value)
};
+#define MAX_POWERS_PER_CLASS 5
+
enum SpellSchools
{
SPELL_SCHOOL_NORMAL = 0,
@@ -427,7 +437,7 @@ enum SpellAttr4
SPELL_ATTR4_UNK13 = 0x00002000, // 13
SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS = 0x00004000, // 14 doesn't break auras by damage from these spells
SPELL_ATTR4_UNK15 = 0x00008000, // 15
- SPELL_ATTR4_NOT_USABLE_IN_ARENA = 0x00010000, // 16
+ SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG = 0x00010000, // 16 Cannot be used in both Arenas or Rated Battlegrounds
SPELL_ATTR4_USABLE_IN_ARENA = 0x00020000, // 17
SPELL_ATTR4_AREA_TARGET_CHAIN = 0x00040000, // 18 (NYI)hits area targets one after another instead of all at once
SPELL_ATTR4_UNK19 = 0x00080000, // 19 proc dalayed, after damage or don't proc on absorb?
@@ -524,7 +534,7 @@ enum SpellAttr7
SPELL_ATTR7_REACTIVATE_AT_RESURRECT = 0x00000004, // 2 Paladin's auras and 65607 only.
SPELL_ATTR7_IS_CHEAT_SPELL = 0x00000008, // 3 Cannot cast if caster doesn't have UnitFlag2 & UNIT_FLAG2_ALLOW_CHEAT_SPELLS
SPELL_ATTR7_UNK4 = 0x00000010, // 4 Only 47883 (Soulstone Resurrection) and test spell.
- SPELL_ATTR7_SUMMON_PLAYER_TOTEM = 0x00000020, // 5 Only Shaman player totems.
+ SPELL_ATTR7_SUMMON_TOTEM = 0x00000020, // 5 Only Shaman totems.
SPELL_ATTR7_UNK6 = 0x00000040, // 6 Dark Surge, Surge of Light, Burning Breath triggers (boss spells).
SPELL_ATTR7_UNK7 = 0x00000080, // 7 66218 (Launch) spell.
SPELL_ATTR7_HORDE_ONLY = 0x00000100, // 8 Teleports, mounts and other spells.
@@ -553,11 +563,120 @@ enum SpellAttr7
SPELL_ATTR7_CLIENT_INDICATOR = 0x80000000
};
+enum SpellAttr8
+{
+ SPELL_ATTR8_CANT_MISS = 0x00000001, // 0
+ SPELL_ATTR8_UNK1 = 0x00000002, // 1
+ SPELL_ATTR8_UNK2 = 0x00000004, // 2
+ SPELL_ATTR8_UNK3 = 0x00000008, // 3
+ SPELL_ATTR8_UNK4 = 0x00000010, // 4
+ SPELL_ATTR8_UNK5 = 0x00000020, // 5
+ SPELL_ATTR8_UNK6 = 0x00000040, // 6
+ SPELL_ATTR8_UNK7 = 0x00000080, // 7
+ SPELL_ATTR8_AFFECT_PARTY_AND_RAID = 0x00000100, // 8 Nearly all spells have "all party and raid" in description
+ SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER = 0x00000200, // 9 Periodic auras with this flag keep old periodic timer when refreshing at close to one tick remaining (kind of anti DoT clipping)
+ SPELL_ATTR8_NAME_CHANGED_DURING_TRANSFORM = 0x00000400, // 10 according to wowhead comments, name changes, title remains
+ SPELL_ATTR8_UNK11 = 0x00000800, // 11
+ SPELL_ATTR8_AURA_SEND_AMOUNT = 0x00001000, // 12 Aura must have flag AFLAG_ANY_EFFECT_AMOUNT_SENT to send amount
+ SPELL_ATTR8_UNK13 = 0x00002000, // 13
+ SPELL_ATTR8_UNK14 = 0x00004000, // 14
+ SPELL_ATTR8_WATER_MOUNT = 0x00008000, // 15 only one River Boat used in Thousand Needles
+ SPELL_ATTR8_UNK16 = 0x00010000, // 16
+ SPELL_ATTR8_UNK17 = 0x00020000, // 17
+ SPELL_ATTR8_REMEMBER_SPELLS = 0x00040000, // 18 at some point in time, these auras remember spells and allow to cast them later
+ SPELL_ATTR8_USE_COMBO_POINTS_ON_ANY_TARGET = 0x00080000, // 19 allows to consume combo points from dead targets
+ SPELL_ATTR8_ARMOR_SPECIALIZATION = 0x00100000, // 20
+ SPELL_ATTR8_UNK21 = 0x00200000, // 21
+ SPELL_ATTR8_UNK22 = 0x00400000, // 22
+ SPELL_ATTR8_UNK23 = 0x00800000, // 23
+ SPELL_ATTR8_HEALING_SPELL = 0x01000000, // 24
+ SPELL_ATTR8_UNK25 = 0x02000000, // 25
+ SPELL_ATTR8_RAID_MARKER = 0x04000000, // 26 probably spell no need learn to cast
+ SPELL_ATTR8_UNK27 = 0x08000000, // 27
+ SPELL_ATTR8_NOT_IN_BG_OR_ARENA = 0x10000000, // 28 not allow to cast or deactivate currently active effect, not sure about Fast Track
+ SPELL_ATTR8_MASTERY_SPECIALIZATION = 0x20000000, // 29
+ SPELL_ATTR8_UNK30 = 0x40000000, // 30
+ SPELL_ATTR8_ATTACK_IGNORE_IMMUNE_TO_PC_FLAG = 0x80000000 // 31 Do not check UNIT_FLAG_IMMUNE_TO_PC in IsValidAttackTarget
+};
+
+enum SpellAttr9
+{
+ SPELL_ATTR9_UNK0 = 0x00000001, // 0
+ SPELL_ATTR9_UNK1 = 0x00000002, // 1
+ SPELL_ATTR9_RESTRICTED_FLIGHT_AREA = 0x00000004, // 2 Dalaran and Wintergrasp flight area auras have it
+ SPELL_ATTR9_UNK3 = 0x00000008, // 3
+ SPELL_ATTR9_SPECIAL_DELAY_CALCULATION = 0x00000010, // 4
+ SPELL_ATTR9_SUMMON_PLAYER_TOTEM = 0x00000020, // 5
+ SPELL_ATTR9_UNK6 = 0x00000040, // 6
+ SPELL_ATTR9_UNK7 = 0x00000080, // 7
+ SPELL_ATTR9_AIMED_SHOT = 0x00000100, // 8
+ SPELL_ATTR9_NOT_USABLE_IN_ARENA = 0x00000200, // 9 Cannot be used in arenas
+ SPELL_ATTR9_UNK10 = 0x00000400, // 10
+ SPELL_ATTR9_UNK11 = 0x00000800, // 11
+ SPELL_ATTR9_UNK12 = 0x00001000, // 12
+ SPELL_ATTR9_SLAM = 0x00002000, // 13
+ SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS = 0x00004000, // 14 Can be used in Rated Battlegrounds
+ SPELL_ATTR9_UNK15 = 0x00008000, // 15
+ SPELL_ATTR9_UNK16 = 0x00010000, // 16
+ SPELL_ATTR9_UNK17 = 0x00020000, // 17
+ SPELL_ATTR9_UNK18 = 0x00040000, // 18
+ SPELL_ATTR9_UNK19 = 0x00080000, // 19
+ SPELL_ATTR9_UNK20 = 0x00100000, // 20
+ SPELL_ATTR9_UNK21 = 0x00200000, // 21
+ SPELL_ATTR9_UNK22 = 0x00400000, // 22
+ SPELL_ATTR9_UNK23 = 0x00800000, // 23
+ SPELL_ATTR9_UNK24 = 0x01000000, // 24
+ SPELL_ATTR9_UNK25 = 0x02000000, // 25
+ SPELL_ATTR9_UNK26 = 0x04000000, // 26
+ SPELL_ATTR9_UNK27 = 0x08000000, // 27
+ SPELL_ATTR9_UNK28 = 0x10000000, // 28
+ SPELL_ATTR9_UNK29 = 0x20000000, // 29
+ SPELL_ATTR9_UNK30 = 0x40000000, // 30
+ SPELL_ATTR9_UNK31 = 0x80000000 // 31
+};
+
+enum SpellAttr10
+{
+ SPELL_ATTR10_UNK0 = 0x00000001, // 0
+ SPELL_ATTR10_UNK1 = 0x00000002, // 1
+ SPELL_ATTR10_UNK2 = 0x00000004, // 2
+ SPELL_ATTR10_UNK3 = 0x00000008, // 3
+ SPELL_ATTR10_WATER_SPOUT = 0x00000010, // 4
+ SPELL_ATTR10_UNK5 = 0x00000020, // 5
+ SPELL_ATTR10_UNK6 = 0x00000040, // 6
+ SPELL_ATTR10_TELEPORT_PLAYER = 0x00000080, // 7 4 Teleport Player spells
+ SPELL_ATTR10_UNK8 = 0x00000100, // 8
+ SPELL_ATTR10_UNK9 = 0x00000200, // 9
+ SPELL_ATTR10_UNK10 = 0x00000400, // 10
+ SPELL_ATTR10_HERB_GATHERING_MINING = 0x00000800, // 11 Only Herb Gathering and Mining
+ SPELL_ATTR10_UNK12 = 0x00001000, // 12
+ SPELL_ATTR10_UNK13 = 0x00002000, // 13
+ SPELL_ATTR10_UNK14 = 0x00004000, // 14
+ SPELL_ATTR10_UNK15 = 0x00008000, // 15
+ SPELL_ATTR10_UNK16 = 0x00010000, // 16
+ SPELL_ATTR10_UNK17 = 0x00020000, // 17
+ SPELL_ATTR10_UNK18 = 0x00040000, // 18
+ SPELL_ATTR10_UNK19 = 0x00080000, // 19
+ SPELL_ATTR10_UNK20 = 0x00100000, // 20
+ SPELL_ATTR10_UNK21 = 0x00200000, // 21
+ SPELL_ATTR10_UNK22 = 0x00400000, // 22
+ SPELL_ATTR10_UNK23 = 0x00800000, // 23
+ SPELL_ATTR10_UNK24 = 0x01000000, // 24
+ SPELL_ATTR10_UNK25 = 0x02000000, // 25
+ SPELL_ATTR10_UNK26 = 0x04000000, // 26
+ SPELL_ATTR10_UNK27 = 0x08000000, // 27
+ SPELL_ATTR10_UNK28 = 0x10000000, // 28
+ SPELL_ATTR10_UNK29 = 0x20000000, // 29
+ SPELL_ATTR10_UNK30 = 0x40000000, // 30
+ SPELL_ATTR10_UNK31 = 0x80000000 // 31
+};
+
#define MIN_TALENT_SPEC 0
#define MAX_TALENT_SPEC 1
#define MIN_TALENT_SPECS 1
#define MAX_TALENT_SPECS 2
-#define MAX_GLYPH_SLOT_INDEX 6
+#define MAX_GLYPH_SLOT_INDEX 9
+#define REQ_PRIMARY_TREE_TALENTS 31
// Custom values
enum SpellClickUserTypes
@@ -634,10 +753,12 @@ enum Language
LANG_ZOMBIE = 36,
LANG_GNOMISH_BINARY = 37,
LANG_GOBLIN_BINARY = 38,
+ LANG_WORGEN = 39,
+ LANG_GOBLIN = 40,
LANG_ADDON = 0xFFFFFFFF // used by addons, in 2.4.0 not exist, replaced by messagetype?
};
-#define LANGUAGES_COUNT 19
+#define LANGUAGES_COUNT 21
enum TeamId
{
@@ -663,7 +784,7 @@ enum SpellEffects
SPELL_EFFECT_INSTAKILL = 1,
SPELL_EFFECT_SCHOOL_DAMAGE = 2,
SPELL_EFFECT_DUMMY = 3,
- SPELL_EFFECT_PORTAL_TELEPORT = 4,
+ SPELL_EFFECT_PORTAL_TELEPORT = 4, // Unused (4.3.4)
SPELL_EFFECT_TELEPORT_UNITS = 5,
SPELL_EFFECT_APPLY_AURA = 6,
SPELL_EFFECT_ENVIRONMENTAL_DAMAGE = 7,
@@ -672,9 +793,9 @@ enum SpellEffects
SPELL_EFFECT_HEAL = 10,
SPELL_EFFECT_BIND = 11,
SPELL_EFFECT_PORTAL = 12,
- SPELL_EFFECT_RITUAL_BASE = 13,
- SPELL_EFFECT_RITUAL_SPECIALIZE = 14,
- SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15,
+ SPELL_EFFECT_RITUAL_BASE = 13, // Unused (4.3.4)
+ SPELL_EFFECT_RITUAL_SPECIALIZE = 14, // Unused (4.3.4)
+ SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, // Unused (4.3.4)
SPELL_EFFECT_QUEST_COMPLETE = 16,
SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17,
SPELL_EFFECT_RESURRECT = 18,
@@ -704,14 +825,14 @@ enum SpellEffects
SPELL_EFFECT_JUMP_DEST = 42,
SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43,
SPELL_EFFECT_SKILL_STEP = 44,
- SPELL_EFFECT_ADD_HONOR = 45,
+ SPELL_EFFECT_PLAY_MOVIE = 45,
SPELL_EFFECT_SPAWN = 46,
SPELL_EFFECT_TRADE_SKILL = 47,
SPELL_EFFECT_STEALTH = 48,
SPELL_EFFECT_DETECT = 49,
SPELL_EFFECT_TRANS_DOOR = 50,
- SPELL_EFFECT_FORCE_CRITICAL_HIT = 51,
- SPELL_EFFECT_GUARANTEE_HIT = 52,
+ SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, // Unused (4.3.4)
+ SPELL_EFFECT_GUARANTEE_HIT = 52, // Unused (4.3.4)
SPELL_EFFECT_ENCHANT_ITEM = 53,
SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54,
SPELL_EFFECT_TAMECREATURE = 55,
@@ -781,7 +902,7 @@ enum SpellEffects
SPELL_EFFECT_APPLY_AREA_AURA_PET = 119,
SPELL_EFFECT_TELEPORT_GRAVEYARD = 120,
SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121,
- SPELL_EFFECT_122 = 122,
+ SPELL_EFFECT_122 = 122, // Unused (4.3.4)
SPELL_EFFECT_SEND_TAXI = 123,
SPELL_EFFECT_PULL_TOWARDS = 124,
SPELL_EFFECT_MODIFY_THREAT_PERCENT = 125,
@@ -822,203 +943,236 @@ enum SpellEffects
SPELL_EFFECT_160 = 160,
SPELL_EFFECT_TALENT_SPEC_COUNT = 161,
SPELL_EFFECT_TALENT_SPEC_SELECT = 162,
- SPELL_EFFECT_163 = 163,
+ SPELL_EFFECT_163 = 163, // Unused (4.3.4)
SPELL_EFFECT_REMOVE_AURA = 164,
- TOTAL_SPELL_EFFECTS = 165
+ SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT = 165,
+ SPELL_EFFECT_GIVE_CURRENCY = 166,
+ SPELL_EFFECT_167 = 167,
+ SPELL_EFFECT_168 = 168,
+ SPELL_EFFECT_DESTROY_ITEM = 169,
+ SPELL_EFFECT_170 = 170,
+ SPELL_EFFECT_171 = 171, // Summons gamebject
+ SPELL_EFFECT_RESURRECT_WITH_AURA = 172,
+ SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB = 173, // Guild tab unlocked (guild perk)
+ SPELL_EFFECT_174 = 174,
+ SPELL_EFFECT_175 = 175, // Unused (4.3.4)
+ SPELL_EFFECT_176 = 176, // Some kind of sanctuary effect (Vanish)
+ SPELL_EFFECT_177 = 177,
+ SPELL_EFFECT_178 = 178, // Unused (4.3.4)
+ SPELL_EFFECT_CREATE_AREATRIGGER = 179,
+ SPELL_EFFECT_180 = 180, // Unused (4.3.4)
+ SPELL_EFFECT_181 = 181, // Unused (4.3.4)
+ SPELL_EFFECT_182 = 182,
+ TOTAL_SPELL_EFFECTS = 183,
};
enum SpellCastResult
{
- SPELL_FAILED_SUCCESS = 0,
- SPELL_FAILED_AFFECTING_COMBAT = 1,
- SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2,
- SPELL_FAILED_ALREADY_AT_FULL_MANA = 3,
- SPELL_FAILED_ALREADY_AT_FULL_POWER = 4,
- SPELL_FAILED_ALREADY_BEING_TAMED = 5,
- SPELL_FAILED_ALREADY_HAVE_CHARM = 6,
- SPELL_FAILED_ALREADY_HAVE_SUMMON = 7,
- SPELL_FAILED_ALREADY_OPEN = 8,
- SPELL_FAILED_AURA_BOUNCED = 9,
- SPELL_FAILED_AUTOTRACK_INTERRUPTED = 10,
- SPELL_FAILED_BAD_IMPLICIT_TARGETS = 11,
- SPELL_FAILED_BAD_TARGETS = 12,
- SPELL_FAILED_CANT_BE_CHARMED = 13,
- SPELL_FAILED_CANT_BE_DISENCHANTED = 14,
- SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 15,
- SPELL_FAILED_CANT_BE_MILLED = 16,
- SPELL_FAILED_CANT_BE_PROSPECTED = 17,
- SPELL_FAILED_CANT_CAST_ON_TAPPED = 18,
- SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 19,
- SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 20,
- SPELL_FAILED_CANT_STEALTH = 21,
- SPELL_FAILED_CASTER_AURASTATE = 22,
- SPELL_FAILED_CASTER_DEAD = 23,
- SPELL_FAILED_CHARMED = 24,
- SPELL_FAILED_CHEST_IN_USE = 25,
- SPELL_FAILED_CONFUSED = 26,
- SPELL_FAILED_DONT_REPORT = 27,
- SPELL_FAILED_EQUIPPED_ITEM = 28,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS = 29,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 30,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 31,
- SPELL_FAILED_ERROR = 32,
- SPELL_FAILED_FIZZLE = 33,
- SPELL_FAILED_FLEEING = 34,
- SPELL_FAILED_FOOD_LOWLEVEL = 35,
- SPELL_FAILED_HIGHLEVEL = 36,
- SPELL_FAILED_HUNGER_SATIATED = 37,
- SPELL_FAILED_IMMUNE = 38,
- SPELL_FAILED_INCORRECT_AREA = 39,
- SPELL_FAILED_INTERRUPTED = 40,
- SPELL_FAILED_INTERRUPTED_COMBAT = 41,
- SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 42,
- SPELL_FAILED_ITEM_GONE = 43,
- SPELL_FAILED_ITEM_NOT_FOUND = 44,
- SPELL_FAILED_ITEM_NOT_READY = 45,
- SPELL_FAILED_LEVEL_REQUIREMENT = 46,
- SPELL_FAILED_LINE_OF_SIGHT = 47,
- SPELL_FAILED_LOWLEVEL = 48,
- SPELL_FAILED_LOW_CASTLEVEL = 49,
- SPELL_FAILED_MAINHAND_EMPTY = 50,
- SPELL_FAILED_MOVING = 51,
- SPELL_FAILED_NEED_AMMO = 52,
- SPELL_FAILED_NEED_AMMO_POUCH = 53,
- SPELL_FAILED_NEED_EXOTIC_AMMO = 54,
- SPELL_FAILED_NEED_MORE_ITEMS = 55,
- SPELL_FAILED_NOPATH = 56,
- SPELL_FAILED_NOT_BEHIND = 57,
- SPELL_FAILED_NOT_FISHABLE = 58,
- SPELL_FAILED_NOT_FLYING = 59,
- SPELL_FAILED_NOT_HERE = 60,
- SPELL_FAILED_NOT_INFRONT = 61,
- SPELL_FAILED_NOT_IN_CONTROL = 62,
- SPELL_FAILED_NOT_KNOWN = 63,
- SPELL_FAILED_NOT_MOUNTED = 64,
- SPELL_FAILED_NOT_ON_TAXI = 65,
- SPELL_FAILED_NOT_ON_TRANSPORT = 66,
- SPELL_FAILED_NOT_READY = 67,
- SPELL_FAILED_NOT_SHAPESHIFT = 68,
- SPELL_FAILED_NOT_STANDING = 69,
- SPELL_FAILED_NOT_TRADEABLE = 70,
- SPELL_FAILED_NOT_TRADING = 71,
- SPELL_FAILED_NOT_UNSHEATHED = 72,
- SPELL_FAILED_NOT_WHILE_GHOST = 73,
- SPELL_FAILED_NOT_WHILE_LOOTING = 74,
- SPELL_FAILED_NO_AMMO = 75,
- SPELL_FAILED_NO_CHARGES_REMAIN = 76,
- SPELL_FAILED_NO_CHAMPION = 77,
- SPELL_FAILED_NO_COMBO_POINTS = 78,
- SPELL_FAILED_NO_DUELING = 79,
- SPELL_FAILED_NO_ENDURANCE = 80,
- SPELL_FAILED_NO_FISH = 81,
- SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 82,
- SPELL_FAILED_NO_MOUNTS_ALLOWED = 83,
- SPELL_FAILED_NO_PET = 84,
- SPELL_FAILED_NO_POWER = 85,
- SPELL_FAILED_NOTHING_TO_DISPEL = 86,
- SPELL_FAILED_NOTHING_TO_STEAL = 87,
- SPELL_FAILED_ONLY_ABOVEWATER = 88,
- SPELL_FAILED_ONLY_DAYTIME = 89,
- SPELL_FAILED_ONLY_INDOORS = 90,
- SPELL_FAILED_ONLY_MOUNTED = 91,
- SPELL_FAILED_ONLY_NIGHTTIME = 92,
- SPELL_FAILED_ONLY_OUTDOORS = 93,
- SPELL_FAILED_ONLY_SHAPESHIFT = 94,
- SPELL_FAILED_ONLY_STEALTHED = 95,
- SPELL_FAILED_ONLY_UNDERWATER = 96,
- SPELL_FAILED_OUT_OF_RANGE = 97,
- SPELL_FAILED_PACIFIED = 98,
- SPELL_FAILED_POSSESSED = 99,
- SPELL_FAILED_REAGENTS = 100,
- SPELL_FAILED_REQUIRES_AREA = 101,
- SPELL_FAILED_REQUIRES_SPELL_FOCUS = 102,
- SPELL_FAILED_ROOTED = 103,
- SPELL_FAILED_SILENCED = 104,
- SPELL_FAILED_SPELL_IN_PROGRESS = 105,
- SPELL_FAILED_SPELL_LEARNED = 106,
- SPELL_FAILED_SPELL_UNAVAILABLE = 107,
- SPELL_FAILED_STUNNED = 108,
- SPELL_FAILED_TARGETS_DEAD = 109,
- SPELL_FAILED_TARGET_AFFECTING_COMBAT = 110,
- SPELL_FAILED_TARGET_AURASTATE = 111,
- SPELL_FAILED_TARGET_DUELING = 112,
- SPELL_FAILED_TARGET_ENEMY = 113,
- SPELL_FAILED_TARGET_ENRAGED = 114,
- SPELL_FAILED_TARGET_FRIENDLY = 115,
- SPELL_FAILED_TARGET_IN_COMBAT = 116,
- SPELL_FAILED_TARGET_IS_PLAYER = 117,
- SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 118,
- SPELL_FAILED_TARGET_NOT_DEAD = 119,
- SPELL_FAILED_TARGET_NOT_IN_PARTY = 120,
- SPELL_FAILED_TARGET_NOT_LOOTED = 121,
- SPELL_FAILED_TARGET_NOT_PLAYER = 122,
- SPELL_FAILED_TARGET_NO_POCKETS = 123,
- SPELL_FAILED_TARGET_NO_WEAPONS = 124,
- SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 125,
- SPELL_FAILED_TARGET_UNSKINNABLE = 126,
- SPELL_FAILED_THIRST_SATIATED = 127,
- SPELL_FAILED_TOO_CLOSE = 128,
- SPELL_FAILED_TOO_MANY_OF_ITEM = 129,
- SPELL_FAILED_TOTEM_CATEGORY = 130,
- SPELL_FAILED_TOTEMS = 131,
- SPELL_FAILED_TRY_AGAIN = 132,
- SPELL_FAILED_UNIT_NOT_BEHIND = 133,
- SPELL_FAILED_UNIT_NOT_INFRONT = 134,
- SPELL_FAILED_WRONG_PET_FOOD = 135,
- SPELL_FAILED_NOT_WHILE_FATIGUED = 136,
- SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 137,
- SPELL_FAILED_NOT_WHILE_TRADING = 138,
- SPELL_FAILED_TARGET_NOT_IN_RAID = 139,
- SPELL_FAILED_TARGET_FREEFORALL = 140,
- SPELL_FAILED_NO_EDIBLE_CORPSES = 141,
- SPELL_FAILED_ONLY_BATTLEGROUNDS = 142,
- SPELL_FAILED_TARGET_NOT_GHOST = 143,
- SPELL_FAILED_TRANSFORM_UNUSABLE = 144,
- SPELL_FAILED_WRONG_WEATHER = 145,
- SPELL_FAILED_DAMAGE_IMMUNE = 146,
- SPELL_FAILED_PREVENTED_BY_MECHANIC = 147,
- SPELL_FAILED_PLAY_TIME = 148,
- SPELL_FAILED_REPUTATION = 149,
- SPELL_FAILED_MIN_SKILL = 150,
- SPELL_FAILED_NOT_IN_ARENA = 151,
- SPELL_FAILED_NOT_ON_SHAPESHIFT = 152,
- SPELL_FAILED_NOT_ON_STEALTHED = 153,
- SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 154,
- SPELL_FAILED_NOT_ON_MOUNTED = 155,
- SPELL_FAILED_TOO_SHALLOW = 156,
- SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 157,
- SPELL_FAILED_TARGET_IS_TRIVIAL = 158,
- SPELL_FAILED_BM_OR_INVISGOD = 159,
- SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 160,
- SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 161,
- SPELL_FAILED_NOT_IDLE = 162,
- SPELL_FAILED_NOT_INACTIVE = 163,
- SPELL_FAILED_PARTIAL_PLAYTIME = 164,
- SPELL_FAILED_NO_PLAYTIME = 165,
- SPELL_FAILED_NOT_IN_BATTLEGROUND = 166,
- SPELL_FAILED_NOT_IN_RAID_INSTANCE = 167,
- SPELL_FAILED_ONLY_IN_ARENA = 168,
- SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 169,
- SPELL_FAILED_ON_USE_ENCHANT = 170,
- SPELL_FAILED_NOT_ON_GROUND = 171,
- SPELL_FAILED_CUSTOM_ERROR = 172,
- SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 173,
- SPELL_FAILED_TOO_MANY_SOCKETS = 174,
- SPELL_FAILED_INVALID_GLYPH = 175,
- SPELL_FAILED_UNIQUE_GLYPH = 176,
- SPELL_FAILED_GLYPH_SOCKET_LOCKED = 177,
- SPELL_FAILED_NO_VALID_TARGETS = 178,
- SPELL_FAILED_ITEM_AT_MAX_CHARGES = 179,
- SPELL_FAILED_NOT_IN_BARBERSHOP = 180,
- SPELL_FAILED_FISHING_TOO_LOW = 181,
- SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 182,
- SPELL_FAILED_SUMMON_PENDING = 183,
- SPELL_FAILED_MAX_SOCKETS = 184,
- SPELL_FAILED_PET_CAN_RENAME = 185,
- SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 186,
- SPELL_FAILED_UNKNOWN = 187, // actually doesn't exist in client
-
- SPELL_CAST_OK = 255 // custom value, must not be sent to client
+ SPELL_FAILED_SUCCESS = 0,
+ SPELL_FAILED_AFFECTING_COMBAT = 1,
+ SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2,
+ SPELL_FAILED_ALREADY_AT_FULL_MANA = 3,
+ SPELL_FAILED_ALREADY_AT_FULL_POWER = 4,
+ SPELL_FAILED_ALREADY_BEING_TAMED = 5,
+ SPELL_FAILED_ALREADY_HAVE_CHARM = 6,
+ SPELL_FAILED_ALREADY_HAVE_SUMMON = 7,
+ SPELL_FAILED_ALREADY_HAVE_PET = 8,
+ SPELL_FAILED_ALREADY_OPEN = 9,
+ SPELL_FAILED_AURA_BOUNCED = 10,
+ SPELL_FAILED_AUTOTRACK_INTERRUPTED = 11,
+ SPELL_FAILED_BAD_IMPLICIT_TARGETS = 12,
+ SPELL_FAILED_BAD_TARGETS = 13,
+ SPELL_FAILED_CANT_BE_CHARMED = 14,
+ SPELL_FAILED_CANT_BE_DISENCHANTED = 15,
+ SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 16,
+ SPELL_FAILED_CANT_BE_MILLED = 17,
+ SPELL_FAILED_CANT_BE_PROSPECTED = 18,
+ SPELL_FAILED_CANT_CAST_ON_TAPPED = 19,
+ SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 20,
+ SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 21,
+ SPELL_FAILED_CANT_STEALTH = 22,
+ SPELL_FAILED_CASTER_AURASTATE = 23,
+ SPELL_FAILED_CASTER_DEAD = 24,
+ SPELL_FAILED_CHARMED = 25,
+ SPELL_FAILED_CHEST_IN_USE = 26,
+ SPELL_FAILED_CONFUSED = 27,
+ SPELL_FAILED_DONT_REPORT = 28,
+ SPELL_FAILED_EQUIPPED_ITEM = 29,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS = 30,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 31,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 32,
+ SPELL_FAILED_ERROR = 33,
+ SPELL_FAILED_FALLING = 34,
+ SPELL_FAILED_FIZZLE = 35,
+ SPELL_FAILED_FLEEING = 36,
+ SPELL_FAILED_FOOD_LOWLEVEL = 37,
+ SPELL_FAILED_HIGHLEVEL = 38,
+ SPELL_FAILED_HUNGER_SATIATED = 39,
+ SPELL_FAILED_IMMUNE = 40,
+ SPELL_FAILED_INCORRECT_AREA = 41,
+ SPELL_FAILED_INTERRUPTED = 42,
+ SPELL_FAILED_INTERRUPTED_COMBAT = 43,
+ SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 44,
+ SPELL_FAILED_ITEM_GONE = 45,
+ SPELL_FAILED_ITEM_NOT_FOUND = 46,
+ SPELL_FAILED_ITEM_NOT_READY = 47,
+ SPELL_FAILED_LEVEL_REQUIREMENT = 48,
+ SPELL_FAILED_LINE_OF_SIGHT = 49,
+ SPELL_FAILED_LOWLEVEL = 50,
+ SPELL_FAILED_LOW_CASTLEVEL = 51,
+ SPELL_FAILED_MAINHAND_EMPTY = 52,
+ SPELL_FAILED_MOVING = 53,
+ SPELL_FAILED_NEED_AMMO = 54,
+ SPELL_FAILED_NEED_AMMO_POUCH = 55,
+ SPELL_FAILED_NEED_EXOTIC_AMMO = 56,
+ SPELL_FAILED_NEED_MORE_ITEMS = 57,
+ SPELL_FAILED_NOPATH = 58,
+ SPELL_FAILED_NOT_BEHIND = 59,
+ SPELL_FAILED_NOT_FISHABLE = 60,
+ SPELL_FAILED_NOT_FLYING = 61,
+ SPELL_FAILED_NOT_HERE = 62,
+ SPELL_FAILED_NOT_INFRONT = 63,
+ SPELL_FAILED_NOT_IN_CONTROL = 64,
+ SPELL_FAILED_NOT_KNOWN = 65,
+ SPELL_FAILED_NOT_MOUNTED = 66,
+ SPELL_FAILED_NOT_ON_TAXI = 67,
+ SPELL_FAILED_NOT_ON_TRANSPORT = 68,
+ SPELL_FAILED_NOT_READY = 69,
+ SPELL_FAILED_NOT_SHAPESHIFT = 70,
+ SPELL_FAILED_NOT_STANDING = 71,
+ SPELL_FAILED_NOT_TRADEABLE = 72,
+ SPELL_FAILED_NOT_TRADING = 73,
+ SPELL_FAILED_NOT_UNSHEATHED = 74,
+ SPELL_FAILED_NOT_WHILE_GHOST = 75,
+ SPELL_FAILED_NOT_WHILE_LOOTING = 76,
+ SPELL_FAILED_NO_AMMO = 77,
+ SPELL_FAILED_NO_CHARGES_REMAIN = 78,
+ SPELL_FAILED_NO_CHAMPION = 79,
+ SPELL_FAILED_NO_COMBO_POINTS = 80,
+ SPELL_FAILED_NO_DUELING = 81,
+ SPELL_FAILED_NO_ENDURANCE = 82,
+ SPELL_FAILED_NO_FISH = 83,
+ SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 84,
+ SPELL_FAILED_NO_MOUNTS_ALLOWED = 85,
+ SPELL_FAILED_NO_PET = 86,
+ SPELL_FAILED_NO_POWER = 87,
+ SPELL_FAILED_NOTHING_TO_DISPEL = 88,
+ SPELL_FAILED_NOTHING_TO_STEAL = 89,
+ SPELL_FAILED_ONLY_ABOVEWATER = 90,
+ SPELL_FAILED_ONLY_DAYTIME = 91,
+ SPELL_FAILED_ONLY_INDOORS = 92,
+ SPELL_FAILED_ONLY_MOUNTED = 93,
+ SPELL_FAILED_ONLY_NIGHTTIME = 94,
+ SPELL_FAILED_ONLY_OUTDOORS = 95,
+ SPELL_FAILED_ONLY_SHAPESHIFT = 96,
+ SPELL_FAILED_ONLY_STEALTHED = 97,
+ SPELL_FAILED_ONLY_UNDERWATER = 98,
+ SPELL_FAILED_OUT_OF_RANGE = 99,
+ SPELL_FAILED_PACIFIED = 100,
+ SPELL_FAILED_POSSESSED = 101,
+ SPELL_FAILED_REAGENTS = 102,
+ SPELL_FAILED_REQUIRES_AREA = 103,
+ SPELL_FAILED_REQUIRES_SPELL_FOCUS = 104,
+ SPELL_FAILED_ROOTED = 105,
+ SPELL_FAILED_SILENCED = 106,
+ SPELL_FAILED_SPELL_IN_PROGRESS = 107,
+ SPELL_FAILED_SPELL_LEARNED = 108,
+ SPELL_FAILED_SPELL_UNAVAILABLE = 109,
+ SPELL_FAILED_STUNNED = 110,
+ SPELL_FAILED_TARGETS_DEAD = 111,
+ SPELL_FAILED_TARGET_AFFECTING_COMBAT = 112,
+ SPELL_FAILED_TARGET_AURASTATE = 113,
+ SPELL_FAILED_TARGET_DUELING = 114,
+ SPELL_FAILED_TARGET_ENEMY = 115,
+ SPELL_FAILED_TARGET_ENRAGED = 116,
+ SPELL_FAILED_TARGET_FRIENDLY = 117,
+ SPELL_FAILED_TARGET_IN_COMBAT = 118,
+ SPELL_FAILED_TARGET_IS_PLAYER = 119,
+ SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 120,
+ SPELL_FAILED_TARGET_NOT_DEAD = 121,
+ SPELL_FAILED_TARGET_NOT_IN_PARTY = 122,
+ SPELL_FAILED_TARGET_NOT_LOOTED = 123,
+ SPELL_FAILED_TARGET_NOT_PLAYER = 124,
+ SPELL_FAILED_TARGET_NO_POCKETS = 125,
+ SPELL_FAILED_TARGET_NO_WEAPONS = 126,
+ SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 127,
+ SPELL_FAILED_TARGET_UNSKINNABLE = 128,
+ SPELL_FAILED_THIRST_SATIATED = 129,
+ SPELL_FAILED_TOO_CLOSE = 130,
+ SPELL_FAILED_TOO_MANY_OF_ITEM = 131,
+ SPELL_FAILED_TOTEM_CATEGORY = 132,
+ SPELL_FAILED_TOTEMS = 133,
+ SPELL_FAILED_TRY_AGAIN = 134,
+ SPELL_FAILED_UNIT_NOT_BEHIND = 135,
+ SPELL_FAILED_UNIT_NOT_INFRONT = 136,
+ SPELL_FAILED_VISION_OBSCURED = 137,
+ SPELL_FAILED_WRONG_PET_FOOD = 138,
+ SPELL_FAILED_NOT_WHILE_FATIGUED = 139,
+ SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 140,
+ SPELL_FAILED_NOT_WHILE_TRADING = 141,
+ SPELL_FAILED_TARGET_NOT_IN_RAID = 142,
+ SPELL_FAILED_TARGET_FREEFORALL = 143,
+ SPELL_FAILED_NO_EDIBLE_CORPSES = 144,
+ SPELL_FAILED_ONLY_BATTLEGROUNDS = 145,
+ SPELL_FAILED_TARGET_NOT_GHOST = 146,
+ SPELL_FAILED_TRANSFORM_UNUSABLE = 147,
+ SPELL_FAILED_WRONG_WEATHER = 148,
+ SPELL_FAILED_DAMAGE_IMMUNE = 149,
+ SPELL_FAILED_PREVENTED_BY_MECHANIC = 150,
+ SPELL_FAILED_PLAY_TIME = 151,
+ SPELL_FAILED_REPUTATION = 152,
+ SPELL_FAILED_MIN_SKILL = 153,
+ SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 154,
+ SPELL_FAILED_NOT_ON_SHAPESHIFT = 155,
+ SPELL_FAILED_NOT_ON_STEALTHED = 156,
+ SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 157,
+ SPELL_FAILED_NOT_ON_MOUNTED = 158,
+ SPELL_FAILED_TOO_SHALLOW = 159,
+ SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 160,
+ SPELL_FAILED_TARGET_IS_TRIVIAL = 161,
+ SPELL_FAILED_BM_OR_INVISGOD = 162,
+ SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 163,
+ SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 164,
+ SPELL_FAILED_NOT_IDLE = 165,
+ SPELL_FAILED_NOT_INACTIVE = 166,
+ SPELL_FAILED_PARTIAL_PLAYTIME = 167,
+ SPELL_FAILED_NO_PLAYTIME = 168,
+ SPELL_FAILED_NOT_IN_BATTLEGROUND = 169,
+ SPELL_FAILED_NOT_IN_RAID_INSTANCE = 170,
+ SPELL_FAILED_ONLY_IN_ARENA = 171,
+ SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 172,
+ SPELL_FAILED_ON_USE_ENCHANT = 173,
+ SPELL_FAILED_NOT_ON_GROUND = 174,
+ SPELL_FAILED_CUSTOM_ERROR = 175,
+ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 176,
+ SPELL_FAILED_TOO_MANY_SOCKETS = 177,
+ SPELL_FAILED_INVALID_GLYPH = 178,
+ SPELL_FAILED_UNIQUE_GLYPH = 179,
+ SPELL_FAILED_GLYPH_SOCKET_LOCKED = 180,
+ SPELL_FAILED_NO_VALID_TARGETS = 181,
+ SPELL_FAILED_ITEM_AT_MAX_CHARGES = 182,
+ SPELL_FAILED_NOT_IN_BARBERSHOP = 183,
+ SPELL_FAILED_FISHING_TOO_LOW = 184,
+ SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 185,
+ SPELL_FAILED_SUMMON_PENDING = 186,
+ SPELL_FAILED_MAX_SOCKETS = 187,
+ SPELL_FAILED_PET_CAN_RENAME = 188,
+ SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 189,
+ SPELL_FAILED_NO_ACTIONS = 190,
+ SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 191,
+ SPELL_FAILED_WEIGHT_NOT_ENOUGH = 192,
+ SPELL_FAILED_WEIGHT_TOO_MUCH = 193,
+ SPELL_FAILED_NO_VACANT_SEAT = 194,
+ SPELL_FAILED_NO_LIQUID = 195,
+ SPELL_FAILED_ONLY_NOT_SWIMMING = 196,
+ SPELL_FAILED_BY_NOT_MOVING = 197,
+ SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 198,
+ SPELL_FAILED_NOT_IN_ARENA = 199,
+ SPELL_FAILED_TARGET_NOT_GROUNDED = 200,
+ SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 201,
+ SPELL_FAILED_NOT_IN_LFG_DUNGEON = 202,
+ SPELL_FAILED_UNKNOWN = 254, // custom value, default case
+ SPELL_CAST_OK = 255, // custom value, must not be sent to client
};
enum SpellCustomErrors
@@ -1091,38 +1245,80 @@ enum SpellCustomErrors
SPELL_CUSTOM_ERROR_GM_ONLY = 65, // Only GMs may use that. Your account has been reported for investigation.
SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_58 = 66, // You must reach level 58 to use this portal.
SPELL_CUSTOM_ERROR_AT_HONOR_CAP = 67, // You already have the maximum amount of honor.
- SPELL_CUSTOM_ERROR_68 = 68, // ""
- SPELL_CUSTOM_ERROR_69 = 69, // ""
- SPELL_CUSTOM_ERROR_70 = 70, // ""
- SPELL_CUSTOM_ERROR_71 = 71, // ""
- SPELL_CUSTOM_ERROR_72 = 72, // ""
- SPELL_CUSTOM_ERROR_73 = 73, // ""
- SPELL_CUSTOM_ERROR_74 = 74, // ""
+ SPELL_CUSTOM_ERROR_HAVE_HOT_ROD = 68, // You already have a Hot Rod.
+ SPELL_CUSTOM_ERROR_PARTYGOER_MORE_BUBBLY = 69, // This partygoer wants some more bubbly
+ SPELL_CUSTOM_ERROR_PARTYGOER_NEED_BUCKET = 70, // This partygoer needs a bucket!
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_TO_DANCE = 71, // This partygoer wants to dance with you.
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_FIREWORKS = 72, // This partygoer wants to see some fireworks.
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_APPETIZER = 73, // This partygoer wants some more hors d'oeuvres.
+ SPELL_CUSTOM_ERROR_GOBLIN_BATTERY_DEPLETED = 74, // The Goblin All-In-1-Der Belt's battery is depleted.
SPELL_CUSTOM_ERROR_MUST_HAVE_DEMONIC_CIRCLE = 75, // You must have a demonic circle active.
SPELL_CUSTOM_ERROR_AT_MAX_RAGE = 76, // You already have maximum rage
SPELL_CUSTOM_ERROR_REQUIRES_350_ENGINEERING = 77, // Requires Engineering (350)
SPELL_CUSTOM_ERROR_SOUL_BELONGS_TO_LICH_KING = 78, // Your soul belongs to the Lich King
SPELL_CUSTOM_ERROR_ATTENDANT_HAS_PONY = 79, // Your attendant already has an Argent Pony
- SPELL_CUSTOM_ERROR_80 = 80, // ""
- SPELL_CUSTOM_ERROR_81 = 81, // ""
- SPELL_CUSTOM_ERROR_82 = 82, // ""
+ SPELL_CUSTOM_ERROR_GOBLIN_STARTING_MISSION = 80, // First, Overload the Defective Generator, Activate the Leaky Stove, and Drop a Cigar on the Flammable Bed.
+ SPELL_CUSTOM_ERROR_GASBOT_ALREADY_SENT = 81, // You've already sent in the Gasbot and destroyed headquarters!
+ SPELL_CUSTOM_ERROR_GOBLIN_IS_PARTIED_OUT = 82, // This goblin is all partied out!
SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM = 83, // You must have a Fire Totem active.
SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES = 84, // You may not bite other vampires.
SPELL_CUSTOM_ERROR_PET_ALREADY_AT_YOUR_LEVEL = 85, // Your pet is already at your level.
SPELL_CUSTOM_ERROR_MISSING_ITEM_REQUIREMENS = 86, // You do not meet the level requirements for this item.
SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS = 87, // There are too many Mutated Abominations.
SPELL_CUSTOM_ERROR_ALL_POTIONS_USED = 88, // The potions have all been depleted by Professor Putricide.
- SPELL_CUSTOM_ERROR_89 = 89, // ""
+ SPELL_CUSTOM_ERROR_DEFEATED_ENOUGH_ALREADY = 89, // You have already defeated enough of them.
SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_65 = 90, // Requires level 65
- SPELL_CUSTOM_ERROR_91 = 91, // ""
- SPELL_CUSTOM_ERROR_92 = 92, // ""
- SPELL_CUSTOM_ERROR_93 = 93, // ""
- SPELL_CUSTOM_ERROR_94 = 94, // ""
- SPELL_CUSTOM_ERROR_95 = 95, // ""
+ SPELL_CUSTOM_ERROR_DESTROYED_KTC_OIL_PLATFORM = 91, // You have already destroyed the KTC Oil Platform.
+ SPELL_CUSTOM_ERROR_LAUNCHED_ENOUGH_CAGES = 92, // You have already launched enough cages.
+ SPELL_CUSTOM_ERROR_REQUIRES_BOOSTER_ROCKETS = 93, // Requires Single-Stage Booster Rockets. Return to Hobart Grapplehammer to get more.
+ SPELL_CUSTOM_ERROR_ENOUGH_WILD_CLUCKERS = 94, // You have already captured enough wild cluckers.
+ SPELL_CUSTOM_ERROR_REQUIRES_CONTROL_FIREWORKS = 95, // Requires Remote Control Fireworks. Return to Hobart Grapplehammer to get more.
SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_RECRUITS = 96, // You already have the max number of recruits.
SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_VOLUNTEERS = 97, // You already have the max number of volunteers.
SPELL_CUSTOM_ERROR_FROSTMOURNE_RENDERED_RESSURECT = 98, // Frostmourne has rendered you unable to ressurect.
- SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99 // You can't mount while affected by that shapeshift.
+ SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99, // You can't mount while affected by that shapeshift.
+ SPELL_CUSTOM_ERROR_FAWNS_ALREADY_FOLLOWING = 100, // Three fawns are already following you!
+ SPELL_CUSTOM_ERROR_ALREADY_HAVE_RIVER_BOAT = 101, // You already have a River Boat.
+ SPELL_CUSTOM_ERROR_NO_ACTIVE_ENCHANTMENT = 102, // You have no active enchantment to unleash.
+ SPELL_CUSTOM_ERROR_ENOUGH_HIGHBOURNE_SOULS = 103, // You have bound enough Highborne souls. Return to Arcanist Valdurian.
+ SPELL_CUSTOM_ERROR_ATLEAST_40YD_FROM_OIL_DRILLING = 104, // You must be at least 40 yards away from all other Oil Drilling Rigs.
+ SPELL_CUSTOM_ERROR_ABOVE_ENSLAVED_PEARL_MINER = 106, // You must be above the Enslaved Pearl Miner.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_CORPSE_SPECIAL_1 = 107, // You must target the corpse of a Seabrush Terrapin, Scourgut Remora, or Spinescale Hammerhead.
+ SPELL_CUSTOM_ERROR_SLAGHAMMER_ALREADY_PRISONER = 108, // Ambassador Slaghammer is already your prisoner.
+ SPELL_CUSTOM_ERROR_REQUIRE_ATTUNED_LOCATION_1 = 109, // Requires a location that is attuned with the Naz'jar Battlemaiden.
+ SPELL_CUSTOM_ERROR_NEED_TO_FREE_DRAKE_FIRST = 110, // Free the Drake from the net first!
+ SPELL_CUSTOM_ERROR_DRAGONMAW_ALLIES_ALREADY_FOLLOW = 111, // You already have three Dragonmaw allies following you.
+ SPELL_CUSTOM_ERROR_REQUIRE_OPPOSABLE_THUMBS = 112, // Requires Opposable Thumbs.
+ SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH_2 = 113, // Not enough health
+ SPELL_CUSTOM_ERROR_ENOUGH_FORSAKEN_TROOPERS = 114, // You already have enough Forsaken Troopers.
+ SPELL_CUSTOM_ERROR_CANNOT_JUMP_TO_BOULDER = 115, // You cannot jump to another boulder yet.
+ SPELL_CUSTOM_ERROR_SKILL_TOO_HIGH = 116, // Skill too high.
+ SPELL_CUSTOM_ERROR_ALREADY_6_SURVIVORS_RESCUED = 117, // You have already rescued 6 Survivors.
+ SPELL_CUSTOM_ERROR_MUST_FACE_SHIPS_FROM_BALLOON = 118, // You need to be facing the ships from the rescue balloon.
+ SPELL_CUSTOM_ERROR_CANNOT_SUPERVISE_MORE_CULTISTS = 119, // You cannot supervise more than 5 Arrested Cultists at a time.
+ SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_85 = 120, // You must reach level 85 to use this portal.
+ SPELL_CUSTOM_ERROR_MUST_BE_BELOW_35_HEALTH = 121, // Your target must be below 35% health.
+ SPELL_CUSTOM_ERROR_MUST_SELECT_TALENT_SPECIAL = 122, // You must select a talent specialization first.
+ SPELL_CUSTOM_ERROR_TOO_WISE_AND_POWERFUL = 123, // You are too wise and powerful to gain any benefit from that item.
+ SPELL_CUSTOM_ERROR_TOO_CLOSE_ARGENT_LIGHTWELL = 124, // You are within 10 yards of another Argent Lightwell.
+ SPELL_CUSTOM_ERROR_NOT_WHILE_SHAPESHIFTED = 125, // You can't do that while shapeshifted.
+ SPELL_CUSTOM_ERROR_MANA_GEM_IN_BANK = 126, // You already have a Mana Gem in your bank.
+ SPELL_CUSTOM_ERROR_FLAME_SHOCK_NOT_ACTIVE = 127, // You must have at least one Flame Shock active.
+ SPELL_CUSTOM_ERROR_CANT_TRANSFORM = 128, // You cannot transform right now
+ SPELL_CUSTOM_ERROR_PET_MUST_BE_ATTACKING = 129, // Your pet must be attacking a target.
+ SPELL_CUSTOM_ERROR_GNOMISH_ENGINEERING = 130, // Requires Gnomish Engineering
+ SPELL_CUSTOM_ERROR_GOBLIN_ENGINEERING = 131, // Requires Goblin Engineering
+ SPELL_CUSTOM_ERROR_NO_TARGET = 132, // You have no target.
+ SPELL_CUSTOM_ERROR_PET_OUT_OF_RANGE = 133, // Your Pet is out of range of the target.
+ SPELL_CUSTOM_ERROR_HOLDING_FLAG = 134, // You can't do that while holding the flag.
+ SPELL_CUSTOM_ERROR_TARGET_HOLDING_FLAG = 135, // You can't do that to targets holding the flag.
+ SPELL_CUSTOM_ERROR_PORTAL_NOT_OPEN = 136, // The portal is not yet open. Continue helping the druids at the Sanctuary of Malorne.
+ SPELL_CUSTOM_ERROR_AGGRA_AIR_TOTEM = 137, // You need to be closer to Aggra's Air Totem, in the west.
+ SPELL_CUSTOM_ERROR_AGGRA_WATER_TOTEM = 138, // You need to be closer to Aggra's Water Totem, in the north.
+ SPELL_CUSTOM_ERROR_AGGRA_EARTH_TOTEM = 139, // You need to be closer to Aggra's Earth Totem, in the east.
+ SPELL_CUSTOM_ERROR_AGGRA_FIRE_TOTEM = 140, // You need to be closer to Aggra's Fire Totem, near Thrall.
+ SPELL_CUSTOM_ERROR_TARGET_HAS_STARTDUST_2 = 148, // Target is already affected by Stardust No. 2.
+ SPELL_CUSTOM_ERROR_ELEMENTIUM_GEM_CLUSTERS = 149 // You cannot deconstruct Elementium Gem Clusters while collecting them!
};
enum StealthType
@@ -1233,14 +1429,15 @@ enum Mechanics
MECHANIC_DISCOVERY = 28,
MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block
MECHANIC_SAPPED = 30,
- MECHANIC_ENRAGED = 31
+ MECHANIC_ENRAGED = 31,
+ MECHANIC_WOUNDED = 32,
};
// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967ca6)
#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK (\
(1<<MECHANIC_CHARM)|(1<<MECHANIC_DISORIENTED)|(1<<MECHANIC_FEAR)| \
(1<<MECHANIC_ROOT)|(1<<MECHANIC_SLEEP)|(1<<MECHANIC_SNARE)| \
- (1<<MECHANIC_STUN)|(1<<MECHANIC_FREEZE)|(1<<MECHANIC_KNOCKOUT)| \
+ (1<<MECHANIC_STUN)|(1<<MECHANIC_FREEZE)|(1<<MECHANIC_SILENCE)|(1<<MECHANIC_DISARM)|(1<<MECHANIC_KNOCKOUT)| \
(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)|(1<<MECHANIC_SHACKLE)| \
(1<<MECHANIC_TURN)|(1<<MECHANIC_HORROR)|(1<<MECHANIC_DAZE)| \
(1<<MECHANIC_SAPPED))
@@ -1389,6 +1586,23 @@ enum Targets
TARGET_UNK_DEST_AREA_UNK_107 = 107, // not enough info - only generic spells avalible
TARGET_GAMEOBJECT_CONE = 108,
TARGET_DEST_UNK_110 = 110, // 1 spell
+ TARGET_UNK_111 = 111,
+ TARGET_UNK_112 = 112,
+ TARGET_UNK_113 = 113,
+ TARGET_UNK_114 = 114,
+ TARGET_UNK_115 = 115,
+ TARGET_UNK_116 = 116,
+ TARGET_UNK_117 = 117,
+ TARGET_UNK_118 = 118,
+ TARGET_UNK_119 = 119,
+ TARGET_UNK_120 = 120,
+ TARGET_UNK_121 = 121,
+ TARGET_UNK_122 = 122,
+ TARGET_UNK_123 = 123,
+ TARGET_UNK_124 = 124,
+ TARGET_UNK_125 = 125,
+ TARGET_UNK_126 = 126,
+ TARGET_UNK_127 = 127,
TOTAL_SPELL_TARGETS
};
@@ -1430,7 +1644,8 @@ enum SpellPreventionType
{
SPELL_PREVENTION_TYPE_NONE = 0,
SPELL_PREVENTION_TYPE_SILENCE = 1,
- SPELL_PREVENTION_TYPE_PACIFY = 2
+ SPELL_PREVENTION_TYPE_PACIFY = 2,
+ SPELL_PREVENTION_TYPE_UNK = 3 // Only a few spells have this, but most of the should be interruptable.
};
enum GameobjectTypes
@@ -1474,7 +1689,7 @@ enum GameobjectTypes
};
#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client.
-#define MAX_GAMEOBJECT_DATA 24 // Max number of uint32 vars in gameobject_template data field
+#define MAX_GAMEOBJECT_DATA 32 // Max number of uint32 vars in gameobject_template data field
enum GameObjectFlags
{
@@ -1759,7 +1974,8 @@ enum TextEmotes
TEXT_EMOTE_LOOK = 449,
TEXT_EMOTE_OBJECT = 450,
TEXT_EMOTE_SWEAT = 451,
- TEXT_EMOTE_YW = 453
+ TEXT_EMOTE_YW = 453,
+ TEXT_EMOTE_READ = 456
};
// Emotes.dbc
@@ -1939,7 +2155,19 @@ enum Emote
EMOTE_STATE_STRANGULATE = 473,
EMOTE_STATE_READY_SPELL_OMNI = 474,
EMOTE_STATE_HOLD_JOUST = 475,
- EMOTE_ONESHOT_CRY_JAINA = 476
+ EMOTE_ONESHOT_CRY_JAINA = 476,
+ EMOTE_ONESHOT_SPECIAL_UNARMED = 477,
+ EMOTE_STATE_DANCE_NOSHEATHE = 478,
+ EMOTE_ONESHOT_SNIFF = 479,
+ EMOTE_ONESHOT_DRAGONSTOMP = 480,
+ EMOTE_ONESHOT_KNOCKDOWN = 482,
+ EMOTE_STATE_READ = 483,
+ EMOTE_ONESHOT_FLYEMOTETALK = 485,
+ EMOTE_STATE_READ_ALLOWMOVEMENT = 492,
+ EMOTE_STATE_READY1H_ALLOW_MOVEMENT = 505,
+ EMOTE_STATE_READY2H_ALLOW_MOVEMENT = 506,
+ EMOTE_ONESHOT_OPEN = 517,
+ EMOTE_STATE_READ_CHRISTMAS = 518
};
// AnimationData.dbc
@@ -2450,7 +2678,161 @@ enum Anim
ANIM_CARRY2H = 502,
ANIM_CARRIED2H = 503,
ANIM_FLY_CARRY2H = 504,
- ANIM_FLY_CARRIED2H = 505
+ ANIM_FLY_CARRIED2H = 505,
+ ANIM_EMOTE_SNIFF = 506,
+ ANIM_EMOTE_FLY_SNIFF = 507,
+ ANIM_ATTACK_FIST1H = 508,
+ ANIM_FLY_ATTACK_FIST1H = 509,
+ ANIM_ATTACK_FIST_1H_OFF = 510,
+ ANIM_FLY_ATTACK_FIST_1H_OFF = 511,
+ ANIM_PARRY_FIST1H = 512,
+ ANIM_FLY_PARRY_FIST1H = 513,
+ ANIM_READY_FIST1H = 514,
+ ANIM_FLY_READY_FIST1H = 515,
+ ANIM_SPECIAL_FIST1H = 516,
+ ANIM_FLY_SPECIAL_FIST1H = 517,
+ ANIM_EMOTE_READ_START = 518,
+ ANIM_FLY_EMOTE_READ_START = 519,
+ ANIM_EMOTE_READ_LOOP = 520,
+ ANIM_FLY_EMOTE_READ_LOOP = 521,
+ ANIM_EMOTE_READ_END = 522,
+ ANIM_FLY_EMOTE_READ_END = 523,
+ ANIM_SWIM_RUN = 524,
+ ANIM_FLY_SWIM_RUN = 525,
+ ANIM_SWIM_WALK = 526,
+ ANIM_FLY_SWIM_WALK = 527,
+ ANIM_SWIM_WALK_BACKWARDS = 528,
+ ANIM_FLY_SWIM_WALK_BACKWARDS = 529,
+ ANIM_SWIM_SPRINT = 530,
+ ANIM_FLY_SWIM_SPRINT = 531,
+ ANIM_MOUNT_SWIM_IDLE = 532,
+ ANIM_FLY_MOUNT_SWIM_IDLE = 533,
+ ANIM_MOUNT_SWIM_BACKWARDS = 534,
+ ANIM_FLY_MOUNT_SWIM_BACKWARDS = 535,
+ ANIM_MOUNT_SWIM_LEFT = 536,
+ ANIM_FLY_MOUNT_SWIM_LEFT = 537,
+ ANIM_MOUNT_SWIM_RIGHT = 538,
+ ANIM_FLY_MOUNT_SWIM_RIGHT = 539,
+ ANIM_MOUNT_SWIM_RUN = 540,
+ ANIM_FLY_MOUNT_SWIM_RUN = 541,
+ ANIM_MOUNT_SWIM_SPRINT = 542,
+ ANIM_FLY_MOUNT_SWIM_SPRINT = 543,
+ ANIM_MOUNT_SWIM_WALK = 544,
+ ANIM_FLY_MOUNT_SWIM_WALK = 545,
+ ANIM_MOUNT_SWIM_WALK_BACKWARDS = 546,
+ ANIM_FLY_MOUNT_SWIM_WALK_BACKWARDS = 547,
+ ANIM_MOUNT_FLIGHT_IDLE = 548,
+ ANIM_FLY_MOUNT_FLIGHT_IDLE = 549,
+ ANIM_MOUNT_FLIGHT_BACKWARDS = 550,
+ ANIM_FLY_MOUNT_FLIGHT_BACKWARDS = 551,
+ ANIM_MOUNT_FLIGHT_LEFT = 552,
+ ANIM_FLY_MOUNT_FLIGHT_LEFT = 553,
+ ANIM_MOUNT_FLIGHT_RIGHT = 554,
+ ANIM_FLY_MOUNT_FLIGHT_RIGHT = 555,
+ ANIM_MOUNT_FLIGHT_RUN = 556,
+ ANIM_FLY_MOUNT_FLIGHT_RUN = 557,
+ ANIM_MOUNT_FLIGHT_SPRINT = 558,
+ ANIM_FLY_MOUNT_FLIGHT_SPRINT = 559,
+ ANIM_MOUNT_FLIGHT_WALK = 560,
+ ANIM_FLY_MOUNT_FLIGHT_WALK = 561,
+ ANIM_MOUNT_FLIGHT_WALK_BACKWARDS = 562,
+ ANIM_FLY_MOUNT_FLIGHT_WALK_BACKWARDS = 563,
+ ANIM_MOUNT_FLIGHT_START = 564,
+ ANIM_FLY_MOUNT_FLIGHT_START = 565,
+ ANIM_MOUNT_SWIM_START = 566,
+ ANIM_FLY_MOUNT_SWIM_START = 567,
+ ANIM_MOUNT_SWIM_LAND = 568,
+ ANIM_FLY_MOUNT_SWIM_LAND = 569,
+ ANIM_MOUNT_SWIM_LAND_RUN = 570,
+ ANIM_FLY_MOUNT_SWIM_LAND_RUN = 571,
+ ANIM_MOUNT_FLIGHT_LAND = 572,
+ ANIM_FLY_MOUNT_FLIGHT_LAND = 573,
+ ANIM_MOUNT_FLIGHT_LAND_RUN = 574,
+ ANIM_FLY_MOUNT_FLIGHT_LAND_RUN = 575,
+ ANIM_READY_BLOW_DART = 576,
+ ANIM_FLY_READY_BLOW_DART = 577,
+ ANIM_LOAD_BLOW_DART = 578,
+ ANIM_FLY_LOAD_BLOW_DART = 579,
+ ANIM_HOLD_BLOW_DART = 580,
+ ANIM_FLY_HOLD_BLOW_DART = 581,
+ ANIM_ATTACK_BLOW_DART = 582,
+ ANIM_FLY_ATTACK_BLOW_DART = 583,
+ ANIM_CARRIAGE_MOUNT = 584,
+ ANIM_FLY_CARRIAGE_MOUNT = 585,
+ ANIM_CARRIAGE_PASSENGER_MOUNT = 586,
+ ANIM_FLY_CARRIAGE_PASSENGER_MOUNT = 587,
+ ANIM_CARRIAGE_MOUNT_ATTACK = 588,
+ ANIM_FLY_CARRIAGE_MOUNT_ATTACK = 589,
+ ANIM_BARTENDER_STAND = 590,
+ ANIM_FLY_BARTENDER_STAND = 591,
+ ANIM_BARTENDER_WALK = 592,
+ ANIM_FLY_BARTENDER_WALK = 593,
+ ANIM_BARTENDER_RUN = 594,
+ ANIM_FLY_BARTENDER_RUN = 595,
+ ANIM_BARTENDER_SHUFFLE_LEFT = 596,
+ ANIM_FLY_BARTENDER_SHUFFLE_LEFT = 597,
+ ANIM_BARTENDER_SHUFFLE_RIGHT = 598,
+ ANIM_FLY_BARTENDER_SHUFFLE_RIGHT = 599,
+ ANIM_BARTENDER_EMOTE_TALK = 600,
+ ANIM_FLY_BARTENDER_EMOTE_TALK = 601,
+ ANIM_BARTENDER_EMOTE_POINT = 602,
+ ANIM_FLY_BARTENDER_EMOTE_POINT = 603,
+ ANIM_BARMAID_STAND = 604,
+ ANIM_FLY_BARMAID_STAND = 605,
+ ANIM_BARMAID_WALK = 606,
+ ANIM_FLY_BARMAID_WALK = 607,
+ ANIM_BARMAID_RUN = 608,
+ ANIM_FLY_BARMAID_RUN = 609,
+ ANIM_BARMAID_SHUFFLE_LEFT = 610,
+ ANIM_FLY_BARMAID_SHUFFLE_LEFT = 611,
+ ANIM_BARMAID_SHUFFLE_RIGHT = 612,
+ ANIM_FLY_BARMAID_SHUFFLE_RIGHT = 613,
+ ANIM_BARMAID_EMOTE_TALK = 614,
+ ANIM_FLY_BARMAID_EMOTE_TALK = 615,
+ ANIM_BARMAID_EMOTE_POINT = 616,
+ ANIM_FLY_BARMAID_EMOTE_POINT = 617,
+ ANIM_MOUNT_SELF_IDLE = 618,
+ ANIM_FLY_MOUNT_SELF_IDLE = 619,
+ ANIM_MOUNT_SELF_WALK = 620,
+ ANIM_FLY_MOUNT_SELF_WALK = 621,
+ ANIM_MOUNT_SELF_RUN = 622,
+ ANIM_FLY_MOUNT_SELF_RUN = 623,
+ ANIM_MOUNT_SELF_SPRINT = 624,
+ ANIM_FLY_MOUNT_SELF_SPRINT = 625,
+ ANIM_MOUNT_SELF_RUN_LEFT = 626,
+ ANIM_FLY_MOUNT_SELF_RUN_LEFT = 627,
+ ANIM_MOUNT_SELF_RUN_RIGHT = 628,
+ ANIM_FLY_MOUNT_SELF_RUN_RIGHT = 629,
+ ANIM_MOUNT_SELF_SHUFFLE_LEFT = 630,
+ ANIM_FLY_MOUNT_SELF_SHUFFLE_LEFT = 631,
+ ANIM_MOUNT_SELF_SHUFFLE_RIGHT = 632,
+ ANIM_FLY_MOUNT_SELF_SHUFFLE_RIGHT = 633,
+ ANIM_MOUNT_SELF_WALK_BACKWARDS = 634,
+ ANIM_FLY_MOUNT_SELF_WALK_BACKWARDS = 635,
+ ANIM_MOUNT_SELF_SPECIAL = 636,
+ ANIM_FLY_MOUNT_SELF_SPECIAL = 637,
+ ANIM_MOUNT_SELF_JUMP = 638,
+ ANIM_FLY_MOUNT_SELF_JUMP = 639,
+ ANIM_MOUNT_SELF_JUMP_START = 640,
+ ANIM_FLY_MOUNT_SELF_JUMP_START = 641,
+ ANIM_MOUNT_SELF_JUMP_END = 642,
+ ANIM_FLY_MOUNT_SELF_JUMP_END = 643,
+ ANIM_MOUNT_SELF_JUMP_LAND_RUN = 644,
+ ANIM_FLY_MOUNT_SELF_JUMP_LAND_RUN = 645,
+ ANIM_MOUNT_SELF_START = 646,
+ ANIM_FLY_MOUNT_SELF_START = 647,
+ ANIM_MOUNT_SELF_FALL = 648,
+ ANIM_FLY_MOUNT_SELF_FALL = 649,
+ ANIM_STORMSTRIKE = 650,
+ ANIM_FLY_STORMSTRIKE = 651,
+ ANIM_READY_JOUST_NO_SHEATHE = 652,
+ ANIM_FLY_READY_JOUST_NO_SHEATHE = 653,
+ ANIM_SLAM = 654,
+ ANIM_FLY_SLAM = 655,
+ ANIM_DEATH_STRIKE = 656,
+ ANIM_FLY_DEATH_STRIKE = 657,
+ ANIM_SWIM_ATTACK_UNARMED = 658,
+ ANIM_FLY_SWIM_ATTACK_UNARMED = 659
};
enum LockKeyType
@@ -2560,7 +2942,18 @@ enum CreatureFamily
CREATURE_FAMILY_RHINO = 43,
CREATURE_FAMILY_WASP = 44,
CREATURE_FAMILY_CORE_HOUND = 45,
- CREATURE_FAMILY_SPIRIT_BEAST = 46
+ CREATURE_FAMILY_SPIRIT_BEAST = 46,
+ CREATURE_FAMILY_WATER_ELEMENTAL = 49,
+ CREATURE_FAMILY_FOX = 50,
+ CREATURE_FAMILY_MONKEY = 51,
+ CREATURE_FAMILY_DOG = 52,
+ CREATURE_FAMILY_BEETLE = 53,
+ CREATURE_FAMILY_SHALE_SPIDER = 55,
+ CREATURE_FAMILY_ZOMBIE = 56,
+ CREATURE_FAMILY_BEETLE_OLD = 57,
+ CREATURE_FAMILY_SILITHID_2 = 59,
+ CREATURE_FAMILY_WASP_2 = 66,
+ CREATURE_FAMILY_HYDRA = 68,
};
enum CreatureTypeFlags
@@ -2599,6 +2992,18 @@ enum CreatureTypeFlags
CREATURE_TYPEFLAGS_UNK31 = 0x80000000
};
+enum CreatureTypeFlags2
+{
+ CREATURE_TYPEFLAGS_2_UNK1 = 0x00000001,
+ CREATURE_TYPEFLAGS_2_UNK2 = 0x00000002,
+ CREATURE_TYPEFLAGS_2_UNK3 = 0x00000004,
+ CREATURE_TYPEFLAGS_2_UNK4 = 0x00000008,
+ CREATURE_TYPEFLAGS_2_UNK5 = 0x00000010,
+ CREATURE_TYPEFLAGS_2_UNK6 = 0x00000020,
+ CREATURE_TYPEFLAGS_2_UNK7 = 0x00000040,
+ CREATURE_TYPEFLAGS_2_UNK8 = 0x00000080
+};
+
enum CreatureEliteType
{
CREATURE_ELITE_NORMAL = 0,
@@ -2639,7 +3044,14 @@ enum HolidayIds
HOLIDAY_DAY_OF_DEAD = 409,
HOLIDAY_CALL_TO_ARMS_IC = 420,
HOLIDAY_LOVE_IS_IN_THE_AIR = 423,
- HOLIDAY_KALU_AK_FISHING_DERBY = 424
+ HOLIDAY_KALU_AK_FISHING_DERBY = 424,
+ HOLIDAY_CALL_TO_ARMS_BFG = 435,
+ HOLIDAY_CALL_TO_ARMS_TP = 436,
+ HOLIDAY_RATED_BG_15_VS_15 = 442,
+ HOLIDAY_RATED_BG_25_VS_25 = 443,
+ HOLIDAY_ANNIVERSARY_7_YEARS = 467,
+ HOLIDAY_DARKMOON_FAIRE_TEROKKAR = 479,
+ HOLIDAY_ANNIVERSARY_8_YEARS = 484
};
// values based at QuestInfo.dbc
@@ -2701,7 +3113,12 @@ enum QuestSort
QUEST_SORT_JEWELCRAFTING = 373,
QUEST_SORT_NOBLEGARDEN = 374,
QUEST_SORT_PILGRIMS_BOUNTY = 375,
- QUEST_SORT_LOVE_IS_IN_THE_AIR = 376
+ QUEST_SORT_LOVE_IS_IN_THE_AIR = 376,
+ QUEST_SORT_ARCHAEOLOGY = 377,
+ QUEST_SORT_CHILDRENS_WEEK = 378,
+ QUEST_SORT_FIRELANDS_INVASION = 379,
+ QUEST_SORT_ZANDALARI = 380,
+ QUEST_SORT_ELEMENTAL_BONDS = 381
};
inline uint8 ClassByQuestSort(int32 QuestSort)
@@ -2847,7 +3264,7 @@ enum SkillType
SKILL_RACIAL_HUMAN = 754,
SKILL_JEWELCRAFTING = 755,
SKILL_RACIAL_BLOODELF = 756,
- SKILL_PET_EVENT_RC = 758,
+ SKILL_PET_EVENT_RC = 758, // SkillCategory = -1
SKILL_LANG_DRAENEI = 759,
SKILL_RACIAL_DRAENEI = 760,
SKILL_PET_FELGUARD = 761,
@@ -2875,10 +3292,34 @@ enum SkillType
SKILL_PET_WASP = 785,
SKILL_PET_EXOTIC_RHINO = 786,
SKILL_PET_EXOTIC_CORE_HOUND = 787,
- SKILL_PET_EXOTIC_SPIRIT_BEAST = 788
-};
-
-#define MAX_SKILL_TYPE 789
+ SKILL_PET_EXOTIC_SPIRIT_BEAST = 788,
+ SKILL_RACIAL_WORGEN = 789,
+ SKILL_RACIAL_GOBLIN = 790,
+ SKILL_LANG_WORGEN = 791,
+ SKILL_LANG_GOBLIN = 792,
+ SKILL_ARCHAEOLOGY = 794,
+ SKILL_GENERAL_HUNTER = 795,
+ SKILL_GENERAL_DEATH_KNIGHT = 796,
+ SKILL_GENERAL_ROGUE = 797,
+ SKILL_GENERAL_DRUID = 798,
+ SKILL_GENERAL_MAGE = 799,
+ SKILL_GENERAL_PALADIN = 800,
+ SKILL_GENERAL_SHAMAN = 801,
+ SKILL_GENERAL_WARLOCK = 802,
+ SKILL_GENERAL_WARRIOR = 803,
+ SKILL_GENERAL_PRIEST = 804,
+ SKILL_PET_WATER_ELEMENTAL = 805,
+ SKILL_PET_FOX = 808,
+ SKILL_ALL_GLYPHS = 810,
+ SKILL_PET_DOG = 811,
+ SKILL_PET_MONKEY = 815,
+ SKILL_PET_SHALE_SPIDER = 817,
+ SKILL_PET_BEETLE = 818,
+ SKILL_ALL_GUILD_PERKS = 821,
+ SKILL_PET_HYDRA = 824
+};
+
+#define MAX_SKILL_TYPE 825
inline SkillType SkillByLockType(LockType locktype)
{
@@ -2909,12 +3350,14 @@ inline uint32 SkillByQuestSort(int32 QuestSort)
case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID;
case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING;
case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION;
+ case QUEST_SORT_ARCHAEOLOGY: return SKILL_ARCHAEOLOGY;
}
return 0;
}
enum SkillCategory
{
+ SKILL_CATEGORY_UNK1 = 0,
SKILL_CATEGORY_ATTRIBUTES = 5,
SKILL_CATEGORY_WEAPON = 6,
SKILL_CATEGORY_CLASS = 7,
@@ -2958,7 +3401,9 @@ enum TotemCategory
TC_BLADED_PICKAXE = 168,
TC_FLINT_AND_TINDER = 169,
TC_RUNED_COBALT_ROD = 189,
- TC_RUNED_TITANIUM_ROD = 190
+ TC_RUNED_TITANIUM_ROD = 190,
+ TC_RUNED_ELEMENTIUM_ROD = 209,
+ TC_HIGH_POWERED_BOLT_GUN = 210,
};
enum UnitDynFlags
@@ -3017,6 +3462,7 @@ enum ChatMsg
CHAT_MSG_CHANNEL_LIST = 0x14,
CHAT_MSG_CHANNEL_NOTICE = 0x15,
CHAT_MSG_CHANNEL_NOTICE_USER = 0x16,
+ // CHAT_MSG_TARGETICONS
CHAT_MSG_AFK = 0x17,
CHAT_MSG_DND = 0x18,
CHAT_MSG_IGNORED = 0x19,
@@ -3081,6 +3527,7 @@ enum GuildLogs
{
GUILD_BANKLOG_MAX_RECORDS = 25,
GUILD_EVENTLOG_MAX_RECORDS = 100,
+ GUILD_NEWSLOG_MAX_RECORDS = 250
};
enum AiReaction
@@ -3151,7 +3598,8 @@ enum SummonType
SUMMON_TYPE_VEHICLE = 9,
SUMMON_TYPE_VEHICLE2 = 10, // Oculus and Argent Tournament vehicles (3.3.5a)
SUMMON_TYPE_LIGHTWELL = 11,
- SUMMON_TYPE_JEEVES = 12
+ SUMMON_TYPE_JEEVES = 12,
+ SUMMON_TYPE_UNK13 = 13
};
enum EventId
@@ -3250,36 +3698,38 @@ enum ResponseCodes
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 73,
CHAR_DELETE_FAILED_GUILD_LEADER = 74,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 75,
-
- CHAR_LOGIN_IN_PROGRESS = 76,
- CHAR_LOGIN_SUCCESS = 77,
- CHAR_LOGIN_NO_WORLD = 78,
- CHAR_LOGIN_DUPLICATE_CHARACTER = 79,
- CHAR_LOGIN_NO_INSTANCES = 80,
- CHAR_LOGIN_FAILED = 81,
- CHAR_LOGIN_DISABLED = 82,
- CHAR_LOGIN_NO_CHARACTER = 83,
- CHAR_LOGIN_LOCKED_FOR_TRANSFER = 84,
- CHAR_LOGIN_LOCKED_BY_BILLING = 85,
- CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 86,
-
- CHAR_NAME_SUCCESS = 87,
- CHAR_NAME_FAILURE = 88,
- CHAR_NAME_NO_NAME = 89,
- CHAR_NAME_TOO_SHORT = 90,
- CHAR_NAME_TOO_LONG = 91,
- CHAR_NAME_INVALID_CHARACTER = 92,
- CHAR_NAME_MIXED_LANGUAGES = 93,
- CHAR_NAME_PROFANE = 94,
- CHAR_NAME_RESERVED = 95,
- CHAR_NAME_INVALID_APOSTROPHE = 96,
- CHAR_NAME_MULTIPLE_APOSTROPHES = 97,
- CHAR_NAME_THREE_CONSECUTIVE = 98,
- CHAR_NAME_INVALID_SPACE = 99,
- CHAR_NAME_CONSECUTIVE_SPACES = 100,
- CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 101,
- CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 102,
- CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 103
+ CHAR_DELETE_FAILED_HAS_HEIRLOOM_OR_MAIL = 76,
+
+ CHAR_LOGIN_IN_PROGRESS = 77,
+ CHAR_LOGIN_SUCCESS = 78,
+ CHAR_LOGIN_NO_WORLD = 79,
+ CHAR_LOGIN_DUPLICATE_CHARACTER = 80,
+ CHAR_LOGIN_NO_INSTANCES = 81,
+ CHAR_LOGIN_FAILED = 82,
+ CHAR_LOGIN_DISABLED = 83,
+ CHAR_LOGIN_NO_CHARACTER = 84,
+ CHAR_LOGIN_LOCKED_FOR_TRANSFER = 85,
+ CHAR_LOGIN_LOCKED_BY_BILLING = 86,
+ CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 87,
+ CHAR_LOGIN_TEMPORARY_GM_LOCK = 88,
+
+ CHAR_NAME_SUCCESS = 89,
+ CHAR_NAME_FAILURE = 90,
+ CHAR_NAME_NO_NAME = 91,
+ CHAR_NAME_TOO_SHORT = 92,
+ CHAR_NAME_TOO_LONG = 93,
+ CHAR_NAME_INVALID_CHARACTER = 94,
+ CHAR_NAME_MIXED_LANGUAGES = 95,
+ CHAR_NAME_PROFANE = 96,
+ CHAR_NAME_RESERVED = 97,
+ CHAR_NAME_INVALID_APOSTROPHE = 98,
+ CHAR_NAME_MULTIPLE_APOSTROPHES = 99,
+ CHAR_NAME_THREE_CONSECUTIVE = 100,
+ CHAR_NAME_INVALID_SPACE = 101,
+ CHAR_NAME_CONSECUTIVE_SPACES = 102,
+ CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 103,
+ CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 104,
+ CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 105,
};
/// Ban function modes
@@ -3314,10 +3764,18 @@ enum BattlegroundTypeId
BATTLEGROUND_DS = 10, // Dalaran Sewers
BATTLEGROUND_RV = 11, // Ring of Valor
BATTLEGROUND_IC = 30, // Isle of Conquest
- BATTLEGROUND_RB = 32 // Random Battleground
+ BATTLEGROUND_RB = 32, // Random Battleground
+ BATTLEGROUND_RATED_10_VS_10 = 100, // Rated BG 10 vs 10
+ BATTLEGROUND_RATED_15_VS_15 = 101, // Rated BG 15 vs 15
+ BATTLEGROUND_RATED_25_VS_25 = 102, // Rated BG 25 vs 25
+ BATTLEGROUND_TP = 108, // Twin Peaks
+ BATTLEGROUND_BFG = 120, // Battle For Gilneas
+ // 441 = "Icecrown Citadel"
+ // 443 = "The Ruby Sanctum"
+ // 656 = "Rated Eye of the Storm"
};
-#define MAX_BATTLEGROUND_TYPE_ID 33
+#define MAX_BATTLEGROUND_TYPE_ID 121
enum MailResponseType
{
@@ -3366,35 +3824,44 @@ enum SpellFamilyNames
// 14 - unused
SPELLFAMILY_DEATHKNIGHT = 15,
// 16 - unused
- SPELLFAMILY_PET = 17
+ SPELLFAMILY_PET = 17,
+ SPELLFAMILY_UNK3 = 50,
};
enum TradeStatus
{
- TRADE_STATUS_BUSY = 0,
- TRADE_STATUS_BEGIN_TRADE = 1,
- TRADE_STATUS_OPEN_WINDOW = 2,
- TRADE_STATUS_TRADE_CANCELED = 3,
- TRADE_STATUS_TRADE_ACCEPT = 4,
- TRADE_STATUS_BUSY_2 = 5,
- TRADE_STATUS_NO_TARGET = 6,
- TRADE_STATUS_BACK_TO_TRADE = 7,
- TRADE_STATUS_TRADE_COMPLETE = 8,
- // 9?
- TRADE_STATUS_TARGET_TO_FAR = 10,
- TRADE_STATUS_WRONG_FACTION = 11,
- TRADE_STATUS_CLOSE_WINDOW = 12,
- // 13?
- TRADE_STATUS_IGNORE_YOU = 14,
- TRADE_STATUS_YOU_STUNNED = 15,
- TRADE_STATUS_TARGET_STUNNED = 16,
- TRADE_STATUS_YOU_DEAD = 17,
- TRADE_STATUS_TARGET_DEAD = 18,
- TRADE_STATUS_YOU_LOGOUT = 19,
- TRADE_STATUS_TARGET_LOGOUT = 20,
- TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action
- TRADE_STATUS_ONLY_CONJURED = 22, // You can only trade conjured items... (cross realm BG related).
- TRADE_STATUS_NOT_ELIGIBLE = 23 // Related to trading soulbound loot items
+ TRADE_STATUS_OPEN_WINDOW = 0,
+ // 1 - Related to EVENT_PLAYER_MONEY
+ TRADE_STATUS_NOT_ELIGIBLE = 2, // Related to trading soulbound loot items
+ TRADE_STATUS_YOU_LOGOUT = 3,
+ TRADE_STATUS_IGNORE_YOU = 4,
+ TRADE_STATUS_TARGET_DEAD = 5,
+ TRADE_STATUS_TRADE_ACCEPT = 6,
+ TRADE_STATUS_TARGET_LOGOUT = 7,
+ // 8 - nonexistent
+ TRADE_STATUS_TRADE_COMPLETE = 9,
+ TRADE_STATUS_TRIAL_ACCOUNT = 10, // Trial accounts can not perform that action
+ // 11 - nonexistent
+ TRADE_STATUS_BEGIN_TRADE = 12,
+ TRADE_STATUS_YOU_DEAD = 13,
+ // 14 - nonexistent
+ // 15 - nonexistent
+ TRADE_STATUS_TARGET_TO_FAR = 16,
+ TRADE_STATUS_NO_TARGET = 17,
+ TRADE_STATUS_BUSY_2 = 18,
+ TRADE_STATUS_CURRENCY_NOT_TRADABLE = 19, // new 4.x
+ TRADE_STATUS_WRONG_FACTION = 20,
+ TRADE_STATUS_BUSY = 21,
+ // 22 - equivalent to 335 unk status 9
+ TRADE_STATUS_TRADE_CANCELED = 23,
+ TRADE_STATUS_CURRENCY = 24, // new 4.x
+ TRADE_STATUS_BACK_TO_TRADE = 25,
+ TRADE_STATUS_ONLY_CONJURED = 26, // You can only trade conjured items... (cross realm BG related).
+ TRADE_STATUS_YOU_STUNNED = 27,
+ // 28 - nonexistent
+ TRADE_STATUS_TARGET_STUNNED = 29,
+ // 30 - nonexistent
+ TRADE_STATUS_CLOSE_WINDOW = 31,
};
enum XPColorChar
@@ -3431,6 +3898,12 @@ enum ActivateTaxiReply
ERR_TAXINOTSTANDING = 12
};
+enum ProfessionUI
+{
+ MAX_PRIMARY_PROFESSIONS = 2,
+ MAX_SECONDARY_SKILLS = 5
+};
+
enum DuelCompleteType
{
DUEL_INTERRUPTED = 0,
@@ -3447,32 +3920,44 @@ enum BattlegroundQueueTypeId
BATTLEGROUND_QUEUE_EY = 4,
BATTLEGROUND_QUEUE_SA = 5,
BATTLEGROUND_QUEUE_IC = 6,
- BATTLEGROUND_QUEUE_RB = 7,
- BATTLEGROUND_QUEUE_2v2 = 8,
- BATTLEGROUND_QUEUE_3v3 = 9,
- BATTLEGROUND_QUEUE_5v5 = 10,
+ BATTLEGROUND_QUEUE_TP = 7,
+ BATTLEGROUND_QUEUE_BFG = 8,
+ BATTLEGROUND_QUEUE_RB = 9,
+ BATTLEGROUND_QUEUE_2v2 = 10,
+ BATTLEGROUND_QUEUE_3v3 = 11,
+ BATTLEGROUND_QUEUE_5v5 = 12,
MAX_BATTLEGROUND_QUEUE_TYPES
};
enum GroupJoinBattlegroundResult
{
- // positive values are indexes in BattlemasterList.dbc
- ERR_GROUP_JOIN_BATTLEGROUND_FAIL = 0, // Your group has joined a battleground queue, but you are not eligible (showed for non existing BattlemasterList.dbc indexes)
- ERR_BATTLEGROUND_NONE = -1, // not show anything
- ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS = -2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
- ERR_ARENA_TEAM_PARTY_SIZE = -3, // Incorrect party size for this arena.
- ERR_BATTLEGROUND_TOO_MANY_QUEUES = -4, // You can only be queued for 2 battles at once
- ERR_BATTLEGROUND_CANNOT_QUEUE_FOR_RATED = -5, // You cannot queue for a rated match while queued for other battles
- ERR_BATTLEDGROUND_QUEUED_FOR_RATED = -6, // You cannot queue for another battle while queued for a rated arena match
- ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = -7, // Your team has left the arena queue
- ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND = -8, // You can't do that in a battleground.
- ERR_BATTLEGROUND_JOIN_XP_GAIN = -9, // wtf, doesn't exist in client...
- ERR_BATTLEGROUND_JOIN_RANGE_INDEX = -10, // Cannot join the queue unless all members of your party are in the same battleground level range.
- ERR_BATTLEGROUND_JOIN_TIMED_OUT = -11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
- ERR_BATTLEGROUND_JOIN_FAILED = -12, // Join as a group failed (uint64 guid doesn't exist in client cache)
- ERR_LFG_CANT_USE_BATTLEGROUND = -13, // You cannot queue for a battleground or arena while using the dungeon system.
- ERR_IN_RANDOM_BG = -14, // Can't do that while in a Random Battleground queue.
- ERR_IN_NON_RANDOM_BG = -15 // Can't queue for Random Battleground while in another Battleground queue.
+ ERR_BATTLEGROUND_NONE = 0,
+ ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS = 2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
+ ERR_ARENA_TEAM_PARTY_SIZE = 3, // Incorrect party size for this arena.
+ ERR_BATTLEGROUND_TOO_MANY_QUEUES = 4, // You can only be queued for 2 battles at once
+ ERR_BATTLEGROUND_CANNOT_QUEUE_FOR_RATED = 5, // You cannot queue for a rated match while queued for other battles
+ ERR_BATTLEDGROUND_QUEUED_FOR_RATED = 6, // You cannot queue for another battle while queued for a rated arena match
+ ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = 7, // Your team has left the arena queue
+ ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND = 8, // You can't do that in a battleground.
+ ERR_BATTLEGROUND_JOIN_XP_GAIN = 9, // wtf, doesn't exist in client...
+ ERR_BATTLEGROUND_JOIN_RANGE_INDEX = 10, // Cannot join the queue unless all members of your party are in the same battleground level range.
+ ERR_BATTLEGROUND_JOIN_TIMED_OUT = 11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
+ //ERR_BATTLEGROUND_JOIN_TIMED_OUT = 12, // same as 11
+ //ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = 13, // same as 7
+ ERR_LFG_CANT_USE_BATTLEGROUND = 14, // You cannot queue for a battleground or arena while using the dungeon system.
+ ERR_IN_RANDOM_BG = 15, // Can't do that while in a Random Battleground queue.
+ ERR_IN_NON_RANDOM_BG = 16, // Can't queue for Random Battleground while in another Battleground queue.
+ ERR_BG_DEVELOPER_ONLY = 17,
+ ERR_BATTLEGROUND_INVITATION_DECLINED = 18,
+ ERR_MEETING_STONE_NOT_FOUND = 19,
+ ERR_WARGAME_REQUEST_FAILURE = 20,
+ ERR_BATTLEFIELD_TEAM_PARTY_SIZE = 22,
+ ERR_NOT_ON_TOURNAMENT_REALM = 23,
+ ERR_BATTLEGROUND_PLAYERS_FROM_DIFFERENT_REALMS = 24,
+ ERR_REMOVE_FROM_PVP_QUEUE_GRANT_LEVEL = 33,
+ ERR_REMOVE_FROM_PVP_QUEUE_FACTION_CHANGE = 34,
+ ERR_BATTLEGROUND_JOIN_FAILED = 35,
+ ERR_BATTLEGROUND_DUPE_QUEUE = 43
};
enum PetNameInvalidReason
@@ -3506,6 +3991,28 @@ enum DungeonStatusFlag
RAID_STATUSFLAG_25MAN_HEROIC = 0x08
};
+#define VOID_STORAGE_UNLOCK 100*GOLD
+#define VOID_STORAGE_STORE_ITEM 25*GOLD
+#define VOID_STORAGE_MAX_DEPOSIT 9
+#define VOID_STORAGE_MAX_WITHDRAW 9
+#define VOID_STORAGE_MAX_SLOT 80
+
+enum VoidTransferError
+{
+ VOID_TRANSFER_ERROR_NO_ERROR = 0,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_1 = 1,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_2 = 2,
+ VOID_TRANSFER_ERROR_FULL = 3,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_3 = 4,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_4 = 5,
+ VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY = 6,
+ VOID_TRANSFER_ERROR_INVENTORY_FULL = 7,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_5 = 8,
+ VOID_TRANSFER_ERROR_TRANSFER_UNKNOWN = 9,
+};
+
+#define CURRENCY_PRECISION 100
+
enum PartyResult
{
ERR_PARTY_RESULT_OK = 0,
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
index 81442570940..2c3d5b3bf61 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
@@ -19,6 +19,7 @@
#include "IdleMovementGenerator.h"
#include "CreatureAI.h"
#include "Creature.h"
+#include <G3D/g3dmath.h>
IdleMovementGenerator si_idleMovement;
@@ -44,25 +45,17 @@ void RotateMovementGenerator::Initialize(Unit* owner)
owner->SetInFront(owner->getVictim());
owner->AddUnitState(UNIT_STATE_ROTATING);
-
owner->AttackStop();
}
bool RotateMovementGenerator::Update(Unit* owner, uint32 diff)
{
float angle = owner->GetOrientation();
- if (m_direction == ROTATE_DIRECTION_LEFT)
- {
- angle += (float)diff * static_cast<float>(M_PI * 2) / m_maxDuration;
- while (angle >= static_cast<float>(M_PI * 2)) angle -= static_cast<float>(M_PI * 2);
- }
- else
- {
- angle -= (float)diff * static_cast<float>(M_PI * 2) / m_maxDuration;
- while (angle < 0) angle += static_cast<float>(M_PI * 2);
- }
- owner->SetOrientation(angle);
- owner->SendMovementFlagUpdate(); // this is a hack. we do not have anything correct to send in the beginning
+ angle += (float(diff) * static_cast<float>(M_PI * 2) / m_maxDuration) * (m_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f);
+ angle = G3D::wrap(angle, 0.0f, float(G3D::twoPi()));
+
+ owner->SetOrientation(angle); // UpdateSplinePosition does not set orientation with UNIT_STATE_ROTATING
+ owner->SetFacingTo(angle); // Send spline movement to clients
if (m_duration > diff)
m_duration -= diff;
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index 8086e60c912..8086e60c912 100644..100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 3e0274255fa..56621c8aac5 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -237,6 +237,9 @@ void FlightPathMovementGenerator::DoReset(Player* player)
}
init.SetFirstPointId(GetCurrentNode());
init.SetFly();
+ init.SetSmooth();
+ init.SetUncompressed();
+ init.SetWalk(true);
init.SetVelocity(PLAYER_FLIGHT_SPEED);
init.Launch();
}
diff --git a/src/server/game/Movement/MovementStructures.cpp b/src/server/game/Movement/MovementStructures.cpp
new file mode 100644
index 00000000000..632e8017898
--- /dev/null
+++ b/src/server/game/Movement/MovementStructures.cpp
@@ -0,0 +1,5179 @@
+/*
+* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "MovementStructures.h"
+#include "Player.h"
+
+MovementStatusElements const PlayerMove[] =
+{
+ MSEHasFallData,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasFallDirection,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasPitch,
+ MSEGuidByte5,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEGuidByte7,
+ MSEPositionY,
+ MSEGuidByte3,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportGuidByte0,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSEGuidByte4,
+ MSEPositionX,
+ MSEGuidByte6,
+ MSEPositionZ,
+ MSETimestamp,
+ MSEGuidByte2,
+ MSEPitch,
+ MSEGuidByte0,
+ MSEOrientation,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFallLand[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte2,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementHeartBeat[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte7,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSEOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementJump[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSEPitch,
+ MSETimestamp,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetFacing[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte3,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSEOrientation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetPitch[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasSplineElevation,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartBackward[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTimestamp,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSEPitch,
+ MSETimestamp,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartForward[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasSpline,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSESplineElevation,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartStrafeLeft[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasFallDirection,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportGuidByte3,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSETransportPositionX,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartStrafeRight[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportPositionY,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSEPitch,
+ MSEOrientation,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartTurnLeft[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasFallData,
+ MSEMovementFlags2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte7,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartTurnRight[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSETransportPositionY,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStop[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasPitch,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopStrafe[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportTime,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopTurn[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasFallData,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSESplineElevation,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartAscend[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartDescend[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasGuidByte0,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte6,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasTransportData,
+ MSEHasSpline,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEPitch,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartSwim[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEPitch,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportTime,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopSwim[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasSpline,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasTransportData,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopAscend[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopPitch[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETimestamp,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartPitchDown[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartPitchUp[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEMovementFlags2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveChngTransport[]=
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTransportData,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte1,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportTime2,
+
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSplineDone[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+
+ MSEPitch,
+ MSEOrientation,
+
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveNotActiveMover[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportTime,
+
+ MSETimestamp,
+ MSESplineElevation,
+ MSEPitch,
+ MSEOrientation,
+
+ MSEEnd,
+};
+
+MovementStatusElements const DismissControlledVehicle[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte0,
+
+ MSETimestamp,
+
+ MSETransportTime3,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportGuidByte3,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUpdateTeleport[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasOrientation,
+
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte5,
+
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+
+ MSEZeroBit,
+
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEHasSplineElevation,
+ MSEMovementFlags,
+ MSEHasGuidByte1,
+
+ MSEGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportPositionX,
+
+ MSEGuidByte6,
+ MSEPitch,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte1,
+
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSETimestamp,
+ MSEGuidByte0,
+
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetRunMode[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEZeroBit,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEPitch,
+ MSETransportTime2,
+ MSETransportGuidByte3,
+ MSETransportPositionX,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte6,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetWalkMode[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanFly[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportTime3,
+ MSESplineElevation,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanTransitionBetweenSwimAndFlyAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateSwimSpeed[] =
+{
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEMovementFlags,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasGuidByte7,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSEPositionX,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEGuidByte7,
+ MSETimestamp,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateRunSpeed[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEMovementFlags2,
+ MSEHasGuidByte3,
+ MSEMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasFallData,
+ MSEHasFallDirection,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSETimestamp,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSEGuidByte6,
+ MSESplineElevation,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateFlightSpeed[] =
+{
+ MSEPositionY,
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasFallDirection,
+ MSEHasGuidByte0,
+ MSEPitch,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSETimestamp,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateCollisionHeight[] =
+{
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasFallDirection,
+ MSEHasGuidByte1,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSEPitch,
+ MSEGuidByte6,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEGuidByte7,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSETimestamp,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceRunSpeedChangeAck[] =
+{
+ MSECounter,
+ MSEPositionX,
+ MSEExtraElement,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasSpline,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSETransportPositionZ,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportGuidByte4,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCollisionHeightAck[] =
+{
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionY,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasFallData,
+ MSEHasGuidByte3,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceFlightSpeedChangeAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanFlyAck[] =
+{
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte3,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEZeroBit,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceSwimSpeedChangeAck[] =
+{
+ MSEPositionX,
+ MSECounter,
+ MSEExtraElement,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasTimestamp,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceWalkSpeedChangeAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEPositionX,
+ MSECounter,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasSplineElevation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportPositionY,
+ MSETransportGuidByte2,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceRunBackSpeedChangeAck[] =
+{
+ MSEExtraElement,
+ MSECounter,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateRunBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+ MSEHasOrientation,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasGuidByte7,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSEGuidByte4,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEGuidByte1,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEPositionX,
+ MSEPositionY,
+ MSEPitch,
+ MSEGuidByte7,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEPositionZ,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateWalkSpeed[] =
+{
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEHasGuidByte4,
+ MSEPitch,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPositionY,
+ MSEGuidByte0,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const ForceMoveRootAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETimestamp,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const ForceMoveUnrootAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasGuidByte6,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFallReset[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFeatherFallAck[] =
+{
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionY,
+ MSEPositionX,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte1,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementGravityDisableAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportTime3,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementGravityEnableAck[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSECounter,
+ MSEPositionY,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportGuidByte6,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementHoverAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasTimestamp,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasPitch,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasOrientation,
+ MSEHasGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSETimestamp,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementKnockBackAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportSeat,
+ MSEPitch,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementWaterWalkAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasFallData,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSESplineElevation,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateKnockBack[] =
+{
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEHasOrientation,
+ MSEOrientation,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSEPitch,
+ MSEPositionZ,
+ MSETimestamp,
+ MSEPositionX,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEPositionY,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetWalkSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetSwimSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetSwimBackSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetTurnRate[] =
+{
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFlightSpeed[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFlightBackSpeed[] =
+{
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetPitchRate[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetWalkSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetRunSpeed[] =
+{
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSECounter,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetRunBackSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSECounter,
+ MSEExtraElement,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetSwimSpeed[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetSwimBackSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSECounter,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetTurnRate[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetFlightSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSECounter,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetFlightBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEGuidByte3,
+ MSECounter,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetPitchRate[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetCollisionHeight[] =
+{
+ MSEZeroBit,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetWalkMode[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunMode[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveGravityDisable[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveGravityEnable[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetHover[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveUnsetHover[] =
+{
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetCanFly[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSECounter,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUnsetCanFly[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetHover[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUnsetHover[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveWaterWalk[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveLandWalk[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveFeatherFall[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveNormalFall[] =
+{
+ MSECounter,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const ChangeSeatsOnControlledVehicle[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEExtraElement,
+ MSEHasGuidByte7,
+ MSEExtraElement,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEExtraElement,
+ MSEHasMovementFlags2,
+ MSEHasPitch,
+ MSEExtraElement,
+ MSEHasGuidByte0,
+ MSEExtraElement,
+ MSEHasFallData,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEMovementFlags,
+ MSEExtraElement,
+ MSEHasGuidByte3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEGuidByte3,
+ MSEExtraElement,
+ MSEGuidByte0,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEPitch,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportPositionY,
+ MSESplineElevation,
+ MSEOrientation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const CastSpellEmbeddedMovement[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+void Movement::ExtraMovementStatusElement::ReadNextElement(ByteBuffer& packet)
+{
+ MovementStatusElements const element = _elements[_index++];
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ Data.guid[element - MSEHasGuidByte0] = packet.ReadBit();
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ packet.ReadByteSeq(Data.guid[element - MSEGuidByte0]);
+ break;
+ case MSEExtraFloat:
+ packet >> Data.floatData;
+ break;
+ case MSEExtraInt8:
+ packet >> Data.byteData;
+ break;
+ default:
+ ASSERT(PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+}
+
+void Movement::ExtraMovementStatusElement::WriteNextElement(ByteBuffer& packet)
+{
+ MovementStatusElements const element = _elements[_index++];
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ packet.WriteBit(Data.guid[element - MSEHasGuidByte0]);
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ packet.WriteByteSeq(Data.guid[element - MSEGuidByte0]);
+ break;
+ case MSEExtraFloat:
+ packet << Data.floatData;
+ break;
+ case MSEExtraInt8:
+ packet << Data.byteData;
+ break;
+ default:
+ ASSERT(PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+}
+
+bool Movement::PrintInvalidSequenceElement(MovementStatusElements const element, char const* function)
+{
+ TC_LOG_ERROR(LOG_FILTER_UNITS, "Incorrect sequence element %d detected at %s", element, function);
+ return false;
+}
+
+Movement::PacketSender::PacketSender(Unit* unit, Opcodes serverControl, Opcodes playerControl, Opcodes broadcast /*= SMSG_PLAYER_MOVE*/, ExtraMovementStatusElement* extras /*= NULL*/)
+ : _extraElements(extras), _unit(unit)
+{
+ if (unit->GetTypeId() == TYPEID_PLAYER && unit->ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER)
+ {
+ _selfOpcode = playerControl;
+ _broadcast = broadcast;
+ }
+ else
+ {
+ _selfOpcode = NULL_OPCODE;
+ _broadcast = serverControl;
+ }
+}
+
+void Movement::PacketSender::Send() const
+{
+ bool isPlayerMovement = false;
+ if (Player* player = _unit->ToPlayer())
+ {
+ isPlayerMovement = player->m_mover->GetTypeId() == TYPEID_PLAYER;
+ if (isPlayerMovement && _selfOpcode != NULL_OPCODE)
+ {
+ WorldPacket data(_selfOpcode);
+ _unit->WriteMovementInfo(data, _extraElements);
+ player->SendDirectMessage(&data);
+ }
+ }
+
+ if (_broadcast != NULL_OPCODE)
+ {
+ ///! Need to reset current extra element index before writing another packet
+ if (_extraElements)
+ _extraElements->ResetIndex();
+
+ WorldPacket data(_broadcast);
+ _unit->WriteMovementInfo(data, _extraElements);
+ _unit->SendMessageToSet(&data, !isPlayerMovement);
+ }
+}
+
+MovementStatusElements const* GetMovementStatusElementsSequence(Opcodes opcode)
+{
+ switch (opcode)
+ {
+ case MSG_MOVE_FALL_LAND:
+ return MovementFallLand;
+ case MSG_MOVE_HEARTBEAT:
+ return MovementHeartBeat;
+ case MSG_MOVE_JUMP:
+ return MovementJump;
+ case MSG_MOVE_SET_FACING:
+ return MovementSetFacing;
+ case MSG_MOVE_SET_PITCH:
+ return MovementSetPitch;
+ case MSG_MOVE_START_ASCEND:
+ return MovementStartAscend;
+ case MSG_MOVE_START_BACKWARD:
+ return MovementStartBackward;
+ case MSG_MOVE_START_DESCEND:
+ return MovementStartDescend;
+ case MSG_MOVE_START_FORWARD:
+ return MovementStartForward;
+ case MSG_MOVE_START_PITCH_DOWN:
+ return MovementStartPitchDown;
+ case MSG_MOVE_START_PITCH_UP:
+ return MovementStartPitchUp;
+ case MSG_MOVE_START_STRAFE_LEFT:
+ return MovementStartStrafeLeft;
+ case MSG_MOVE_START_STRAFE_RIGHT:
+ return MovementStartStrafeRight;
+ case MSG_MOVE_START_SWIM:
+ return MovementStartSwim;
+ case MSG_MOVE_START_TURN_LEFT:
+ return MovementStartTurnLeft;
+ case MSG_MOVE_START_TURN_RIGHT:
+ return MovementStartTurnRight;
+ case MSG_MOVE_STOP:
+ return MovementStop;
+ case MSG_MOVE_STOP_ASCEND:
+ return MovementStopAscend;
+ case MSG_MOVE_STOP_PITCH:
+ return MovementStopPitch;
+ case MSG_MOVE_STOP_STRAFE:
+ return MovementStopStrafe;
+ case MSG_MOVE_STOP_SWIM:
+ return MovementStopSwim;
+ case MSG_MOVE_STOP_TURN:
+ return MovementStopTurn;
+ case SMSG_PLAYER_MOVE:
+ return PlayerMove;
+ case CMSG_MOVE_CHNG_TRANSPORT:
+ return MoveChngTransport;
+ case CMSG_MOVE_SPLINE_DONE:
+ return MoveSplineDone;
+ case CMSG_MOVE_NOT_ACTIVE_MOVER:
+ return MoveNotActiveMover;
+ case CMSG_DISMISS_CONTROLLED_VEHICLE:
+ return DismissControlledVehicle;
+ case SMSG_MOVE_UPDATE_TELEPORT:
+ return MoveUpdateTeleport;
+ case CMSG_FORCE_MOVE_ROOT_ACK:
+ return ForceMoveRootAck;
+ case CMSG_FORCE_MOVE_UNROOT_ACK:
+ return ForceMoveUnrootAck;
+ case CMSG_MOVE_FALL_RESET:
+ return MovementFallReset;
+ case CMSG_MOVE_FEATHER_FALL_ACK:
+ return MovementFeatherFallAck;
+ case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK:
+ return MovementForceFlightSpeedChangeAck;
+ case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK:
+ return MovementForceRunBackSpeedChangeAck;
+ case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK:
+ return MovementForceRunSpeedChangeAck;
+ case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK:
+ return MovementForceSwimSpeedChangeAck;
+ case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK:
+ return MovementForceWalkSpeedChangeAck;
+ case CMSG_MOVE_GRAVITY_DISABLE_ACK:
+ return MovementGravityDisableAck;
+ case CMSG_MOVE_GRAVITY_ENABLE_ACK:
+ return MovementGravityEnableAck;
+ case CMSG_MOVE_HOVER_ACK:
+ return MovementHoverAck;
+ case CMSG_MOVE_KNOCK_BACK_ACK:
+ return MovementKnockBackAck;
+ case CMSG_MOVE_SET_CAN_FLY:
+ return MovementSetCanFly;
+ case CMSG_MOVE_SET_CAN_FLY_ACK:
+ return MovementSetCanFlyAck;
+ case CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK:
+ return MovementSetCanTransitionBetweenSwimAndFlyAck;
+ case SMSG_MOVE_SET_COLLISION_HEIGHT:
+ return MoveSetCollisionHeight;
+ case CMSG_MOVE_SET_COLLISION_HEIGHT_ACK:
+ return MovementSetCollisionHeightAck;
+ case SMSG_MOVE_UPDATE_COLLISION_HEIGHT:
+ return MovementUpdateCollisionHeight;
+ case CMSG_MOVE_WATER_WALK_ACK:
+ return MovementWaterWalkAck;
+ case MSG_MOVE_SET_RUN_MODE:
+ return MovementSetRunMode;
+ case MSG_MOVE_SET_WALK_MODE:
+ return MovementSetWalkMode;
+ case SMSG_MOVE_UPDATE_FLIGHT_SPEED:
+ return MovementUpdateFlightSpeed;
+ case SMSG_MOVE_UPDATE_RUN_SPEED:
+ return MovementUpdateRunSpeed;
+ case SMSG_MOVE_UPDATE_KNOCK_BACK:
+ return MovementUpdateKnockBack;
+ case SMSG_MOVE_UPDATE_RUN_BACK_SPEED:
+ return MovementUpdateRunBackSpeed;
+ case SMSG_MOVE_UPDATE_SWIM_SPEED:
+ return MovementUpdateSwimSpeed;
+ case SMSG_MOVE_UPDATE_WALK_SPEED:
+ return MovementUpdateWalkSpeed;
+ case SMSG_SPLINE_MOVE_SET_WALK_SPEED:
+ return SplineMoveSetWalkSpeed;
+ case SMSG_SPLINE_MOVE_SET_RUN_SPEED:
+ return SplineMoveSetRunSpeed;
+ case SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED:
+ return SplineMoveSetRunBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_SWIM_SPEED:
+ return SplineMoveSetSwimSpeed;
+ case SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED:
+ return SplineMoveSetSwimBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_TURN_RATE:
+ return SplineMoveSetTurnRate;
+ case SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED:
+ return SplineMoveSetFlightSpeed;
+ case SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED:
+ return SplineMoveSetFlightBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_PITCH_RATE:
+ return SplineMoveSetPitchRate;
+ case SMSG_MOVE_SET_WALK_SPEED:
+ return MoveSetWalkSpeed;
+ case SMSG_MOVE_SET_RUN_SPEED:
+ return MoveSetRunSpeed;
+ case SMSG_MOVE_SET_RUN_BACK_SPEED:
+ return MoveSetRunBackSpeed;
+ case SMSG_MOVE_SET_SWIM_SPEED:
+ return MoveSetSwimSpeed;
+ case SMSG_MOVE_SET_SWIM_BACK_SPEED:
+ return MoveSetSwimBackSpeed;
+ case SMSG_MOVE_SET_TURN_RATE:
+ return MoveSetTurnRate;
+ case SMSG_MOVE_SET_FLIGHT_SPEED:
+ return MoveSetFlightSpeed;
+ case SMSG_MOVE_SET_FLIGHT_BACK_SPEED:
+ return MoveSetFlightBackSpeed;
+ case SMSG_MOVE_SET_PITCH_RATE:
+ return MoveSetPitchRate;
+ case SMSG_SPLINE_MOVE_SET_WALK_MODE:
+ return SplineMoveSetWalkMode;
+ case SMSG_SPLINE_MOVE_SET_RUN_MODE:
+ return SplineMoveSetRunMode;
+ case SMSG_SPLINE_MOVE_GRAVITY_DISABLE:
+ return SplineMoveGravityDisable;
+ case SMSG_SPLINE_MOVE_GRAVITY_ENABLE:
+ return SplineMoveGravityEnable;
+ case SMSG_SPLINE_MOVE_SET_HOVER:
+ return SplineMoveSetHover;
+ case SMSG_SPLINE_MOVE_UNSET_HOVER:
+ return SplineMoveUnsetHover;
+ case SMSG_MOVE_SET_CAN_FLY:
+ return MoveSetCanFly;
+ case SMSG_MOVE_UNSET_CAN_FLY:
+ return MoveUnsetCanFly;
+ case SMSG_MOVE_SET_HOVER:
+ return MoveSetHover;
+ case SMSG_MOVE_UNSET_HOVER:
+ return MoveUnsetHover;
+ case SMSG_MOVE_WATER_WALK:
+ return MoveWaterWalk;
+ case SMSG_MOVE_LAND_WALK:
+ return MoveLandWalk;
+ case SMSG_MOVE_FEATHER_FALL:
+ return MoveFeatherFall;
+ case SMSG_MOVE_NORMAL_FALL:
+ return MoveNormalFall;
+ case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
+ return ChangeSeatsOnControlledVehicle;
+ case CMSG_CAST_SPELL:
+ case CMSG_PET_CAST_SPELL:
+ case CMSG_USE_ITEM:
+ return CastSpellEmbeddedMovement;
+ default:
+ break;
+ }
+
+ return NULL;
+}
diff --git a/src/server/game/Movement/MovementStructures.h b/src/server/game/Movement/MovementStructures.h
new file mode 100644
index 00000000000..97dc4e6f6b5
--- /dev/null
+++ b/src/server/game/Movement/MovementStructures.h
@@ -0,0 +1,158 @@
+/*
+* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _MOVEMENT_STRUCTURES_H
+#define _MOVEMENT_STRUCTURES_H
+
+#include "Opcodes.h"
+#include "Object.h"
+
+class ByteBuffer;
+class Unit;
+
+enum MovementStatusElements
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasFallDirection,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSETimestamp,
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSEPitch,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSESplineElevation,
+
+ MSECounter,
+
+ // Special
+ MSEZeroBit, // writes bit value 1 or skips read bit
+ MSEOneBit, // writes bit value 0 or skips read bit
+ MSEEnd, // marks end of parsing
+ MSEExtraElement, // Used to signalize reading into ExtraMovementStatusElement, element sequence inside it is declared as separate array
+ // Allowed internal elements are: GUID markers (not transport), MSEExtraFloat, MSEExtraInt8
+ MSEExtraFloat,
+ MSEExtraInt8,
+};
+
+namespace Movement
+{
+ class PacketSender;
+
+ class ExtraMovementStatusElement
+ {
+ friend class PacketSender;
+
+ public:
+ ExtraMovementStatusElement(MovementStatusElements const* elements) : _elements(elements), _index(0) { }
+
+ void ReadNextElement(ByteBuffer& packet);
+ void WriteNextElement(ByteBuffer& packet);
+
+ struct
+ {
+ ObjectGuid guid;
+ float floatData;
+ int8 byteData;
+ } Data;
+
+ protected:
+ void ResetIndex() { _index = 0; }
+
+ private:
+ MovementStatusElements const* _elements;
+ uint32 _index;
+ };
+
+ class PacketSender
+ {
+ public:
+ PacketSender(Unit* unit, Opcodes serverControl, Opcodes playerControl, Opcodes broadcast = SMSG_PLAYER_MOVE, ExtraMovementStatusElement* extras = NULL);
+
+ void Send() const;
+
+ private:
+ ExtraMovementStatusElement* _extraElements;
+ Unit* _unit;
+ Opcodes _selfOpcode;
+ Opcodes _broadcast;
+ };
+
+ bool PrintInvalidSequenceElement(MovementStatusElements element, char const* function);
+}
+
+MovementStatusElements const* GetMovementStatusElementsSequence(Opcodes opcode);
+
+#endif
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 04c88c784ed..02be702d3c2 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -56,7 +56,7 @@ Location MoveSpline::ComputePosition() const
}
else
{
- if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling))
+ if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling | MoveSplineFlag::Unknown0))
{
Vector3 hermite;
spline.evaluate_derivative(point_Idx, u, hermite);
@@ -173,6 +173,13 @@ void MoveSpline::Initialize(const MoveSplineInitArgs& args)
vertical_acceleration = 0.f;
effect_start_time = 0;
+ // Check if its a stop spline
+ if (args.flags.done)
+ {
+ spline.clear();
+ return;
+ }
+
init_spline(args);
// init parabolic / animation
@@ -216,7 +223,7 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const
// each vertex offset packed into 11 bytes
bool MoveSplineInitArgs::_checkPathBounds() const
{
- if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
+ if (!(flags & MoveSplineFlag::Catmullrom) && path.size() > 2)
{
enum{
MAX_OFFSET = (1 << 11) / 2
@@ -266,7 +273,7 @@ MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff)
{
point_Idx = spline.first();
time_passed = time_passed % Duration();
- result = Result_NextSegment;
+ result = Result_NextCycle;
}
else
{
diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h
index ec7eaf7e763..08e73c0344b 100644
--- a/src/server/game/Movement/Spline/MoveSplineFlag.h
+++ b/src/server/game/Movement/Spline/MoveSplineFlag.h
@@ -36,42 +36,45 @@ namespace Movement
enum eFlags
{
None = 0x00000000,
- // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag
- Done = 0x00000100,
- Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
- No_Spline = 0x00000400,
- Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
- Walkmode = 0x00001000,
- Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
- OrientationFixed = 0x00004000, // Model orientation fixed
- Final_Point = 0x00008000,
- Final_Target = 0x00010000,
- Final_Angle = 0x00020000,
- Catmullrom = 0x00040000, // Used Catmullrom interpolation mode
- Cyclic = 0x00080000, // Movement by cycled spline
- Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
- Animation = 0x00200000, // Plays animation after some time passed
- Frozen = 0x00400000, // Will never arrive
- TransportEnter = 0x00800000,
- TransportExit = 0x01000000,
- Unknown7 = 0x02000000,
- Unknown8 = 0x04000000,
- OrientationInversed = 0x08000000,
- Unknown10 = 0x10000000,
- Unknown11 = 0x20000000,
- Unknown12 = 0x40000000,
- Unknown13 = 0x80000000,
+ // x00-x07 used as animation Ids storage in pair with Animation flag
+ Unknown0 = 0x00000008, // NOT VERIFIED
+ FallingSlow = 0x00000010,
+ Done = 0x00000020,
+ Falling = 0x00000040, // Affects elevation computation, can't be combined with Parabolic flag
+ No_Spline = 0x00000080,
+ Unknown2 = 0x00000100, // NOT VERIFIED
+ Flying = 0x00000200, // Smooth movement(Catmullrom interpolation mode), flying animation
+ OrientationFixed = 0x00000400, // Model orientation fixed
+ Catmullrom = 0x00000800, // Used Catmullrom interpolation mode
+ Cyclic = 0x00001000, // Movement by cycled spline
+ Enter_Cycle = 0x00002000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
+ Frozen = 0x00004000, // Will never arrive
+ TransportEnter = 0x00008000,
+ TransportExit = 0x00010000,
+ Unknown3 = 0x00020000, // NOT VERIFIED
+ Unknown4 = 0x00040000, // NOT VERIFIED
+ OrientationInversed = 0x00080000,
+ SmoothGroundPath = 0x00100000,
+ Walkmode = 0x00200000,
+ UncompressedPath = 0x00400000,
+ Unknown6 = 0x00800000, // NOT VERIFIED
+ Animation = 0x01000000, // Plays animation after some time passed
+ Parabolic = 0x02000000, // Affects elevation computation, can't be combined with Falling flag
+ Final_Point = 0x04000000,
+ Final_Target = 0x08000000,
+ Final_Angle = 0x10000000,
+ Unknown7 = 0x20000000, // NOT VERIFIED
+ Unknown8 = 0x40000000, // NOT VERIFIED
+ Unknown9 = 0x80000000, // NOT VERIFIED
// Masks
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
// animation ids stored here, see AnimType enum, used with Animation flag
- Mask_Animations = 0xFF,
+ Mask_Animations = 0x7,
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
- // CatmullRom interpolation mode used
- Mask_CatmullRom = Flying | Catmullrom,
// Unused, not suported flags
- Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13
+ Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown2|Unknown3|Unknown4|Unknown6|Unknown7|Unknown8|Unknown9
};
inline uint32& raw() { return (uint32&)*this; }
@@ -83,7 +86,7 @@ namespace Movement
// Constant interface
- bool isSmooth() const { return raw() & Mask_CatmullRom; }
+ bool isSmooth() const { return raw() & Catmullrom; }
bool isLinear() const { return !isSmooth(); }
bool isFacing() const { return raw() & Mask_Final_Facing; }
@@ -99,42 +102,46 @@ namespace Movement
void operator &= (uint32 f) { raw() &= f; }
void operator |= (uint32 f) { raw() |= f; }
- void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic)) | Animation | anim; }
- void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation)) | Parabolic; }
+ void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic | FallingSlow)) | Animation | (anim & Mask_Animations); }
+ void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation | FallingSlow)) | Parabolic; }
void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation)) | Falling; }
- void EnableFlying() { raw() = (raw() & ~Catmullrom) | Flying; }
- void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; }
+ void EnableCatmullRom() { raw() = (raw() & ~SmoothGroundPath) | Catmullrom; }
void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; }
void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; }
void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target; }
void EnableTransportEnter() { raw() = (raw() & ~TransportExit) | TransportEnter; }
void EnableTransportExit() { raw() = (raw() & ~TransportEnter) | TransportExit; }
- uint8 animId : 8;
+ uint8 animId : 3;
+ bool unknown0 : 1;
+ bool fallingSlow : 1;
bool done : 1;
bool falling : 1;
bool no_spline : 1;
- bool parabolic : 1;
- bool walkmode : 1;
+ bool unknown2 : 1;
bool flying : 1;
bool orientationFixed : 1;
- bool final_point : 1;
- bool final_target : 1;
- bool final_angle : 1;
bool catmullrom : 1;
bool cyclic : 1;
bool enter_cycle : 1;
- bool animation : 1;
bool frozen : 1;
bool transportEnter : 1;
bool transportExit : 1;
+ bool unknown3 : 1;
+ bool unknown4 : 1;
+ bool orientationInversed : 1;
+ bool smoothGroundPath : 1;
+ bool walkmode : 1;
+ bool uncompressedPath : 1;
+ bool unknown6 : 1;
+ bool animation : 1;
+ bool parabolic : 1;
+ bool final_point : 1;
+ bool final_target : 1;
+ bool final_angle : 1;
bool unknown7 : 1;
bool unknown8 : 1;
- bool orientationInversed : 1;
- bool unknown10 : 1;
- bool unknown11 : 1;
- bool unknown12 : 1;
- bool unknown13 : 1;
+ bool unknown9 : 1;
};
#if defined( __GNUC__ )
#pragma pack()
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
index 2f4224c8b91..9cc1dbb3f43 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.cpp
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -60,12 +60,10 @@ namespace Movement
{
MoveSpline& move_spline = *unit->movespline;
- bool transport = false;
Location real_position(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZMinusOffset(), unit->GetOrientation());
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
- if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID())
+ if (unit->GetTransGUID())
{
- transport = true;
real_position.x = unit->GetTransOffsetX();
real_position.y = unit->GetTransOffsetY();
real_position.z = unit->GetTransOffsetZ();
@@ -73,22 +71,22 @@ namespace Movement
}
// there is a big chance that current position is unknown if current state is not finalized, need compute it
- // this also allows CalculatePath spline position and update map position in much greater intervals
+ // this also allows calculate spline position and update map position in much greater intervals
// Don't compute for transport movement if the unit is in a motion between two transports
- if (!move_spline.Finalized() && move_spline.onTransport == transport)
+ if (!move_spline.Finalized() && move_spline.onTransport == (unit->GetTransGUID() != 0))
real_position = move_spline.ComputePosition();
// should i do the things that user should do? - no.
if (args.path.empty())
return 0;
- // corrent first vertex
+ // correct first vertex
args.path[0] = real_position;
args.initialOrientation = real_position.orientation;
- move_spline.onTransport = transport;
+ move_spline.onTransport = (unit->GetTransGUID() != 0);
uint32 moveFlags = unit->m_movementInfo.GetMovementFlags();
- moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD);
+ moveFlags |= MOVEMENTFLAG_FORWARD;
if (moveFlags & MOVEMENTFLAG_ROOT)
moveFlags &= ~MOVEMENTFLAG_MASK_MOVING;
@@ -107,13 +105,14 @@ namespace Movement
if (!args.Validate(unit))
return 0;
- unit->m_movementInfo.SetMovementFlags((MovementFlags)moveFlags);
+ unit->m_movementInfo.SetMovementFlags(moveFlags);
move_spline.Initialize(args);
- WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64);
+ WorldPacket data(SMSG_MONSTER_MOVE, 64);
data.append(unit->GetPackGUID());
- if (transport)
+ if (unit->GetTransGUID())
{
+ data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
data.appendPackGUID(unit->GetTransGUID());
data << int8(unit->GetTransSeat());
}
@@ -124,14 +123,41 @@ namespace Movement
return move_spline.Duration();
}
+ void MoveSplineInit::Stop()
+ {
+ MoveSpline& move_spline = *unit->movespline;
+
+ // No need to stop if we are not moving
+ if (move_spline.Finalized())
+ return;
+
+ Location loc = move_spline.ComputePosition();
+ args.flags = MoveSplineFlag::Done;
+ unit->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD);
+ move_spline.Initialize(args);
+
+ WorldPacket data(SMSG_MONSTER_MOVE, 64);
+ data.append(unit->GetPackGUID());
+ if (unit->GetTransGUID())
+ {
+ data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
+ data.appendPackGUID(unit->GetTransGUID());
+ data << int8(unit->GetTransSeat());
+ }
+
+ PacketBuilder::WriteStopMovement(loc, args.splineId, data);
+ unit->SendMessageToSet(&data, true);
+ }
+
MoveSplineInit::MoveSplineInit(Unit* m) : unit(m)
{
args.splineId = splineIdGen.NewId();
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
- args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
+ args.TransformForTransport = unit->GetTransGUID();
// mix existing state into new
args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
- args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
+ args.flags.flying = unit->m_movementInfo.HasMovementFlag(MovementFlags(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
+ args.flags.smoothGroundPath = true; // enabled by default, CatmullRom mode or client config "pathSmoothing" will disable this
}
void MoveSplineInit::SetFacing(const Unit* target)
@@ -173,6 +199,12 @@ namespace Movement
args.path[1] = transform(dest);
}
+ void MoveSplineInit::SetFall()
+ {
+ args.flags.EnableFalling();
+ args.flags.fallingSlow = unit->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ }
+
Vector3 TransportPathTransform::operator()(Vector3 input)
{
if (_transformForTransport)
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h
index 441bad66142..1eaf1011a2c 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.h
+++ b/src/server/game/Movement/Spline/MoveSplineInit.h
@@ -59,6 +59,10 @@ namespace Movement
*/
int32 Launch();
+ /* Final pass of initialization that stops movement.
+ */
+ void Stop();
+
/* Adds movement by parabolic trajectory
* @param amplitude - the maximum height of parabola, value could be negative and positive
* @param start_time - delay between movement starting time and beginning to move by parabolic trajectory
@@ -98,27 +102,39 @@ namespace Movement
* if not enabled linear spline mode will be choosen. Disabled by default
*/
void SetSmooth();
- /* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default
+
+ /* Waypoints in packets will be sent without compression
+ */
+ void SetUncompressed();
+
+ /* Enables flying animation. Disabled by default
*/
void SetFly();
+
/* Enables walk mode. Disabled by default
*/
void SetWalk(bool enable);
+
/* Makes movement cyclic. Disabled by default
*/
void SetCyclic();
+
/* Enables falling mode. Disabled by default
*/
void SetFall();
+
/* Enters transport. Disabled by default
*/
void SetTransportEnter();
+
/* Exits transport. Disabled by default
*/
void SetTransportExit();
+
/* Inverses unit model orientation. Disabled by default
*/
void SetOrientationInversed();
+
/* Fixes unit's model rotation. Disabled by default
*/
void SetOrientationFixed(bool enable);
@@ -141,11 +157,11 @@ namespace Movement
Unit* unit;
};
- inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); }
+ inline void MoveSplineInit::SetFly() { args.flags.flying = true; }
inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; }
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); }
+ inline void MoveSplineInit::SetUncompressed() { args.flags.uncompressedPath = true; }
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; }
- inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();}
inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; }
inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;}
inline void MoveSplineInit::SetTransportEnter() { args.flags.EnableTransportEnter(); }
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
index 29d1bb50a8f..3376021b494 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
@@ -20,6 +20,7 @@
#include "MovementPacketBuilder.h"
#include "MoveSpline.h"
#include "WorldPacket.h"
+#include "Object.h"
namespace Movement
{
@@ -88,10 +89,18 @@ namespace Movement
}
}
- void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
+ void PacketBuilder::WriteStopMovement(Vector3 const& pos, uint32 splineId, ByteBuffer& data)
+ {
+ data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40)
+ data << pos;
+ data << splineId;
+ data << uint8(MonsterMoveStop);
+ }
+
+ void WriteLinearPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 last_idx = spline.getPointCount() - 3;
- const Vector3 * real_path = &spline.getPoint(1);
+ Vector3 const* real_path = &spline.getPoint(1);
data << last_idx;
data << real_path[last_idx]; // destination
@@ -108,14 +117,14 @@ namespace Movement
}
}
- void WriteCatmullRomPath(const Spline<int32>& spline, ByteBuffer& data)
+ void WriteUncompressedPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 count = spline.getPointCount() - 3;
data << count;
data.append<Vector3>(&spline.getPoint(2), count);
}
- void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data)
+ void WriteUncompressedCyclicPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 count = spline.getPointCount() - 3;
data << uint32(count + 1);
@@ -127,57 +136,113 @@ namespace Movement
{
WriteCommonMonsterMovePart(move_spline, data);
- const Spline<int32>& spline = move_spline.spline;
+ Spline<int32> const& spline = move_spline.spline;
MoveSplineFlag splineflags = move_spline.splineflags;
- if (splineflags & MoveSplineFlag::Mask_CatmullRom)
+ if (splineflags & MoveSplineFlag::UncompressedPath)
{
- if (splineflags.cyclic)
- WriteCatmullRomCyclicPath(spline, data);
+ if (!splineflags.cyclic)
+ WriteUncompressedPath(spline, data);
else
- WriteCatmullRomPath(spline, data);
+ WriteUncompressedCyclicPath(spline, data);
}
else
WriteLinearPath(spline, data);
}
- void PacketBuilder::WriteCreate(const MoveSpline& move_spline, ByteBuffer& data)
+ void PacketBuilder::WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data)
+ {
+ if (!data.WriteBit(!moveSpline.Finalized()))
+ return;
+
+ data.WriteBits(uint8(moveSpline.spline.mode()), 2);
+ data.WriteBit(moveSpline.splineflags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation));
+ data.WriteBits(moveSpline.getPath().size(), 22);
+ switch (moveSpline.splineflags & MoveSplineFlag::Mask_Final_Facing)
+ {
+ case MoveSplineFlag::Final_Target:
+ {
+ ObjectGuid targetGuid = moveSpline.facing.target;
+ data.WriteBits(2, 2);
+ data.WriteBit(targetGuid[4]);
+ data.WriteBit(targetGuid[3]);
+ data.WriteBit(targetGuid[7]);
+ data.WriteBit(targetGuid[2]);
+ data.WriteBit(targetGuid[6]);
+ data.WriteBit(targetGuid[1]);
+ data.WriteBit(targetGuid[0]);
+ data.WriteBit(targetGuid[5]);
+ break;
+ }
+ case MoveSplineFlag::Final_Angle:
+ data.WriteBits(0, 2);
+ break;
+ case MoveSplineFlag::Final_Point:
+ data.WriteBits(1, 2);
+ break;
+ default:
+ data.WriteBits(3, 2);
+ break;
+ }
+
+ data.WriteBit((moveSpline.splineflags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration());
+ data.WriteBits(moveSpline.splineflags.raw(), 25);
+ }
+
+ void PacketBuilder::WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data)
{
- //WriteClientStatus(mov, data);
- //data.append<float>(&mov.m_float_values[SpeedWalk], SpeedMaxCount);
- //if (mov.SplineEnabled())
+ if (!moveSpline.Finalized())
{
- MoveSplineFlag const& splineFlags = move_spline.splineflags;
+ MoveSplineFlag const& splineFlags = moveSpline.splineflags;
+
+ if ((splineFlags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration())
+ data << moveSpline.vertical_acceleration; // added in 3.1
- data << splineFlags.raw();
+ data << moveSpline.timePassed();
if (splineFlags.final_angle)
- {
- data << move_spline.facing.angle;
- }
+ data << moveSpline.facing.angle;
else if (splineFlags.final_target)
{
- data << move_spline.facing.target;
+ ObjectGuid facingGuid = moveSpline.facing.target;
+ data.WriteByteSeq(facingGuid[5]);
+ data.WriteByteSeq(facingGuid[3]);
+ data.WriteByteSeq(facingGuid[7]);
+ data.WriteByteSeq(facingGuid[1]);
+ data.WriteByteSeq(facingGuid[6]);
+ data.WriteByteSeq(facingGuid[4]);
+ data.WriteByteSeq(facingGuid[2]);
+ data.WriteByteSeq(facingGuid[0]);
}
- else if (splineFlags.final_point)
+
+ uint32 nodes = moveSpline.getPath().size();
+ for (uint32 i = 0; i < nodes; ++i)
{
- data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
+ data << float(moveSpline.getPath()[i].z);
+ data << float(moveSpline.getPath()[i].x);
+ data << float(moveSpline.getPath()[i].y);
}
- data << move_spline.timePassed();
- data << move_spline.Duration();
- data << move_spline.GetId();
+ if (splineFlags.final_point)
+ data << moveSpline.facing.f.x << moveSpline.facing.f.z << moveSpline.facing.f.y;
- data << float(1.f); // splineInfo.duration_mod; added in 3.1
data << float(1.f); // splineInfo.duration_mod_next; added in 3.1
+ data << moveSpline.Duration();
+ if (splineFlags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation))
+ data << moveSpline.effect_start_time; // added in 3.1
- data << move_spline.vertical_acceleration; // added in 3.1
- data << move_spline.effect_start_time; // added in 3.1
+ data << float(1.f); // splineInfo.duration_mod; added in 3.1
+ }
- uint32 nodes = move_spline.getPath().size();
- data << nodes;
- data.append<Vector3>(&move_spline.getPath()[0], nodes);
- data << uint8(move_spline.spline.mode()); // added in 3.1
- data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
+ if (!moveSpline.isCyclic())
+ {
+ Vector3 dest = moveSpline.FinalDestination();
+ data << float(dest.z);
+ data << float(dest.x);
+ data << float(dest.y);
}
+ else
+ data << Vector3::zero();
+
+ data << moveSpline.GetId();
}
}
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.h b/src/server/game/Movement/Spline/MovementPacketBuilder.h
index b502e203656..fb6d0f435a0 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.h
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h
@@ -20,6 +20,10 @@
#ifndef TRINITYSERVER_PACKET_BUILDER_H
#define TRINITYSERVER_PACKET_BUILDER_H
+#include "Define.h" // for uint32
+#include "G3D/Vector3.h"
+using G3D::Vector3;
+
class ByteBuffer;
class WorldPacket;
@@ -32,7 +36,9 @@ namespace Movement
public:
static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data);
- static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
+ static void WriteStopMovement(Vector3 const& loc, uint32 splineId, ByteBuffer& data);
+ static void WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data);
+ static void WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data);
};
}
#endif // TRINITYSERVER_PACKET_BUILDER_H
diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h
index 51679260ebb..f044d249fcb 100644
--- a/src/server/game/Movement/Spline/MovementTypedefs.h
+++ b/src/server/game/Movement/Spline/MovementTypedefs.h
@@ -77,6 +77,8 @@ namespace Movement
extern double gravity;
extern float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity);
extern UInt32Counter splineIdGen;
+ extern std::string MovementFlags_ToString(uint32 flags);
+ extern std::string MovementFlagsExtra_ToString(uint32 flags);
}
#endif // TRINITYSERVER_TYPEDEFS_H
diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp
index 3531b629454..aaa575c752f 100644
--- a/src/server/game/Movement/Spline/MovementUtil.cpp
+++ b/src/server/game/Movement/Spline/MovementUtil.cpp
@@ -113,82 +113,86 @@ namespace Movement
STR(Pitch_Up ), // 0x00000040,
STR(Pitch_Down ), // 0x00000080,
- STR(Walk ), // 0x00000100, // Walking
- STR(Ontransport ), // 0x00000200,
- STR(Levitation ), // 0x00000400,
- STR(Root ), // 0x00000800,
- STR(Falling ), // 0x00001000,
- STR(Fallingfar ), // 0x00002000,
- STR(Pendingstop ), // 0x00004000,
- STR(PendingSTRafestop ), // 0x00008000,
- STR(Pendingforward ), // 0x00010000,
- STR(Pendingbackward ), // 0x00020000,
- STR(PendingSTRafeleft ), // 0x00040000,
- STR(PendingSTRaferight ), // 0x00080000,
- STR(Pendingroot ), // 0x00100000,
- STR(Swimming ), // 0x00200000, // Appears With Fly Flag Also
- STR(Ascending ), // 0x00400000, // Swim Up Also
- STR(Descending ), // 0x00800000, // Swim Down Also
- STR(Can_Fly ), // 0x01000000, // Can Fly In 3.3?
- STR(Flying ), // 0x02000000, // Actual Flying Mode
- STR(Spline_Elevation ), // 0x04000000, // Used For Flight Paths
- STR(Spline_Enabled ), // 0x08000000, // Used For Flight Paths
- STR(Waterwalking ), // 0x10000000, // Prevent Unit From Falling Through Water
- STR(Safe_Fall ), // 0x20000000, // Active Rogue Safe Fall Spell (Passive)
- STR(Hover ), // 0x40000000
- STR(Unknown13 ), // 0x80000000
- STR(Unk1 ),
- STR(Unk2 ),
- STR(Unk3 ),
- STR(Fullspeedturning ),
- STR(Fullspeedpitching ),
- STR(Allow_Pitching ),
- STR(Unk4 ),
- STR(Unk5 ),
- STR(Unk6 ),
- STR(Unk7 ),
- STR(Interp_Move ),
- STR(Interp_Turning ),
- STR(Interp_Pitching ),
- STR(Unk8 ),
- STR(Unk9 ),
- STR(Unk10 ),
+ STR(Walking ), // 0x00000100, // Walking
+ STR(DisableGravity ), // 0x00000200,
+ STR(Root ), // 0x00000400,
+ STR(Falling ), // 0x00000800,
+ STR(FallingFar ), // 0x00001000,
+ STR(PendingStop ), // 0x00002000,
+ STR(PendingStrafeStop ), // 0x00004000,
+ STR(PendingForward ), // 0x00008000,
+ STR(PendingBackward ), // 0x00010000,
+ STR(PendingStrafeLeft ), // 0x00020000,
+ STR(PendingStrafeRight ), // 0x00040000,
+ STR(PendingRoot ), // 0x00080000,
+ STR(Swimming ), // 0x00100000, // Appears With Fly Flag Also
+ STR(Ascending ), // 0x00200000, // Swim Up Also
+ STR(Descending ), // 0x00400000, // Swim Down Also
+ STR(Can_Fly ), // 0x00800000, // Can Fly In 3.3?
+ STR(Flying ), // 0x01000000, // Actual Flying Mode
+ STR(Spline_Elevation ), // 0x02000000, // Used For Flight Paths
+ STR(Waterwalking ), // 0x04000000, // Prevent Unit From Falling Through Water
+ STR(Safe_Fall ), // 0x08000000, // Active Rogue Safe Fall Spell (Passive)
+ STR(Hover ), // 0x10000000
+ STR(Local_Dirty ), // 0x20000000
+ STR(None31 ), // 0x40000000
+ STR(None32 ), // 0x80000000
+ };
+
+ char const* g_MovementFlagExtra_names[] =
+ {
+ STR(NoStrafe ),
+ STR(NoJump ),
+ STR(FullSpeedTurning ),
+ STR(FullSpeedPitching ),
+ STR(Allow_Pitching ),
+ STR(Unk6 ),
+ STR(Unk7 ),
+ STR(Unk8 ),
+ STR(Unk9 ),
+ STR(Unk10 ),
+ STR(Unk11 ),
+ STR(Unk12 ),
+ STR(Unk13 ),
+ STR(Interpolated_Movement),
+ STR(Interpolated_Turning ),
+ STR(Interpolated_Pitching),
};
char const* g_SplineFlag_names[32] =
{
- STR(AnimBit1 ), // 0x00000001,
- STR(AnimBit2 ), // 0x00000002,
- STR(AnimBit3 ), // 0x00000004,
- STR(AnimBit4 ), // 0x00000008,
- STR(AnimBit5 ), // 0x00000010,
- STR(AnimBit6 ), // 0x00000020,
- STR(AnimBit7 ), // 0x00000040,
- STR(AnimBit8 ), // 0x00000080,
- STR(Done ), // 0x00000100,
- STR(Falling ), // 0x00000200, // Not Compartible With Trajectory Movement
- STR(No_Spline ), // 0x00000400,
- STR(Trajectory ), // 0x00000800, // Not Compartible With Fall Movement
- STR(Walkmode ), // 0x00001000,
- STR(Flying ), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
- STR(Knockback ), // 0x00004000, // Model Orientation Fixed
- STR(Final_Point ), // 0x00008000,
- STR(Final_Target ), // 0x00010000,
- STR(Final_Angle ), // 0x00020000,
- STR(Catmullrom ), // 0x00040000, // Used Catmullrom Interpolation Mode
- STR(Cyclic ), // 0x00080000, // Movement By Cycled Spline
- STR(Enter_Cycle ), // 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
- STR(Animation ), // 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
- STR(Unknown4 ), // 0x00400000, // Disables Movement By Path
- STR(Unknown5 ), // 0x00800000,
- STR(Unknown6 ), // 0x01000000,
- STR(Unknown7 ), // 0x02000000,
- STR(Unknown8 ), // 0x04000000,
- STR(OrientationInversed ), // 0x08000000, // Appears With Runmode Flag, Nodes ), // 1, Handles Orientation
- STR(Unknown10 ), // 0x10000000,
- STR(Unknown11 ), // 0x20000000,
- STR(Unknown12 ), // 0x40000000,
- STR(Unknown13 ), // 0x80000000,
+ STR(AnimBit1 ), // 0x00000001,
+ STR(AnimBit2 ), // 0x00000002,
+ STR(AnimBit3 ), // 0x00000004,
+ STR(Unknown0 ), // 0x00000008,
+ STR(FallingSlow ), // 0x00000010,
+ STR(Done ), // 0x00000020,
+ STR(Falling ), // 0x00000040, // Not Compartible With Trajectory Movement
+ STR(No_Spline ), // 0x00000080,
+ STR(Unknown2 ), // 0x00000100,
+ STR(Flying ), // 0x00000200, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
+ STR(OrientationFixed ), // 0x00000400, // Model Orientation Fixed
+ STR(Catmullrom ), // 0x00000800, // Used Catmullrom Interpolation Mode
+ STR(Cyclic ), // 0x00001000, // Movement By Cycled Spline
+ STR(Enter_Cycle ), // 0x00002000, // Everytime Appears With Cyclic Flag In Monster Move Packet
+ STR(Frozen ), // 0x00004000,
+ STR(TransportEnter ), // 0x00008000
+ STR(TransportExit ), // 0x00010000
+ STR(Unknown3 ), // 0x00020000,
+ STR(Unknown4 ), // 0x00040000,
+ STR(OrientationInversed), // 0x00080000, // Appears With Runmode Flag, Nodes ), // 1, Handles Orientation
+ STR(SmoothGroundPath ), // 0x00100000,
+ STR(Walkmode ), // 0x00200000,
+ STR(UncompressedPath ), // 0x00400000,
+ STR(Unknown6 ), // 0x00800000,
+ STR(Animation ), // 0x01000000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
+ STR(Parabolic ), // 0x02000000, // Not Compartible With Fall Movement
+ STR(Final_Point ), // 0x04000000,
+ STR(Final_Target ), // 0x08000000,
+ STR(Final_Angle ), // 0x10000000,
+ STR(Unknown7 ), // 0x20000000,
+ STR(Unknown8 ), // 0x40000000,
+ STR(Unknown9 ), // 0x80000000,
};
template<class Flags, int N>
@@ -207,4 +211,18 @@ namespace Movement
print_flags(raw(), g_SplineFlag_names, str);
return str;
}
+
+ std::string MovementFlags_ToString(uint32 flags)
+ {
+ std::string str;
+ print_flags(flags, g_MovementFlag_names, str);
+ return str;
+ }
+
+ std::string MovementFlagsExtra_ToString(uint32 flags)
+ {
+ std::string str;
+ print_flags(flags, g_MovementFlagExtra_names, str);
+ return str;
+ }
}
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h
index 1e23f87a52e..662e80eba7f 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.h
@@ -30,11 +30,10 @@ enum OutdoorPvPTypes
OUTDOOR_PVP_NA = 2,
OUTDOOR_PVP_TF = 3,
OUTDOOR_PVP_ZM = 4,
- OUTDOOR_PVP_SI = 5,
- OUTDOOR_PVP_EP = 6
+ OUTDOOR_PVP_SI = 5
};
-#define MAX_OUTDOORPVP_TYPES 7
+#define MAX_OUTDOORPVP_TYPES 6
enum ObjectiveStates
{
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 3fefa812489..8d4f3b42e72 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -19,20 +19,21 @@
#include "QuestDef.h"
#include "Player.h"
#include "World.h"
+#include "ObjectMgr.h"
Quest::Quest(Field* questRecord)
{
Id = questRecord[0].GetUInt32();
Method = questRecord[1].GetUInt8();
Level = questRecord[2].GetInt16();
- MinLevel = questRecord[3].GetUInt8();
- MaxLevel = questRecord[4].GetUInt8();
+ MinLevel = uint32(questRecord[3].GetInt16());
+ MaxLevel = uint32(questRecord[4].GetInt16());
ZoneOrSort = questRecord[5].GetInt16();
Type = questRecord[6].GetUInt16();
SuggestedPlayers = questRecord[7].GetUInt8();
LimitTime = questRecord[8].GetUInt32();
RequiredClasses = questRecord[9].GetUInt16();
- RequiredRaces = questRecord[10].GetUInt16();
+ RequiredRaces = questRecord[10].GetUInt32();
RequiredSkillId = questRecord[11].GetUInt16();
RequiredSkillPoints = questRecord[12].GetUInt16();
RequiredFactionId1 = questRecord[13].GetUInt16();
@@ -60,112 +61,147 @@ Quest::Quest(Field* questRecord)
SourceItemIdCount = questRecord[35].GetUInt8();
SourceSpellid = questRecord[36].GetUInt32();
Flags = questRecord[37].GetUInt32();
- uint32 SpecialFlags = questRecord[38].GetUInt8();
- RewardTitleId = questRecord[39].GetUInt8();
- RequiredPlayerKills = questRecord[40].GetUInt8();
- RewardTalents = questRecord[41].GetUInt8();
- RewardArenaPoints = questRecord[42].GetUInt16();
+ SpecialFlags = questRecord[38].GetUInt8();
+ MinimapTargetMark = questRecord[39].GetUInt8();
+ RewardTitleId = questRecord[40].GetUInt8();
+ RequiredPlayerKills = questRecord[41].GetUInt8();
+ RewardTalents = questRecord[42].GetUInt8();
+ RewardArenaPoints = questRecord[43].GetUInt16();
+ RewardSkillId = questRecord[44].GetUInt16();
+ RewardSkillPoints = questRecord[45].GetUInt8();
+ RewardReputationMask = questRecord[46].GetUInt8();
+ QuestGiverPortrait = questRecord[47].GetUInt32();
+ QuestTurnInPortrait = questRecord[48].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemId[i] = questRecord[43+i].GetUInt32();
+ RewardItemId[i] = questRecord[49+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemIdCount[i] = questRecord[47+i].GetUInt16();
+ RewardItemIdCount[i] = questRecord[53+i].GetUInt16();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemId[i] = questRecord[51+i].GetUInt32();
+ RewardChoiceItemId[i] = questRecord[57+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemCount[i] = questRecord[57+i].GetUInt16();
+ RewardChoiceItemCount[i] = questRecord[63+i].GetUInt16();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionId[i] = questRecord[63+i].GetUInt16();
+ RewardFactionId[i] = questRecord[69+i].GetUInt16();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueId[i] = questRecord[68+i].GetInt32();
+ RewardFactionValueId[i] = questRecord[74+i].GetInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueIdOverride[i] = questRecord[73+i].GetInt32();
-
- PointMapId = questRecord[78].GetUInt16();
- PointX = questRecord[79].GetFloat();
- PointY = questRecord[80].GetFloat();
- PointOption = questRecord[81].GetUInt32();
- Title = questRecord[82].GetString();
- Objectives = questRecord[83].GetString();
- Details = questRecord[84].GetString();
- EndText = questRecord[85].GetString();
- OfferRewardText = questRecord[86].GetString();
- RequestItemsText = questRecord[87].GetString();
- CompletedText = questRecord[88].GetString();
+ RewardFactionValueIdOverride[i] = questRecord[79+i].GetInt32();
+
+ PointMapId = questRecord[84].GetUInt16();
+ PointX = questRecord[85].GetFloat();
+ PointY = questRecord[86].GetFloat();
+ PointOption = questRecord[87].GetUInt32();
+ Title = questRecord[88].GetString();
+ Objectives = questRecord[89].GetString();
+ Details = questRecord[90].GetString();
+ EndText = questRecord[91].GetString();
+ CompletedText = questRecord[92].GetString();
+ OfferRewardText = questRecord[93].GetString();
+ RequestItemsText = questRecord[94].GetString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGo[i] = questRecord[89+i].GetInt32();
+ RequiredNpcOrGo[i] = questRecord[95+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGoCount[i] = questRecord[93+i].GetUInt16();
+ RequiredNpcOrGoCount[i] = questRecord[99+i].GetUInt16();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemId[i] = questRecord[97+i].GetUInt32();
+ RequiredSourceItemId[i] = questRecord[103+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemCount[i] = questRecord[101+i].GetUInt16();
+ RequiredSourceItemCount[i] = questRecord[107+i].GetUInt16();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemId[i] = questRecord[105+i].GetUInt32();
+ RequiredItemId[i] = questRecord[111+i].GetUInt32();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemCount[i] = questRecord[111+i].GetUInt16();
+ RequiredItemCount[i] = questRecord[117+i].GetUInt16();
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredSpellCast[i] = questRecord[117+i].GetUInt32();
+ RequiredSpell = questRecord[123].GetUInt32();
- // int8 Unknown0 = questRecord[121].GetUInt8();
+ for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) // To be removed
+ RequiredSpellCast[i] = questRecord[124+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ObjectiveText[i] = questRecord[122+i].GetString();
+ ObjectiveText[i] = questRecord[128+i].GetString();
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ RewardCurrencyId[i] = questRecord[132+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ RewardCurrencyCount[i] = questRecord[136+i].GetUInt8();
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ RequiredCurrencyId[i] = questRecord[140+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ RequiredCurrencyCount[i] = questRecord[144+i].GetUInt8();
+
+ QuestGiverTextWindow = questRecord[148].GetString();
+ QuestGiverTargetName = questRecord[149].GetString();
+ QuestTurnTextWindow = questRecord[150].GetString();
+ QuestTurnTargetName = questRecord[151].GetString();
+ SoundAccept = questRecord[152].GetUInt16();
+ SoundTurnIn = questRecord[153].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmote[i] = questRecord[126+i].GetUInt16();
+ DetailsEmote[i] = questRecord[154+i].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmoteDelay[i] = questRecord[130+i].GetUInt32();
+ DetailsEmoteDelay[i] = questRecord[158+i].GetUInt32();
- EmoteOnIncomplete = questRecord[134].GetUInt16();
- EmoteOnComplete = questRecord[135].GetUInt16();
+ EmoteOnIncomplete = questRecord[162].GetUInt16();
+ EmoteOnComplete = questRecord[163].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmote[i] = questRecord[136+i].GetInt16();
+ OfferRewardEmote[i] = questRecord[164+i].GetInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmoteDelay[i] = questRecord[140+i].GetInt32();
+ OfferRewardEmoteDelay[i] = questRecord[168+i].GetInt32();
- //int32 WDBVerified = questRecord[144].GetInt32();
+ // int32 WDBVerified = questRecord[172].GetInt32();
- Flags |= SpecialFlags << 20;
- if (Flags & QUEST_TRINITY_FLAGS_AUTO_ACCEPT)
+ if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
Flags |= QUEST_FLAGS_AUTO_ACCEPT;
- m_reqitemscount = 0;
- m_reqCreatureOrGOcount = 0;
- m_rewitemscount = 0;
- m_rewchoiceitemscount = 0;
+ m_reqItemsCount = 0;
+ m_reqNpcOrGoCount = 0;
+ m_rewItemsCount = 0;
+ m_rewChoiceItemsCount = 0;
+ m_rewCurrencyCount = 0;
+ m_reqCurrencyCount = 0;
- for (int i=0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
+ for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
if (RequiredItemId[i])
- ++m_reqitemscount;
+ ++m_reqItemsCount;
- for (int i=0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
if (RequiredNpcOrGo[i])
- ++m_reqCreatureOrGOcount;
+ ++m_reqNpcOrGoCount;
- for (int i=0; i < QUEST_REWARDS_COUNT; ++i)
+ for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
if (RewardItemId[i])
- ++m_rewitemscount;
+ ++m_rewItemsCount;
- for (int i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
if (RewardChoiceItemId[i])
- ++m_rewchoiceitemscount;
+ ++m_rewChoiceItemsCount;
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ if (RewardCurrencyId[i])
+ ++m_rewCurrencyCount;
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ if (RequiredCurrencyId[i])
+ ++m_reqCurrencyCount;
+
}
uint32 Quest::XPValue(Player* player) const
@@ -207,6 +243,79 @@ int32 Quest::GetRewOrReqMoney() const
return int32(RewardOrRequiredMoney * sWorld->getRate(RATE_DROP_MONEY));
}
+void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const
+{
+ data << uint32(GetRewChoiceItemsCount());
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ data << uint32(RewardChoiceItemId[i]);
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ data << uint32(RewardChoiceItemCount[i]);
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ {
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i]))
+ data << uint32(itemTemplate->DisplayInfoID);
+ else
+ data << uint32(0);
+ }
+
+ data << uint32(GetReqItemsCount());
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ data << uint32(RewardItemId[i]);
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ data << uint32(RewardItemIdCount[i]);
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i]))
+ data << uint32(itemTemplate->DisplayInfoID);
+ else
+ data << uint32(0);
+ }
+
+ data << uint32(GetRewOrReqMoney());
+ data << uint32(XPValue(player) * sWorld->getRate(RATE_XP_QUEST));
+
+ data << uint32(GetCharTitleId());
+ data << uint32(0); // unk
+ data << float(0.0f); // unk
+ data << uint32(GetBonusTalents());
+ data << uint32(0); // unk
+ data << uint32(GetRewardReputationMask());
+
+ /* Pre cata struct, some of these unks might be the missing values in cata:
+ // rewarded honor points. Multiply with 10 to satisfy client
+ data << 10 * Trinity::Honor::hk_honor_at_level(_session->GetPlayer()->getLevel(), quest->GetRewHonorMultiplier());
+ data << float(0); // unk, honor multiplier?
+ data << uint32(0x08); // unused by client?
+ data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
+ data << int32(quest->GetRewSpellCast()); // casted spell
+ data << uint32(0); // unknown
+ data << uint32(quest->GetBonusTalents()); // bonus talents
+ data << uint32(quest->GetRewArenaPoints()); // arena points
+ data << uint32(0);
+ */
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
+ data << uint32(RewardFactionId[i]);
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (zero based)?
+ data << int32(RewardFactionValueId[i]);
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override?
+ data << uint32(RewardFactionValueIdOverride[i]);
+
+ data << uint32(GetRewSpell());
+ data << uint32(GetRewSpellCast());
+
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ data << uint32(RewardCurrencyId[i]);
+
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ data << uint32(RewardCurrencyCount[i]);
+
+ data << uint32(GetRewardSkillId());
+ data << uint32(GetRewardSkillPoints());
+}
+
uint32 Quest::GetRewMoneyMaxLevel() const
{
if (HasFlag(QUEST_FLAGS_NO_MONEY_FROM_XP))
@@ -257,7 +366,7 @@ uint32 Quest::CalculateHonorGain(uint8 level) const
uint32 honor = 0;
- if (GetRewHonorAddition() > 0 || GetRewHonorMultiplier() > 0.0f)
+ /*if (GetRewHonorAddition() > 0 || GetRewHonorMultiplier() > 0.0f)
{
// values stored from 0.. for 1...
TeamContributionPointsEntry const* tc = sTeamContributionPointsStore.LookupEntry(level);
@@ -266,7 +375,7 @@ uint32 Quest::CalculateHonorGain(uint8 level) const
honor = uint32(tc->value * GetRewHonorMultiplier() * 0.1f);
honor += GetRewHonorAddition();
- }
+ }*/
return honor;
}
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index a447f4a8f52..34c0a1fd9d8 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -22,6 +22,7 @@
#include "Define.h"
#include "DatabaseEnv.h"
#include "SharedDefines.h"
+#include "WorldPacket.h"
#include "DBCEnums.h"
#include <string>
@@ -42,6 +43,8 @@ class ObjectMgr;
#define QUEST_REPUTATIONS_COUNT 5
#define QUEST_EMOTE_COUNT 4
#define QUEST_PVP_KILL_SLOT 0
+#define QUEST_REWARD_CURRENCY_COUNT 4
+#define QUEST_REQUIRED_CURRENCY_COUNT 4
enum QuestFailedReasons
{
@@ -108,22 +111,22 @@ enum QuestStatus
enum __QuestGiverStatus
{
- DIALOG_STATUS_NONE = 0,
- DIALOG_STATUS_UNAVAILABLE = 1,
- DIALOG_STATUS_LOW_LEVEL_AVAILABLE = 2,
- DIALOG_STATUS_LOW_LEVEL_REWARD_REP = 3,
- DIALOG_STATUS_LOW_LEVEL_AVAILABLE_REP = 4,
- DIALOG_STATUS_INCOMPLETE = 5,
- DIALOG_STATUS_REWARD_REP = 6,
- DIALOG_STATUS_AVAILABLE_REP = 7,
- DIALOG_STATUS_AVAILABLE = 8,
- DIALOG_STATUS_REWARD2 = 9, // no yellow dot on minimap
- DIALOG_STATUS_REWARD = 10 // yellow dot on minimap
+ DIALOG_STATUS_NONE = 0x000,
+ DIALOG_STATUS_UNK = 0x001,
+ DIALOG_STATUS_UNAVAILABLE = 0x002,
+ DIALOG_STATUS_LOW_LEVEL_AVAILABLE = 0x004,
+ DIALOG_STATUS_LOW_LEVEL_REWARD_REP = 0x008,
+ DIALOG_STATUS_LOW_LEVEL_AVAILABLE_REP = 0x010,
+ DIALOG_STATUS_INCOMPLETE = 0x020,
+ DIALOG_STATUS_REWARD_REP = 0x040,
+ DIALOG_STATUS_AVAILABLE_REP = 0x080,
+ DIALOG_STATUS_AVAILABLE = 0x100,
+ DIALOG_STATUS_REWARD2 = 0x200, // no yellow dot on minimap
+ DIALOG_STATUS_REWARD = 0x400 // yellow dot on minimap
};
enum QuestFlags
{
- // Flags used at server and sent to client
QUEST_FLAGS_NONE = 0x00000000,
QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
@@ -145,22 +148,32 @@ enum QuestFlags
QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x00020000, // Displays usable item in quest tracker
QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
+ QUEST_FLAGS_AUTO_SUBMIT = 0x00100000, // Quests with this flag player submit automatically by special button in player gui
+ QUEST_FLAGS_AUTO_TAKE = 0x00200000, // Automatically suggestion of accepting quest. Not from npc.
+ //QUEST_FLAGS_UNK2 = 0x00400000,
+ //QUEST_FLAGS_UNK3 = 0x00800000, // Found in quest 14069
+ //QUEST_FLAGS_UNK4 = 0x01000000,
+ // ... 4.x added flags up to 0x80000000 - all unknown for now
+};
+enum __QuestSpecialFlags
+{
+ QUEST_SPECIAL_FLAGS_NONE = 0x000,
// Trinity flags for set SpecialFlags in DB if required but used only at server
- QUEST_TRINITY_FLAGS_REPEATABLE = 0x00100000, // Set by 1 in SpecialFlags from DB
- QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT = 0x00200000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
- QUEST_TRINITY_FLAGS_AUTO_ACCEPT = 0x00400000, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
- QUEST_TRINITY_FLAGS_DF_QUEST = 0x00800000, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
- QUEST_TRINITY_FLAGS_MONTHLY = 0x01000000, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
+ QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001,
+ QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
+ QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // quest is to be auto-accepted.
+ QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // quest is used by Dungeon Finder.
+ QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // quest is reset at the begining of the month
+ // room for more custom flags
- QUEST_TRINITY_FLAGS_DB_ALLOWED = 0xFFFFF | QUEST_TRINITY_FLAGS_REPEATABLE | QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT | QUEST_TRINITY_FLAGS_AUTO_ACCEPT | QUEST_TRINITY_FLAGS_DF_QUEST | QUEST_TRINITY_FLAGS_MONTHLY,
+ QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY,
- // Trinity flags for internal use only
- QUEST_TRINITY_FLAGS_DELIVER = 0x04000000, // Internal flag computed only
- QUEST_TRINITY_FLAGS_SPEAKTO = 0x08000000, // Internal flag computed only
- QUEST_TRINITY_FLAGS_KILL_OR_CAST = 0x10000000, // Internal flag computed only
- QUEST_TRINITY_FLAGS_TIMED = 0x20000000, // Internal flag computed only
- QUEST_TRINITY_FLAGS_PLAYER_KILL = 0x40000000 // Internal flag computed only
+ QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
+ QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
+ QUEST_SPECIAL_FLAGS_KILL_OR_CAST = 0x200, // Internal flag computed only
+ QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only
+ QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800 // Internal flag computed only
};
struct QuestLocale
@@ -175,6 +188,11 @@ struct QuestLocale
StringVector EndText;
StringVector CompletedText;
std::vector< StringVector > ObjectiveText;
+ // new on 4.x
+ StringVector QuestGiverTextWindow;
+ StringVector QuestGiverTargetName;
+ StringVector QuestTurnTextWindow;
+ StringVector QuestTurnTargetName;
};
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
@@ -190,6 +208,9 @@ class Quest
bool HasFlag(uint32 flag) const { return (Flags & flag) != 0; }
void SetFlag(uint32 flag) { Flags |= flag; }
+ bool HasSpecialFlag(uint32 flag) const { return (SpecialFlags & flag) != 0; }
+ void SetSpecialFlag(uint32 flag) { SpecialFlags |= flag; }
+
// table data accessors:
uint32 GetQuestId() const { return Id; }
uint32 GetQuestMethod() const { return Method; }
@@ -231,6 +252,10 @@ class Quest
std::string const& GetRequestItemsText() const { return RequestItemsText; }
std::string const& GetEndText() const { return EndText; }
std::string const& GetCompletedText() const { return CompletedText; }
+ std::string const& GetQuestGiverTextWindow() const { return QuestGiverTextWindow; }
+ std::string const& GetQuestGiverTargetName() const { return QuestGiverTargetName; }
+ std::string const& GetQuestTurnTextWindow() const { return QuestTurnTextWindow; }
+ std::string const& GetQuestTurnTargetName() const { return QuestTurnTargetName; }
int32 GetRewOrReqMoney() const;
uint32 GetRewHonorAddition() const { return RewardHonor; }
float GetRewHonorMultiplier() const { return RewardHonorMultiplier; }
@@ -243,20 +268,30 @@ class Quest
float GetPointX() const { return PointX; }
float GetPointY() const { return PointY; }
uint32 GetPointOpt() const { return PointOption; }
+ uint32 GetRequiredSpell() const { return RequiredSpell; }
+ uint32 GetSoundAccept() const { return SoundAccept; }
+ uint32 GetSoundTurnIn() const { return SoundTurnIn; }
uint32 GetIncompleteEmote() const { return EmoteOnIncomplete; }
uint32 GetCompleteEmote() const { return EmoteOnComplete; }
- bool IsRepeatable() const { return Flags & QUEST_TRINITY_FLAGS_REPEATABLE; }
+ bool IsRepeatable() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
bool IsAutoAccept() const;
bool IsAutoComplete() const;
uint32 GetFlags() const { return Flags; }
+ uint32 GetSpecialFlags() const { return SpecialFlags; }
+ uint32 GetMinimapTargetMark() const { return MinimapTargetMark; }
+ uint32 GetRewardSkillId() const { return RewardSkillId; }
+ uint32 GetRewardSkillPoints() const { return RewardSkillPoints; }
+ uint32 GetRewardReputationMask() const { return RewardReputationMask; }
+ uint32 GetQuestGiverPortrait() const { return QuestGiverPortrait; }
+ uint32 GetQuestTurnInPortrait() const { return QuestTurnInPortrait; }
bool IsDaily() const { return Flags & QUEST_FLAGS_DAILY; }
bool IsWeekly() const { return Flags & QUEST_FLAGS_WEEKLY; }
- bool IsMonthly() const { return Flags & QUEST_TRINITY_FLAGS_MONTHLY; }
+ bool IsMonthly() const { return Flags & QUEST_SPECIAL_FLAGS_MONTHLY; }
bool IsSeasonal() const { return (ZoneOrSort == -QUEST_SORT_SEASONAL || ZoneOrSort == -QUEST_SORT_SPECIAL || ZoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || ZoneOrSort == -QUEST_SORT_MIDSUMMER || ZoneOrSort == -QUEST_SORT_BREWFEST || ZoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || ZoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
bool IsDailyOrWeekly() const { return Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); }
bool IsRaidQuest(Difficulty difficulty) const;
bool IsAllowedInRaid(Difficulty difficulty) const;
- bool IsDFQuest() const { return Flags & QUEST_TRINITY_FLAGS_DF_QUEST; }
+ bool IsDFQuest() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST; }
uint32 CalculateHonorGain(uint8 level) const;
// multiple values
@@ -279,11 +314,20 @@ class Quest
uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmote[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT];
+ // 4.x
+ uint32 RewardCurrencyId[QUEST_REWARD_CURRENCY_COUNT];
+ uint32 RewardCurrencyCount[QUEST_REWARD_CURRENCY_COUNT];
+ uint32 RequiredCurrencyId[QUEST_REQUIRED_CURRENCY_COUNT];
+ uint32 RequiredCurrencyCount[QUEST_REQUIRED_CURRENCY_COUNT];
- uint32 GetReqItemsCount() const { return m_reqitemscount; }
- uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; }
- uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; }
- uint32 GetRewItemsCount() const { return m_rewitemscount; }
+ uint32 GetReqItemsCount() const { return m_reqItemsCount; }
+ uint32 GetReqCreatureOrGOcount() const { return m_reqNpcOrGoCount; }
+ uint32 GetRewChoiceItemsCount() const { return m_rewChoiceItemsCount; }
+ uint32 GetRewItemsCount() const { return m_rewItemsCount; }
+ uint32 GetRewCurrencyCount() const { return m_rewCurrencyCount; }
+ uint32 GetReqCurrencyCount() const { return m_reqCurrencyCount; }
+
+ void BuildExtraQuestInfo(WorldPacket& data, Player* player) const;
typedef std::vector<int32> PrevQuests;
PrevQuests prevQuests;
@@ -292,10 +336,12 @@ class Quest
// cached data
private:
- uint32 m_reqitemscount;
- uint32 m_reqCreatureOrGOcount;
- uint32 m_rewchoiceitemscount;
- uint32 m_rewitemscount;
+ uint32 m_reqItemsCount;
+ uint32 m_reqNpcOrGoCount;
+ uint32 m_rewChoiceItemsCount;
+ uint32 m_rewItemsCount;
+ uint32 m_rewCurrencyCount;
+ uint32 m_reqCurrencyCount;
// table data
protected:
@@ -354,6 +400,22 @@ class Quest
uint32 PointOption;
uint32 EmoteOnIncomplete;
uint32 EmoteOnComplete;
+ // new in 4.x
+ uint32 MinimapTargetMark;
+ uint32 RewardSkillId;
+ uint32 RewardSkillPoints;
+ uint32 RewardReputationMask;
+ uint32 QuestGiverPortrait;
+ uint32 QuestTurnInPortrait;
+ uint32 RequiredSpell;
+ std::string QuestGiverTextWindow;
+ std::string QuestGiverTargetName;
+ std::string QuestTurnTextWindow;
+ std::string QuestTurnTargetName;
+ uint32 SoundAccept;
+ uint32 SoundTurnIn;
+
+ uint32 SpecialFlags; // custom flags, not sniffed/WDB
};
struct QuestStatusData
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index 9c996a9c386..3f8f58df8a7 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -25,6 +25,7 @@
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "Opcodes.h"
+#include "WorldSession.h"
const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
@@ -198,7 +199,7 @@ void ReputationMgr::SendState(FactionState const* faction)
void ReputationMgr::SendInitialReputations()
{
- uint8 count = 128;
+ uint16 count = 256;
WorldPacket data(SMSG_INITIALIZE_FACTIONS, 4 + count * 5);
data << uint32(count);
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index 9eb6dbed73b..bb791cd3810 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -886,12 +886,10 @@ void Map::ScriptsProcess()
if (!targetUnit)
break;
- sourceUnit->SetInFront(targetUnit);
+ sourceUnit->SetFacingToObject(targetUnit);
}
else
- sourceUnit->SetOrientation(step.script->Orientation.Orientation);
-
- sourceUnit->SendMovementFlagUpdate();
+ sourceUnit->SetFacingTo(step.script->Orientation.Orientation);
}
break;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index e65c5884319..b566f9dabe1 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -101,6 +101,8 @@ void AddSC_boss_balinda();
void AddSC_boss_drekthar();
void AddSC_boss_galvangar();
void AddSC_boss_vanndar();
+void AddSC_boss_alizabal(); //Baradin Hold
+void AddSC_instance_baradin_hold();
void AddSC_blackrock_depths(); //Blackrock Depths
void AddSC_boss_ambassador_flamelash();
void AddSC_boss_anubshiah();
@@ -235,25 +237,19 @@ void AddSC_boss_nalorakk();
void AddSC_boss_zuljin();
void AddSC_instance_zulaman();
void AddSC_zulaman();
-void AddSC_boss_jeklik(); //Zul'Gurub
-void AddSC_boss_venoxis();
-void AddSC_boss_marli();
-void AddSC_boss_mandokir();
-void AddSC_boss_gahzranka();
-void AddSC_boss_thekal();
-void AddSC_boss_arlokk();
-void AddSC_boss_jindo();
-void AddSC_boss_hakkar();
-void AddSC_boss_grilek();
+void AddSC_boss_grilek(); // Zul'Gurub
void AddSC_boss_hazzarah();
+void AddSC_boss_jindo_the_godbreaker();
+void AddSC_boss_kilnara();
+void AddSC_boss_mandokir();
void AddSC_boss_renataki();
+void AddSC_boss_venoxis();
void AddSC_boss_wushoolay();
+void AddSC_boss_zanzil();
void AddSC_instance_zulgurub();
-
//void AddSC_alterac_mountains();
void AddSC_arathi_highlands();
void AddSC_blasted_lands();
-void AddSC_boss_kruul();
void AddSC_burning_steppes();
void AddSC_duskwood();
void AddSC_eastern_plaguelands();
@@ -339,12 +335,17 @@ void AddSC_wailing_caverns(); //Wailing caverns
void AddSC_instance_wailing_caverns();
void AddSC_zulfarrak(); //Zul'Farrak generic
void AddSC_instance_zulfarrak(); //Zul'Farrak instance script
+void AddSC_instance_halls_of_origination();
+void AddSC_boss_temple_guardian_anhuur();
+void AddSC_boss_earthrager_ptah();
+void AddSC_boss_anraphet();
+void AddSC_instance_firelands();
+void AddSC_boss_alysrazor();
void AddSC_ashenvale();
void AddSC_azshara();
void AddSC_azuremyst_isle();
void AddSC_bloodmyst_isle();
-void AddSC_boss_azuregos();
void AddSC_darkshore();
void AddSC_desolace();
void AddSC_durotar();
@@ -618,7 +619,6 @@ void AddSC_event_childrens_week();
// battlegrounds
// outdoor pvp
-void AddSC_outdoorpvp_ep();
void AddSC_outdoorpvp_hp();
void AddSC_outdoorpvp_na();
void AddSC_outdoorpvp_si();
@@ -743,6 +743,8 @@ void AddEasternKingdomsScripts()
AddSC_boss_drekthar();
AddSC_boss_galvangar();
AddSC_boss_vanndar();
+ AddSC_boss_alizabal(); //Baradin Hold
+ AddSC_instance_baradin_hold();
AddSC_blackrock_depths(); //Blackrock Depths
AddSC_boss_ambassador_flamelash();
AddSC_boss_anubshiah();
@@ -877,25 +879,20 @@ void AddEasternKingdomsScripts()
AddSC_boss_zuljin();
AddSC_instance_zulaman();
AddSC_zulaman();
- AddSC_boss_jeklik(); //Zul'Gurub
- AddSC_boss_venoxis();
- AddSC_boss_marli();
- AddSC_boss_mandokir();
- AddSC_boss_gahzranka();
- AddSC_boss_thekal();
- AddSC_boss_arlokk();
- AddSC_boss_jindo();
- AddSC_boss_hakkar();
- AddSC_boss_grilek();
+ AddSC_boss_grilek(); // Zul'Gurub
AddSC_boss_hazzarah();
+ AddSC_boss_jindo_the_godbreaker();
+ AddSC_boss_kilnara();
+ AddSC_boss_mandokir();
AddSC_boss_renataki();
+ AddSC_boss_venoxis();
AddSC_boss_wushoolay();
+ AddSC_boss_zanzil();
AddSC_instance_zulgurub();
//AddSC_alterac_mountains();
AddSC_arathi_highlands();
AddSC_blasted_lands();
- AddSC_boss_kruul();
AddSC_burning_steppes();
AddSC_duskwood();
AddSC_eastern_plaguelands();
@@ -990,7 +987,6 @@ void AddKalimdorScripts()
AddSC_azshara();
AddSC_azuremyst_isle();
AddSC_bloodmyst_isle();
- AddSC_boss_azuregos();
AddSC_darkshore();
AddSC_desolace();
AddSC_durotar();
@@ -1009,6 +1005,14 @@ void AddKalimdorScripts()
AddSC_thunder_bluff();
AddSC_ungoro_crater();
AddSC_winterspring();
+
+ AddSC_instance_halls_of_origination();
+ AddSC_boss_temple_guardian_anhuur();
+ AddSC_boss_earthrager_ptah();
+ AddSC_boss_anraphet();
+
+ AddSC_instance_firelands();
+ AddSC_boss_alysrazor();
#endif
}
@@ -1278,7 +1282,6 @@ void AddEventScripts()
void AddOutdoorPvPScripts()
{
#ifdef SCRIPTS
- AddSC_outdoorpvp_ep();
AddSC_outdoorpvp_hp();
AddSC_outdoorpvp_na();
AddSC_outdoorpvp_si();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 0dc96b3dfd9..3272498662b 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1153,7 +1153,7 @@ void ScriptMgr::OnPlayerTalentsReset(Player* player, bool noCost)
FOREACH_SCRIPT(PlayerScript)->OnTalentsReset(player, noCost);
}
-void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount)
+void ScriptMgr::OnPlayerMoneyChanged(Player* player, int64& amount)
{
FOREACH_SCRIPT(PlayerScript)->OnMoneyChanged(player, amount);
}
@@ -1289,12 +1289,12 @@ void ScriptMgr::OnGuildDisband(Guild* guild)
FOREACH_SCRIPT(GuildScript)->OnDisband(guild);
}
-void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair)
+void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint64 &amount, bool isRepair)
{
FOREACH_SCRIPT(GuildScript)->OnMemberWitdrawMoney(guild, player, amount, isRepair);
}
-void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount)
+void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint64 &amount)
{
FOREACH_SCRIPT(GuildScript)->OnMemberDepositMoney(guild, player, amount);
}
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index fa484fc725d..85797ac351b 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -60,7 +60,6 @@ class WorldPacket;
class WorldSocket;
class WorldObject;
-struct AchievementCriteriaData;
struct AuctionEntry;
struct ConditionSourceInfo;
struct Condition;
@@ -698,7 +697,7 @@ class PlayerScript : public UnitScript
virtual void OnTalentsReset(Player* /*player*/, bool /*noCost*/) { }
// Called when a player's money is modified (before the modification is done)
- virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
+ virtual void OnMoneyChanged(Player* /*player*/, int64& /*amount*/) { }
// Called when a player gains XP (before anything is given)
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
@@ -788,10 +787,10 @@ class GuildScript : public ScriptObject
virtual void OnDisband(Guild* /*guild*/) { }
// Called when a guild member withdraws money from a guild bank.
- virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/, bool /*isRepair*/) { }
+ virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint64& /*amount*/, bool /*isRepair*/) { }
// Called when a guild member deposits money in a guild bank.
- virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/) { }
+ virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint64& /*amount*/) { }
// Called when a guild member moves an item in a guild bank.
virtual void OnItemMove(Guild* /*guild*/, Player* /*player*/, Item* /*pItem*/, bool /*isSrcBank*/, uint8 /*srcContainer*/, uint8 /*srcSlotId*/,
@@ -1010,7 +1009,7 @@ class ScriptMgr
void OnPlayerLevelChanged(Player* player, uint8 oldLevel);
void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints);
void OnPlayerTalentsReset(Player* player, bool noCost);
- void OnPlayerMoneyChanged(Player* player, int32& amount);
+ void OnPlayerMoneyChanged(Player* player, int64& amount);
void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
void OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
void OnPlayerDuelRequest(Player* target, Player* challenger);
@@ -1040,8 +1039,8 @@ class ScriptMgr
void OnGuildInfoChanged(Guild* guild, const std::string& newInfo);
void OnGuildCreate(Guild* guild, Player* leader, const std::string& name);
void OnGuildDisband(Guild* guild);
- void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair);
- void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount);
+ void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint64 &amount, bool isRepair);
+ void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint64 &amount);
void OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
bool isDestBank, uint8 destContainer, uint8 destSlotId);
void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 065b80cb08f..9acc4a15dc4 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -16,1325 +16,1651 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- \ingroup u2w
-*/
-
#include "Opcodes.h"
#include "WorldSession.h"
+OpcodeTable opcodeTable;
+
+template<bool isInValidRange, bool isNonZero>
+void OpcodeTable::ValidateAndSetOpcode(uint16 /*opcode*/, char const* /*name*/, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ // if for some reason we are here, that means NUM_OPCODE_HANDLERS == 0 (or your compiler is broken)
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<true, true>(uint16 opcode, char const* name, SessionStatus status, PacketProcessing processing, pOpcodeHandler handler)
+{
+ if (_internalTable[opcode] != NULL)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Tried to override handler of %s with %s (opcode %u)", opcodeTable[opcode]->Name, name, opcode);
+ return;
+ }
+
+ _internalTable[opcode] = new OpcodeHandler(name, status, processing, handler);
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<false, true>(uint16 opcode, char const* /*name*/, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Tried to set handler for an invalid opcode %d", opcode);
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<true, false>(uint16 /*opcode*/, char const* name, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Opcode %s got value 0", name);
+}
+
/// Correspondence between opcodes and their names
-OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
+void OpcodeTable::Initialize()
{
- /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode },
- /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCreateOpcode },
- /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharEnumOpcode },
- /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharDeleteOpcode },
- /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLoginOpcode },
- /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLogoutOpcode },
- /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode },
- /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode },
- /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode },
- /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery },
- /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryOpcode },
- /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleItemQuerySingleOpcode },
- /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePageTextQueryOpcode },
- /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode },
- /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGameObjectQueryOpcode },
- /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode },
- /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode },
- /*0x063*/ { "SMSG_WHO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode },
- /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode },
- /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddFriendOpcode },
- /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode },
- /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetContactNotesOpcode },
- /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddIgnoreOpcode },
- /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode },
- /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode },
- /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAcceptOpcode },
- /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDeclineOpcode },
- /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode },
- /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteGuidOpcode },
- /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSetLeaderOpcode },
- /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode },
- /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDisbandOpcode },
- /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildCreateOpcode },
- /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInviteOpcode },
- /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAcceptOpcode },
- /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDeclineOpcode },
- /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInfoOpcode },
- /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRosterOpcode },
- /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPromoteOpcode },
- /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDemoteOpcode },
- /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaveOpcode },
- /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode },
- /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode },
- /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaderOpcode },
- /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildMOTDOpcode },
- /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode },
- /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleJoinChannel },
- /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveChannel },
- /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelList },
- /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelPassword },
- /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelSetOwner },
- /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelOwner },
- /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerator },
- /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmoderator },
- /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelMute },
- /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmute },
- /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelInvite },
- /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelKick },
- /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelBan },
- /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnban },
- /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements },
- /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL },
- /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode },
- /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode },
- /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem },
- /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameObjectUseOpcode },
- /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaTriggerOpcode },
- /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAck },
- /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode },
- /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E0*/ { "CMSG_MOVE_CHARM_PORT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck },
- /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck },
- /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck },
- /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck },
- /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera },
- /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic },
- /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag },
- /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialClear },
- /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialReset },
- /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode },
- /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode },
- /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode },
- /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutostoreLootItemOpcode },
- /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode },
- /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBagItemOpcode },
- /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem },
- /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode },
- /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSplitItemOpcode },
- /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemSlotOpcode },
- /*0x110*/ { "CMSG_UNCLAIM_LICENSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode },
- /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectOpcode },
- /*0x115*/ { "SMSG_INSPECT_RESULTS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode },
- /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode },
- /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode },
- /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode },
- /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode },
- /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode },
- /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode },
- /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode },
- /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode },
- /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode },
- /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar },
- /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionCheat },
- /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionButtonOpcode },
- /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode },
- /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode },
- /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode },
- /*0x137*/ { "SMSG_EQUIPMENT_SET_SAVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelChanneling },
- /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode },
- /*0x13E*/ { "CMSG_DELETEEQUIPMENT_SET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete },
- /*0x13F*/ { "CMSG_INSTANCE_LOCK_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse },
- /*0x140*/ { "CMSG_DEBUG_PASSIVE_AURA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode },
- /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode },
- /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x147*/ { "SMSG_INSTANCE_LOCK_WARNING_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14C*/ { "CMSG_PERFORM_ACTION_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x14D*/ { "SMSG_RESUME_CAST_BAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode },
- /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResurrectResponseOpcode },
- /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode },
- /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMoneyOpcode },
- /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootReleaseOpcode },
- /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelAcceptedOpcode },
- /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelCancelledOpcode },
- /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x170*/ { "SMSG_REMOVED_FROM_PVP_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode },
- /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSetAction },
- /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction },
- /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon },
- /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename },
- /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipHelloOpcode },
- /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipSelectOptionOpcode },
- /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNpcTextQueryOpcode },
- /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverStatusQueryOpcode},
- /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverHelloOpcode },
- /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode},
- /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQuestAutoLaunch },
- /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode},
- /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest },
- /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode},
- /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode},
- /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCancel },
- /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogSwapQuest },
- /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest },
- /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept },
- /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty },
- /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode },
- /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode },
- /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemOpcode },
- /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemInSlotOpcode },
- /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNodeStatusQueryOpcode },
- /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes },
- /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode },
- /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerListOpcode },
- /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode },
- /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode },
- /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBankerActivateOpcode },
- /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankSlotOpcode },
- /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowListOpcode },
- /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionBuyOpcode },
- /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowSignOpcode },
- /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionSignOpcode },
- /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionDeclineOpcode },
- /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOfferPetitionOpcode },
- /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetitionOpcode },
- /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionQueryOpcode },
- /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode },
- /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayedTime },
- /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode },
- /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode },
- /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode },
- /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode },
- /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess },
- /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode },
- /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E3*/ { "CMSG_QUEST_POI_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery },
- /*0x1E4*/ { "SMSG_QUEST_POI_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess },
- /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode },
- /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode },
- /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode},
- /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleZoneUpdateOpcode },
- /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomRollOpcode },
- /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1FD*/ { "CMSG_CHANGEPLAYER_DIFFICULTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode },
- /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketCreateOpcode },
- /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateOpcode },
- /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData },
- /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData },
- /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20E*/ { "SMSG_CHANGEPLAYER_DIFFICULTY_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketGetTicketOpcode },
- /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x214*/ { "SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode },
- /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteOpcode },
- /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketSystemStatusOpcode},
- /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpiritHealerActivateOpcode},
- /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x21E*/ { "SMSG_QUEST_FORCE_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode },
- /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRankOpcode },
- /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAddRankOpcode },
- /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDelRankOpcode },
- /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetPublicNoteOpcode },
- /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetOfficerNoteOpcode },
- /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail },
- /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetMailList },
- /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldListOpcode },
- /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x23F*/ { "SMSG_FORCE_SET_VEHICLE_REC_ID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x240*/ { "CMSG_SET_VEHICLE_REC_ID_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery },
- /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeMoney },
- /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeItem },
- /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead },
- /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailReturnToSender },
- /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete },
- /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem },
- /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode },
- /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP },
- /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode },
- /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem },
- /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem },
- /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems },
- /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems },
- /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid },
- /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x261*/ { "SMSG_COMBAT_EVENT_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems },
- /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetAmmoOpcode },
- /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode },
- /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode },
- /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode},
- /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode },
- /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStablePet },
- /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnstablePet },
- /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyStableSlot },
- /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableRevivePet },
- /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableSwapPet },
- /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult },
- /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode },
- /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode },
- /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupChangeSubGroupOpcode },
- /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode},
- /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBankItemOpcode },
- /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode },
- /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryNextMailTime },
- /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRaidConvertOpcode },
- /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAssistantLeaderOpcode},
- /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuybackItem },
- /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x292*/ { "CMSG_SET_SAVED_INSTANCE_EXTEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend },
- /*0x293*/ { "SMSG_LFG_OFFER_CONTINUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x294*/ { "CMSG_TEST_DROP_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x295*/ { "SMSG_TEST_DROP_RATE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x296*/ { "CMSG_LFG_GET_STATUS", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus },
- /*0x297*/ { "SMSG_SHOW_MAILBOX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x298*/ { "SMSG_RESET_RANGED_COMBAT_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29A*/ { "SMSG_CHAT_NOT_IN_PARTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode },
- /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll },
- /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode },
- /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode },
- /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTalentWipeConfirmOpcode },
- /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode },
- /*0x2AD*/ { "MSG_DEV_SHOWLABEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode },
- /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingHelmOpcode },
- /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingCloakOpcode },
- /*0x2BB*/ { "SMSG_LFG_ROLE_CHOSEN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarToggles },
- /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionRenameOpcode },
- /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemNameQueryOpcode },
- /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharRenameOpcode },
- /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode },
- /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode },
- /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode },
- /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck },
- /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck },
- /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover },
- /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode },
- /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode },
- /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode },
- /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode },
- /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePVPLogDataOpcode },
- /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldLeaveOpcode },
- /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueryOpcode},
- /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueueOpcode},
- /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_AUTHED, PROCESS_THREADSAFE, &WorldSession::HandleWardenDataOpcode },
- /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode},
- /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack },
- /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode },
- /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode },
- /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildChangeInfoTextOpcode },
- /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiExpressOpcode },
- /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode },
- /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode },
- /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode },
- /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode },
- /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode },
- /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetDungeonDifficultyOpcode},
- /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMSurveySubmit },
- /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33E*/ { "SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33F*/ { "SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x340*/ { "CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode },
- /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSocketOpcode },
- /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34A*/ { "MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamQueryOpcode },
- /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode },
- /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamInviteOpcode },
- /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamAcceptOpcode },
- /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDeclineOpcode },
- /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaveOpcode },
- /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRemoveOpcode },
- /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDisbandOpcode },
- /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaderOpcode },
- /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena },
- /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode },
- /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode },
- /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode },
- /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode },
- /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x362*/ { "CMSG_LFG_PROPOSAL_RESULT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode },
- /*0x363*/ { "SMSG_LFG_ROLE_CHECK_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x364*/ { "SMSG_LFG_JOIN_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x365*/ { "SMSG_LFG_QUEUE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetCommentOpcode },
- /*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x369*/ { "SMSG_LFG_UPDATE_SEARCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode },
- /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode },
- /*0x36D*/ { "SMSG_LFG_BOOT_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode},
- /*0x36F*/ { "SMSG_LFG_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode },
- /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPartyLockInfoRequestOpcode},
- /*0x372*/ { "SMSG_LFG_PARTY_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode },
- /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode },
- /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode },
- /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode},
- /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode },
- /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode },
- /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode },
- /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResp },
- /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode },
- /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckFinishedOpcode},
- /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode },
- /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelDisplayListQuery },
- /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel },
- /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetChannelMemberCount },
- /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode },
- /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK },
- /*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankerActivate },
- /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankQueryTab },
- /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankSwapItems },
- /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankBuyTab },
- /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankUpdateTab },
- /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankDepositMoney },
- /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankWithdrawMoney },
- /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankLogQuery },
- /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetChannelWatch },
- /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpellClick },
- /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPermissions },
- /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankMoneyWithdrawn },
- /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode },
- /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest },
- /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess },
- /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode },
- /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryGuildBankTabText },
- /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText },
- /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGrantLevel },
- /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x40F*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleChannelDeclineInvite },
- /*0x411*/ { "SMSG_GROUPACTION_THROTTLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed },
- /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery},
- /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames },
- /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptGrantLevel },
- /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAlterAppearance },
- /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetCalendar },
- /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetEvent },
- /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter },
- /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam },
- /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent },
- /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent },
- /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent },
- /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarCopyEvent },
- /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventInvite },
- /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRsvp },
- /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRemoveInvite },
- /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventStatus },
- /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventModeratorStatus},
- /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain },
- /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetNumPending },
- /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x45F*/ { "CMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x460*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x461*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory },
- /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryInspectAchievements },
- /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle },
- /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x471*/ { "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomize },
- /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit },
- /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent },
- /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameobjectReportUse },
- /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRemoveGlyph },
- /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter },
- /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListPendingSales },
- /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes },
- /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect },
- /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A4*/ { "CMSG_SET_BREATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A5*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle },
- /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPassenger },
- /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AC*/ { "CMSG_CHANGE_GDF_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AD*/ { "CMSG_SET_ARENA_TEAM_RATING_BY_INDEX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AE*/ { "CMSG_SET_ARENA_TEAM_WEEKLY_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AF*/ { "CMSG_SET_ARENA_TEAM_SEASON_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B0*/ { "CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B1*/ { "CMSG_SET_ARENA_MEMBER_SEASON_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B2*/ { "SMSG_ITEM_REFUND_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefundInfoRequest },
- /*0x4B4*/ { "CMSG_ITEM_REFUND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund },
- /*0x4B5*/ { "SMSG_ITEM_REFUND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery },
- /*0x4B7*/ { "SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B8*/ { "CMSG_UNUSED5", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL },
- /*0x4B9*/ { "CMSG_UNUSED6", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4BA*/ { "CMSG_CALENDAR_EVENT_SIGNUP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventSignup },
- /*0x4BB*/ { "SMSG_CALENDAR_CLEAR_PENDING_ACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4BC*/ { "SMSG_EQUIPMENT_SET_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4BD*/ { "CMSG_EQUIPMENT_SET_SAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave },
- /*0x4BE*/ { "CMSG_UPDATE_PROJECTILE_POSITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition },
- /*0x4BF*/ { "SMSG_SET_PROJECTILE_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C0*/ { "SMSG_TALENTS_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C1*/ { "CMSG_LEARN_PREVIEW_TALENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents },
- /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet },
- /*0x4C3*/ { "CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C4*/ { "CMSG_GM_GRANT_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C5*/ { "CMSG_GM_REMOVE_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C6*/ { "CMSG_GM_SET_CRITERIA_FOR_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C7*/ { "SMSG_ARENA_UNIT_DESTROYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C8*/ { "SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C9*/ { "CMSG_PROFILEDATA_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CA*/ { "SMSG_PROFILEDATA_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CB*/ { "CMSG_START_BATTLEFIELD_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CC*/ { "CMSG_END_BATTLEFIELD_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CE*/ { "SMSG_MOVE_GRAVITY_DISABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CF*/ { "CMSG_MOVE_GRAVITY_DISABLE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D0*/ { "SMSG_MOVE_GRAVITY_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D1*/ { "CMSG_MOVE_GRAVITY_ENABLE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D2*/ { "MSG_MOVE_GRAVITY_CHNG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D3*/ { "SMSG_SPLINE_MOVE_GRAVITY_DISABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D4*/ { "SMSG_SPLINE_MOVE_GRAVITY_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse },
- /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D7*/ { "CMSG_FORCE_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D8*/ { "SMSG_FORCE_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D9*/ { "CMSG_CHAR_FACTION_CHANGE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange },
- /*0x4DA*/ { "SMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DB*/ { "CMSG_PVP_QUEUE_STATS_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4DC*/ { "SMSG_PVP_QUEUE_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DD*/ { "CMSG_SET_PAID_SERVICE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse },
- /*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse },
- /*0x4E3*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4E4*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E5*/ { "SMSG_BATTLEFIELD_MGR_EJECT_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E6*/ { "SMSG_BATTLEFIELD_MGR_EJECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest },
- /*0x4E8*/ { "SMSG_BATTLEFIELD_MGR_STATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E9*/ { "CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4EA*/ { "CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4EB*/ { "MSG_SET_RAID_DIFFICULTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetRaidDifficultyOpcode },
- /*0x4EC*/ { "CMSG_TOGGLE_XP_GAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4ED*/ { "SMSG_TOGGLE_XP_GAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4EE*/ { "SMSG_GMRESPONSE_DB_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4EF*/ { "SMSG_GMRESPONSE_RECEIVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F0*/ { "CMSG_GMRESPONSE_RESOLVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMResponseResolve },
- /*0x4F1*/ { "SMSG_GMRESPONSE_STATUS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F2*/ { "SMSG_GMRESPONSE_CREATE_TICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F3*/ { "CMSG_GMRESPONSE_CREATE_TICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4F4*/ { "CMSG_SERVERINFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4F5*/ { "SMSG_SERVERINFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F6*/ { "CMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleWorldStateUITimerUpdate },
- /*0x4F7*/ { "SMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F8*/ { "CMSG_CHAR_RACE_CHANGE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange },
- /*0x4F9*/ { "MSG_VIEW_PHASE_SHIFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FA*/ { "SMSG_TALENTS_INVOLUNTARILY_RESET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FB*/ { "CMSG_DEBUG_SERVER_GEO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FC*/ { "SMSG_DEBUG_SERVER_GEO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FD*/ { "SMSG_LOOT_SLOT_CHANGED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FE*/ { "UMSG_UPDATE_GROUP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FF*/ { "CMSG_READY_FOR_ACCOUNT_DATA_TIMES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadyForAccountDataTimes },
- /*0x500*/ { "CMSG_QUERY_QUESTS_COMPLETED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryQuestsCompleted },
- /*0x501*/ { "SMSG_QUERY_QUESTS_COMPLETED_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x502*/ { "CMSG_GM_REPORT_LAG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportLag },
- /*0x503*/ { "CMSG_AFK_MONITOR_INFO_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x504*/ { "SMSG_AFK_MONITOR_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x505*/ { "CMSG_AFK_MONITOR_INFO_CLEAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x506*/ { "SMSG_CORPSE_IS_NOT_IN_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x507*/ { "CMSG_GM_NUKE_CHARACTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x508*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID1", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x509*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50A*/ { "SMSG_CAMERA_SHAKE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50B*/ { "SMSG_SOCKET_GEMS_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50C*/ { "CMSG_SET_CHARACTER_MODEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50D*/ { "SMSG_REDIRECT_CLIENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50E*/ { "CMSG_REDIRECTION_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50F*/ { "SMSG_SUSPEND_COMMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x510*/ { "CMSG_SUSPEND_COMMS_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x511*/ { "SMSG_FORCE_SEND_QUEUED_PACKETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x512*/ { "CMSG_REDIRECTION_AUTH_PROOF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x513*/ { "CMSG_DROP_NEW_CONNECTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x514*/ { "SMSG_SEND_ALL_COMBAT_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x515*/ { "SMSG_OPEN_LFG_DUNGEON_FINDER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x516*/ { "SMSG_MOVE_SET_COLLISION_HGT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x517*/ { "CMSG_MOVE_SET_COLLISION_HGT_ACK", STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x518*/ { "MSG_MOVE_SET_COLLISION_HGT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x519*/ { "CMSG_CLEAR_RANDOM_BG_WIN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51A*/ { "CMSG_CLEAR_HOLIDAY_BG_WIN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51B*/ { "CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51C*/ { "SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x51D*/ { "SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x51E*/ { "SMSG_COMPRESSED_UNKNOWN_1310", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
+#define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \
+ ValidateAndSetOpcode<(opcode < NUM_OPCODE_HANDLERS), (opcode != 0)>(opcode, #opcode, status, processing, handler);
+
+ DEFINE_OPCODE_HANDLER(CMSG_ACCEPT_LEVEL_GRANT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptGrantLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ACTIVATETAXI, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ACTIVATETAXIEXPRESS, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiExpressOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADDON_REGISTERED_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddFriendOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddIgnoreOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_ALTER_APPEARANCE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAlterAppearance );
+ DEFINE_OPCODE_HANDLER(CMSG_AREATRIGGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaTriggerOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AREA_SPIRIT_HEALER_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueryOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_AREA_SPIRIT_HEALER_QUEUE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueueOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamAcceptOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaderOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRemoveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ATTACKSTOP, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ATTACKSWING, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_BIDDER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_OWNER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_PENDING_SALES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListPendingSales );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_PLACE_BID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_REMOVE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTH_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOBANK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_ITEM_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemSlotOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_BAG_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBagItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_BANK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBankItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_LOOT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutostoreLootItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTO_DECLINE_GUILD_INVITES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoDeclineGuildInvites );
+ DEFINE_OPCODE_HANDLER(CMSG_BANKER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBankerActivateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LEAVE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBattlefieldLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_EXIT_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_PORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEGROUND_PLAYER_POSITIONS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN_RATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BINDER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUYBACK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuybackItem );
+ DEFINE_OPCODE_HANDLER(CMSG_BUY_BANK_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankSlotOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_ADD_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_ARENA_TEAM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COMPLAIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COPY_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarCopyEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_MODERATOR_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventModeratorStatus);
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_REMOVE_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRemoveInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_RSVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRsvp );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_SIGNUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventSignup );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventStatus );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_CALENDAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetCalendar );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_NUM_PENDING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetNumPending );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GUILD_FILTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_REMOVE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_UPDATE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelChanneling );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_ANNOUNCEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_BAN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelBan );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_DISPLAY_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelDisplayListQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_KICK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelKick );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelList );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MODERATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MODERATOR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerator );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MUTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelMute );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelOwner );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_PASSWORD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelPassword );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_ROSTER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SET_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelSetOwner );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SILENCE_ALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SILENCE_VOICE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNBAN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnban );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNMODERATOR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmoderator );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNMUTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmute );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNSILENCE_ALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNSILENCE_VOICE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_VOICE_OFF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_VOICE_ON, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_CREATE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_CUSTOMIZE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomize );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_DELETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharDeleteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_ENUM, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharEnumOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_FACTION_CHANGE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_RACE_CHANGE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_RENAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharRenameOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAT_FILTERED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAT_IGNORED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_CHANNEL_WATCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_ENTER_INSTANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_EXIT_INSTANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_MAP_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_INSTANCE_COMMAND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_START_WARGAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLAIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CONTACT_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CORPSE_MAP_POSITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DANCE_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_DELETEEQUIPMENT_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_DESTROY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DISMISS_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle );
+ DEFINE_OPCODE_HANDLER(CMSG_DISMISS_CRITTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter );
+ DEFINE_OPCODE_HANDLER(CMSG_DUEL_ACCEPTED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelAcceptedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DUEL_CANCELLED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelCancelledOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DUNGEON_FINDER_GET_SYSTEM_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_EJECT_PASSENGER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ENABLETAXI, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
+ DEFINE_OPCODE_HANDLER(CMSG_ENABLE_NAGLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_SAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave );
+ DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse );
+ DEFINE_OPCODE_HANDLER(CMSG_FAR_SIGHT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_FORCE_MOVE_ROOT_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
+ DEFINE_OPCODE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJECT_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGameObjectQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJ_REPORT_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameobjectReportUse );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJ_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameObjectUseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GET_MAIL_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetMailList );
+ DEFINE_OPCODE_HANDLER(CMSG_GET_MIRRORIMAGE_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_GMRESPONSE_RESOLVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMResponseResolve );
+ DEFINE_OPCODE_HANDLER(CMSG_GMSURVEY_SUBMIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMSurveySubmit );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_DELETETICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_GETTICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketGetTicketOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_SYSTEMSTATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketSystemStatusOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_UPDATETEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GM_REPORT_LAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportLag );
+ DEFINE_OPCODE_HANDLER(CMSG_GOSSIP_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipHelloOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GOSSIP_SELECT_OPTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipSelectOptionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GRANT_LEVEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGrantLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_ASSISTANT_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAssistantLeaderOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupChangeSubGroupOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_RAID_CONVERT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRaidConvertOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_REQUEST_JOIN_UPDATES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SET_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSetLeaderOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SET_ROLES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGroupSetRolesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SWAP_SUB_GROUP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSwapSubGroupOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_UNINVITE_GUID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteGuidOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAcceptOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACHIEVEMENT_PROGRESS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAchievementProgressQuery);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ADD_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAddRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ASSIGN_MEMBER_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAssignRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANKER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankerActivate );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_BUY_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankBuyTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_DEPOSIT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankDepositMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankLogQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_MONEY_WITHDRAWN_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankMoneyWithdrawn );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_QUERY_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankQueryTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_QUERY_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryGuildBankTabText );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_SWAP_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankSwapItems );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_UPDATE_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankUpdateTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_WITHDRAW_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankWithdrawMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_CHANGE_NAME_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEL_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDelRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDemoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_EVENT_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_INFO_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildChangeInfoTextOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_MEMBER_SEND_SOR_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_MOTD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildMOTDOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_NEWS_UPDATE_STICKY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildNewsUpdateStickyOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_PERMISSIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPermissions );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_PROMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPromoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY_NEWS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildQueryNewsOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY_RANKS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryRanksOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_CHALLENGE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_MAX_DAILY_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestMaxDailyXP );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_PARTY_STATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestPartyState );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRosterOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_GUILD_MASTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetGuildMaster );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_NOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetNoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_RANK_PERMISSIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetRankPermissionsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SWITCH_RANK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_HEARTH_AND_RESURRECT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect );
+ DEFINE_OPCODE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSTANCE_LOCK_WARNING_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_REFUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_REFUND_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefundInfoRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_JOIN_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleJoinChannel );
+ DEFINE_OPCODE_HANDLER(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_PREVIEW_TALENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_PREVIEW_TALENTS_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LEAVE_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveChannel );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_GET_STATUS, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LEAVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LFR_JOIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LFR_LEAVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_PROPOSAL_RESULT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_BOOT_VOTE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_COMMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_ROLES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_ADD_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderAddRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_BROWSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderBrowse );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_DECLINE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderDeclineRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_APPLICATIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetApplications);
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_RECRUITS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetRecruits );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_POST_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderPostRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderRemoveRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderSetGuildPost );
+ DEFINE_OPCODE_HANDLER(CMSG_LIST_INVENTORY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOAD_SCREEN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleLoadScreenOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOG_DISCONNECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MASTER_GIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMoneyOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_RELEASE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootReleaseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_CREATE_TEXT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_MARK_AS_READ, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_RETURN_TO_SENDER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailReturnToSender );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_TAKE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeItem );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_AFK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_DND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_RAID_WARNING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_SAY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_YELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MINIGAME_MOVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOUNTSPECIAL_ANIM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHNG_TRANSPORT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FALL_RESET, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FEATHER_FALL_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_HOVER_ACK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_KNOCK_BACK_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_NOT_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_COLLISION_HEIGHT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleSetCollisionHeightAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SPLINE_DONE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_TIME_SKIPPED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck );
+ DEFINE_OPCODE_HANDLER(CMSG_NAME_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera );
+ DEFINE_OPCODE_HANDLER(CMSG_NPC_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNpcTextQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OBJECT_UPDATE_RESCUED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_OFFER_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOfferPetitionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OPENING_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpeningCinematic );
+ DEFINE_OPCODE_HANDLER(CMSG_OPEN_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OPT_OUT_OF_LOOT, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PAGE_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePageTextQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PARTY_SILENCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PARTY_UNSILENCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_BUY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionBuyOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SHOWLIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SHOW_SIGNATURES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowSignOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SIGN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionSignOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_ABANDON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_ACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_NAME_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_SET_ACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSetAction );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_SPELL_AUTOCAST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_STOP_ATTACK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack );
+ DEFINE_OPCODE_HANDLER(CMSG_PING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYED_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayedTime );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYER_LOGIN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLoginOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYER_VEHICLE_ENTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAY_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PUSHQUESTTOPARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty );
+ DEFINE_OPCODE_HANDLER(CMSG_PVP_LOG_DATA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandlePVPLogDataOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_BATTLEFIELD_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MEMBERS_FOR_RECIPE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_REWARDS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildRewardsQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryXPOpcode ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_INSPECT_ACHIEVEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryInspectAchievements );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_QUESTS_COMPLETED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryQuestsCompleted );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_ACCEPT_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_CHOOSE_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_COMPLETE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverHelloOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_QUERY_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_REQUEST_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_STATUS_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverStatusQueryOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTLOG_REMOVE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_NPC_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_POI_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RANDOMIZE_CHAR_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomizeCharNameOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_READY_FOR_ACCOUNT_DATA_TIMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadyForAccountDataTimes );
+ DEFINE_OPCODE_HANDLER(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem );
+ DEFINE_OPCODE_HANDLER(CMSG_REALM_SPLIT, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REDIRECTION_AUTH_PROOF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REFORGE_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleReforgeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleReorderCharacters );
+ DEFINE_OPCODE_HANDLER(CMSG_REPAIR_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REPOP_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REPORT_PVP_AFK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_CATEGORY_COOLDOWNS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestCategoryCooldowns );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_CEMETERY_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_HOTFIX, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleRequestHotfix );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_INSPECT_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PET_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestPvpOptions );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PVP_REWARDS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestPvpReward );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_INFO, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestRatedBgInfo );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_STATS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestRatedBgStats );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RESEARCH_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_EXIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_NEXT_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_PREV_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_SWITCH_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_RESET_FACTION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_RESET_INSTANCES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResurrectResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RETURN_TO_GRAVEYARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReturnToGraveyard );
+ DEFINE_OPCODE_HANDLER(CMSG_ROLE_POLL_BEGIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSaveCUFProfiles );
+ DEFINE_OPCODE_HANDLER(CMSG_SELF_RES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_ADDRESS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SETSHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIONBAR_TOGGLES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarToggles );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTION_BUTTON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionButtonOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ALLOW_LOW_LEVEL_RAID1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ALLOW_LOW_LEVEL_RAID2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CHANNEL_WATCH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetChannelWatch );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CONTACT_NOTES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetContactNotesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CURRENCY_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_ATWAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_INACTIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_GUILD_BANK_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PREFERED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PRIMARY_TALENT_TREE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_RELATIVE_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TITLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_VEHICLE_REC_ID_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_WATCHED_FACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SHOWING_CLOAK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingCloakOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SHOWING_HELM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingHelmOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SOCKET_GEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSocketOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SPELLCLICK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpellClick );
+ DEFINE_OPCODE_HANDLER(CMSG_SPIRIT_HEALER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpiritHealerActivateOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_SPLIT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSplitItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_STANDSTATECHANGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_STOP_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUBMIT_BUG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUBMIT_COMPLAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUGGESTION_SUBMIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUMMON_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SWAP_INV_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem );
+ DEFINE_OPCODE_HANDLER(CMSG_SYNC_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TAXINODE_STATUS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNodeStatusQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TAXIQUERYAVAILABLENODES, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
+ DEFINE_OPCODE_HANDLER(CMSG_TELEPORT_TO_UNIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_ADJUSTMENT_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_SYNC_RESP, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResp );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_SYNC_RESP_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TOGGLE_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP );
+ DEFINE_OPCODE_HANDLER(CMSG_TOTEM_DESTROYED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed );
+ DEFINE_OPCODE_HANDLER(CMSG_TRAINER_BUY_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TRAINER_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TRANSMOGRIFY_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems );
+ DEFINE_OPCODE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetitionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_CLEAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialClear );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_FLAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_RESET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialReset );
+ DEFINE_OPCODE_HANDLER(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SKILL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnregisterAddonPrefixesOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData );
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory );
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_PROJECTILE_POSITION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition );
+ DEFINE_OPCODE_HANDLER(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_VIOLENCE_LEVEL, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleViolenceLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_VOICE_SESSION_ENABLE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_TRANSFER, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageTransfer );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_UNLOCK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageUnlock );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidSwapItem );
+ DEFINE_OPCODE_HANDLER(CMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_WARGAME_ACCEPT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_WARGAME_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleWorldStateUITimerUpdate );
+ DEFINE_OPCODE_HANDLER(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ZONEUPDATE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleZoneUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_AUCTION_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_CHANNEL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_CHANNEL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_CORPSE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_INSPECT_ARENA_TEAMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_LIST_STABLED_PETS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_FALL_LAND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_JUMP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FACING, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_WALK_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_ASCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_BACKWARD, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_DESCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_FORWARD, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_PITCH_DOWN, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_PITCH_UP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_STRAFE_LEFT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_STRAFE_RIGHT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_SWIM, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_TURN_LEFT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_TURN_RIGHT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_ASCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_STRAFE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_SWIM, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_TURN, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAck );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TIME_SKIPPED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_COLLISION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_WORLDPORT_ACK, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_NOTIFY_PARTY_SQUELCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_PARTY_ASSIGNMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_PETITION_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_PETITION_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionRenameOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_QUERY_NEXT_MAIL_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryNextMailTime );
+ DEFINE_OPCODE_HANDLER(MSG_QUEST_PUSH_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK_CONFIRM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK_FINISHED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckFinishedOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_RAID_TARGET_UPDATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_RANDOM_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomRollOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetDungeonDifficultyOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetRaidDifficultyOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_TABARDVENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_TALENT_WIPE_CONFIRM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTalentWipeConfirmOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_VERIFY_CONNECTIVITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_INFO_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_RESTRICTED_WARNING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACTION_BUTTONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACTIVATETAXIREPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ADDON_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ADD_RUNE_POWER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AI_REACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ALL_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_SPIRIT_HEALER_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MOVEMENT_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_ERROR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_UNIT_DESTROYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKERSTATEUPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSTART, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSTOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_BADFACING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_CANT_ATTACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_DEADTARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_NOTINRANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_OWNER_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_OWNER_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_REMOVED_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_UPDATE_ALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AVERAGE_ITEM_LEVEL_INFORM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BARBER_SHOP_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EJECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EJECT_PENDING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_ENTERED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EXIT_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_STATE_CHANGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_PLAYER_POSITIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_PORT_DENIED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_RATED_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_QUEUED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_ACTIVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_WAITFORGROUPS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_INFO_THROTTLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_JOINED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BINDER_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BINDPOINTUPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BREAK_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BUY_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BUY_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_ARENA_TEAM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_CLEAR_PENDING_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_REMOVED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_UPDATED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_FILTER_GUILD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_CALENDAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_NUM_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CAMERA_SHAKE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CANCEL_COMBAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_MEMBER_COUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_CREATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_DELETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_ENUM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_FACTION_CHANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_RENAME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_IGNORED_ACCOUNT_MUTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_NOT_IN_PARTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_PLAYER_AMBIGUOUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_PLAYER_NOT_FOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_RESTRICTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_SERVER_DISCONNECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_SERVER_RECONNECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_WRONG_FACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_BOSS_EMOTES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWNS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLIENTCACHE_VERSION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLIENT_CONTROL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMBAT_EVENT_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_MAP_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_STATE_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMPLAIN_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_MOVES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_CONNECT_FAIL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_DISCONNECT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_RECONNECT_TRY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CONTACT_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CONVERT_RUNE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COOLDOWN_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COOLDOWN_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_NOT_IN_INSTANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_RECLAIM_DELAY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CREATURE_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CRITERIA_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CRITERIA_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CROSSED_INEBRIATION_THRESHOLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CURRENCY_LOOT_REMOVED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CURRENCY_LOOT_RESTORED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CUSTOM_LOAD_SCREEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DAMAGE_CALC_LOG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DANCE_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DB_REPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEATH_RELEASE_LOC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEBUG_RUNE_REGEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEFENSE_MESSAGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DESTROY_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DIFFERENT_INSTANCE_FROM_PARTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISENCHANT_CREDIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISMOUNTRESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISPLAY_GAME_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DROP_NEW_CONNECTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_COUNTDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_INBOUNDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_OUTOFBOUNDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_REQUESTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_WINNER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUMP_RIDE_TICKETS_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DURABILITY_DAMAGE_DEATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ECHO_PARTY_SQUELCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENABLE_BARBER_SHOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENCHANTMENTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENVIRONMENTALDAMAGELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_SAVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_USE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EXPECTED_SPAM_RECORDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EXPLORATION_EXPERIENCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FAILED_PLAYER_CONDITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FEIGN_DEATH_RESISTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FISH_ESCAPED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FISH_NOT_HOOKED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FLIGHT_SPLINE_SYNC, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FLOOD_DETECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCED_DEATH_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCE_SEND_QUEUED_PACKETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCE_SET_VEHICLE_REC_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORGE_MASTER_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FRIEND_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_CUSTOM_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_DESPAWN_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_PAGETEXT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_RESET_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMESPEED_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMETIME_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMETIME_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAME_EVENT_DEBUG_LOG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_DB_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_RECEIVED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_STATUS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_CREATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_DELETETICKET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_GETTICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_SYSTEMSTATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_UPDATETEXT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_MESSAGECHAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_TICKET_STATUS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_POI, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUPACTION_THROTTLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_SET_LEADER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_SET_ROLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_LOG_QUERY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_MONEY_WITHDRAWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_QUERY_TEXT_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHALLENGE_COMPLETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHALLENGE_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHANGE_NAME_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_COMMAND_RESULT_2, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CRITERIA_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CRITERIA_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_DECLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_EVENT_LOG_QUERY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_FLAGGED_FOR_RENAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MAX_DAILY_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBERS_FOR_RECIPE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_DAILY_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_UPDATE_NOTE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MOVE_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MOVE_STARTING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_NEWS_DELETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_NEWS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_PARTY_STATE_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RANKS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RENAMED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REPUTATION_REACTION_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REPUTATION_WEEKLY_CAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REWARDS_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_UPDATE_ROSTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HEALTH_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HIGHEST_THREAT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HOTFIX_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INITIALIZE_FACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INITIAL_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INIT_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INIT_WORLD_STATES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_HONOR_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_RESULTS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_LOCK_WARNING_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_SAVE_CREATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALIDATE_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALIDATE_PLAYER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALID_PROMOTION_CODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVENTORY_CHANGE_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_ADD_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_EXPIRE_PURCHASE_REFUND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REFUND_INFO_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REFUND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REMOVE_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_SEND_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_TEXT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEARNED_DANCE_MOVES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_OFFER_CONTINUE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_REWARD, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PROPOSAL_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_QUEUE_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHECK_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHOSEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_SLOT_INVALID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_TELEPORT_DENIED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_SEARCH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS_NONE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_BROWSE_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LIST_INVENTORY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGIN_SETTIMESPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGIN_VERIFY_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_CANCEL_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOG_XPGAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ALL_PASSED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_CLEAR_MONEY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_CONTENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ITEM_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_MASTER_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_MONEY_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_RELEASE_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ROLL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ROLL_WON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_SLOT_CHANGED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_START_ROLL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_IN_PROGRESS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MESSAGECHAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MESSAGE_BOX, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_SETUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MIRRORIMAGE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MODIFY_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONEY_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONSTER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONSTER_MOVE_TRANSPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOTD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOUNTRESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOUNTSPECIAL_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_COLLISION_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_KNOCK_BACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_ACTIVE_MOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_COLLISION_HEIGHT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_COMPOUND_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_COLLISION_HEIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_KNOCK_BACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_PITCH_RATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_RUN_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_SWIM_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_SWIM_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_TURN_RATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_WALK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NAME_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_WORLD_ABORT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFY_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFY_DEST_LOC_SPELL_CAST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NPC_TEXT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OPEN_CONTAINER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OPEN_LFG_DUNGEON_FINDER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OVERRIDE_LIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PAGE_TEXT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTYKILLLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PAUSE_MIRROR_TIMER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PERIODICAURALOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETGODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_ALREADY_SIGNED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SHOWLIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SHOW_SIGNATURES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SIGN_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ACTION_FEEDBACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ACTION_SOUND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ADDED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_BROKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_GUIDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_NAME_INVALID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_NAME_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_REMOVED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_RENAMEABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_SLOT_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_UPDATE_COMBO_POINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYED_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYERBINDERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYERBOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_DIFFICULTY_CHANGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_SKINNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_VEHICLE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_MUSIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_OBJECT_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_ONE_SHOT_ANIM_KIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL_KIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_TIME_WARNING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PONG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_POWER_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PRE_RESURRECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PROCRESIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PROPOSE_LEVEL_GRANT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_INVALID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_REQUEST_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTLOG_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_PVP_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILEDTIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_CONFIRM_ACCEPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_FORCE_REMOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_NPC_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_POI_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_GROUP_ONLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_INSTANCE_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_INSTANCE_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_READY_CHECK_THROTTLED_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_SUMMON_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RANDOMIZE_CHAR_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RATED_BG_RATING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RATED_BG_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_READ_ITEM_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_READ_ITEM_OK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REAL_GROUP_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RECEIVED_MAIL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REPORT_PVP_AFK_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REQUEST_CEMETERY_LIST_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REQUEST_PVP_REWARDS_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESEARCH_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESEARCH_SETUP_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ROLE_POLL_BEGIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RWHOIS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SELL_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SEND_MAIL_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SEND_UNLEARN_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVERTIME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_FIRST_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_INFO_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_PERF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_DF_FAST_LAUNCH_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_STANDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_VISIBLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FORCED_REACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PROJECTILE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOWTAXINODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOW_RATINGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SOCKET_GEMS_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SOR_START_EXPERIENCE_INCOMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLBREAKLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLDAMAGESHIELD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLDISPELLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLENERGIZELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLHEALLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLINSTAKILLLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLINTERRUPTLOG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLLOGEXECUTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLLOGMISS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLNONMELEEDAMAGELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLORDAMAGE_IMMUNE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLSTEALLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_CATEGORY_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FEATHER_FALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLYING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_LAND_WALK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_NORMAL_FALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_START_SWIM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_FLYING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_WATER_WALK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STABLE_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STANDSTATE_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_START_MIRROR_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_START_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STOP_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STOP_MIRROR_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STREAMING_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUMMON_CANCEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUMMON_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUPPRESS_NPC_GREETINGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TAXINODE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TEST_DROP_RATE_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TEXT_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_CLEAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_REMOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TIME_ADJUSTMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TIME_SYNC_REQ, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TITLE_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TOGGLE_XP_GAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TOTEM_CREATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRADE_STATUS_EXTENDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_SUCCEEDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TUTORIAL_FLAGS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UNIT_HEALTH_FREQUENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UNIT_SPELLCAST_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_ACCOUNT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_COMBO_POINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_SERVER_PLAYER_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICESESSION_FULL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_CHAT_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_PARENTAL_CONTROLS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_LEAVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ROSTER_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SET_TALKER_MUTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_ITEM_SWAP_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_CONTENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_TRANSFER_CHANGES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_TRANSFER_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WAIT_QUEUE_FINISH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WAIT_QUEUE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARGAME_CHECK_ENTRY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARGAME_REQUEST_SENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEATHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_LAST_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_RESET_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WORLD_SERVER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_XP_GAIN_ABORTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ZONE_UNDER_ATTACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+
+ // These opcodes are not in WPP
+
+ //DEFINE_OPCODE_HANDLER(CMSG_ACTIVE_PVP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ADD_PVP_MEDAL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ADVANCE_SPAWN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AFK_MONITOR_INFO_CLEAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AFK_MONITOR_INFO_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_BEGIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_PROOF, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_RECODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_JOIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_REQUEST_SCORE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); Need to send the response
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_BEASTMASTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOOTME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOT_DETECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOT_DETECTED2, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_ITEM_IN_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemInSlotOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_LOTTERY_TICKET_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_STABLE_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyStableSlot );
+ //DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHANGE_GDF_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHANGE_PERSONAL_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHARACTER_POINT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_PLAYER_LOGIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_PLAYER_LOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SETMONEY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SET_ARENA_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SET_HONOR_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHECK_LOGIN_CRITERIA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_EXPLORATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_HOLIDAY_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_RANDOM_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_ACHIEVEMENT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CONTROLLER_EJECT_PASSENGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPassenger );
+ //DEFINE_OPCODE_HANDLER(CMSG_COOLDOWN_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEGAMEOBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEMONSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_ACTIONS_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_ACTIONS_STOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_AISTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_CHANGECELLZONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_LIST_TARGETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_PASSIVE_AURA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_SERVER_GEO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DECHARGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DECLINE_CHANNEL_INVITE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleChannelDeclineInvite );
+ //DEFINE_OPCODE_HANDLER(CMSG_DELETE_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEL_PVP_MEDAL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DESTROYMONSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DESTROY_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DISABLE_PVP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DROP_NEW_CONNECTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DUMP_OBJECTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ENABLE_DAMAGE_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_END_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete );
+ //DEFINE_OPCODE_HANDLER(CMSG_EXPIRE_RAID_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLAG_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLAG_QUEST_FINISH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLOOD_GRACE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTIONONOTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTIONSHOW, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCE_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCE_SAY_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GAMESPEED_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GAMETIME_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GETDEATHBINDZONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GET_CHANNEL_MEMBER_COUNT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetChannelMemberCount );
+ //DEFINE_OPCODE_HANDLER(CMSG_GHOST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GMRESPONSE_CREATE_TICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CHARACTER_RESTORE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CHARACTER_SAVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CREATE_ITEM_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_DESTROY_ONLINE_CORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_FREEZE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_GRANT_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_INVIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_MOVECORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE_ACCOUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE_CHARACTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REMOVE_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REQUEST_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_RESURRECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REVEALTO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SET_CRITERIA_FOR_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SET_SECURITY_GROUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SHOW_COMPLAINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SILENCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SUMMONMOB, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_TEACH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UBERINVIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UNSQUELCH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UNTEACH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UPDATE_TICKET_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_VISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_WHISPER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GROUP_CANCEL, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GROUP_UNINVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_NOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildCreateOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInfoOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_KNOCKBACK_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_REQUIREMENTS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEARN_DANCE_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEARN_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEVEL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LFD_PARTY_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPartyLockInfoRequestOpcode);
+ //DEFINE_OPCODE_HANDLER(CMSG_LFD_PLAYER_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode);
+ //DEFINE_OPCODE_HANDLER(CMSG_LFG_GET_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LFG_PARTY_LOCK_INFO_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_NEEDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_JOIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LOAD_DANCES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LOTTERY_QUERY_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LUA_USAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_GM_SENT_MAIL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_INVALIDATE_CACHE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_RENAME_GUILD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAKEMONSTERATTACKGUID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MEETINGSTONE_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARACTER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_PORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RELATIVE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_VEHICLE_REC_ID_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_NEW_SPELL_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_NO_SPELL_VARIANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PERFORM_ACTION_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PETGODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_LEVEL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_NAME_CACHE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_UNLEARN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_UNLEARN_TALENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_AI_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_DIFFICULTY_CHANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_LOGOUT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLogoutOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_PROFILEDATA_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PVP_QUEUE_STATS_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MAX_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_OBJECT_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_OBJECT_ROTATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_VEHICLE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCancel );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_QUEST_AUTOLAUNCH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQuestAutoLaunch );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTLOG_SWAP_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogSwapQuest );
+ //DEFINE_OPCODE_HANDLER(CMSG_RECHARGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REDIRECTION_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REFER_A_FRIEND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REMOVE_GLYPH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRemoveGlyph );
+ //DEFINE_OPCODE_HANDLER(CMSG_REPLACE_ACCOUNT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_RUN_SCRIPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SAVE_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SAVE_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEARCH_LFG_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEARCH_LFG_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_COMBAT_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_GENERAL_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_LOCAL_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVERTIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_BROADCAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_COMMAND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_INFO_QUERY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SETDEATHBINDPOINT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_MEMBER_SEASON_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_RATING_BY_INDEX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_SEASON_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_WEEKLY_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_BREATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_CHARACTER_MODEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_CRITERIA_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_DURABILITY_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_EXPLORATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_EXPLORATION_ALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_CHEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionCheat );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GLYPH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GLYPH_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GRANTABLE_LEVELS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_LFG_COMMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetCommentOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PAID_SERVICE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PVP_RANK_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PVP_TITLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_RUNE_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_RUNE_COUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_SKILL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_STAT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_TITLE_SUFFIX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_WORLDSTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SKILL_BUY_RANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SKILL_BUY_STEP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStablePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_REVIVE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableRevivePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_SWAP_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableSwapPet );
+ //DEFINE_OPCODE_HANDLER(CMSG_START_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_START_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_STORE_LOOT_IN_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SUSPEND_COMMS_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TARGET_CAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TARGET_SCRIPT_CAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXICLEARALLNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXICLEARNODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXIENABLEALLNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXIENABLENODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXISHOWNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TEST_DROP_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TOGGLE_XP_GAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TRIGGER_CINEMATIC_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNCLAIM_LICENSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNDRESSPLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNITANIMTIER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_DANCE_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_TALENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNSTABLE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnstablePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNUSED5, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNUSED6, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_USE_SKILL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_VOICE_SET_TALKER_MUTED_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_WEATHER_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_XP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_DELAY_GHOST_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_DEV_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_ACCOUNT_ONLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_BIND_OTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_CHANGE_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_DESTROY_CORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_GEARRATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_RESETINSTANCELIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_SUMMON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_ALL_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_PITCH_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RAW_POSITION_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_TURN_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_WALK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_FALL_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_NULL_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_PVP_LOG_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePVPLogDataOpcode );
+ //DEFINE_OPCODE_HANDLER(MSG_VIEW_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(SMSG_AFK_MONITOR_INFO_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_AURACASTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_BINDZONEREPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_BUY_BANK_SLOT_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_ACTION_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_UPDATE_INVITE_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHANGEPLAYER_DIFFICULTY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_PROFILE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_PROFILE_REALM_CONNECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_PLAYER_LOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHECK_FOR_BOTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMBAT_LOG_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_GET_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMPLETION_NPC_RESPONCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CORPSE_IS_NOT_IN_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DAMAGE_DONE_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUGAURAPROC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_AISTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_LIST_TARGETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_SERVER_GEO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DUMP_OBJECTS_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DYNAMIC_DROP_ROLL_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCEACTIONSHOW, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCE_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCE_DISPLAY_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GAMETIMEBIAS_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GHOSTEE_GONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_CREATE_TICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GOGOGO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_CANCEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_KNOWN_RECIPES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_SET_NOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_TRADESKILL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_IGNORE_REQUIREMENTS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_INSPECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_DIFFICULTY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_JOINED_BATTLEGROUND_QUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_OPEN_FROM_GOSSIP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_PARTY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_SEARCH_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LOTTERY_QUERY_RESULT_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LOTTERY_RESULT_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_MEMBER_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_SETQUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_MOVE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_CHARACTER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_VEHICLE_REC_ID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SKIP_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_NPC_WONT_TALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PET_UNLEARN_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PLAYER_UNK_DEAD_ALIVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PROFILEDATA_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PUREMOUNT_CANCELLED_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PVP_QUEUE_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_QUERY_OBJECT_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_QUERY_OBJECT_ROTATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RAID_READY_CHECK_ERROR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_REMOVED_FROM_PVP_QUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESET_RANGED_COMBAT_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESISTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESUME_CAST_BAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESURRECT_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SCRIPT_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SEND_ALL_COMBAT_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVER_BUCK_DATA_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SET_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_PROC_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_RESIST_PUSHBACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ADJUST_PRIORITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+
+#undef DEFINE_OPCODE_HANDLER
};
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 254f9fe5350..cd72faf5740 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -25,1327 +25,1365 @@
#include "Common.h"
-// Note: this include need for be sure have full definition of class WorldSession
-// if this class definition not complete then VS for x64 release use different size for
-// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from
-// table opcodeTable in source when Opcode.h included but WorldSession.h not included
-#include "WorldSession.h"
-
/// List of Opcodes
enum Opcodes
{
- MSG_NULL_ACTION = 0x000,
- CMSG_BOOTME = 0x001,
- CMSG_DBLOOKUP = 0x002,
- SMSG_DBLOOKUP = 0x003,
- CMSG_QUERY_OBJECT_POSITION = 0x004,
- SMSG_QUERY_OBJECT_POSITION = 0x005,
- CMSG_QUERY_OBJECT_ROTATION = 0x006,
- SMSG_QUERY_OBJECT_ROTATION = 0x007,
- CMSG_WORLD_TELEPORT = 0x008,
- CMSG_TELEPORT_TO_UNIT = 0x009,
- CMSG_ZONE_MAP = 0x00A,
- SMSG_ZONE_MAP = 0x00B,
- CMSG_DEBUG_CHANGECELLZONE = 0x00C,
- CMSG_MOVE_CHARACTER_CHEAT = 0x00D,
- SMSG_MOVE_CHARACTER_CHEAT = 0x00E,
- CMSG_RECHARGE = 0x00F,
- CMSG_LEARN_SPELL = 0x010,
- CMSG_CREATEMONSTER = 0x011,
- CMSG_DESTROYMONSTER = 0x012,
- CMSG_CREATEITEM = 0x013,
- CMSG_CREATEGAMEOBJECT = 0x014,
- SMSG_CHECK_FOR_BOTS = 0x015,
- CMSG_MAKEMONSTERATTACKGUID = 0x016,
- CMSG_BOT_DETECTED2 = 0x017,
- CMSG_FORCEACTION = 0x018,
- CMSG_FORCEACTIONONOTHER = 0x019,
- CMSG_FORCEACTIONSHOW = 0x01A,
- SMSG_FORCEACTIONSHOW = 0x01B,
- CMSG_PETGODMODE = 0x01C,
- SMSG_PETGODMODE = 0x01D,
- SMSG_REFER_A_FRIEND_EXPIRED = 0x01E,
- CMSG_WEATHER_SPEED_CHEAT = 0x01F,
- CMSG_UNDRESSPLAYER = 0x020,
- CMSG_BEASTMASTER = 0x021,
- CMSG_GODMODE = 0x022,
- SMSG_GODMODE = 0x023,
- CMSG_CHEAT_SETMONEY = 0x024,
- CMSG_LEVEL_CHEAT = 0x025,
- CMSG_PET_LEVEL_CHEAT = 0x026,
- CMSG_SET_WORLDSTATE = 0x027,
- CMSG_COOLDOWN_CHEAT = 0x028,
- CMSG_USE_SKILL_CHEAT = 0x029,
- CMSG_FLAG_QUEST = 0x02A,
- CMSG_FLAG_QUEST_FINISH = 0x02B,
- CMSG_CLEAR_QUEST = 0x02C,
- CMSG_SEND_EVENT = 0x02D,
- CMSG_DEBUG_AISTATE = 0x02E,
- SMSG_DEBUG_AISTATE = 0x02F,
- CMSG_DISABLE_PVP_CHEAT = 0x030,
- CMSG_ADVANCE_SPAWN_TIME = 0x031,
- SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032,
- CMSG_AUTH_SRP6_BEGIN = 0x033,
- CMSG_AUTH_SRP6_PROOF = 0x034,
- CMSG_AUTH_SRP6_RECODE = 0x035,
- CMSG_CHAR_CREATE = 0x036,
- CMSG_CHAR_ENUM = 0x037,
- CMSG_CHAR_DELETE = 0x038,
- SMSG_AUTH_SRP6_RESPONSE = 0x039,
- SMSG_CHAR_CREATE = 0x03A,
- SMSG_CHAR_ENUM = 0x03B,
- SMSG_CHAR_DELETE = 0x03C,
- CMSG_PLAYER_LOGIN = 0x03D,
- SMSG_NEW_WORLD = 0x03E,
- SMSG_TRANSFER_PENDING = 0x03F,
- SMSG_TRANSFER_ABORTED = 0x040,
- SMSG_CHARACTER_LOGIN_FAILED = 0x041,
- SMSG_LOGIN_SETTIMESPEED = 0x042,
- SMSG_GAMETIME_UPDATE = 0x043,
- CMSG_GAMETIME_SET = 0x044,
- SMSG_GAMETIME_SET = 0x045,
- CMSG_GAMESPEED_SET = 0x046,
- SMSG_GAMESPEED_SET = 0x047,
- CMSG_SERVERTIME = 0x048,
- SMSG_SERVERTIME = 0x049,
- CMSG_PLAYER_LOGOUT = 0x04A,
- CMSG_LOGOUT_REQUEST = 0x04B,
- SMSG_LOGOUT_RESPONSE = 0x04C,
- SMSG_LOGOUT_COMPLETE = 0x04D,
- CMSG_LOGOUT_CANCEL = 0x04E,
- SMSG_LOGOUT_CANCEL_ACK = 0x04F,
- CMSG_NAME_QUERY = 0x050,
- SMSG_NAME_QUERY_RESPONSE = 0x051,
- CMSG_PET_NAME_QUERY = 0x052,
- SMSG_PET_NAME_QUERY_RESPONSE = 0x053,
- CMSG_GUILD_QUERY = 0x054,
- SMSG_GUILD_QUERY_RESPONSE = 0x055,
- CMSG_ITEM_QUERY_SINGLE = 0x056,
- CMSG_ITEM_QUERY_MULTIPLE = 0x057,
- SMSG_ITEM_QUERY_SINGLE_RESPONSE = 0x058,
- SMSG_ITEM_QUERY_MULTIPLE_RESPONSE = 0x059,
- CMSG_PAGE_TEXT_QUERY = 0x05A,
- SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x05B,
- CMSG_QUEST_QUERY = 0x05C,
- SMSG_QUEST_QUERY_RESPONSE = 0x05D,
- CMSG_GAMEOBJECT_QUERY = 0x05E,
- SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x05F,
- CMSG_CREATURE_QUERY = 0x060,
- SMSG_CREATURE_QUERY_RESPONSE = 0x061,
- CMSG_WHO = 0x062,
- SMSG_WHO = 0x063,
- CMSG_WHOIS = 0x064,
- SMSG_WHOIS = 0x065,
- CMSG_CONTACT_LIST = 0x066,
- SMSG_CONTACT_LIST = 0x067,
- SMSG_FRIEND_STATUS = 0x068,
- CMSG_ADD_FRIEND = 0x069,
- CMSG_DEL_FRIEND = 0x06A,
- CMSG_SET_CONTACT_NOTES = 0x06B,
- CMSG_ADD_IGNORE = 0x06C,
- CMSG_DEL_IGNORE = 0x06D,
- CMSG_GROUP_INVITE = 0x06E,
- SMSG_GROUP_INVITE = 0x06F,
- CMSG_GROUP_CANCEL = 0x070,
- SMSG_GROUP_CANCEL = 0x071,
- CMSG_GROUP_ACCEPT = 0x072,
- CMSG_GROUP_DECLINE = 0x073,
- SMSG_GROUP_DECLINE = 0x074,
- CMSG_GROUP_UNINVITE = 0x075,
- CMSG_GROUP_UNINVITE_GUID = 0x076,
- SMSG_GROUP_UNINVITE = 0x077,
- CMSG_GROUP_SET_LEADER = 0x078,
- SMSG_GROUP_SET_LEADER = 0x079,
- CMSG_LOOT_METHOD = 0x07A,
- CMSG_GROUP_DISBAND = 0x07B,
- SMSG_GROUP_DESTROYED = 0x07C,
- SMSG_GROUP_LIST = 0x07D,
- SMSG_PARTY_MEMBER_STATS = 0x07E,
- SMSG_PARTY_COMMAND_RESULT = 0x07F,
- UMSG_UPDATE_GROUP_MEMBERS = 0x080,
- CMSG_GUILD_CREATE = 0x081,
- CMSG_GUILD_INVITE = 0x082,
- SMSG_GUILD_INVITE = 0x083,
- CMSG_GUILD_ACCEPT = 0x084,
- CMSG_GUILD_DECLINE = 0x085,
- SMSG_GUILD_DECLINE = 0x086,
- CMSG_GUILD_INFO = 0x087,
- SMSG_GUILD_INFO = 0x088,
- CMSG_GUILD_ROSTER = 0x089,
- SMSG_GUILD_ROSTER = 0x08A,
- CMSG_GUILD_PROMOTE = 0x08B,
- CMSG_GUILD_DEMOTE = 0x08C,
- CMSG_GUILD_LEAVE = 0x08D,
- CMSG_GUILD_REMOVE = 0x08E,
- CMSG_GUILD_DISBAND = 0x08F,
- CMSG_GUILD_LEADER = 0x090,
- CMSG_GUILD_MOTD = 0x091,
- SMSG_GUILD_EVENT = 0x092,
- SMSG_GUILD_COMMAND_RESULT = 0x093,
- UMSG_UPDATE_GUILD = 0x094,
- CMSG_MESSAGECHAT = 0x095,
- SMSG_MESSAGECHAT = 0x096,
- CMSG_JOIN_CHANNEL = 0x097,
- CMSG_LEAVE_CHANNEL = 0x098,
- SMSG_CHANNEL_NOTIFY = 0x099,
- CMSG_CHANNEL_LIST = 0x09A,
- SMSG_CHANNEL_LIST = 0x09B,
- CMSG_CHANNEL_PASSWORD = 0x09C,
- CMSG_CHANNEL_SET_OWNER = 0x09D,
- CMSG_CHANNEL_OWNER = 0x09E,
- CMSG_CHANNEL_MODERATOR = 0x09F,
- CMSG_CHANNEL_UNMODERATOR = 0x0A0,
- CMSG_CHANNEL_MUTE = 0x0A1,
- CMSG_CHANNEL_UNMUTE = 0x0A2,
- CMSG_CHANNEL_INVITE = 0x0A3,
- CMSG_CHANNEL_KICK = 0x0A4,
- CMSG_CHANNEL_BAN = 0x0A5,
- CMSG_CHANNEL_UNBAN = 0x0A6,
- CMSG_CHANNEL_ANNOUNCEMENTS = 0x0A7,
- CMSG_CHANNEL_MODERATE = 0x0A8,
- SMSG_UPDATE_OBJECT = 0x0A9,
- SMSG_DESTROY_OBJECT = 0x0AA,
- CMSG_USE_ITEM = 0x0AB,
- CMSG_OPEN_ITEM = 0x0AC,
- CMSG_READ_ITEM = 0x0AD,
- SMSG_READ_ITEM_OK = 0x0AE,
- SMSG_READ_ITEM_FAILED = 0x0AF,
- SMSG_ITEM_COOLDOWN = 0x0B0,
- CMSG_GAMEOBJ_USE = 0x0B1,
- CMSG_DESTROY_ITEMS = 0x0B2,
- SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3,
- CMSG_AREATRIGGER = 0x0B4,
- MSG_MOVE_START_FORWARD = 0x0B5,
- MSG_MOVE_START_BACKWARD = 0x0B6,
- MSG_MOVE_STOP = 0x0B7,
- MSG_MOVE_START_STRAFE_LEFT = 0x0B8,
- MSG_MOVE_START_STRAFE_RIGHT = 0x0B9,
- MSG_MOVE_STOP_STRAFE = 0x0BA,
- MSG_MOVE_JUMP = 0x0BB,
- MSG_MOVE_START_TURN_LEFT = 0x0BC,
- MSG_MOVE_START_TURN_RIGHT = 0x0BD,
- MSG_MOVE_STOP_TURN = 0x0BE,
- MSG_MOVE_START_PITCH_UP = 0x0BF,
- MSG_MOVE_START_PITCH_DOWN = 0x0C0,
- MSG_MOVE_STOP_PITCH = 0x0C1,
- MSG_MOVE_SET_RUN_MODE = 0x0C2,
- MSG_MOVE_SET_WALK_MODE = 0x0C3,
- MSG_MOVE_TOGGLE_LOGGING = 0x0C4,
- MSG_MOVE_TELEPORT = 0x0C5,
- MSG_MOVE_TELEPORT_CHEAT = 0x0C6,
- MSG_MOVE_TELEPORT_ACK = 0x0C7,
- MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0C8,
- MSG_MOVE_FALL_LAND = 0x0C9,
- MSG_MOVE_START_SWIM = 0x0CA,
- MSG_MOVE_STOP_SWIM = 0x0CB,
- MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0CC,
- MSG_MOVE_SET_RUN_SPEED = 0x0CD,
- MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0CE,
- MSG_MOVE_SET_RUN_BACK_SPEED = 0x0CF,
- MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0D0,
- MSG_MOVE_SET_WALK_SPEED = 0x0D1,
- MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0D2,
- MSG_MOVE_SET_SWIM_SPEED = 0x0D3,
- MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0D4,
- MSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D5,
- MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0D6,
- MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0D7,
- MSG_MOVE_SET_TURN_RATE = 0x0D8,
- MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x0D9,
- MSG_MOVE_SET_FACING = 0x0DA,
- MSG_MOVE_SET_PITCH = 0x0DB,
- MSG_MOVE_WORLDPORT_ACK = 0x0DC,
- SMSG_MONSTER_MOVE = 0x0DD,
- SMSG_MOVE_WATER_WALK = 0x0DE,
- SMSG_MOVE_LAND_WALK = 0x0DF,
- CMSG_MOVE_CHARM_PORT_CHEAT = 0x0E0,
- CMSG_MOVE_SET_RAW_POSITION = 0x0E1,
- SMSG_FORCE_RUN_SPEED_CHANGE = 0x0E2,
- CMSG_FORCE_RUN_SPEED_CHANGE_ACK = 0x0E3,
- SMSG_FORCE_RUN_BACK_SPEED_CHANGE = 0x0E4,
- CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x0E5,
- SMSG_FORCE_SWIM_SPEED_CHANGE = 0x0E6,
- CMSG_FORCE_SWIM_SPEED_CHANGE_ACK = 0x0E7,
- SMSG_FORCE_MOVE_ROOT = 0x0E8,
- CMSG_FORCE_MOVE_ROOT_ACK = 0x0E9,
- SMSG_FORCE_MOVE_UNROOT = 0x0EA,
- CMSG_FORCE_MOVE_UNROOT_ACK = 0x0EB,
- MSG_MOVE_ROOT = 0x0EC,
- MSG_MOVE_UNROOT = 0x0ED,
- MSG_MOVE_HEARTBEAT = 0x0EE,
- SMSG_MOVE_KNOCK_BACK = 0x0EF,
- CMSG_MOVE_KNOCK_BACK_ACK = 0x0F0,
- MSG_MOVE_KNOCK_BACK = 0x0F1,
- SMSG_MOVE_FEATHER_FALL = 0x0F2,
- SMSG_MOVE_NORMAL_FALL = 0x0F3,
- SMSG_MOVE_SET_HOVER = 0x0F4,
- SMSG_MOVE_UNSET_HOVER = 0x0F5,
- CMSG_MOVE_HOVER_ACK = 0x0F6,
- MSG_MOVE_HOVER = 0x0F7,
- CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0F8,
- CMSG_OPENING_CINEMATIC = 0x0F9,
- SMSG_TRIGGER_CINEMATIC = 0x0FA,
- CMSG_NEXT_CINEMATIC_CAMERA = 0x0FB,
- CMSG_COMPLETE_CINEMATIC = 0x0FC,
- SMSG_TUTORIAL_FLAGS = 0x0FD,
- CMSG_TUTORIAL_FLAG = 0x0FE,
- CMSG_TUTORIAL_CLEAR = 0x0FF,
- CMSG_TUTORIAL_RESET = 0x100,
- CMSG_STANDSTATECHANGE = 0x101,
- CMSG_EMOTE = 0x102,
- SMSG_EMOTE = 0x103,
- CMSG_TEXT_EMOTE = 0x104,
- SMSG_TEXT_EMOTE = 0x105,
- CMSG_AUTOEQUIP_GROUND_ITEM = 0x106,
- CMSG_AUTOSTORE_GROUND_ITEM = 0x107,
- CMSG_AUTOSTORE_LOOT_ITEM = 0x108,
- CMSG_STORE_LOOT_IN_SLOT = 0x109,
- CMSG_AUTOEQUIP_ITEM = 0x10A,
- CMSG_AUTOSTORE_BAG_ITEM = 0x10B,
- CMSG_SWAP_ITEM = 0x10C,
- CMSG_SWAP_INV_ITEM = 0x10D,
- CMSG_SPLIT_ITEM = 0x10E,
- CMSG_AUTOEQUIP_ITEM_SLOT = 0x10F,
- CMSG_UNCLAIM_LICENSE = 0x110,
- CMSG_DESTROYITEM = 0x111,
- SMSG_INVENTORY_CHANGE_FAILURE = 0x112,
- SMSG_OPEN_CONTAINER = 0x113,
- CMSG_INSPECT = 0x114,
- SMSG_INSPECT_RESULTS_UPDATE = 0x115,
- CMSG_INITIATE_TRADE = 0x116,
- CMSG_BEGIN_TRADE = 0x117,
- CMSG_BUSY_TRADE = 0x118,
- CMSG_IGNORE_TRADE = 0x119,
- CMSG_ACCEPT_TRADE = 0x11A,
- CMSG_UNACCEPT_TRADE = 0x11B,
- CMSG_CANCEL_TRADE = 0x11C,
- CMSG_SET_TRADE_ITEM = 0x11D,
- CMSG_CLEAR_TRADE_ITEM = 0x11E,
- CMSG_SET_TRADE_GOLD = 0x11F,
- SMSG_TRADE_STATUS = 0x120,
- SMSG_TRADE_STATUS_EXTENDED = 0x121,
- SMSG_INITIALIZE_FACTIONS = 0x122,
- SMSG_SET_FACTION_VISIBLE = 0x123,
- SMSG_SET_FACTION_STANDING = 0x124,
- CMSG_SET_FACTION_ATWAR = 0x125,
- CMSG_SET_FACTION_CHEAT = 0x126,
- SMSG_SET_PROFICIENCY = 0x127,
- CMSG_SET_ACTION_BUTTON = 0x128,
- SMSG_ACTION_BUTTONS = 0x129,
- SMSG_INITIAL_SPELLS = 0x12A,
- SMSG_LEARNED_SPELL = 0x12B,
- SMSG_SUPERCEDED_SPELL = 0x12C,
- CMSG_NEW_SPELL_SLOT = 0x12D,
- CMSG_CAST_SPELL = 0x12E,
- CMSG_CANCEL_CAST = 0x12F,
- SMSG_CAST_FAILED = 0x130,
- SMSG_SPELL_START = 0x131,
- SMSG_SPELL_GO = 0x132,
- SMSG_SPELL_FAILURE = 0x133,
- SMSG_SPELL_COOLDOWN = 0x134,
- SMSG_COOLDOWN_EVENT = 0x135,
- CMSG_CANCEL_AURA = 0x136,
- SMSG_EQUIPMENT_SET_SAVED = 0x137,
- SMSG_PET_CAST_FAILED = 0x138,
- MSG_CHANNEL_START = 0x139,
- MSG_CHANNEL_UPDATE = 0x13A,
- CMSG_CANCEL_CHANNELLING = 0x13B,
- SMSG_AI_REACTION = 0x13C,
- CMSG_SET_SELECTION = 0x13D,
- CMSG_DELETEEQUIPMENT_SET = 0x13E,
- CMSG_INSTANCE_LOCK_RESPONSE = 0x13F,
- CMSG_DEBUG_PASSIVE_AURA = 0x140,
- CMSG_ATTACKSWING = 0x141,
- CMSG_ATTACKSTOP = 0x142,
- SMSG_ATTACKSTART = 0x143,
- SMSG_ATTACKSTOP = 0x144,
- SMSG_ATTACKSWING_NOTINRANGE = 0x145,
- SMSG_ATTACKSWING_BADFACING = 0x146,
- SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x147,
- SMSG_ATTACKSWING_DEADTARGET = 0x148,
- SMSG_ATTACKSWING_CANT_ATTACK = 0x149,
- SMSG_ATTACKERSTATEUPDATE = 0x14A,
- SMSG_BATTLEFIELD_PORT_DENIED = 0x14B,
- CMSG_PERFORM_ACTION_SET = 0x14C,
- SMSG_RESUME_CAST_BAR = 0x14D,
- SMSG_CANCEL_COMBAT = 0x14E,
- SMSG_SPELLBREAKLOG = 0x14F,
- SMSG_SPELLHEALLOG = 0x150,
- SMSG_SPELLENERGIZELOG = 0x151,
- SMSG_BREAK_TARGET = 0x152,
- CMSG_SAVE_PLAYER = 0x153,
- CMSG_SETDEATHBINDPOINT = 0x154,
- SMSG_BINDPOINTUPDATE = 0x155,
- CMSG_GETDEATHBINDZONE = 0x156,
- SMSG_BINDZONEREPLY = 0x157,
- SMSG_PLAYERBOUND = 0x158,
- SMSG_CLIENT_CONTROL_UPDATE = 0x159,
- CMSG_REPOP_REQUEST = 0x15A,
- SMSG_RESURRECT_REQUEST = 0x15B,
- CMSG_RESURRECT_RESPONSE = 0x15C,
- CMSG_LOOT = 0x15D,
- CMSG_LOOT_MONEY = 0x15E,
- CMSG_LOOT_RELEASE = 0x15F,
- SMSG_LOOT_RESPONSE = 0x160,
- SMSG_LOOT_RELEASE_RESPONSE = 0x161,
- SMSG_LOOT_REMOVED = 0x162,
- SMSG_LOOT_MONEY_NOTIFY = 0x163,
- SMSG_LOOT_ITEM_NOTIFY = 0x164,
- SMSG_LOOT_CLEAR_MONEY = 0x165,
- SMSG_ITEM_PUSH_RESULT = 0x166,
- SMSG_DUEL_REQUESTED = 0x167,
- SMSG_DUEL_OUTOFBOUNDS = 0x168,
- SMSG_DUEL_INBOUNDS = 0x169,
- SMSG_DUEL_COMPLETE = 0x16A,
- SMSG_DUEL_WINNER = 0x16B,
- CMSG_DUEL_ACCEPTED = 0x16C,
- CMSG_DUEL_CANCELLED = 0x16D,
- SMSG_MOUNTRESULT = 0x16E,
- SMSG_DISMOUNTRESULT = 0x16F,
- SMSG_REMOVED_FROM_PVP_QUEUE = 0x170,
- CMSG_MOUNTSPECIAL_ANIM = 0x171,
- SMSG_MOUNTSPECIAL_ANIM = 0x172,
- SMSG_PET_TAME_FAILURE = 0x173,
- CMSG_PET_SET_ACTION = 0x174,
- CMSG_PET_ACTION = 0x175,
- CMSG_PET_ABANDON = 0x176,
- CMSG_PET_RENAME = 0x177,
- SMSG_PET_NAME_INVALID = 0x178,
- SMSG_PET_SPELLS = 0x179,
- SMSG_PET_MODE = 0x17A,
- CMSG_GOSSIP_HELLO = 0x17B,
- CMSG_GOSSIP_SELECT_OPTION = 0x17C,
- SMSG_GOSSIP_MESSAGE = 0x17D,
- SMSG_GOSSIP_COMPLETE = 0x17E,
- CMSG_NPC_TEXT_QUERY = 0x17F,
- SMSG_NPC_TEXT_UPDATE = 0x180,
- SMSG_NPC_WONT_TALK = 0x181,
- CMSG_QUESTGIVER_STATUS_QUERY = 0x182,
- SMSG_QUESTGIVER_STATUS = 0x183,
- CMSG_QUESTGIVER_HELLO = 0x184,
- SMSG_QUESTGIVER_QUEST_LIST = 0x185,
- CMSG_QUESTGIVER_QUERY_QUEST = 0x186,
- CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187,
- SMSG_QUESTGIVER_QUEST_DETAILS = 0x188,
- CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189,
- CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A,
- SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B,
- CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C,
- SMSG_QUESTGIVER_OFFER_REWARD = 0x18D,
- CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E,
- SMSG_QUESTGIVER_QUEST_INVALID = 0x18F,
- CMSG_QUESTGIVER_CANCEL = 0x190,
- SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191,
- SMSG_QUESTGIVER_QUEST_FAILED = 0x192,
- CMSG_QUESTLOG_SWAP_QUEST = 0x193,
- CMSG_QUESTLOG_REMOVE_QUEST = 0x194,
- SMSG_QUESTLOG_FULL = 0x195,
- SMSG_QUESTUPDATE_FAILED = 0x196,
- SMSG_QUESTUPDATE_FAILEDTIMER = 0x197,
- SMSG_QUESTUPDATE_COMPLETE = 0x198,
- SMSG_QUESTUPDATE_ADD_KILL = 0x199,
- SMSG_QUESTUPDATE_ADD_ITEM = 0x19A,
- CMSG_QUEST_CONFIRM_ACCEPT = 0x19B,
- SMSG_QUEST_CONFIRM_ACCEPT = 0x19C,
- CMSG_PUSHQUESTTOPARTY = 0x19D,
- CMSG_LIST_INVENTORY = 0x19E,
- SMSG_LIST_INVENTORY = 0x19F,
- CMSG_SELL_ITEM = 0x1A0,
- SMSG_SELL_ITEM = 0x1A1,
- CMSG_BUY_ITEM = 0x1A2,
- CMSG_BUY_ITEM_IN_SLOT = 0x1A3,
- SMSG_BUY_ITEM = 0x1A4,
- SMSG_BUY_FAILED = 0x1A5,
- CMSG_TAXICLEARALLNODES = 0x1A6,
- CMSG_TAXIENABLEALLNODES = 0x1A7,
- CMSG_TAXISHOWNODES = 0x1A8,
- SMSG_SHOWTAXINODES = 0x1A9,
- CMSG_TAXINODE_STATUS_QUERY = 0x1AA,
- SMSG_TAXINODE_STATUS = 0x1AB,
- CMSG_TAXIQUERYAVAILABLENODES = 0x1AC,
- CMSG_ACTIVATETAXI = 0x1AD,
- SMSG_ACTIVATETAXIREPLY = 0x1AE,
- SMSG_NEW_TAXI_PATH = 0x1AF,
- CMSG_TRAINER_LIST = 0x1B0,
- SMSG_TRAINER_LIST = 0x1B1,
- CMSG_TRAINER_BUY_SPELL = 0x1B2,
- SMSG_TRAINER_BUY_SUCCEEDED = 0x1B3,
- SMSG_TRAINER_BUY_FAILED = 0x1B4,
- CMSG_BINDER_ACTIVATE = 0x1B5,
- SMSG_PLAYERBINDERROR = 0x1B6,
- CMSG_BANKER_ACTIVATE = 0x1B7,
- SMSG_SHOW_BANK = 0x1B8,
- CMSG_BUY_BANK_SLOT = 0x1B9,
- SMSG_BUY_BANK_SLOT_RESULT = 0x1BA,
- CMSG_PETITION_SHOWLIST = 0x1BB,
- SMSG_PETITION_SHOWLIST = 0x1BC,
- CMSG_PETITION_BUY = 0x1BD,
- CMSG_PETITION_SHOW_SIGNATURES = 0x1BE,
- SMSG_PETITION_SHOW_SIGNATURES = 0x1BF,
- CMSG_PETITION_SIGN = 0x1C0,
- SMSG_PETITION_SIGN_RESULTS = 0x1C1,
- MSG_PETITION_DECLINE = 0x1C2,
- CMSG_OFFER_PETITION = 0x1C3,
- CMSG_TURN_IN_PETITION = 0x1C4,
- SMSG_TURN_IN_PETITION_RESULTS = 0x1C5,
- CMSG_PETITION_QUERY = 0x1C6,
- SMSG_PETITION_QUERY_RESPONSE = 0x1C7,
- SMSG_FISH_NOT_HOOKED = 0x1C8,
- SMSG_FISH_ESCAPED = 0x1C9,
- CMSG_BUG = 0x1CA,
- SMSG_NOTIFICATION = 0x1CB,
- CMSG_PLAYED_TIME = 0x1CC,
- SMSG_PLAYED_TIME = 0x1CD,
- CMSG_QUERY_TIME = 0x1CE,
- SMSG_QUERY_TIME_RESPONSE = 0x1CF,
- SMSG_LOG_XPGAIN = 0x1D0,
- SMSG_AURACASTLOG = 0x1D1,
- CMSG_RECLAIM_CORPSE = 0x1D2,
- CMSG_WRAP_ITEM = 0x1D3,
- SMSG_LEVELUP_INFO = 0x1D4,
- MSG_MINIMAP_PING = 0x1D5,
- SMSG_RESISTLOG = 0x1D6,
- SMSG_ENCHANTMENTLOG = 0x1D7,
- CMSG_SET_SKILL_CHEAT = 0x1D8,
- SMSG_START_MIRROR_TIMER = 0x1D9,
- SMSG_PAUSE_MIRROR_TIMER = 0x1DA,
- SMSG_STOP_MIRROR_TIMER = 0x1DB,
- CMSG_PING = 0x1DC,
- SMSG_PONG = 0x1DD,
- SMSG_CLEAR_COOLDOWN = 0x1DE,
- SMSG_GAMEOBJECT_PAGETEXT = 0x1DF,
- CMSG_SETSHEATHED = 0x1E0,
- SMSG_COOLDOWN_CHEAT = 0x1E1,
- SMSG_SPELL_DELAYED = 0x1E2,
- CMSG_QUEST_POI_QUERY = 0x1E3,
- SMSG_QUEST_POI_QUERY_RESPONSE = 0x1E4,
- CMSG_GHOST = 0x1E5,
- CMSG_GM_INVIS = 0x1E6,
- SMSG_INVALID_PROMOTION_CODE = 0x1E7,
- MSG_GM_BIND_OTHER = 0x1E8,
- MSG_GM_SUMMON = 0x1E9,
- SMSG_ITEM_TIME_UPDATE = 0x1EA,
- SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1EB,
- SMSG_AUTH_CHALLENGE = 0x1EC,
- CMSG_AUTH_SESSION = 0x1ED,
- SMSG_AUTH_RESPONSE = 0x1EE,
- MSG_GM_SHOWLABEL = 0x1EF,
- CMSG_PET_CAST_SPELL = 0x1F0,
- MSG_SAVE_GUILD_EMBLEM = 0x1F1,
- MSG_TABARDVENDOR_ACTIVATE = 0x1F2,
- SMSG_PLAY_SPELL_VISUAL = 0x1F3,
- CMSG_ZONEUPDATE = 0x1F4,
- SMSG_PARTYKILLLOG = 0x1F5,
- SMSG_COMPRESSED_UPDATE_OBJECT = 0x1F6,
- SMSG_PLAY_SPELL_IMPACT = 0x1F7,
- SMSG_EXPLORATION_EXPERIENCE = 0x1F8,
- CMSG_GM_SET_SECURITY_GROUP = 0x1F9,
- CMSG_GM_NUKE = 0x1FA,
- MSG_RANDOM_ROLL = 0x1FB,
- SMSG_ENVIRONMENTALDAMAGELOG = 0x1FC,
- CMSG_CHANGEPLAYER_DIFFICULTY = 0x1FD,
- SMSG_RWHOIS = 0x1FE,
- SMSG_LFG_PLAYER_REWARD = 0x1FF, // uint32, uint8, uint32, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}
- SMSG_LFG_TELEPORT_DENIED = 0x200, // uint32 (1, 2, 4, 6;0, 5, 7)
- CMSG_UNLEARN_SPELL = 0x201,
- CMSG_UNLEARN_SKILL = 0x202,
- SMSG_REMOVED_SPELL = 0x203,
- CMSG_DECHARGE = 0x204,
- CMSG_GMTICKET_CREATE = 0x205,
- SMSG_GMTICKET_CREATE = 0x206,
- CMSG_GMTICKET_UPDATETEXT = 0x207,
- SMSG_GMTICKET_UPDATETEXT = 0x208,
- SMSG_ACCOUNT_DATA_TIMES = 0x209,
- CMSG_REQUEST_ACCOUNT_DATA = 0x20A,
- CMSG_UPDATE_ACCOUNT_DATA = 0x20B,
- SMSG_UPDATE_ACCOUNT_DATA = 0x20C,
- SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x20D,
- SMSG_CHANGEPLAYER_DIFFICULTY_RESULT = 0x20E,
- CMSG_GM_TEACH = 0x20F,
- CMSG_GM_CREATE_ITEM_TARGET = 0x210,
- CMSG_GMTICKET_GETTICKET = 0x211,
- SMSG_GMTICKET_GETTICKET = 0x212,
- CMSG_UNLEARN_TALENTS = 0x213,
- SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT = 0x214,
- SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x215,
- MSG_CORPSE_QUERY = 0x216,
- CMSG_GMTICKET_DELETETICKET = 0x217,
- SMSG_GMTICKET_DELETETICKET = 0x218,
- SMSG_CHAT_WRONG_FACTION = 0x219,
- CMSG_GMTICKET_SYSTEMSTATUS = 0x21A,
- SMSG_GMTICKET_SYSTEMSTATUS = 0x21B,
- CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C,
- CMSG_SET_STAT_CHEAT = 0x21D,
- SMSG_QUEST_FORCE_REMOVE = 0x21E, // uint32 questid
- CMSG_SKILL_BUY_STEP = 0x21F,
- CMSG_SKILL_BUY_RANK = 0x220,
- CMSG_XP_CHEAT = 0x221,
- SMSG_SPIRIT_HEALER_CONFIRM = 0x222,
- CMSG_CHARACTER_POINT_CHEAT = 0x223,
- SMSG_GOSSIP_POI = 0x224,
- CMSG_CHAT_IGNORED = 0x225,
- CMSG_GM_VISION = 0x226,
- CMSG_SERVER_COMMAND = 0x227,
- CMSG_GM_SILENCE = 0x228,
- CMSG_GM_REVEALTO = 0x229,
- CMSG_GM_RESURRECT = 0x22A,
- CMSG_GM_SUMMONMOB = 0x22B,
- CMSG_GM_MOVECORPSE = 0x22C,
- CMSG_GM_FREEZE = 0x22D,
- CMSG_GM_UBERINVIS = 0x22E,
- CMSG_GM_REQUEST_PLAYER_INFO = 0x22F,
- SMSG_GM_PLAYER_INFO = 0x230,
- CMSG_GUILD_RANK = 0x231,
- CMSG_GUILD_ADD_RANK = 0x232,
- CMSG_GUILD_DEL_RANK = 0x233,
- CMSG_GUILD_SET_PUBLIC_NOTE = 0x234,
- CMSG_GUILD_SET_OFFICER_NOTE = 0x235,
- SMSG_LOGIN_VERIFY_WORLD = 0x236,
- CMSG_CLEAR_EXPLORATION = 0x237,
- CMSG_SEND_MAIL = 0x238,
- SMSG_SEND_MAIL_RESULT = 0x239,
- CMSG_GET_MAIL_LIST = 0x23A,
- SMSG_MAIL_LIST_RESULT = 0x23B,
- CMSG_BATTLEFIELD_LIST = 0x23C,
- SMSG_BATTLEFIELD_LIST = 0x23D,
- CMSG_BATTLEFIELD_JOIN = 0x23E,
- SMSG_FORCE_SET_VEHICLE_REC_ID = 0x23F,
- CMSG_SET_VEHICLE_REC_ID_ACK = 0x240,
- CMSG_TAXICLEARNODE = 0x241,
- CMSG_TAXIENABLENODE = 0x242,
- CMSG_ITEM_TEXT_QUERY = 0x243,
- SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x244,
- CMSG_MAIL_TAKE_MONEY = 0x245,
- CMSG_MAIL_TAKE_ITEM = 0x246,
- CMSG_MAIL_MARK_AS_READ = 0x247,
- CMSG_MAIL_RETURN_TO_SENDER = 0x248,
- CMSG_MAIL_DELETE = 0x249,
- CMSG_MAIL_CREATE_TEXT_ITEM = 0x24A,
- SMSG_SPELLLOGMISS = 0x24B,
- SMSG_SPELLLOGEXECUTE = 0x24C,
- SMSG_DEBUGAURAPROC = 0x24D,
- SMSG_PERIODICAURALOG = 0x24E,
- SMSG_SPELLDAMAGESHIELD = 0x24F,
- SMSG_SPELLNONMELEEDAMAGELOG = 0x250,
- CMSG_LEARN_TALENT = 0x251,
- SMSG_RESURRECT_FAILED = 0x252,
- CMSG_TOGGLE_PVP = 0x253,
- SMSG_ZONE_UNDER_ATTACK = 0x254,
- MSG_AUCTION_HELLO = 0x255,
- CMSG_AUCTION_SELL_ITEM = 0x256,
- CMSG_AUCTION_REMOVE_ITEM = 0x257,
- CMSG_AUCTION_LIST_ITEMS = 0x258,
- CMSG_AUCTION_LIST_OWNER_ITEMS = 0x259,
- CMSG_AUCTION_PLACE_BID = 0x25A,
- SMSG_AUCTION_COMMAND_RESULT = 0x25B,
- SMSG_AUCTION_LIST_RESULT = 0x25C,
- SMSG_AUCTION_OWNER_LIST_RESULT = 0x25D,
- SMSG_AUCTION_BIDDER_NOTIFICATION = 0x25E,
- SMSG_AUCTION_OWNER_NOTIFICATION = 0x25F,
- SMSG_PROCRESIST = 0x260,
- SMSG_COMBAT_EVENT_FAILED = 0x261,
- SMSG_DISPEL_FAILED = 0x262,
- SMSG_SPELLORDAMAGE_IMMUNE = 0x263,
- CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x264,
- SMSG_AUCTION_BIDDER_LIST_RESULT = 0x265,
- SMSG_SET_FLAT_SPELL_MODIFIER = 0x266,
- SMSG_SET_PCT_SPELL_MODIFIER = 0x267,
- CMSG_SET_AMMO = 0x268,
- SMSG_CORPSE_RECLAIM_DELAY = 0x269,
- CMSG_SET_ACTIVE_MOVER = 0x26A,
- CMSG_PET_CANCEL_AURA = 0x26B,
- CMSG_PLAYER_AI_CHEAT = 0x26C,
- CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x26D,
- MSG_GM_ACCOUNT_ONLINE = 0x26E,
- MSG_LIST_STABLED_PETS = 0x26F,
- CMSG_STABLE_PET = 0x270,
- CMSG_UNSTABLE_PET = 0x271,
- CMSG_BUY_STABLE_SLOT = 0x272,
- SMSG_STABLE_RESULT = 0x273,
- CMSG_STABLE_REVIVE_PET = 0x274,
- CMSG_STABLE_SWAP_PET = 0x275,
- MSG_QUEST_PUSH_RESULT = 0x276,
- SMSG_PLAY_MUSIC = 0x277,
- SMSG_PLAY_OBJECT_SOUND = 0x278,
- CMSG_REQUEST_PET_INFO = 0x279,
- CMSG_FAR_SIGHT = 0x27A,
- SMSG_SPELLDISPELLOG = 0x27B,
- SMSG_DAMAGE_CALC_LOG = 0x27C,
- CMSG_ENABLE_DAMAGE_LOG = 0x27D,
- CMSG_GROUP_CHANGE_SUB_GROUP = 0x27E,
- CMSG_REQUEST_PARTY_MEMBER_STATS = 0x27F,
- CMSG_GROUP_SWAP_SUB_GROUP = 0x280,
- CMSG_RESET_FACTION_CHEAT = 0x281,
- CMSG_AUTOSTORE_BANK_ITEM = 0x282,
- CMSG_AUTOBANK_ITEM = 0x283,
- MSG_QUERY_NEXT_MAIL_TIME = 0x284,
- SMSG_RECEIVED_MAIL = 0x285,
- SMSG_RAID_GROUP_ONLY = 0x286,
- CMSG_SET_DURABILITY_CHEAT = 0x287,
- CMSG_SET_PVP_RANK_CHEAT = 0x288,
- CMSG_ADD_PVP_MEDAL_CHEAT = 0x289,
- CMSG_DEL_PVP_MEDAL_CHEAT = 0x28A,
- CMSG_SET_PVP_TITLE = 0x28B,
- SMSG_PVP_CREDIT = 0x28C,
- SMSG_AUCTION_REMOVED_NOTIFICATION = 0x28D,
- CMSG_GROUP_RAID_CONVERT = 0x28E,
- CMSG_GROUP_ASSISTANT_LEADER = 0x28F,
- CMSG_BUYBACK_ITEM = 0x290,
- SMSG_SERVER_MESSAGE = 0x291,
- CMSG_SET_SAVED_INSTANCE_EXTEND = 0x292,
- SMSG_LFG_OFFER_CONTINUE = 0x293,
- CMSG_TEST_DROP_RATE = 0x294,
- SMSG_TEST_DROP_RATE_RESULT = 0x295,
- CMSG_LFG_GET_STATUS = 0x296,
- SMSG_SHOW_MAILBOX = 0x297,
- SMSG_RESET_RANGED_COMBAT_TIMER = 0x298,
- SMSG_CHAT_NOT_IN_PARTY = 0x299, // uint32, errors: ERR_NOT_IN_GROUP (2, 51) and ERR_NOT_IN_RAID (3, 39, 40)
- CMSG_GMTICKETSYSTEM_TOGGLE = 0x29A,
- CMSG_CANCEL_GROWTH_AURA = 0x29B,
- SMSG_CANCEL_AUTO_REPEAT = 0x29C,
- SMSG_STANDSTATE_UPDATE = 0x29D,
- SMSG_LOOT_ALL_PASSED = 0x29E,
- SMSG_LOOT_ROLL_WON = 0x29F,
- CMSG_LOOT_ROLL = 0x2A0,
- SMSG_LOOT_START_ROLL = 0x2A1,
- SMSG_LOOT_ROLL = 0x2A2,
- CMSG_LOOT_MASTER_GIVE = 0x2A3,
- SMSG_LOOT_MASTER_LIST = 0x2A4,
- SMSG_SET_FORCED_REACTIONS = 0x2A5,
- SMSG_SPELL_FAILED_OTHER = 0x2A6,
- SMSG_GAMEOBJECT_RESET_STATE = 0x2A7,
- CMSG_REPAIR_ITEM = 0x2A8,
- SMSG_CHAT_PLAYER_NOT_FOUND = 0x2A9,
- MSG_TALENT_WIPE_CONFIRM = 0x2AA,
- SMSG_SUMMON_REQUEST = 0x2AB,
- CMSG_SUMMON_RESPONSE = 0x2AC,
- MSG_DEV_SHOWLABEL = 0x2AD,
- SMSG_MONSTER_MOVE_TRANSPORT = 0x2AE,
- SMSG_PET_BROKEN = 0x2AF,
- MSG_MOVE_FEATHER_FALL = 0x2B0,
- MSG_MOVE_WATER_WALK = 0x2B1,
- CMSG_SERVER_BROADCAST = 0x2B2,
- CMSG_SELF_RES = 0x2B3,
- SMSG_FEIGN_DEATH_RESISTED = 0x2B4,
- CMSG_RUN_SCRIPT = 0x2B5,
- SMSG_SCRIPT_MESSAGE = 0x2B6,
- SMSG_DUEL_COUNTDOWN = 0x2B7,
- SMSG_AREA_TRIGGER_MESSAGE = 0x2B8,
- CMSG_SHOWING_HELM = 0x2B9,
- CMSG_SHOWING_CLOAK = 0x2BA,
- SMSG_LFG_ROLE_CHOSEN = 0x2BB,
- SMSG_PLAYER_SKINNED = 0x2BC,
- SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD,
- CMSG_SET_EXPLORATION = 0x2BE,
- CMSG_SET_ACTIONBAR_TOGGLES = 0x2BF,
- UMSG_DELETE_GUILD_CHARTER = 0x2C0,
- MSG_PETITION_RENAME = 0x2C1,
- SMSG_INIT_WORLD_STATES = 0x2C2,
- SMSG_UPDATE_WORLD_STATE = 0x2C3,
- CMSG_ITEM_NAME_QUERY = 0x2C4,
- SMSG_ITEM_NAME_QUERY_RESPONSE = 0x2C5,
- SMSG_PET_ACTION_FEEDBACK = 0x2C6,
- CMSG_CHAR_RENAME = 0x2C7,
- SMSG_CHAR_RENAME = 0x2C8,
- CMSG_MOVE_SPLINE_DONE = 0x2C9,
- CMSG_MOVE_FALL_RESET = 0x2CA,
- SMSG_INSTANCE_SAVE_CREATED = 0x2CB,
- SMSG_RAID_INSTANCE_INFO = 0x2CC,
- CMSG_REQUEST_RAID_INFO = 0x2CD,
- CMSG_MOVE_TIME_SKIPPED = 0x2CE,
- CMSG_MOVE_FEATHER_FALL_ACK = 0x2CF,
- CMSG_MOVE_WATER_WALK_ACK = 0x2D0,
- CMSG_MOVE_NOT_ACTIVE_MOVER = 0x2D1,
- SMSG_PLAY_SOUND = 0x2D2,
- CMSG_BATTLEFIELD_STATUS = 0x2D3,
- SMSG_BATTLEFIELD_STATUS = 0x2D4,
- CMSG_BATTLEFIELD_PORT = 0x2D5,
- MSG_INSPECT_HONOR_STATS = 0x2D6,
- CMSG_BATTLEMASTER_HELLO = 0x2D7,
- CMSG_MOVE_START_SWIM_CHEAT = 0x2D8,
- CMSG_MOVE_STOP_SWIM_CHEAT = 0x2D9,
- SMSG_FORCE_WALK_SPEED_CHANGE = 0x2DA,
- CMSG_FORCE_WALK_SPEED_CHANGE_ACK = 0x2DB,
- SMSG_FORCE_SWIM_BACK_SPEED_CHANGE = 0x2DC,
- CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x2DD,
- SMSG_FORCE_TURN_RATE_CHANGE = 0x2DE,
- CMSG_FORCE_TURN_RATE_CHANGE_ACK = 0x2DF,
- MSG_PVP_LOG_DATA = 0x2E0,
- CMSG_LEAVE_BATTLEFIELD = 0x2E1,
- CMSG_AREA_SPIRIT_HEALER_QUERY = 0x2E2,
- CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x2E3,
- SMSG_AREA_SPIRIT_HEALER_TIME = 0x2E4,
- CMSG_GM_UNTEACH = 0x2E5,
- SMSG_WARDEN_DATA = 0x2E6,
- CMSG_WARDEN_DATA = 0x2E7,
- SMSG_GROUP_JOINED_BATTLEGROUND = 0x2E8,
- MSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2E9,
- CMSG_PET_STOP_ATTACK = 0x2EA,
- SMSG_BINDER_CONFIRM = 0x2EB,
- SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2EC,
- SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2ED,
- CMSG_BATTLEMASTER_JOIN = 0x2EE,
- SMSG_ADDON_INFO = 0x2EF,
- CMSG_PET_UNLEARN = 0x2F0, // Deprecated 3.x
- SMSG_PET_UNLEARN_CONFIRM = 0x2F1, // Deprecated 3.x
- SMSG_PARTY_MEMBER_STATS_FULL = 0x2F2,
- CMSG_PET_SPELL_AUTOCAST = 0x2F3,
- SMSG_WEATHER = 0x2F4,
- SMSG_PLAY_TIME_WARNING = 0x2F5,
- SMSG_MINIGAME_SETUP = 0x2F6,
- SMSG_MINIGAME_STATE = 0x2F7,
- CMSG_MINIGAME_MOVE = 0x2F8,
- SMSG_MINIGAME_MOVE_FAILED = 0x2F9,
- SMSG_RAID_INSTANCE_MESSAGE = 0x2FA,
- SMSG_COMPRESSED_MOVES = 0x2FB,
- CMSG_GUILD_INFO_TEXT = 0x2FC,
- SMSG_CHAT_RESTRICTED = 0x2FD,
- SMSG_SPLINE_SET_RUN_SPEED = 0x2FE,
- SMSG_SPLINE_SET_RUN_BACK_SPEED = 0x2FF,
- SMSG_SPLINE_SET_SWIM_SPEED = 0x300,
- SMSG_SPLINE_SET_WALK_SPEED = 0x301,
- SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x302,
- SMSG_SPLINE_SET_TURN_RATE = 0x303,
- SMSG_SPLINE_MOVE_UNROOT = 0x304,
- SMSG_SPLINE_MOVE_FEATHER_FALL = 0x305,
- SMSG_SPLINE_MOVE_NORMAL_FALL = 0x306,
- SMSG_SPLINE_MOVE_SET_HOVER = 0x307,
- SMSG_SPLINE_MOVE_UNSET_HOVER = 0x308,
- SMSG_SPLINE_MOVE_WATER_WALK = 0x309,
- SMSG_SPLINE_MOVE_LAND_WALK = 0x30A,
- SMSG_SPLINE_MOVE_START_SWIM = 0x30B,
- SMSG_SPLINE_MOVE_STOP_SWIM = 0x30C,
- SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x30D,
- SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x30E,
- CMSG_GM_NUKE_ACCOUNT = 0x30F,
- MSG_GM_DESTROY_CORPSE = 0x310,
- CMSG_GM_DESTROY_ONLINE_CORPSE = 0x311,
- CMSG_ACTIVATETAXIEXPRESS = 0x312,
- SMSG_SET_FACTION_ATWAR = 0x313,
- SMSG_GAMETIMEBIAS_SET = 0x314,
- CMSG_DEBUG_ACTIONS_START = 0x315,
- CMSG_DEBUG_ACTIONS_STOP = 0x316,
- CMSG_SET_FACTION_INACTIVE = 0x317,
- CMSG_SET_WATCHED_FACTION = 0x318,
- MSG_MOVE_TIME_SKIPPED = 0x319,
- SMSG_SPLINE_MOVE_ROOT = 0x31A,
- CMSG_SET_EXPLORATION_ALL = 0x31B,
- SMSG_INVALIDATE_PLAYER = 0x31C,
- CMSG_RESET_INSTANCES = 0x31D,
- SMSG_INSTANCE_RESET = 0x31E,
- SMSG_INSTANCE_RESET_FAILED = 0x31F,
- SMSG_UPDATE_LAST_INSTANCE = 0x320,
- MSG_RAID_TARGET_UPDATE = 0x321,
- MSG_RAID_READY_CHECK = 0x322,
- CMSG_LUA_USAGE = 0x323,
- SMSG_PET_ACTION_SOUND = 0x324,
- SMSG_PET_DISMISS_SOUND = 0x325,
- SMSG_GHOSTEE_GONE = 0x326,
- CMSG_GM_UPDATE_TICKET_STATUS = 0x327,
- SMSG_GM_TICKET_STATUS_UPDATE = 0x328,
- MSG_SET_DUNGEON_DIFFICULTY = 0x329,
- CMSG_GMSURVEY_SUBMIT = 0x32A,
- SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x32B,
- CMSG_IGNORE_KNOCKBACK_CHEAT = 0x32C,
- SMSG_CHAT_PLAYER_AMBIGUOUS = 0x32D,
- MSG_DELAY_GHOST_TELEPORT = 0x32E,
- SMSG_SPELLINSTAKILLLOG = 0x32F,
- SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x330,
- CMSG_CHAT_FILTERED = 0x331,
- SMSG_EXPECTED_SPAM_RECORDS = 0x332,
- SMSG_SPELLSTEALLOG = 0x333,
- CMSG_LOTTERY_QUERY_OBSOLETE = 0x334,
- SMSG_LOTTERY_QUERY_RESULT_OBSOLETE = 0x335,
- CMSG_BUY_LOTTERY_TICKET_OBSOLETE = 0x336,
- SMSG_LOTTERY_RESULT_OBSOLETE = 0x337,
- SMSG_CHARACTER_PROFILE = 0x338,
- SMSG_CHARACTER_PROFILE_REALM_CONNECTED = 0x339,
- SMSG_DEFENSE_MESSAGE = 0x33A,
- SMSG_INSTANCE_DIFFICULTY = 0x33B,
- MSG_GM_RESETINSTANCELIMIT = 0x33C,
- SMSG_MOTD = 0x33D,
- SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x33E,
- SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x33F,
- CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK= 0x340,
- MSG_MOVE_START_SWIM_CHEAT = 0x341,
- MSG_MOVE_STOP_SWIM_CHEAT = 0x342,
- SMSG_MOVE_SET_CAN_FLY = 0x343,
- SMSG_MOVE_UNSET_CAN_FLY = 0x344,
- CMSG_MOVE_SET_CAN_FLY_ACK = 0x345,
- CMSG_MOVE_SET_FLY = 0x346,
- CMSG_SOCKET_GEMS = 0x347,
- CMSG_ARENA_TEAM_CREATE = 0x348,
- SMSG_ARENA_TEAM_COMMAND_RESULT = 0x349,
- MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x34A,
- CMSG_ARENA_TEAM_QUERY = 0x34B,
- SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x34C,
- CMSG_ARENA_TEAM_ROSTER = 0x34D,
- SMSG_ARENA_TEAM_ROSTER = 0x34E,
- CMSG_ARENA_TEAM_INVITE = 0x34F,
- SMSG_ARENA_TEAM_INVITE = 0x350,
- CMSG_ARENA_TEAM_ACCEPT = 0x351,
- CMSG_ARENA_TEAM_DECLINE = 0x352,
- CMSG_ARENA_TEAM_LEAVE = 0x353,
- CMSG_ARENA_TEAM_REMOVE = 0x354,
- CMSG_ARENA_TEAM_DISBAND = 0x355,
- CMSG_ARENA_TEAM_LEADER = 0x356,
- SMSG_ARENA_TEAM_EVENT = 0x357,
- CMSG_BATTLEMASTER_JOIN_ARENA = 0x358,
- MSG_MOVE_START_ASCEND = 0x359,
- MSG_MOVE_STOP_ASCEND = 0x35A,
- SMSG_ARENA_TEAM_STATS = 0x35B,
- CMSG_LFG_JOIN = 0x35C,
- CMSG_LFG_LEAVE = 0x35D,
- CMSG_SEARCH_LFG_JOIN = 0x35E,
- CMSG_SEARCH_LFG_LEAVE = 0x35F,
- SMSG_UPDATE_LFG_LIST = 0x360, // uint32, uint32, if (uint8) { uint32 count, for (count) { uint64} }, uint32 count2, uint32, for (count2) { uint64, uint32 flags, if (flags & 0x2) {string}, if (flags & 0x10) {for (3) uint8}, if (flags & 0x80) {uint64, uint32}}, uint32 count3, uint32, for (count3) {uint64, uint32 flags, if (flags & 0x1) {uint8, uint8, uint8, for (3) uint8, uint32, uint32, uint32, uint32, uint32, uint32, float, float, uint32, uint32, uint32, uint32, uint32, float, uint32, uint32, uint32, uint32, uint32, uint32}, if (flags&0x2) string, if (flags&0x4) uint8, if (flags&0x8) uint64, if (flags&0x10) uint8, if (flags&0x20) uint32, if (flags&0x40) uint8, if (flags& 0x80) {uint64, uint32}}
- SMSG_LFG_PROPOSAL_UPDATE = 0x361, // uint32, uint8, uint32, uint32, uint8, for (uint8) {uint32, uint8, uint8, uint8, uint8}
- CMSG_LFG_PROPOSAL_RESULT = 0x362,
- SMSG_LFG_ROLE_CHECK_UPDATE = 0x363, // uint32, uint8, for (uint8) uint32, uint8, for (uint8) { uint64, uint8, uint32, uint8, }
- SMSG_LFG_JOIN_RESULT = 0x364, // uint32 unk, uint32, if (unk == 6) { uint8 count, for (count) uint64 }
- SMSG_LFG_QUEUE_STATUS = 0x365, // uint32 dungeon, uint32 lfgtype, uint32, uint32, uint32, uint32, uint8, uint8, uint8, uint8
- CMSG_SET_LFG_COMMENT = 0x366,
- SMSG_LFG_UPDATE_PLAYER = 0x367, // uint8, if (uint8) { uint8, uint8, uint8, uint8, if (uint8) for (uint8) uint32, string}
- SMSG_LFG_UPDATE_PARTY = 0x368, // uint8, if (uint8) { uint8, uint8, uint8, for (3) uint8, uint8, if (uint8) for (uint8) uint32, string}
- SMSG_LFG_UPDATE_SEARCH = 0x369, // uint8
- CMSG_LFG_SET_ROLES = 0x36A,
- CMSG_LFG_SET_NEEDS = 0x36B,
- CMSG_LFG_SET_BOOT_VOTE = 0x36C,
- SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
- CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E,
- SMSG_LFG_PLAYER_INFO = 0x36F, // uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}}, uint32, for (uint32) {uint32, uint32}
- CMSG_LFG_TELEPORT = 0x370,
- CMSG_LFD_PARTY_LOCK_INFO_REQUEST = 0x371,
- SMSG_LFG_PARTY_INFO = 0x372, // uint8, for (uint8) uint64
- SMSG_TITLE_EARNED = 0x373,
- CMSG_SET_TITLE = 0x374,
- CMSG_CANCEL_MOUNT_AURA = 0x375,
- SMSG_ARENA_ERROR = 0x376,
- MSG_INSPECT_ARENA_TEAMS = 0x377,
- SMSG_DEATH_RELEASE_LOC = 0x378,
- CMSG_CANCEL_TEMP_ENCHANTMENT = 0x379,
- SMSG_FORCED_DEATH_UPDATE = 0x37A,
- CMSG_CHEAT_SET_HONOR_CURRENCY = 0x37B,
- CMSG_CHEAT_SET_ARENA_CURRENCY = 0x37C,
- MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x37D,
- MSG_MOVE_SET_FLIGHT_SPEED = 0x37E,
- MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT = 0x37F,
- MSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x380,
- SMSG_FORCE_FLIGHT_SPEED_CHANGE = 0x381,
- CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x382,
- SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE = 0x383,
- CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x384,
- SMSG_SPLINE_SET_FLIGHT_SPEED = 0x385,
- SMSG_SPLINE_SET_FLIGHT_BACK_SPEED = 0x386,
- CMSG_MAELSTROM_INVALIDATE_CACHE = 0x387,
- SMSG_FLIGHT_SPLINE_SYNC = 0x388,
- CMSG_SET_TAXI_BENCHMARK_MODE = 0x389,
- SMSG_JOINED_BATTLEGROUND_QUEUE = 0x38A,
- SMSG_REALM_SPLIT = 0x38B,
- CMSG_REALM_SPLIT = 0x38C,
- CMSG_MOVE_CHNG_TRANSPORT = 0x38D,
- MSG_PARTY_ASSIGNMENT = 0x38E,
- SMSG_OFFER_PETITION_ERROR = 0x38F,
- SMSG_TIME_SYNC_REQ = 0x390,
- CMSG_TIME_SYNC_RESP = 0x391,
- CMSG_SEND_LOCAL_EVENT = 0x392,
- CMSG_SEND_GENERAL_TRIGGER = 0x393,
- CMSG_SEND_COMBAT_TRIGGER = 0x394,
- CMSG_MAELSTROM_GM_SENT_MAIL = 0x395,
- SMSG_RESET_FAILED_NOTIFY = 0x396,
- SMSG_REAL_GROUP_UPDATE = 0x397,
- SMSG_LFG_DISABLED = 0x398,
- CMSG_ACTIVE_PVP_CHEAT = 0x399,
- CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY = 0x39A,
- SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE = 0x39B,
- SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE = 0x39C,
- SMSG_UPDATE_COMBO_POINTS = 0x39D,
- SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x39E,
- SMSG_VOICE_SESSION_LEAVE = 0x39F,
- SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0,
- CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1,
- SMSG_VOICE_SET_TALKER_MUTED = 0x3A2,
- SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3,
- SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4,
- SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5,
- SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6,
- MSG_MOVE_START_DESCEND = 0x3A7,
- CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8,
- SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9,
- SMSG_SPELL_CHANCE_PROC_LOG = 0x3AA,
- CMSG_MOVE_SET_RUN_SPEED = 0x3AB,
- SMSG_DISMOUNT = 0x3AC,
- MSG_MOVE_UPDATE_CAN_FLY = 0x3AD,
- MSG_RAID_READY_CHECK_CONFIRM = 0x3AE,
- CMSG_VOICE_SESSION_ENABLE = 0x3AF,
- SMSG_VOICE_SESSION_ENABLE = 0x3B0,
- SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1,
- CMSG_GM_WHISPER = 0x3B2,
- SMSG_GM_MESSAGECHAT = 0x3B3,
- MSG_GM_GEARRATING = 0x3B4,
- CMSG_COMMENTATOR_ENABLE = 0x3B5,
- SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6,
- CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7,
- SMSG_COMMENTATOR_MAP_INFO = 0x3B8,
- CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9,
- SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA,
- SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB,
- CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC,
- CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD,
- CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE,
- SMSG_CLEAR_TARGET = 0x3BF,
- CMSG_BOT_DETECTED = 0x3C0,
- SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1,
- CMSG_CHEAT_PLAYER_LOGIN = 0x3C2,
- CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3,
- SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4,
- SMSG_KICK_REASON = 0x3C5,
- MSG_RAID_READY_CHECK_FINISHED = 0x3C6,
- CMSG_COMPLAIN = 0x3C7,
- SMSG_COMPLAIN_RESULT = 0x3C8,
- SMSG_FEATURE_SYSTEM_STATUS = 0x3C9,
- CMSG_GM_SHOW_COMPLAINTS = 0x3CA,
- CMSG_GM_UNSQUELCH = 0x3CB,
- CMSG_CHANNEL_SILENCE_VOICE = 0x3CC,
- CMSG_CHANNEL_SILENCE_ALL = 0x3CD,
- CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE,
- CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF,
- CMSG_TARGET_CAST = 0x3D0,
- CMSG_TARGET_SCRIPT_CAST = 0x3D1,
- CMSG_CHANNEL_DISPLAY_LIST = 0x3D2,
- CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3,
- CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4,
- SMSG_CHANNEL_MEMBER_COUNT = 0x3D5,
- CMSG_CHANNEL_VOICE_ON = 0x3D6,
- CMSG_CHANNEL_VOICE_OFF = 0x3D7,
- CMSG_DEBUG_LIST_TARGETS = 0x3D8,
- SMSG_DEBUG_LIST_TARGETS = 0x3D9,
- SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA,
- CMSG_ADD_VOICE_IGNORE = 0x3DB,
- CMSG_DEL_VOICE_IGNORE = 0x3DC,
- CMSG_PARTY_SILENCE = 0x3DD,
- CMSG_PARTY_UNSILENCE = 0x3DE,
- MSG_NOTIFY_PARTY_SQUELCH = 0x3DF,
- SMSG_COMSAT_RECONNECT_TRY = 0x3E0,
- SMSG_COMSAT_DISCONNECT = 0x3E1,
- SMSG_COMSAT_CONNECT_FAIL = 0x3E2,
- SMSG_VOICE_CHAT_STATUS = 0x3E3,
- CMSG_REPORT_PVP_AFK = 0x3E4,
- SMSG_REPORT_PVP_AFK_RESULT = 0x3E5,
- CMSG_GUILD_BANKER_ACTIVATE = 0x3E6,
- CMSG_GUILD_BANK_QUERY_TAB = 0x3E7,
- SMSG_GUILD_BANK_LIST = 0x3E8,
- CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9,
- CMSG_GUILD_BANK_BUY_TAB = 0x3EA,
- CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB,
- CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC,
- CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED,
- MSG_GUILD_BANK_LOG_QUERY = 0x3EE,
- CMSG_SET_CHANNEL_WATCH = 0x3EF,
- SMSG_USERLIST_ADD = 0x3F0,
- SMSG_USERLIST_REMOVE = 0x3F1,
- SMSG_USERLIST_UPDATE = 0x3F2,
- CMSG_CLEAR_CHANNEL_WATCH = 0x3F3,
- SMSG_INSPECT_TALENT = 0x3F4,
- SMSG_GOGOGO_OBSOLETE = 0x3F5,
- SMSG_ECHO_PARTY_SQUELCH = 0x3F6,
- CMSG_SET_TITLE_SUFFIX = 0x3F7,
- CMSG_SPELLCLICK = 0x3F8,
- SMSG_LOOT_LIST = 0x3F9,
- CMSG_GM_CHARACTER_RESTORE = 0x3FA,
- CMSG_GM_CHARACTER_SAVE = 0x3FB,
- SMSG_VOICESESSION_FULL = 0x3FC,
- MSG_GUILD_PERMISSIONS = 0x3FD,
- MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE,
- MSG_GUILD_EVENT_LOG_QUERY = 0x3FF,
- CMSG_MAELSTROM_RENAME_GUILD = 0x400,
- CMSG_GET_MIRRORIMAGE_DATA = 0x401,
- SMSG_MIRRORIMAGE_DATA = 0x402,
- SMSG_FORCE_DISPLAY_UPDATE = 0x403,
- SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404,
- CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405,
- SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406,
- CMSG_KEEP_ALIVE = 0x407,
- SMSG_RAID_READY_CHECK_ERROR = 0x408,
- CMSG_OPT_OUT_OF_LOOT = 0x409,
- MSG_QUERY_GUILD_BANK_TEXT = 0x40A,
- CMSG_SET_GUILD_BANK_TEXT = 0x40B,
- CMSG_SET_GRANTABLE_LEVELS = 0x40C,
- CMSG_GRANT_LEVEL = 0x40D,
- CMSG_REFER_A_FRIEND = 0x40E,
- MSG_GM_CHANGE_ARENA_RATING = 0x40F,
- CMSG_DECLINE_CHANNEL_INVITE = 0x410,
- SMSG_GROUPACTION_THROTTLED = 0x411,
- SMSG_OVERRIDE_LIGHT = 0x412, // uint32 defaultMapLight, uint32 overrideLight, uint32 transitionTimeMs
- SMSG_TOTEM_CREATED = 0x413,
- CMSG_TOTEM_DESTROYED = 0x414,
- CMSG_EXPIRE_RAID_INSTANCE = 0x415,
- CMSG_NO_SPELL_VARIANCE = 0x416,
- CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417,
- SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418,
- CMSG_SET_PLAYER_DECLINED_NAMES = 0x419,
- SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A,
- CMSG_QUERY_SERVER_BUCK_DATA = 0x41B,
- CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C,
- SMSG_SERVER_BUCK_DATA = 0x41D,
- SMSG_SEND_UNLEARN_SPELLS = 0x41E,
- SMSG_PROPOSE_LEVEL_GRANT = 0x41F,
- CMSG_ACCEPT_LEVEL_GRANT = 0x420,
- SMSG_REFER_A_FRIEND_FAILURE = 0x421,
- SMSG_SPLINE_MOVE_SET_FLYING = 0x422,
- SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423,
- SMSG_SUMMON_CANCEL = 0x424,
- CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425,
- CMSG_ALTER_APPEARANCE = 0x426,
- SMSG_ENABLE_BARBER_SHOP = 0x427,
- SMSG_BARBER_SHOP_RESULT = 0x428,
- CMSG_CALENDAR_GET_CALENDAR = 0x429,
- CMSG_CALENDAR_GET_EVENT = 0x42A,
- CMSG_CALENDAR_GUILD_FILTER = 0x42B,
- CMSG_CALENDAR_ARENA_TEAM = 0x42C,
- CMSG_CALENDAR_ADD_EVENT = 0x42D,
- CMSG_CALENDAR_UPDATE_EVENT = 0x42E,
- CMSG_CALENDAR_REMOVE_EVENT = 0x42F,
- CMSG_CALENDAR_COPY_EVENT = 0x430,
- CMSG_CALENDAR_EVENT_INVITE = 0x431,
- CMSG_CALENDAR_EVENT_RSVP = 0x432,
- CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433,
- CMSG_CALENDAR_EVENT_STATUS = 0x434,
- CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435,
- SMSG_CALENDAR_SEND_CALENDAR = 0x436,
- SMSG_CALENDAR_SEND_EVENT = 0x437,
- SMSG_CALENDAR_FILTER_GUILD = 0x438,
- SMSG_CALENDAR_ARENA_TEAM = 0x439,
- SMSG_CALENDAR_EVENT_INVITE = 0x43A,
- SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B,
- SMSG_CALENDAR_EVENT_STATUS = 0x43C,
- SMSG_CALENDAR_COMMAND_RESULT = 0x43D,
- SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E,
- SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F,
- SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440,
- SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441,
- SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442,
- SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443,
- SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444,
- SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445,
- CMSG_CALENDAR_COMPLAIN = 0x446,
- CMSG_CALENDAR_GET_NUM_PENDING = 0x447,
- SMSG_CALENDAR_SEND_NUM_PENDING = 0x448,
- CMSG_SAVE_DANCE = 0x449,
- SMSG_NOTIFY_DANCE = 0x44A,
- CMSG_PLAY_DANCE = 0x44B,
- SMSG_PLAY_DANCE = 0x44C,
- CMSG_LOAD_DANCES = 0x44D,
- CMSG_STOP_DANCE = 0x44E,
- SMSG_STOP_DANCE = 0x44F,
- CMSG_SYNC_DANCE = 0x450,
- CMSG_DANCE_QUERY = 0x451,
- SMSG_DANCE_QUERY_RESPONSE = 0x452,
- SMSG_INVALIDATE_DANCE = 0x453,
- CMSG_DELETE_DANCE = 0x454,
- SMSG_LEARNED_DANCE_MOVES = 0x455,
- CMSG_LEARN_DANCE_MOVE = 0x456,
- CMSG_UNLEARN_DANCE_MOVE = 0x457,
- CMSG_SET_RUNE_COUNT = 0x458,
- CMSG_SET_RUNE_COOLDOWN = 0x459,
- MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A,
- MSG_MOVE_SET_PITCH_RATE = 0x45B,
- SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C,
- CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D,
- SMSG_SPLINE_SET_PITCH_RATE = 0x45E,
- CMSG_CALENDAR_EVENT_INVITE_NOTES = 0x45F,
- SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x460,
- SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 0x461,
- CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462,
- SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463,
- SMSG_TRIGGER_MOVIE = 0x464,
- CMSG_COMPLETE_MOVIE = 0x465,
- CMSG_SET_GLYPH_SLOT = 0x466,
- CMSG_SET_GLYPH = 0x467,
- SMSG_ACHIEVEMENT_EARNED = 0x468,
- SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469,
- SMSG_CRITERIA_UPDATE = 0x46A,
- CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B,
- SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C,
- CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D,
- CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E,
- SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F,
- CMSG_SET_CRITERIA_CHEAT = 0x470,
- SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x471,
- CMSG_UNITANIMTIER_CHEAT = 0x472,
- CMSG_CHAR_CUSTOMIZE = 0x473,
- SMSG_CHAR_CUSTOMIZE = 0x474,
- SMSG_PET_RENAMEABLE = 0x475,
- CMSG_REQUEST_VEHICLE_EXIT = 0x476,
- CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477,
- CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478,
- CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479,
- CMSG_PET_LEARN_TALENT = 0x47A,
- CMSG_PET_UNLEARN_TALENTS = 0x47B,
- SMSG_SET_PHASE_SHIFT = 0x47C,
- SMSG_ALL_ACHIEVEMENT_DATA = 0x47D,
- CMSG_FORCE_SAY_CHEAT = 0x47E,
- SMSG_HEALTH_UPDATE = 0x47F,
- SMSG_POWER_UPDATE = 0x480,
- CMSG_GAMEOBJ_REPORT_USE = 0x481,
- SMSG_HIGHEST_THREAT_UPDATE = 0x482,
- SMSG_THREAT_UPDATE = 0x483,
- SMSG_THREAT_REMOVE = 0x484,
- SMSG_THREAT_CLEAR = 0x485,
- SMSG_CONVERT_RUNE = 0x486,
- SMSG_RESYNC_RUNES = 0x487,
- SMSG_ADD_RUNE_POWER = 0x488,
- CMSG_START_QUEST = 0x489,
- CMSG_REMOVE_GLYPH = 0x48A,
- CMSG_DUMP_OBJECTS = 0x48B,
- SMSG_DUMP_OBJECTS_DATA = 0x48C,
- CMSG_DISMISS_CRITTER = 0x48D,
- SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E,
- CMSG_AUCTION_LIST_PENDING_SALES = 0x48F,
- SMSG_AUCTION_LIST_PENDING_SALES = 0x490,
- SMSG_MODIFY_COOLDOWN = 0x491,
- SMSG_PET_UPDATE_COMBO_POINTS = 0x492,
- CMSG_ENABLETAXI = 0x493,
- SMSG_PRE_RESURRECT = 0x494,
- SMSG_AURA_UPDATE_ALL = 0x495,
- SMSG_AURA_UPDATE = 0x496,
- CMSG_FLOOD_GRACE_CHEAT = 0x497,
- SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498,
- SMSG_PET_LEARNED_SPELL = 0x499,
- SMSG_PET_REMOVED_SPELL = 0x49A,
- CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B,
- CMSG_HEARTH_AND_RESURRECT = 0x49C,
- SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D,
- SMSG_CRITERIA_DELETED = 0x49E,
- SMSG_ACHIEVEMENT_DELETED = 0x49F,
- CMSG_SERVER_INFO_QUERY = 0x4A0,
- SMSG_SERVER_INFO_RESPONSE = 0x4A1,
- CMSG_CHECK_LOGIN_CRITERIA = 0x4A2,
- SMSG_SERVER_BUCK_DATA_START = 0x4A3,
- CMSG_SET_BREATH = 0x4A4,
- CMSG_QUERY_VEHICLE_STATUS = 0x4A5,
- SMSG_BATTLEGROUND_INFO_THROTTLED = 0x4A6, // empty, "You can't do that yet"
- SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // guid+uint32 (vehicle)
- CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // uint64
- CMSG_CONTROLLER_EJECT_PASSENGER = 0x4A9, // uint64
- SMSG_PET_GUIDS = 0x4AA,
- SMSG_CLIENTCACHE_VERSION = 0x4AB,
- CMSG_CHANGE_GDF_ARENA_RATING = 0x4AC,
- CMSG_SET_ARENA_TEAM_RATING_BY_INDEX = 0x4AD,
- CMSG_SET_ARENA_TEAM_WEEKLY_GAMES = 0x4AE,
- CMSG_SET_ARENA_TEAM_SEASON_GAMES = 0x4AF,
- CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES = 0x4B0,
- CMSG_SET_ARENA_MEMBER_SEASON_GAMES = 0x4B1,
- SMSG_ITEM_REFUND_INFO_RESPONSE = 0x4B2,
- CMSG_ITEM_REFUND_INFO = 0x4B3,
- CMSG_ITEM_REFUND = 0x4B4, // lua: ContainerRefundItemPurchase
- SMSG_ITEM_REFUND_RESULT = 0x4B5,
- CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // uint32
- SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // 3*float+float
- CMSG_UNUSED5 = 0x4B8,
- CMSG_UNUSED6 = 0x4B9,
- CMSG_CALENDAR_EVENT_SIGNUP = 0x4BA, // uint64
- SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x4BB,
- SMSG_EQUIPMENT_SET_LIST = 0x4BC, // equipment manager list?
- CMSG_EQUIPMENT_SET_SAVE = 0x4BD,
- CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE,
- SMSG_SET_PROJECTILE_POSITION = 0x4BF,
- SMSG_TALENTS_INFO = 0x4C0,
- CMSG_LEARN_PREVIEW_TALENTS = 0x4C1,
- CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2,
- CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE = 0x4C3,
- CMSG_GM_GRANT_ACHIEVEMENT = 0x4C4,
- CMSG_GM_REMOVE_ACHIEVEMENT = 0x4C5,
- CMSG_GM_SET_CRITERIA_FOR_PLAYER = 0x4C6,
- SMSG_ARENA_UNIT_DESTROYED = 0x4C7,
- SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x4C8, // uint32 "Can't modify arena team while queued or in a match."
- CMSG_PROFILEDATA_REQUEST = 0x4C9,
- SMSG_PROFILEDATA_RESPONSE = 0x4CA,
- CMSG_START_BATTLEFIELD_CHEAT = 0x4CB,
- CMSG_END_BATTLEFIELD_CHEAT = 0x4CC,
- SMSG_MULTIPLE_PACKETS = 0x4CD,
- SMSG_MOVE_GRAVITY_DISABLE = 0x4CE,
- CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x4CF,
- SMSG_MOVE_GRAVITY_ENABLE = 0x4D0,
- CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x4D1,
- MSG_MOVE_GRAVITY_CHNG = 0x4D2,
- SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x4D3,
- SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0x4D4,
- CMSG_EQUIPMENT_SET_USE = 0x4D5,
- SMSG_EQUIPMENT_SET_USE_RESULT = 0x4D6,
- CMSG_FORCE_ANIM = 0x4D7,
- SMSG_FORCE_ANIM = 0x4D8,
- CMSG_CHAR_FACTION_CHANGE = 0x4D9,
- SMSG_CHAR_FACTION_CHANGE = 0x4DA,
- CMSG_PVP_QUEUE_STATS_REQUEST = 0x4DB,
- SMSG_PVP_QUEUE_STATS = 0x4DC,
- CMSG_SET_PAID_SERVICE_CHEAT = 0x4DD,
- SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x4DE, // uint32
- CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x4DF,
- SMSG_BATTLEFIELD_MGR_ENTERED = 0x4E0, // uint32, uint8, uint8
- SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x4E1, // uint32
- CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x4E2,
- CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x4E3,
- SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x4E4, // uint32, uint8
- SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x4E5, // uint32
- SMSG_BATTLEFIELD_MGR_EJECTED = 0x4E6, // uint32, uint32, uint8
- CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x4E7,
- SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x4E8, // uint32, uint32
- CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE = 0x4E9,
- CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME= 0x4EA,
- MSG_SET_RAID_DIFFICULTY = 0x4EB,
- CMSG_TOGGLE_XP_GAIN = 0x4EC,
- SMSG_TOGGLE_XP_GAIN = 0x4ED, // enable/disable XP gain console message
- SMSG_GMRESPONSE_DB_ERROR = 0x4EE, // empty
- SMSG_GMRESPONSE_RECEIVED = 0x4EF, // uint32, uint32, string[2000], string[4000][4]
- CMSG_GMRESPONSE_RESOLVE = 0x4F0,
- SMSG_GMRESPONSE_STATUS_UPDATE = 0x4F1, // uint8 (1 - EVENT_GMSURVEY_DISPLAY, 0 - EVENT_UPDATE_TICKET)
- SMSG_GMRESPONSE_CREATE_TICKET = 0x4F2,
- CMSG_GMRESPONSE_CREATE_TICKET = 0x4F3,
- CMSG_SERVERINFO = 0x4F4,
- SMSG_SERVERINFO = 0x4F5,
- CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F6,
- SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F7,
- CMSG_CHAR_RACE_CHANGE = 0x4F8,
- MSG_VIEW_PHASE_SHIFT = 0x4F9,
- SMSG_TALENTS_INVOLUNTARILY_RESET = 0x4FA, // uint8
- CMSG_DEBUG_SERVER_GEO = 0x4FB,
- SMSG_DEBUG_SERVER_GEO = 0x4FC,
- SMSG_LOOT_SLOT_CHANGED = 0x4FD,
- UMSG_UPDATE_GROUP_INFO = 0x4FE,
- CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x4FF,
- CMSG_QUERY_QUESTS_COMPLETED = 0x500,
- SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x501,
- CMSG_GM_REPORT_LAG = 0x502,
- CMSG_AFK_MONITOR_INFO_REQUEST = 0x503,
- SMSG_AFK_MONITOR_INFO_RESPONSE = 0x504,
- CMSG_AFK_MONITOR_INFO_CLEAR = 0x505,
- SMSG_CORPSE_NOT_IN_INSTANCE = 0x506,
- CMSG_GM_NUKE_CHARACTER = 0x507,
- CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x508,
- CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x509,
- SMSG_CAMERA_SHAKE = 0x50A, // uint32 SpellEffectCameraShakes.dbc index, uint32
- SMSG_SOCKET_GEMS_RESULT = 0x50B,
- CMSG_SET_CHARACTER_MODEL = 0x50C,
- SMSG_REDIRECT_CLIENT = 0x50D, // uint32 ip, uint16 port, uint32 unk, uint8[20] hash (ip + port, seed=sessionkey)
- CMSG_REDIRECTION_FAILED = 0x50E, // something with networking
- SMSG_SUSPEND_COMMS = 0x50F,
- CMSG_SUSPEND_COMMS_ACK = 0x510,
- SMSG_FORCE_SEND_QUEUED_PACKETS = 0x511,
- CMSG_REDIRECTION_AUTH_PROOF = 0x512,
- CMSG_DROP_NEW_CONNECTION = 0x513,
- SMSG_SEND_ALL_COMBAT_LOG = 0x514,
- SMSG_OPEN_LFG_DUNGEON_FINDER = 0x515,
- SMSG_MOVE_SET_COLLISION_HGT = 0x516,
- CMSG_MOVE_SET_COLLISION_HGT_ACK = 0x517,
- MSG_MOVE_SET_COLLISION_HGT = 0x518,
- CMSG_CLEAR_RANDOM_BG_WIN_TIME = 0x519,
- CMSG_CLEAR_HOLIDAY_BG_WIN_TIME = 0x51A,
- CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND = 0x51B,
- SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1 = 0x51C,
- SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2 = 0x51D,
- SMSG_MULTIPLE_MOVES = 0x51E, // uncompressed version of SMSG_COMPRESSED_MOVES
- NUM_MSG_TYPES = 0x51F
+ NUM_OPCODE_HANDLERS = (0x7FFF+1),
+ UNKNOWN_OPCODE = (0xFFFF+1),
+ NULL_OPCODE = 0,
+ COMPRESSED_OPCODE_MASK = 0x8000,
+
+ CMSG_ACCEPT_LEVEL_GRANT = 0x0205,
+ CMSG_ACCEPT_TRADE = 0x7110,
+ CMSG_ACTIVATETAXI = 0x6E06,
+ CMSG_ACTIVATETAXIEXPRESS = 0x0515,
+ CMSG_ADDON_REGISTERED_PREFIXES = 0x0954,
+ CMSG_ADD_FRIEND = 0x6527,
+ CMSG_ADD_IGNORE = 0x4726,
+ CMSG_ADD_VOICE_IGNORE = 0x0F06,
+ CMSG_ALTER_APPEARANCE = 0x0914,
+ CMSG_AREATRIGGER = 0x0937,
+ CMSG_AREA_SPIRIT_HEALER_QUERY = 0x4907,
+ CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x4815,
+ CMSG_ARENA_TEAM_ACCEPT = 0x2A25,
+ CMSG_ARENA_TEAM_CREATE = 0x04A1,
+ CMSG_ARENA_TEAM_DECLINE = 0x6925,
+ CMSG_ARENA_TEAM_DISBAND = 0x6504,
+ CMSG_ARENA_TEAM_INVITE = 0x2F27,
+ CMSG_ARENA_TEAM_LEADER = 0x4204,
+ CMSG_ARENA_TEAM_LEAVE = 0x0E16,
+ CMSG_ARENA_TEAM_QUERY = 0x0514,
+ CMSG_ARENA_TEAM_REMOVE = 0x2F05,
+ CMSG_ARENA_TEAM_ROSTER = 0x6F37,
+ CMSG_ATTACKSTOP = 0x4106,
+ CMSG_ATTACKSWING = 0x0926,
+ CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x6937,
+ CMSG_AUCTION_LIST_ITEMS = 0x0324,
+ CMSG_AUCTION_LIST_OWNER_ITEMS = 0x0206,
+ CMSG_AUCTION_LIST_PENDING_SALES = 0x2C17,
+ CMSG_AUCTION_PLACE_BID = 0x2306,
+ CMSG_AUCTION_REMOVE_ITEM = 0x6426,
+ CMSG_AUCTION_SELL_ITEM = 0x4A06,
+ CMSG_AUTH_SESSION = 0x0449,
+ CMSG_AUTOBANK_ITEM = 0x2537,
+ CMSG_AUTOEQUIP_GROUND_ITEM = 0x0000,
+ CMSG_AUTOEQUIP_ITEM = 0x4304,
+ CMSG_AUTOEQUIP_ITEM_SLOT = 0x4A17,
+ CMSG_AUTOSTORE_BAG_ITEM = 0x0236,
+ CMSG_AUTOSTORE_BANK_ITEM = 0x0607,
+ CMSG_AUTOSTORE_GROUND_ITEM = 0x0000,
+ CMSG_AUTOSTORE_LOOT_ITEM = 0x0E34,
+ CMSG_AUTO_DECLINE_GUILD_INVITES = 0x2034,
+ CMSG_BANKER_ACTIVATE = 0x0005,
+ CMSG_BATTLEFIELD_JOIN = 0x0000,
+ CMSG_BATTLEFIELD_LEAVE = 0x3018,
+ CMSG_BATTLEFIELD_LIST = 0x3814,
+ CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x05A3,
+ CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x2490,
+ CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x0413,
+ CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x710C,
+ CMSG_BATTLEFIELD_PORT = 0x711A,
+ CMSG_BATTLEFIELD_REQUEST_SCORE_DATA = 0x0000,
+ CMSG_BATTLEFIELD_STATUS = 0x2500,
+ CMSG_BATTLEGROUND_PLAYER_POSITIONS = 0x3902,
+ CMSG_BATTLEMASTER_JOIN = 0x7902,
+ CMSG_BATTLEMASTER_JOIN_ARENA = 0x701C,
+ CMSG_BATTLEMASTER_JOIN_RATED = 0x3B18,
+ CMSG_BEGIN_TRADE = 0x721E,
+ CMSG_BINDER_ACTIVATE = 0x4006,
+ CMSG_BOT_DETECTED2 = 0x0000,
+ CMSG_BUG = 0x4035,
+ CMSG_BUSY_TRADE = 0x331C,
+ CMSG_BUYBACK_ITEM = 0x6C17,
+ CMSG_BUY_BANK_SLOT = 0x0425,
+ CMSG_BUY_ITEM = 0x0736,
+ CMSG_CALENDAR_ADD_EVENT = 0x0726,
+ CMSG_CALENDAR_ARENA_TEAM = 0x0204,
+ CMSG_CALENDAR_COMPLAIN = 0x4C36,
+ CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x0000,
+ CMSG_CALENDAR_COPY_EVENT = 0x0207,
+ CMSG_CALENDAR_EVENT_INVITE = 0x2435,
+ CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x6B35,
+ CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x4337,
+ CMSG_CALENDAR_EVENT_RSVP = 0x0227,
+ CMSG_CALENDAR_EVENT_SIGNUP = 0x6606,
+ CMSG_CALENDAR_EVENT_STATUS = 0x2D24,
+ CMSG_CALENDAR_GET_CALENDAR = 0x2814,
+ CMSG_CALENDAR_GET_EVENT = 0x6416,
+ CMSG_CALENDAR_GET_NUM_PENDING = 0x4D05,
+ CMSG_CALENDAR_GUILD_FILTER = 0x4A16,
+ CMSG_CALENDAR_REMOVE_EVENT = 0x6636,
+ CMSG_CALENDAR_UPDATE_EVENT = 0x2114,
+ CMSG_CANCEL_AURA = 0x0E26,
+ CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x6C35,
+ CMSG_CANCEL_CAST = 0x0115,
+ CMSG_CANCEL_CHANNELLING = 0x6C25,
+ CMSG_CANCEL_GROWTH_AURA = 0x0000,
+ CMSG_CANCEL_MOUNT_AURA = 0x0635,
+ CMSG_CANCEL_QUEUED_SPELL = 0x7B1C,
+ CMSG_CANCEL_TEMP_ENCHANTMENT = 0x6C37,
+ CMSG_CANCEL_TRADE = 0x731E,
+ CMSG_CAST_SPELL = 0x4C07,
+ CMSG_CHANGEPLAYER_DIFFICULTY = 0x6107,
+ CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x7310,
+ CMSG_CHANNEL_ANNOUNCEMENTS = 0x1146,
+ CMSG_CHANNEL_BAN = 0x3D56,
+ CMSG_CHANNEL_DISPLAY_LIST = 0x2144,
+ CMSG_CHANNEL_INVITE = 0x0144,
+ CMSG_CHANNEL_KICK = 0x3156,
+ CMSG_CHANNEL_LIST = 0x1556,
+ CMSG_CHANNEL_MODERATE = 0x2944,
+ CMSG_CHANNEL_MODERATOR = 0x0146,
+ CMSG_CHANNEL_MUTE = 0x2554,
+ CMSG_CHANNEL_OWNER = 0x3D44,
+ CMSG_CHANNEL_PASSWORD = 0x2556,
+ CMSG_CHANNEL_ROSTER_INFO = 0x3546,
+ CMSG_CHANNEL_SET_OWNER = 0x3556,
+ CMSG_CHANNEL_SILENCE_ALL = 0x2154,
+ CMSG_CHANNEL_SILENCE_VOICE = 0x2D54,
+ CMSG_CHANNEL_UNBAN = 0x2D46,
+ CMSG_CHANNEL_UNMODERATOR = 0x1954,
+ CMSG_CHANNEL_UNMUTE = 0x3554,
+ CMSG_CHANNEL_UNSILENCE_ALL = 0x2546,
+ CMSG_CHANNEL_UNSILENCE_VOICE = 0x3146,
+ CMSG_CHANNEL_VOICE_OFF = 0x3144,
+ CMSG_CHANNEL_VOICE_ON = 0x1144,
+ CMSG_CHAR_CREATE = 0x4A36,
+ CMSG_CHAR_CUSTOMIZE = 0x2C34,
+ CMSG_CHAR_DELETE = 0x6425,
+ CMSG_CHAR_ENUM = 0x0502,
+ CMSG_CHAR_FACTION_CHANGE = 0x2735,
+ CMSG_CHAR_RACE_CHANGE = 0x0D24,
+ CMSG_CHAR_RENAME = 0x2327,
+ CMSG_CHAT_FILTERED = 0x0946,
+ CMSG_CHAT_IGNORED = 0x0D54,
+ CMSG_CLEAR_CHANNEL_WATCH = 0x2604,
+ CMSG_CLEAR_RAID_MARKER = 0x7300,
+ CMSG_CLEAR_TRADE_ITEM = 0x7018,
+ CMSG_COMMENTATOR_ENABLE = 0x0B07,
+ CMSG_COMMENTATOR_ENTER_INSTANCE = 0x4105,
+ CMSG_COMMENTATOR_EXIT_INSTANCE = 0x6136,
+ CMSG_COMMENTATOR_GET_MAP_INFO = 0x0026,
+ CMSG_COMMENTATOR_GET_PARTY_INFO = 0x2412,
+ CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x0D14,
+ CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x0917,
+ CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND = 0x0025,
+ CMSG_COMMENTATOR_START_WARGAME = 0x25A0,
+ CMSG_COMPLAIN = 0x0427,
+ CMSG_COMPLETE_CINEMATIC = 0x2116,
+ CMSG_COMPLETE_MOVIE = 0x4136,
+ CMSG_CONNECT_TO_FAILED = 0x2533,
+ CMSG_CONTACT_LIST = 0x4534,
+ CMSG_CORPSE_MAP_POSITION_QUERY = 0x6205,
+ CMSG_CREATURE_QUERY = 0x2706,
+ CMSG_DANCE_QUERY = 0x4E07,
+ CMSG_DECLINE_CHANNEL_INVITE = 0x0000,
+ CMSG_DELETEEQUIPMENT_SET = 0x4D07,
+ CMSG_DEL_FRIEND = 0x6A15,
+ CMSG_DEL_IGNORE = 0x6D26,
+ CMSG_DEL_VOICE_IGNORE = 0x0024,
+ CMSG_DESTROY_ITEM = 0x4A27,
+ CMSG_DISMISS_CONTROLLED_VEHICLE = 0x3218,
+ CMSG_DISMISS_CRITTER = 0x4227,
+ CMSG_DUEL_ACCEPTED = 0x2136,
+ CMSG_DUEL_CANCELLED = 0x6624,
+ CMSG_DUNGEON_FINDER_GET_SYSTEM_INFO = 0x0412,
+ CMSG_EJECT_PASSENGER = 0x6927,
+ CMSG_EMOTE = 0x4C26,
+ CMSG_ENABLETAXI = 0x0C16,
+ CMSG_ENABLE_NAGLE = 0x4449,
+ CMSG_EQUIPMENT_SET_DELETE = 0x0000,
+ CMSG_EQUIPMENT_SET_SAVE = 0x4F27,
+ CMSG_EQUIPMENT_SET_USE = 0x0417,
+ CMSG_FAR_SIGHT = 0x4835,
+ CMSG_FORCE_MOVE_ROOT_ACK = 0x701E,
+ CMSG_FORCE_MOVE_UNROOT_ACK = 0x7808,
+ CMSG_GAMEOBJECT_QUERY = 0x4017,
+ CMSG_GAMEOBJ_REPORT_USE = 0x4827,
+ CMSG_GAMEOBJ_USE = 0x4E17,
+ CMSG_GAMESPEED_SET = 0x0000,
+ CMSG_GAMETIME_SET = 0x0000,
+ CMSG_GETDEATHBINDZONE = 0x0000,
+ CMSG_GET_MAIL_LIST = 0x4D37,
+ CMSG_GET_MIRRORIMAGE_DATA = 0x0C25,
+ CMSG_GHOST = 0x0000,
+ CMSG_GMRESPONSE_RESOLVE = 0x6506,
+ CMSG_GMSURVEY_SUBMIT = 0x2724,
+ CMSG_GMTICKET_CREATE = 0x0137,
+ CMSG_GMTICKET_DELETETICKET = 0x6B14,
+ CMSG_GMTICKET_GETTICKET = 0x0326,
+ CMSG_GMTICKET_SYSTEMSTATUS = 0x4205,
+ CMSG_GMTICKET_UPDATETEXT = 0x0636,
+ CMSG_GM_INVIS = 0x0000,
+ CMSG_GM_NUKE = 0x0000,
+ CMSG_GM_REPORT_LAG = 0x6726,
+ CMSG_GM_SET_SECURITY_GROUP = 0x0000,
+ CMSG_GOSSIP_HELLO = 0x4525,
+ CMSG_GOSSIP_SELECT_OPTION = 0x0216,
+ CMSG_GRANT_LEVEL = 0x6D16,
+ CMSG_GROUP_ASSISTANT_LEADER = 0x6025,
+ CMSG_GROUP_CANCEL = 0x0000,
+ CMSG_GROUP_CHANGE_SUB_GROUP = 0x4124,
+ CMSG_GROUP_DISBAND = 0x2804,
+ CMSG_GROUP_INVITE = 0x0513,
+ CMSG_GROUP_INVITE_RESPONSE = 0x0410,
+ CMSG_GROUP_RAID_CONVERT = 0x6E27,
+ CMSG_GROUP_REQUEST_JOIN_UPDATES = 0x2583,
+ CMSG_GROUP_SET_LEADER = 0x4C17,
+ CMSG_GROUP_SET_ROLES = 0x25B1,
+ CMSG_GROUP_SWAP_SUB_GROUP = 0x0034,
+ CMSG_GROUP_UNINVITE = 0x0000,
+ CMSG_GROUP_UNINVITE_GUID = 0x2E07,
+ CMSG_GUILD_ACCEPT = 0x2531,
+ CMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x3025,
+ CMSG_GUILD_ACHIEVEMENT_PROGRESS_QUERY = 0x3235,
+ CMSG_GUILD_ADD_RANK = 0x3030,
+ CMSG_GUILD_ASSIGN_MEMBER_RANK = 0x3032,
+ CMSG_GUILD_BANKER_ACTIVATE = 0x2E37,
+ CMSG_GUILD_BANK_BUY_TAB = 0x0C37,
+ CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x0707,
+ CMSG_GUILD_BANK_LOG_QUERY = 0x3224,
+ CMSG_GUILD_BANK_MONEY_WITHDRAWN_QUERY = 0x1225,
+ CMSG_GUILD_BANK_NOTE = 0x0000,
+ CMSG_GUILD_BANK_QUERY_TAB = 0x2E35,
+ CMSG_GUILD_BANK_QUERY_TEXT = 0x3220,
+ CMSG_GUILD_BANK_SWAP_ITEMS = 0x2315,
+ CMSG_GUILD_BANK_UPDATE_TAB = 0x0106,
+ CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x0037,
+ CMSG_GUILD_CHANGE_NAME_REQUEST = 0x1232,
+ CMSG_GUILD_DECLINE = 0x3231,
+ CMSG_GUILD_DEL_RANK = 0x3234,
+ CMSG_GUILD_DEMOTE = 0x1020,
+ CMSG_GUILD_DISBAND = 0x3226,
+ CMSG_GUILD_EVENT_LOG_QUERY = 0x1220,
+ CMSG_GUILD_INFO = 0x0000,
+ CMSG_GUILD_INFO_TEXT = 0x3227,
+ CMSG_GUILD_INVITE = 0x24B0,
+ CMSG_GUILD_LEAVE = 0x1021,
+ CMSG_GUILD_MEMBER_SEND_SOR_REQUEST = 0x3225,
+ CMSG_GUILD_MOTD = 0x1035,
+ CMSG_GUILD_NEWS_UPDATE_STICKY = 0x3223,
+ CMSG_GUILD_PERMISSIONS = 0x3022,
+ CMSG_GUILD_PROMOTE = 0x1030,
+ CMSG_GUILD_QUERY = 0x4426,
+ CMSG_GUILD_QUERY_NEWS = 0x3020,
+ CMSG_GUILD_QUERY_RANKS = 0x1026,
+ CMSG_GUILD_REMOVE = 0x1231,
+ CMSG_GUILD_REPLACE_GUILD_MASTER = 0x1034,
+ CMSG_GUILD_REQUEST_CHALLENGE_UPDATE = 0x1224,
+ CMSG_GUILD_REQUEST_MAX_DAILY_XP = 0x3232,
+ CMSG_GUILD_REQUEST_PARTY_STATE = 0x3900,
+ CMSG_GUILD_ROSTER = 0x1226,
+ CMSG_GUILD_SET_ACHIEVEMENT_TRACKING = 0x1027,
+ CMSG_GUILD_SET_GUILD_MASTER = 0x3034,
+ CMSG_GUILD_SET_NOTE = 0x1233,
+ CMSG_GUILD_SET_RANK_PERMISSIONS = 0x1024,
+ CMSG_GUILD_SWITCH_RANK = 0x1221,
+ CMSG_HEARTH_AND_RESURRECT = 0x4B34,
+ CMSG_IGNORE_TRADE = 0x7112,
+ CMSG_INITIATE_TRADE = 0x7916,
+ CMSG_INSPECT = 0x0927,
+ CMSG_INSPECT_HONOR_STATS = 0x791E,
+ CMSG_INSTANCE_LOCK_WARNING_RESPONSE = 0x6234,
+ CMSG_ITEM_REFUND = 0x6134,
+ CMSG_ITEM_REFUND_INFO = 0x2206,
+ CMSG_ITEM_TEXT_QUERY = 0x2406,
+ CMSG_JOIN_CHANNEL = 0x0156,
+ CMSG_KEEP_ALIVE = 0x0015,
+ CMSG_LEARN_PREVIEW_TALENTS = 0x2415,
+ CMSG_LEARN_PREVIEW_TALENTS_PET = 0x6E24,
+ CMSG_LEARN_TALENT = 0x0306,
+ CMSG_LEAVE_CHANNEL = 0x2D56,
+ CMSG_LFG_GET_PLAYER_INFO = 0x0000,
+ CMSG_LFG_GET_STATUS = 0x2581,
+ CMSG_LFG_JOIN = 0x2430,
+ CMSG_LFG_LEAVE = 0x2433,
+ CMSG_LFG_LFR_JOIN = 0x0531,
+ CMSG_LFG_LFR_LEAVE = 0x0500,
+ CMSG_LFG_PARTY_LOCK_INFO_REQUEST = 0x0000,
+ CMSG_LFG_PROPOSAL_RESULT = 0x0403,
+ CMSG_LFG_SET_BOOT_VOTE = 0x04B3,
+ CMSG_LFG_SET_COMMENT = 0x0530,
+ CMSG_LFG_SET_ROLES = 0x0480,
+ CMSG_LFG_TELEPORT = 0x2482,
+ CMSG_LF_GUILD_ADD_RECRUIT = 0x4448,
+ CMSG_LF_GUILD_BROWSE = 0x0548,
+ CMSG_LF_GUILD_DECLINE_RECRUIT = 0x1031,
+ CMSG_LF_GUILD_GET_APPLICATIONS = 0x1230,
+ CMSG_LF_GUILD_GET_RECRUITS = 0x3230,
+ CMSG_LF_GUILD_POST_REQUEST = 0x3237,
+ CMSG_LF_GUILD_REMOVE_RECRUIT = 0x3027,
+ CMSG_LF_GUILD_SET_GUILD_POST = 0x0448,
+ CMSG_LIST_INVENTORY = 0x2806,
+ CMSG_LOAD_SCREEN = 0x2422,
+ CMSG_LOGOUT_CANCEL = 0x2324,
+ CMSG_LOGOUT_REQUEST = 0x0A25,
+ CMSG_LOG_DISCONNECT = 0x446D,
+ CMSG_LOOT = 0x0127,
+ CMSG_LOOT_CURRENCY = 0x781C,
+ CMSG_LOOT_MASTER_GIVE = 0x4F35,
+ CMSG_LOOT_METHOD = 0x2F24,
+ CMSG_LOOT_MONEY = 0x6227,
+ CMSG_LOOT_RELEASE = 0x2007,
+ CMSG_LOOT_ROLL = 0x6934,
+ CMSG_MAIL_CREATE_TEXT_ITEM = 0x0B14,
+ CMSG_MAIL_DELETE = 0x6104,
+ CMSG_MAIL_MARK_AS_READ = 0x0C07,
+ CMSG_MAIL_RETURN_TO_SENDER = 0x0816,
+ CMSG_MAIL_TAKE_ITEM = 0x2B06,
+ CMSG_MAIL_TAKE_MONEY = 0x4034,
+ CMSG_MEETINGSTONE_INFO = 0x0000,
+ CMSG_MESSAGECHAT_ADDON_BATTLEGROUND = 0x0D46,
+ CMSG_MESSAGECHAT_ADDON_GUILD = 0x0544,
+ CMSG_MESSAGECHAT_ADDON_OFFICER = 0x3954,
+ CMSG_MESSAGECHAT_ADDON_PARTY = 0x0546,
+ CMSG_MESSAGECHAT_ADDON_RAID = 0x1D56,
+ CMSG_MESSAGECHAT_ADDON_WHISPER = 0x2146,
+ CMSG_MESSAGECHAT_AFK = 0x0D44,
+ CMSG_MESSAGECHAT_BATTLEGROUND = 0x2156,
+ CMSG_MESSAGECHAT_CHANNEL = 0x1D44,
+ CMSG_MESSAGECHAT_DND = 0x2946,
+ CMSG_MESSAGECHAT_EMOTE = 0x1156,
+ CMSG_MESSAGECHAT_GUILD = 0x3956,
+ CMSG_MESSAGECHAT_OFFICER = 0x1946,
+ CMSG_MESSAGECHAT_PARTY = 0x1D46,
+ CMSG_MESSAGECHAT_RAID = 0x2D44,
+ CMSG_MESSAGECHAT_RAID_WARNING = 0x0944,
+ CMSG_MESSAGECHAT_SAY = 0x1154,
+ CMSG_MESSAGECHAT_WHISPER = 0x0D56,
+ CMSG_MESSAGECHAT_YELL = 0x3544,
+ CMSG_MINIGAME_MOVE = 0x2A34,
+ CMSG_MOUNTSPECIAL_ANIM = 0x2807,
+ CMSG_MOVE_CHARM_TELEPORT_CHEAT = 0x0000,
+ CMSG_MOVE_CHNG_TRANSPORT = 0x3102,
+ CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK = 0x0000,
+ CMSG_MOVE_FALL_RESET = 0x310A,
+ CMSG_MOVE_FEATHER_FALL_ACK = 0x3110,
+ CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x310E,
+ CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x7314,
+ CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK = 0x3100,
+ CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x3216,
+ CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK = 0x7818,
+ CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x7A16,
+ CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0x7A10,
+ CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0x7316,
+ CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0x7210,
+ CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x3118,
+ CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x700A,
+ CMSG_MOVE_HOVER_ACK = 0x3318,
+ CMSG_MOVE_KNOCK_BACK_ACK = 0x721C,
+ CMSG_MOVE_NOT_ACTIVE_MOVER = 0x7A1A,
+ CMSG_MOVE_SET_CAN_FLY = 0x720E,
+ CMSG_MOVE_SET_CAN_FLY_ACK = 0x790C,
+ CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK = 0x3014,
+ CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x7114,
+ CMSG_MOVE_SET_RELATIVE_POSITION = 0x0000,
+ CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0x0000,
+ CMSG_MOVE_SPLINE_DONE = 0x790E,
+ CMSG_MOVE_TIME_SKIPPED = 0x7A0A,
+ CMSG_MOVE_TOGGLE_COLLISION_ACK = 0x0000,
+ CMSG_MOVE_WATER_WALK_ACK = 0x3B00,
+ CMSG_NAME_QUERY = 0x2224,
+ CMSG_NEW_SPELL_SLOT = 0x0000,
+ CMSG_NEXT_CINEMATIC_CAMERA = 0x2014,
+ CMSG_NPC_TEXT_QUERY = 0x4E24,
+ CMSG_OBJECT_UPDATE_FAILED = 0x3808,
+ CMSG_OBJECT_UPDATE_RESCUED = 0x3906,
+ CMSG_OFFER_PETITION = 0x4817,
+ CMSG_OPENING_CINEMATIC = 0x0A16,
+ CMSG_OPEN_ITEM = 0x6A34,
+ CMSG_OPT_OUT_OF_LOOT = 0x6B16,
+ CMSG_PAGE_TEXT_QUERY = 0x6614,
+ CMSG_PARTY_SILENCE = 0x6B26,
+ CMSG_PARTY_UNSILENCE = 0x4D24,
+ CMSG_PETITION_BUY = 0x4E05,
+ CMSG_PETITION_QUERY = 0x4424,
+ CMSG_PETITION_SHOWLIST = 0x4617,
+ CMSG_PETITION_SHOW_SIGNATURES = 0x4F15,
+ CMSG_PETITION_SIGN = 0x0E04,
+ CMSG_PET_ABANDON = 0x0C24,
+ CMSG_PET_ACTION = 0x0226,
+ CMSG_PET_CANCEL_AURA = 0x4B25,
+ CMSG_PET_CAST_SPELL = 0x6337,
+ CMSG_PET_LEARN_TALENT = 0x6725,
+ CMSG_PET_NAME_CACHE = 0x0000,
+ CMSG_PET_NAME_QUERY = 0x6F24,
+ CMSG_PET_RENAME = 0x6406,
+ CMSG_PET_SET_ACTION = 0x6904,
+ CMSG_PET_SPELL_AUTOCAST = 0x2514,
+ CMSG_PET_STOP_ATTACK = 0x6C14,
+ CMSG_PING = 0x444D,
+ CMSG_PLAYED_TIME = 0x0804,
+ CMSG_PLAYER_DIFFICULTY_CHANGE = 0x0000,
+ CMSG_PLAYER_LOGIN = 0x05B1,
+ CMSG_PLAYER_LOGOUT = 0x0000,
+ CMSG_PLAYER_VEHICLE_ENTER = 0x2705,
+ CMSG_PLAY_DANCE = 0x6914,
+ CMSG_PUSHQUESTTOPARTY = 0x4B14,
+ CMSG_PVP_LOG_DATA = 0x7308,
+ CMSG_QUERY_BATTLEFIELD_STATE = 0x7202,
+ CMSG_QUERY_GUILD_MEMBERS_FOR_RECIPE = 0x1036,
+ CMSG_QUERY_GUILD_MEMBER_RECIPES = 0x1037,
+ CMSG_QUERY_GUILD_RECIPES = 0x3033,
+ CMSG_QUERY_GUILD_REWARDS = 0x3012,
+ CMSG_QUERY_GUILD_XP = 0x1237,
+ CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x4D27,
+ CMSG_QUERY_QUESTS_COMPLETED = 0x2317,
+ CMSG_QUERY_TIME = 0x0A36,
+ CMSG_QUESTGIVER_ACCEPT_QUEST = 0x6B37,
+ CMSG_QUESTGIVER_CANCEL = 0x0000,
+ CMSG_QUESTGIVER_CHOOSE_REWARD = 0x2125,
+ CMSG_QUESTGIVER_COMPLETE_QUEST = 0x0114,
+ CMSG_QUESTGIVER_HELLO = 0x0D17,
+ CMSG_QUESTGIVER_QUERY_QUEST = 0x2F14,
+ CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x0000,
+ CMSG_QUESTGIVER_REQUEST_REWARD = 0x2534,
+ CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x6305,
+ CMSG_QUESTGIVER_STATUS_QUERY = 0x4407,
+ CMSG_QUESTLOG_REMOVE_QUEST = 0x0D16,
+ CMSG_QUESTLOG_SWAP_QUEST = 0x0000,
+ CMSG_QUEST_CONFIRM_ACCEPT = 0x0D15,
+ CMSG_QUEST_NPC_QUERY = 0x7302,
+ CMSG_QUEST_POI_QUERY = 0x4037,
+ CMSG_QUEST_QUERY = 0x0D06,
+ CMSG_RANDOMIZE_CHAR_NAME = 0x2413,
+ CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x2B16,
+ CMSG_READ_ITEM = 0x2F16,
+ CMSG_REALM_SPLIT = 0x2906,
+ CMSG_RECLAIM_CORPSE = 0x4036,
+ CMSG_REDIRECTION_AUTH_PROOF = 0x044D,
+ CMSG_REFORGE_ITEM = 0x331A,
+ CMSG_REORDER_CHARACTERS = 0x0593,
+ CMSG_REPAIR_ITEM = 0x2917,
+ CMSG_REPLACE_ACCOUNT_DATA = 0x0000,
+ CMSG_REPOP_REQUEST = 0x6235,
+ CMSG_REPORT_PVP_AFK = 0x6734,
+ CMSG_REQUEST_ACCOUNT_DATA = 0x6505,
+ CMSG_REQUEST_CATEGORY_COOLDOWNS = 0x7102,
+ CMSG_REQUEST_CEMETERY_LIST = 0x720A,
+ CMSG_REQUEST_HOTFIX = 0x2401,
+ CMSG_REQUEST_INSPECT_RATED_BG_STATS = 0x3010,
+ CMSG_REQUEST_PARTY_MEMBER_STATS = 0x0C04,
+ CMSG_REQUEST_PET_INFO = 0x4924,
+ CMSG_REQUEST_PVP_OPTIONS_ENABLED = 0x24A1,
+ CMSG_REQUEST_PVP_REWARDS = 0x780C,
+ CMSG_REQUEST_RAID_INFO = 0x2F26,
+ CMSG_REQUEST_RATED_BG_INFO = 0x2423,
+ CMSG_REQUEST_RATED_BG_STATS = 0x05B3,
+ CMSG_REQUEST_RESEARCH_HISTORY = 0x3306,
+ CMSG_REQUEST_VEHICLE_EXIT = 0x2B35,
+ CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x4434,
+ CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x4C04,
+ CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x4C14,
+ CMSG_RESET_FACTION_CHEAT = 0x4469,
+ CMSG_RESET_INSTANCES = 0x6E14,
+ CMSG_RESURRECT_RESPONSE = 0x6827,
+ CMSG_RETURN_TO_GRAVEYARD = 0x301E,
+ CMSG_ROLE_POLL_BEGIN = 0x0430,
+ CMSG_SAVE_CUF_PROFILES = 0x730E,
+ CMSG_SAVE_PLAYER = 0x0000,
+ CMSG_SEARCH_LFG_JOIN = 0x0000,
+ CMSG_SEARCH_LFG_LEAVE = 0x0000,
+ CMSG_SELF_RES = 0x6115,
+ CMSG_SELL_ITEM = 0x4E15,
+ CMSG_SEND_MAIL = 0x0523,
+ CMSG_SEND_SOR_REQUEST_VIA_ADDRESS = 0x0420,
+ CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID = 0x0482,
+ CMSG_SERVERTIME = 0x0000,
+ CMSG_SETDEATHBINDPOINT = 0x0000,
+ CMSG_SETSHEATHED = 0x4326,
+ CMSG_SET_ACTIONBAR_TOGGLES = 0x2506,
+ CMSG_SET_ACTION_BUTTON = 0x6F06,
+ CMSG_SET_ACTIVE_MOVER = 0x3314,
+ CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x4305,
+ CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x4435,
+ CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x0536,
+ CMSG_SET_CHANNEL_WATCH = 0x4517,
+ CMSG_SET_CONTACT_NOTES = 0x6135,
+ CMSG_SET_CURRENCY_FLAGS = 0x7306,
+ CMSG_SET_EVERYONE_IS_ASSISTANT = 0x2530,
+ CMSG_SET_FACTION_ATWAR = 0x0706,
+ CMSG_SET_FACTION_CHEAT = 0x0000,
+ CMSG_SET_FACTION_INACTIVE = 0x0E37,
+ CMSG_SET_GUILD_BANK_TEXT = 0x3023,
+ CMSG_SET_LFG_COMMENT = 0x0000,
+ CMSG_SET_PET_SLOT = 0x3A04,
+ CMSG_SET_PLAYER_DECLINED_NAMES = 0x6316,
+ CMSG_SET_PREFERED_CEMETERY = 0x311E,
+ CMSG_SET_PRIMARY_TALENT_TREE = 0x4524,
+ CMSG_SET_RELATIVE_POSITION = 0x311A,
+ CMSG_SET_SAVED_INSTANCE_EXTEND = 0x6706,
+ CMSG_SET_SELECTION = 0x0506,
+ CMSG_SET_SKILL_CHEAT = 0x0000,
+ CMSG_SET_TAXI_BENCHMARK_MODE = 0x4314,
+ CMSG_SET_TITLE = 0x2117,
+ CMSG_SET_TRADE_CURRENCY = 0x3312,
+ CMSG_SET_TRADE_GOLD = 0x3008,
+ CMSG_SET_TRADE_ITEM = 0x7B0C,
+ CMSG_SET_VEHICLE_REC_ID_ACK = 0x3108,
+ CMSG_SET_WATCHED_FACTION = 0x2434,
+ CMSG_SHOWING_CLOAK = 0x4135,
+ CMSG_SHOWING_HELM = 0x0735,
+ CMSG_SOCKET_GEMS = 0x2F04,
+ CMSG_SPELLCLICK = 0x0805,
+ CMSG_SPIRIT_HEALER_ACTIVATE = 0x2E26,
+ CMSG_SPLIT_ITEM = 0x0F17,
+ CMSG_STANDSTATECHANGE = 0x0535,
+ CMSG_START_QUEST = 0x0000,
+ CMSG_STOP_DANCE = 0x2907,
+ CMSG_STORE_LOOT_IN_SLOT = 0x0000,
+ CMSG_SUBMIT_BUG = 0x2520,
+ CMSG_SUBMIT_COMPLAIN = 0x2501,
+ CMSG_SUGGESTION_SUBMIT = 0x2512,
+ CMSG_SUMMON_RESPONSE = 0x6F27,
+ CMSG_SUSPEND_TOKEN = 0x046D,
+ CMSG_SWAP_INV_ITEM = 0x2614,
+ CMSG_SWAP_ITEM = 0x6326,
+ CMSG_SYNC_DANCE = 0x0036,
+ CMSG_TAXICLEARALLNODES = 0x0000,
+ CMSG_TAXIENABLEALLNODES = 0x0000,
+ CMSG_TAXINODE_STATUS_QUERY = 0x2F25,
+ CMSG_TAXIQUERYAVAILABLENODES = 0x6C06,
+ CMSG_TAXISHOWNODES = 0x0000,
+ CMSG_TELEPORT_TO_UNIT = 0x4206,
+ CMSG_TEXT_EMOTE = 0x2E24,
+ CMSG_TIME_ADJUSTMENT_RESPONSE = 0x3818,
+ CMSG_TIME_SYNC_RESP = 0x3B0C,
+ CMSG_TIME_SYNC_RESP_FAILED = 0x710A,
+ CMSG_TOGGLE_PVP = 0x6815,
+ CMSG_TOTEM_DESTROYED = 0x4207,
+ CMSG_TRAINER_BUY_SPELL = 0x4415,
+ CMSG_TRAINER_LIST = 0x2336,
+ CMSG_TRANSMOGRIFY_ITEMS = 0x3B0E,
+ CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0000,
+ CMSG_TURN_IN_PETITION = 0x0B27,
+ CMSG_TUTORIAL_CLEAR = 0x6515,
+ CMSG_TUTORIAL_FLAG = 0x6C26,
+ CMSG_TUTORIAL_RESET = 0x2726,
+ CMSG_UNACCEPT_TRADE = 0x391A,
+ CMSG_UNLEARN_SKILL = 0x6106,
+ CMSG_UNLEARN_SPECIALIZATION = 0x3210,
+ CMSG_UNREGISTER_ALL_ADDON_PREFIXES = 0x3D54,
+ CMSG_UPDATE_ACCOUNT_DATA = 0x4736,
+ CMSG_UPDATE_MISSILE_TRAJECTORY = 0x781E,
+ CMSG_UPDATE_PROJECTILE_POSITION = 0x0E24,
+ CMSG_USED_FOLLOW = 0x7912,
+ CMSG_USE_ITEM = 0x2C06,
+ CMSG_VIOLENCE_LEVEL = 0x7816,
+ CMSG_VOICE_SESSION_ENABLE = 0x2314,
+ CMSG_VOID_STORAGE_QUERY = 0x790A,
+ CMSG_VOID_STORAGE_TRANSFER = 0x380E,
+ CMSG_VOID_STORAGE_UNLOCK = 0x7B14,
+ CMSG_VOID_SWAP_ITEM = 0x3204,
+ CMSG_WARDEN_DATA = 0x25A2,
+ CMSG_WARGAME_ACCEPT = 0x2410,
+ CMSG_WARGAME_START = 0x05A0,
+ CMSG_WHO = 0x6C15,
+ CMSG_WHOIS = 0x6B05,
+ CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4605,
+ CMSG_WORLD_TELEPORT = 0x24B2,
+ CMSG_WRAP_ITEM = 0x4F06,
+ CMSG_ZONEUPDATE = 0x4F37,
+ MSG_AUCTION_HELLO = 0x2307,
+ MSG_CHANNEL_START = 0x0A15, // SMSG only?
+ MSG_CHANNEL_UPDATE = 0x2417, // SMSG only?
+ MSG_CORPSE_QUERY = 0x4336,
+ MSG_GM_BIND_OTHER = 0x0000,
+ MSG_GM_SHOWLABEL = 0x0000,
+ MSG_GM_SUMMON = 0x0000,
+ MSG_INSPECT_ARENA_TEAMS = 0x2704,
+ MSG_LIST_STABLED_PETS = 0x0834,
+ MSG_MINIMAP_PING = 0x6635,
+ MSG_MOVE_CHARM_TELEPORT_CHEAT = 0x7A08,
+ MSG_MOVE_FALL_LAND = 0x380A,
+ MSG_MOVE_HEARTBEAT = 0x3914,
+ MSG_MOVE_JUMP = 0x7A06,
+ MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_COLLISION_HEIGHT = 0x0000,
+ MSG_MOVE_SET_FACING = 0x7914,
+ MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_PITCH = 0x7312,
+ MSG_MOVE_SET_RAW_POSITION_ACK = 0x0000,
+ MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_RUN_MODE = 0x791A,
+ MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0000,
+ MSG_MOVE_SET_WALK_MODE = 0x7002,
+ MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_START_ASCEND = 0x390A,
+ MSG_MOVE_START_BACKWARD = 0x330A,
+ MSG_MOVE_START_DESCEND = 0x3800,
+ MSG_MOVE_START_FORWARD = 0x7814,
+ MSG_MOVE_START_PITCH_DOWN = 0x3908,
+ MSG_MOVE_START_PITCH_UP = 0x3304,
+ MSG_MOVE_START_STRAFE_LEFT = 0x3A16,
+ MSG_MOVE_START_STRAFE_RIGHT = 0x3A02,
+ MSG_MOVE_START_SWIM = 0x3206,
+ MSG_MOVE_START_TURN_LEFT = 0x700C,
+ MSG_MOVE_START_TURN_RIGHT = 0x7000,
+ MSG_MOVE_STOP = 0x320A,
+ MSG_MOVE_STOP_ASCEND = 0x7B00,
+ MSG_MOVE_STOP_PITCH = 0x7216,
+ MSG_MOVE_STOP_STRAFE = 0x3002,
+ MSG_MOVE_STOP_SWIM = 0x3802,
+ MSG_MOVE_STOP_TURN = 0x331E,
+ MSG_MOVE_TELEPORT = 0x55A0,
+ MSG_MOVE_TELEPORT_ACK = 0x390C,
+ MSG_MOVE_TELEPORT_CHEAT = 0x3A10,
+ MSG_MOVE_TIME_SKIPPED = 0x19B3,
+ MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x7B04,
+ MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0000,
+ MSG_MOVE_TOGGLE_LOGGING = 0x0000,
+ MSG_MOVE_UPDATE_MOUSE = 0x0000,
+ MSG_MOVE_WORLDPORT_ACK = 0x2411,
+ MSG_NOTIFY_PARTY_SQUELCH = 0x4D06,
+ MSG_PARTY_ASSIGNMENT = 0x0424,
+ MSG_PETITION_DECLINE = 0x4905,
+ MSG_PETITION_RENAME = 0x4005,
+ MSG_PVP_LOG_DATA = 0x0000,
+ MSG_QUERY_NEXT_MAIL_TIME = 0x0F04,
+ MSG_QUEST_PUSH_RESULT = 0x4515,
+ MSG_RAID_READY_CHECK = 0x2304,
+ MSG_RAID_READY_CHECK_CONFIRM = 0x4F05,
+ MSG_RAID_READY_CHECK_FINISHED = 0x2E15,
+ MSG_RAID_TARGET_UPDATE = 0x2C36,
+ MSG_RANDOM_ROLL = 0x0905,
+ MSG_SAVE_GUILD_EMBLEM = 0x2404,
+ MSG_SET_DUNGEON_DIFFICULTY = 0x4925,
+ MSG_SET_RAID_DIFFICULTY = 0x0614,
+ MSG_START_MOVE_FORWARD = 0x0000,
+ MSG_TABARDVENDOR_ACTIVATE = 0x6926,
+ MSG_TALENT_WIPE_CONFIRM = 0x0107,
+ MSG_VERIFY_CONNECTIVITY = 0x4F57,
+ SMSG_ACCOUNT_DATA_TIMES = 0x4B05,
+ SMSG_ACCOUNT_INFO_RESPONSE = 0x10A7,
+ SMSG_ACCOUNT_RESTRICTED_WARNING = 0x51A7,
+ SMSG_ACHIEVEMENT_DELETED = 0x6A16,
+ SMSG_ACHIEVEMENT_EARNED = 0x4405,
+ SMSG_ACTION_BUTTONS = 0x38B5,
+ SMSG_ACTIVATETAXIREPLY = 0x6A37,
+ SMSG_ADDON_INFO = 0x2C14,
+ SMSG_ADD_RUNE_POWER = 0x6915,
+ SMSG_AI_REACTION = 0x0637,
+ SMSG_ALL_ACHIEVEMENT_DATA = 0x58B1,
+ SMSG_AREA_SPIRIT_HEALER_TIME = 0x0734,
+ SMSG_AREA_TRIGGER_MESSAGE = 0x4505,
+ SMSG_AREA_TRIGGER_MOVEMENT_UPDATE = 0x3DB1,
+ SMSG_ARENA_ERROR = 0x2D17,
+ SMSG_ARENA_UNIT_DESTROYED = 0x2637,
+ SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x6E34,
+ SMSG_ARENA_TEAM_COMMAND_RESULT = 0x39B3,
+ SMSG_ARENA_TEAM_EVENT = 0x0617,
+ SMSG_ARENA_TEAM_INVITE = 0x0F36,
+ SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x6336,
+ SMSG_ARENA_TEAM_ROSTER = 0x2717,
+ SMSG_ARENA_TEAM_STATS = 0x4425,
+ SMSG_ATTACKERSTATEUPDATE = 0x0B25,
+ SMSG_ATTACKSTART = 0x2D15,
+ SMSG_ATTACKSTOP = 0x0934,
+ SMSG_ATTACKSWING_BADFACING = 0x0B36,
+ SMSG_ATTACKSWING_CANT_ATTACK = 0x0016,
+ SMSG_ATTACKSWING_DEADTARGET = 0x2B26,
+ SMSG_ATTACKSWING_NOTINRANGE = 0x6C07,
+ SMSG_AUCTION_BIDDER_LIST_RESULT = 0x0027,
+ SMSG_AUCTION_BIDDER_NOTIFICATION = 0x4E27,
+ SMSG_AUCTION_COMMAND_RESULT = 0x4C25,
+ SMSG_AUCTION_LIST_PENDING_SALES = 0x6A27,
+ SMSG_AUCTION_LIST_RESULT = 0x6637,
+ SMSG_AUCTION_OWNER_LIST_RESULT = 0x6C34,
+ SMSG_AUCTION_OWNER_NOTIFICATION = 0x4116,
+ SMSG_AUCTION_REMOVED_NOTIFICATION = 0x2334,
+ SMSG_AURACASTLOG = 0x0000,
+ SMSG_AURA_POINTS_DEPLETED = 0x7CB7,
+ SMSG_AURA_UPDATE = 0x4707,
+ SMSG_AURA_UPDATE_ALL = 0x6916,
+ SMSG_AUTH_CHALLENGE = 0x4542,
+ SMSG_AUTH_RESPONSE = 0x5DB6,
+ SMSG_AVAILABLE_VOICE_CHANNEL = 0x2E16,
+ SMSG_AVERAGE_ITEM_LEVEL_INFORM = 0x5DA7,
+ SMSG_BARBER_SHOP_RESULT = 0x6125,
+ SMSG_BATTLEFIELD_LIST = 0x71B5,
+ SMSG_BATTLEFIELD_MGR_EJECTED = 0x7DB7,
+ SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x34A2,
+ SMSG_BATTLEFIELD_MGR_ENTERED = 0x5CA0,
+ SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x34B3,
+ SMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x51B1,
+ SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x15A6,
+ SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x79B6,
+ SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x35B4,
+ SMSG_BATTLEFIELD_PLAYER_POSITIONS = 0x58B4,
+ SMSG_BATTLEFIELD_PORT_DENIED = 0x35A3,
+ SMSG_BATTLEFIELD_RATED_INFO = 0x54A3,
+ SMSG_BATTLEFIELD_STATUS = 0x7DA1,
+ SMSG_BATTLEFIELD_STATUS_QUEUED = 0x35A1,
+ SMSG_BATTLEFIELD_STATUS_ACTIVE = 0x74A4,
+ SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION = 0x59A0,
+ SMSG_BATTLEFIELD_STATUS_WAITFORGROUPS = 0x75A2,
+ SMSG_BATTLEFIELD_STATUS_FAILED = 0x71A7,
+ SMSG_BATTLEGROUND_INFO_THROTTLED = 0x34B2,
+ SMSG_BATTLEGROUND_PLAYER_JOINED = 0x50B0,
+ SMSG_BATTLEGROUND_PLAYER_LEFT = 0x59A6,
+ SMSG_BINDER_CONFIRM = 0x2835,
+ SMSG_BINDPOINTUPDATE = 0x0527,
+ SMSG_BINDZONEREPLY = 0x0000,
+ SMSG_BREAK_TARGET = 0x0105,
+ SMSG_BUY_BANK_SLOT_RESULT = 0x0000,
+ SMSG_BUY_FAILED = 0x6435,
+ SMSG_BUY_ITEM = 0x0F26,
+ SMSG_CALENDAR_ACTION_PENDING = 0x0000,
+ SMSG_CALENDAR_ARENA_TEAM = 0x0615,
+ SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x2106,
+ SMSG_CALENDAR_COMMAND_RESULT = 0x6F36,
+ SMSG_CALENDAR_EVENT_INVITE = 0x4E16,
+ SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x2A05,
+ SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x0E17,
+ SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 0x2535,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x0725,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x2617,
+ SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x6625,
+ SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x6B06,
+ SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x6D35,
+ SMSG_CALENDAR_EVENT_STATUS = 0x2A27,
+ SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x0907,
+ SMSG_CALENDAR_FILTER_GUILD = 0x4A26,
+ SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x2305,
+ SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x2E25,
+ SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x4636,
+ SMSG_CALENDAR_SEND_CALENDAR = 0x6805,
+ SMSG_CALENDAR_SEND_EVENT = 0x0C35,
+ SMSG_CALENDAR_SEND_NUM_PENDING = 0x0C17,
+ SMSG_CALENDAR_UPDATE_INVITE_LIST = 0x0000,
+ SMSG_CAMERA_SHAKE = 0x4214,
+ SMSG_CANCEL_AUTO_REPEAT = 0x6436,
+ SMSG_CANCEL_COMBAT = 0x4F04,
+ SMSG_CAST_FAILED = 0x4D16,
+ SMSG_CHANNEL_LIST = 0x2214,
+ SMSG_CHANNEL_MEMBER_COUNT = 0x6414,
+ SMSG_CHANNEL_NOTIFY = 0x0825,
+ SMSG_CHARACTER_LOGIN_FAILED = 0x4417,
+ SMSG_CHAR_CREATE = 0x2D05,
+ SMSG_CHAR_CUSTOMIZE = 0x4F16,
+ SMSG_CHAR_DELETE = 0x0304,
+ SMSG_CHAR_ENUM = 0x10B0,
+ SMSG_CHAR_FACTION_CHANGE = 0x4C06,
+ SMSG_CHAR_RENAME = 0x2024,
+ SMSG_CHAT_IGNORED_ACCOUNT_MUTED = 0x15A4,
+ SMSG_CHAT_NOT_IN_PARTY = 0x6A14,
+ SMSG_CHAT_PLAYER_AMBIGUOUS = 0x2F34,
+ SMSG_CHAT_PLAYER_NOT_FOUND = 0x2526,
+ SMSG_CHAT_RESTRICTED = 0x6536,
+ SMSG_CHAT_SERVER_DISCONNECTED = 0x6D34,
+ SMSG_CHAT_SERVER_RECONNECTED = 0x6905,
+ SMSG_CHAT_WRONG_FACTION = 0x6724,
+ SMSG_CHECK_FOR_BOTS = 0x0000,
+ SMSG_CLEAR_BOSS_EMOTES = 0x19A3,
+ SMSG_CLEAR_COOLDOWN = 0x0627,
+ SMSG_CLEAR_COOLDOWNS = 0x59B4,
+ SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x2A04,
+ SMSG_CLEAR_TARGET = 0x4B26,
+ SMSG_CLIENTCACHE_VERSION = 0x2734,
+ SMSG_CLIENT_CONTROL_UPDATE = 0x2837,
+ SMSG_COMBAT_EVENT_FAILED = 0x2B07,
+ SMSG_COMBAT_LOG_MULTIPLE = 0x0000,
+ SMSG_COMMENTATOR_MAP_INFO = 0x0327,
+ SMSG_COMMENTATOR_PARTY_INFO = 0x38B0,
+ SMSG_COMMENTATOR_PLAYER_INFO = 0x2F36,
+ SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1 = 0x2126,
+ SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2 = 0x6814,
+ SMSG_COMMENTATOR_STATE_CHANGED = 0x0737,
+ SMSG_COMPLAIN_RESULT = 0x6D24,
+ SMSG_COMPRESSED_ACHIEVEMENT_DATA = 0x0000,
+ SMSG_COMPRESSED_CHAR_ENUM = 0x0000,
+ SMSG_COMPRESSED_GUILD_ROSTER = 0x0000,
+ SMSG_COMPRESSED_MOVES = 0x0517,
+ SMSG_COMPRESSED_UPDATE_OBJECT = 0x0000,
+ SMSG_COMSAT_CONNECT_FAIL = 0x6317,
+ SMSG_COMSAT_DISCONNECT = 0x0316,
+ SMSG_COMSAT_RECONNECT_TRY = 0x4D35,
+ SMSG_CONTACT_LIST = 0x6017,
+ SMSG_CONVERT_RUNE = 0x4F14,
+ SMSG_COOLDOWN_CHEAT = 0x4537,
+ SMSG_COOLDOWN_EVENT = 0x4F26,
+ SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x0E35,
+ SMSG_CORPSE_NOT_IN_INSTANCE = 0x2A14,
+ SMSG_CORPSE_RECLAIM_DELAY = 0x0D34,
+ SMSG_CREATURE_QUERY_RESPONSE = 0x6024,
+ SMSG_CRITERIA_DELETED = 0x2915,
+ SMSG_CRITERIA_UPDATE = 0x6E37,
+ SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x2036,
+ SMSG_CURRENCY_LOOT_REMOVED = 0x1DB4,
+ SMSG_CURRENCY_LOOT_RESTORED = 0x30A0,
+ SMSG_CUSTOM_LOAD_SCREEN = 0x1DB6,
+ SMSG_DAMAGE_CALC_LOG = 0x2436,
+ SMSG_DAMAGE_DONE_OBSOLETE = 0x0000,
+ SMSG_DANCE_QUERY_RESPONSE = 0x2F06,
+ SMSG_DB_REPLY = 0x38A4,
+ SMSG_DEATH_RELEASE_LOC = 0x2F07,
+ SMSG_DEBUG_RUNE_REGEN = 0x31B3,
+ SMSG_DEFENSE_MESSAGE = 0x0314,
+ SMSG_DESTROY_OBJECT = 0x4724,
+ SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x4825,
+ SMSG_DIFFERENT_INSTANCE_FROM_PARTY = 0x15B1,
+ SMSG_DISENCHANT_CREDIT = 0x55A2,
+ SMSG_DISMOUNT = 0x2135,
+ SMSG_DISMOUNTRESULT = 0x0D25,
+ SMSG_DISPEL_FAILED = 0x0307,
+ SMSG_DISPLAY_GAME_ERROR = 0x31A6,
+ SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR = 0x38A2,
+ SMSG_DROP_NEW_CONNECTION = 0x4D40,
+ SMSG_DUEL_COMPLETE = 0x2527,
+ SMSG_DUEL_COUNTDOWN = 0x4836,
+ SMSG_DUEL_INBOUNDS = 0x0A27,
+ SMSG_DUEL_OUTOFBOUNDS = 0x0C26,
+ SMSG_DUEL_REQUESTED = 0x4504,
+ SMSG_DUEL_WINNER = 0x2D36,
+ SMSG_DUMP_RIDE_TICKETS_RESPONSE = 0x11A3,
+ SMSG_DURABILITY_DAMAGE_DEATH = 0x4C27,
+ SMSG_ECHO_PARTY_SQUELCH = 0x0814,
+ SMSG_EMOTE = 0x0A34,
+ SMSG_ENABLE_BARBER_SHOP = 0x2D16,
+ SMSG_ENCHANTMENTLOG = 0x6035,
+ SMSG_ENVIRONMENTALDAMAGELOG = 0x6C05,
+ SMSG_EQUIPMENT_SET_LIST = 0x2E04,
+ SMSG_EQUIPMENT_SET_SAVED = 0x2216,
+ SMSG_EQUIPMENT_SET_USE_RESULT = 0x2424,
+ SMSG_EXPECTED_SPAM_RECORDS = 0x4D36,
+ SMSG_EXPLORATION_EXPERIENCE = 0x6716,
+ SMSG_FAILED_PLAYER_CONDITION = 0x19A4,
+ SMSG_FEATURE_SYSTEM_STATUS = 0x3DB7,
+ SMSG_FEIGN_DEATH_RESISTED = 0x0D05,
+ SMSG_FISH_ESCAPED = 0x2205,
+ SMSG_FISH_NOT_HOOKED = 0x0A17,
+ SMSG_FLIGHT_SPLINE_SYNC = 0x0924,
+ SMSG_FLOOD_DETECTED = 0x0542,
+ SMSG_FORCEACTIONSHOW = 0x0000,
+ SMSG_FORCED_DEATH_UPDATE = 0x2606,
+ SMSG_FORCE_DISPLAY_UPDATE = 0x0000,
+ SMSG_FORCE_SEND_QUEUED_PACKETS = 0x0140,
+ SMSG_FORCE_SET_VEHICLE_REC_ID = 0x70A1,
+ SMSG_FORGE_MASTER_SET = 0x70B7,
+ SMSG_FRIEND_STATUS = 0x0717,
+ SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x4936,
+ SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x6735,
+ SMSG_GAMEOBJECT_PAGETEXT = 0x2925,
+ SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x0915,
+ SMSG_GAMEOBJECT_RESET_STATE = 0x2A16,
+ SMSG_GAMESPEED_SET = 0x4E34,
+ SMSG_GAMETIME_SET = 0x0014,
+ SMSG_GAMETIME_UPDATE = 0x4127,
+ SMSG_GAME_EVENT_DEBUG_LOG = 0x31A7,
+ SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT = 0x14A3,
+ SMSG_GMRESPONSE_DB_ERROR = 0x0006,
+ SMSG_GMRESPONSE_RECEIVED = 0x2E34,
+ SMSG_GMRESPONSE_STATUS_UPDATE = 0x0A04,
+ SMSG_GMTICKET_CREATE = 0x2107,
+ SMSG_GMTICKET_DELETETICKET = 0x6D17,
+ SMSG_GMTICKET_GETTICKET = 0x2C15,
+ SMSG_GMTICKET_SYSTEMSTATUS = 0x0D35,
+ SMSG_GMTICKET_UPDATETEXT = 0x6535,
+ SMSG_GM_MESSAGECHAT = 0x6434,
+ SMSG_GM_PLAYER_INFO = 0x4A15,
+ SMSG_GM_TICKET_STATUS_UPDATE = 0x2C25,
+ SMSG_GODMODE = 0x0405,
+ SMSG_GOSSIP_COMPLETE = 0x0806,
+ SMSG_GOSSIP_MESSAGE = 0x2035,
+ SMSG_GOSSIP_POI = 0x4316,
+ SMSG_GROUPACTION_THROTTLED = 0x6524,
+ SMSG_GROUP_CANCEL = 0x4D25,
+ SMSG_GROUP_DECLINE = 0x6835,
+ SMSG_GROUP_DESTROYED = 0x2207,
+ SMSG_GROUP_INVITE = 0x31B2,
+ SMSG_GROUP_LIST = 0x4C24,
+ SMSG_GROUP_SET_LEADER = 0x0526,
+ SMSG_GROUP_SET_ROLE = 0x39A6,
+ SMSG_GROUP_UNINVITE = 0x0A07,
+ SMSG_GUILD_ACHIEVEMENT_DATA = 0x54B7,
+ SMSG_GUILD_ACHIEVEMENT_DELETED = 0x35A0,
+ SMSG_GUILD_ACHIEVEMENT_EARNED = 0x50B5,
+ SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x38A5,
+ SMSG_GUILD_BANK_LIST = 0x78A5,
+ SMSG_GUILD_BANK_LOG_QUERY_RESULT = 0x30B2,
+ SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0x5DB4,
+ SMSG_GUILD_BANK_QUERY_TEXT_RESULT = 0x75A3,
+ SMSG_GUILD_CANCEL = 0x0000,
+ SMSG_GUILD_CHALLENGE_COMPLETED = 0x39A3,
+ SMSG_GUILD_CHALLENGE_UPDATED = 0x18B1,
+ SMSG_GUILD_CHANGE_NAME_RESULT = 0x3CB1,
+ SMSG_GUILD_COMMAND_RESULT = 0x7DB3,
+ SMSG_GUILD_COMMAND_RESULT_2 = 0x2707,
+ SMSG_GUILD_CRITERIA_DATA = 0x14B4,
+ SMSG_GUILD_CRITERIA_DELETED = 0x55B1,
+ SMSG_GUILD_DECLINE = 0x2C07,
+ SMSG_GUILD_EVENT = 0x0705,
+ SMSG_GUILD_EVENT_LOG_QUERY_RESULT = 0x10B2,
+ SMSG_GUILD_FLAGGED_FOR_RENAME = 0x30B6,
+ SMSG_GUILD_INVITE = 0x14A2,
+ SMSG_GUILD_INVITE_CANCEL = 0x0606,
+ SMSG_GUILD_KNOWN_RECIPES = 0x0000,
+ SMSG_GUILD_MAX_DAILY_XP = 0x79B5,
+ SMSG_GUILD_MEMBERS_FOR_RECIPE = 0x1CB7,
+ SMSG_GUILD_MEMBER_DAILY_RESET = 0x10A5,
+ SMSG_GUILD_MEMBER_RECIPES = 0x1CB0,
+ SMSG_GUILD_MEMBER_UPDATE_NOTE = 0x7CA0,
+ SMSG_GUILD_MOVE_COMPLETE = 0x11B2,
+ SMSG_GUILD_MOVE_STARTING = 0x70A4,
+ SMSG_GUILD_NEWS_DELETED = 0x74A7,
+ SMSG_GUILD_NEWS_UPDATE = 0x35A7,
+ SMSG_GUILD_PARTY_STATE_RESPONSE = 0x50A6,
+ SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x34A3,
+ SMSG_GUILD_QUERY_RESPONSE = 0x0E06,
+ SMSG_GUILD_RANK = 0x30B4,
+ SMSG_GUILD_RANKS_UPDATE = 0x5DA0,
+ SMSG_GUILD_RECIPES = 0x10B3,
+ SMSG_GUILD_RENAMED = 0x74A6,
+ SMSG_GUILD_REPUTATION_REACTION_CHANGED = 0x74B0,
+ SMSG_GUILD_REPUTATION_WEEKLY_CAP = 0x30B7,
+ SMSG_GUILD_RESET = 0x1CB5,
+ SMSG_GUILD_REWARDS_LIST = 0x1DB0,
+ SMSG_GUILD_ROSTER = 0x3DA3,
+ SMSG_GUILD_SET_NOTE = 0x0000,
+ SMSG_GUILD_TRADESKILL_UPDATE = 0x0000,
+ SMSG_GUILD_UPDATE_ROSTER = 0x18B0,
+ SMSG_GUILD_XP = 0x3DB0,
+ SMSG_GUILD_XP_GAIN = 0x14A1,
+ SMSG_GUILD_XP_UPDATE = 0x0000,
+ SMSG_HEALTH_UPDATE = 0x4734,
+ SMSG_HIGHEST_THREAT_UPDATE = 0x4104,
+ SMSG_HOTFIX_INFO = 0x19B5,
+ SMSG_HOTFIX_NOTIFY = 0x55A7,
+ SMSG_INITIALIZE_FACTIONS = 0x4634,
+ SMSG_INITIAL_SPELLS = 0x0104,
+ SMSG_INIT_CURRENCY = 0x15A5,
+ SMSG_INIT_WORLD_STATES = 0x4C15,
+ SMSG_INSPECT = 0x0000,
+ SMSG_INSPECT_HONOR_STATS = 0x79A5,
+ SMSG_INSPECT_RATED_BG_STATS = 0x19A5,
+ SMSG_INSPECT_RESULTS_UPDATE = 0x0C14,
+ SMSG_INSPECT_TALENT = 0x4014,
+ SMSG_INSTANCE_DIFFICULTY = 0x0000,
+ SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x4F17,
+ SMSG_INSTANCE_RESET = 0x6F05,
+ SMSG_INSTANCE_RESET_FAILED = 0x4725,
+ SMSG_INSTANCE_SAVE_CREATED = 0x0124,
+ SMSG_INVALIDATE_DANCE = 0x0E27,
+ SMSG_INVALIDATE_PLAYER = 0x6325,
+ SMSG_INVALID_PROMOTION_CODE = 0x6F25,
+ SMSG_INVENTORY_CHANGE_FAILURE = 0x2236,
+ SMSG_ITEM_ADD_PASSIVE = 0x7CB4,
+ SMSG_ITEM_COOLDOWN = 0x4D14,
+ SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x0F27,
+ SMSG_ITEM_EXPIRE_PURCHASE_REFUND = 0x1CA0,
+ SMSG_ITEM_PUSH_RESULT = 0x0E15,
+ SMSG_ITEM_REFUND_INFO_RESPONSE = 0x15A3,
+ SMSG_ITEM_REFUND_RESULT = 0x5DB1,
+ SMSG_ITEM_REMOVE_PASSIVE = 0x39A1,
+ SMSG_ITEM_SEND_PASSIVE = 0x70B1,
+ SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x2725,
+ SMSG_ITEM_TIME_UPDATE = 0x2407,
+ SMSG_JOINED_BATTLEGROUND_QUEUE = 0x0000,
+ SMSG_KICK_REASON = 0x0000,
+ SMSG_LEARNED_DANCE_MOVES = 0x0E05,
+ SMSG_LEARNED_SPELL = 0x58A2,
+ SMSG_LEVELUP_INFO = 0x0435,
+ SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x0F05,
+ SMSG_LFG_DISABLED = 0x0815,
+ SMSG_LFG_JOIN_RESULT = 0x38B6,
+ SMSG_LFG_OFFER_CONTINUE = 0x6B27,
+ SMSG_LFG_OPEN_FROM_GOSSIP = 0x0000,
+ SMSG_LFG_PARTY_INFO = 0x2325,
+ SMSG_LFG_PLAYER_INFO = 0x4B36,
+ SMSG_LFG_PLAYER_REWARD = 0x6834,
+ SMSG_LFG_PROPOSAL_UPDATE = 0x7DA6,
+ SMSG_LFG_QUEUE_STATUS = 0x78B4,
+ SMSG_LFG_ROLE_CHECK_UPDATE = 0x0336,
+ SMSG_LFG_ROLE_CHOSEN = 0x6A26,
+ SMSG_LFG_SLOT_INVALID = 0x54B5,
+ SMSG_LFG_TELEPORT_DENIED = 0x0E14,
+ SMSG_LFG_UPDATE_LIST = 0x0000,
+ SMSG_LFG_UPDATE_PARTY = 0x0000,
+ SMSG_LFG_UPDATE_PLAYER = 0x0000,
+ SMSG_LFG_UPDATE_SEARCH = 0x54A1,
+ SMSG_LFG_UPDATE_STATUS = 0x31A4,
+ SMSG_LFG_UPDATE_STATUS_NONE = 0x7CA1,
+ SMSG_LF_GUILD_APPLICANT_LIST_UPDATED = 0x10A4,
+ SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED = 0x71A5,
+ SMSG_LF_GUILD_BROWSE_UPDATED = 0x1DA3,
+ SMSG_LF_GUILD_COMMAND_RESULT = 0x54A6,
+ SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED = 0x1CA5,
+ SMSG_LF_GUILD_POST_UPDATED = 0x35B7,
+ SMSG_LF_GUILD_RECRUIT_LIST_UPDATED = 0x1CB2,
+ SMSG_LIST_INVENTORY = 0x7CB0,
+ SMSG_LOAD_CUF_PROFILES = 0x50B1,
+ SMSG_LOGIN_SETTIMESPEED = 0x4D15,
+ SMSG_LOGIN_VERIFY_WORLD = 0x2005,
+ SMSG_LOGOUT_CANCEL_ACK = 0x6514,
+ SMSG_LOGOUT_COMPLETE = 0x2137,
+ SMSG_LOGOUT_RESPONSE = 0x0524,
+ SMSG_LOG_XPGAIN = 0x4514,
+ SMSG_LOOT_ALL_PASSED = 0x6237,
+ SMSG_LOOT_CLEAR_MONEY = 0x2B37,
+ SMSG_LOOT_CONTENTS = 0x11B1,
+ SMSG_LOOT_ITEM_NOTIFY = 0x6D15,
+ SMSG_LOOT_LIST = 0x6807,
+ SMSG_LOOT_MASTER_LIST = 0x0325,
+ SMSG_LOOT_MONEY_NOTIFY = 0x2836,
+ SMSG_LOOT_RELEASE_RESPONSE = 0x6D25,
+ SMSG_LOOT_REMOVED = 0x6817,
+ SMSG_LOOT_RESPONSE = 0x4C16,
+ SMSG_LOOT_ROLL = 0x6507,
+ SMSG_LOOT_ROLL_WON = 0x6617,
+ SMSG_LOOT_SLOT_CHANGED = 0x2935,
+ SMSG_LOOT_START_ROLL = 0x2227,
+ SMSG_MAIL_LIST_RESULT = 0x4217,
+ SMSG_MAP_OBJ_EVENTS = 0x54B2,
+ SMSG_MEETINGSTONE_COMPLETE = 0x2524,
+ SMSG_MEETINGSTONE_IN_PROGRESS = 0x2D35,
+ SMSG_MEETINGSTONE_MEMBER_ADDED = 0x0000,
+ SMSG_MEETINGSTONE_SETQUEUE = 0x0000,
+ SMSG_MESSAGECHAT = 0x2026,
+ SMSG_MESSAGE_BOX = 0x30A1,
+ SMSG_MINIGAME_SETUP = 0x6727,
+ SMSG_MINIGAME_STATE = 0x2E17,
+ SMSG_MIRRORIMAGE_DATA = 0x2634,
+ SMSG_MISSILE_CANCEL = 0x3DB4,
+ SMSG_MODIFY_COOLDOWN = 0x6016,
+ SMSG_MONEY_NOTIFY = 0x55B6,
+ SMSG_MONSTER_MOVE = 0x6E17,
+ SMSG_MONSTER_MOVE_TRANSPORT = 0x2004,
+ SMSG_MOTD = 0x0A35,
+ SMSG_MOUNTRESULT = 0x2225,
+ SMSG_MOUNTSPECIAL_ANIM = 0x0217,
+ SMSG_MOVE_COLLISION_DISABLE = 0x31B0,
+ SMSG_MOVE_COLLISION_ENABLE = 0x11A7,
+ SMSG_MOVE_FEATHER_FALL = 0x79B0,
+ SMSG_MOVE_GRAVITY_DISABLE = 0x75B2,
+ SMSG_MOVE_GRAVITY_ENABLE = 0x30B3,
+ SMSG_MOVE_KNOCK_BACK = 0x5CB4,
+ SMSG_MOVE_LAND_WALK = 0x34B7,
+ SMSG_MOVE_NORMAL_FALL = 0x51B6,
+ SMSG_MOVE_ROOT = 0x7DA0,
+ SMSG_MOVE_SET_ACTIVE_MOVER = 0x11B3,
+ SMSG_MOVE_SET_CAN_FLY = 0x3DA1,
+ SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x59A2,
+ SMSG_MOVE_SET_COLLISION_HEIGHT = 0x11B0,
+ SMSG_MOVE_SET_COMPOUND_STATE = 0x75A0,
+ SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x30A2,
+ SMSG_MOVE_SET_FLIGHT_SPEED = 0x71A6,
+ SMSG_MOVE_SET_HOVER = 0x5CB3,
+ SMSG_MOVE_SET_PITCH_RATE = 0x75B0,
+ SMSG_MOVE_SET_RUN_BACK_SPEED = 0x71B1,
+ SMSG_MOVE_SET_RUN_SPEED = 0x3DB5,
+ SMSG_MOVE_SET_SWIM_BACK_SPEED = 0x5CA6,
+ SMSG_MOVE_SET_SWIM_SPEED = 0x15A7,
+ SMSG_MOVE_SET_TURN_RATE = 0x30A5,
+ SMSG_MOVE_SET_VEHICLE_REC_ID = 0x0000,
+ SMSG_MOVE_SET_WALK_IN_AIR = 0x0000,
+ SMSG_MOVE_SET_WALK_SPEED = 0x1DA4,
+ SMSG_MOVE_UNROOT = 0x7DB4,
+ SMSG_MOVE_UNSET_CAN_FLY = 0x15A2,
+ SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x7DB2,
+ SMSG_MOVE_UNSET_HOVER = 0x51B3,
+ SMSG_MOVE_UNSET_WALK_IN_AIR = 0x0000,
+ SMSG_MOVE_UPDATE_COLLISION_HEIGHT = 0x59A3,
+ SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED = 0x74A0,
+ SMSG_MOVE_UPDATE_FLIGHT_SPEED = 0x30B1,
+ SMSG_MOVE_UPDATE_KNOCK_BACK = 0x3DB2,
+ SMSG_MOVE_UPDATE_PITCH_RATE = 0x1DB5,
+ SMSG_MOVE_UPDATE_RUN_BACK_SPEED = 0x3DA6,
+ SMSG_MOVE_UPDATE_RUN_SPEED = 0x14A6,
+ SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0x30B5,
+ SMSG_MOVE_UPDATE_SWIM_SPEED = 0x59B5,
+ SMSG_MOVE_UPDATE_TELEPORT = 0x50B2,
+ SMSG_MOVE_UPDATE_TURN_RATE = 0x5DA1,
+ SMSG_MOVE_UPDATE_WALK_SPEED = 0x54A2,
+ SMSG_MOVE_WATER_WALK = 0x75B1,
+ SMSG_MULTIPLE_PACKETS = 0x6736,
+ SMSG_NAME_QUERY_RESPONSE = 0x6E04,
+ SMSG_NEW_TAXI_PATH = 0x4B35,
+ SMSG_NEW_WORLD = 0x79B1,
+ SMSG_NEW_WORLD_ABORT = 0x14B7,
+ SMSG_NOTIFICATION = 0x14A0,
+ SMSG_NOTIFY_DANCE = 0x4904,
+ SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x6204,
+ SMSG_NPC_TEXT_UPDATE = 0x4436,
+ SMSG_NPC_WONT_TALK = 0x0000,
+ SMSG_OFFER_PETITION_ERROR = 0x2716,
+ SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x4D34,
+ SMSG_OPEN_CONTAINER = 0x4714,
+ SMSG_OPEN_LFG_DUNGEON_FINDER = 0x2C37,
+ SMSG_OVERRIDE_LIGHT = 0x4225,
+ SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x2B14,
+ SMSG_PARTYKILLLOG = 0x4937,
+ SMSG_PARTY_COMMAND_RESULT = 0x6E07,
+ SMSG_PARTY_MEMBER_STATS = 0x2104,
+ SMSG_PARTY_MEMBER_STATS_FULL = 0x0215,
+ SMSG_PAUSE_MIRROR_TIMER = 0x4015,
+ SMSG_PERIODICAURALOG = 0x0416,
+ SMSG_PETGODMODE = 0x2E36,
+ SMSG_PETITION_ALREADY_SIGNED = 0x5DA3,
+ SMSG_PETITION_QUERY_RESPONSE = 0x4B37,
+ SMSG_PETITION_SHOWLIST = 0x6405,
+ SMSG_PETITION_SHOW_SIGNATURES = 0x0716,
+ SMSG_PETITION_SIGN_RESULTS = 0x6217,
+ SMSG_PET_ACTION_FEEDBACK = 0x0807,
+ SMSG_PET_ACTION_SOUND = 0x4324,
+ SMSG_PET_ADDED = 0x3CA5,
+ SMSG_PET_BROKEN = 0x2E27,
+ SMSG_PET_CAST_FAILED = 0x2B15,
+ SMSG_PET_DISMISS_SOUND = 0x2B05,
+ SMSG_PET_GUIDS = 0x2D26,
+ SMSG_PET_LEARNED_SPELL = 0x0507,
+ SMSG_PET_MODE = 0x2235,
+ SMSG_PET_NAME_INVALID = 0x6007,
+ SMSG_PET_NAME_QUERY_RESPONSE = 0x4C37,
+ SMSG_PET_REMOVED_SPELL = 0x6A04,
+ SMSG_PET_RENAMEABLE = 0x2B27,
+ SMSG_PET_SLOT_UPDATED = 0x51A3,
+ SMSG_PET_SPELLS = 0x4114,
+ SMSG_PET_TAME_FAILURE = 0x6B24,
+ SMSG_PET_UPDATE_COMBO_POINTS = 0x4325,
+ SMSG_PLAYED_TIME = 0x6037,
+ SMSG_PLAYERBINDERROR = 0x6A24,
+ SMSG_PLAYERBOUND = 0x2516,
+ SMSG_PLAYER_DIFFICULTY_CHANGE = 0x2217,
+ SMSG_PLAYER_MOVE = 0x79A2,
+ SMSG_PLAYER_SKINNED = 0x0116,
+ SMSG_PLAYER_UNK_DEAD_ALIVE = 0x0000,
+ SMSG_PLAYER_VEHICLE_DATA = 0x4115,
+ SMSG_PLAY_DANCE = 0x4704,
+ SMSG_PLAY_MUSIC = 0x4B06,
+ SMSG_PLAY_OBJECT_SOUND = 0x2635,
+ SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0x4A35,
+ SMSG_PLAY_SOUND = 0x2134,
+ SMSG_PLAY_SPELL_VISUAL = 0x10B1,
+ SMSG_PLAY_SPELL_VISUAL_KIT = 0x55A5,
+ SMSG_PLAY_TIME_WARNING = 0x4814,
+ SMSG_PONG = 0x4D42,
+ SMSG_POWER_UPDATE = 0x4A07,
+ SMSG_PRE_RESURRECT = 0x6C36,
+ SMSG_PROCRESIST = 0x0426,
+ SMSG_PROPOSE_LEVEL_GRANT = 0x6114,
+ SMSG_PUREMOUNT_CANCELLED_OBSOLETE = 0x0000,
+ SMSG_PVP_CREDIT = 0x6015,
+ SMSG_PVP_LOG_DATA = 0x5CB2,
+ SMSG_PVP_OPTIONS_ENABLED = 0x50A1,
+ SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x6314,
+ SMSG_QUERY_TIME_RESPONSE = 0x2124,
+ SMSG_QUESTGIVER_OFFER_REWARD = 0x2427,
+ SMSG_QUESTGIVER_QUEST_COMPLETE = 0x55A4,
+ SMSG_QUESTGIVER_QUEST_DETAILS = 0x2425,
+ SMSG_QUESTGIVER_QUEST_FAILED = 0x4236,
+ SMSG_QUESTGIVER_QUEST_INVALID = 0x4016,
+ SMSG_QUESTGIVER_QUEST_LIST = 0x0134,
+ SMSG_QUESTGIVER_REQUEST_ITEMS = 0x6236,
+ SMSG_QUESTGIVER_STATUS = 0x2115,
+ SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x4F25,
+ SMSG_QUESTLOG_FULL = 0x0E36,
+ SMSG_QUESTUPDATE_ADD_ITEM = 0x0000,
+ SMSG_QUESTUPDATE_ADD_KILL = 0x0D27,
+ SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x4416,
+ SMSG_QUESTUPDATE_COMPLETE = 0x2937,
+ SMSG_QUESTUPDATE_FAILED = 0x6324,
+ SMSG_QUESTUPDATE_FAILEDTIMER = 0x6427,
+ SMSG_QUEST_NPC_QUERY_RESPONSE = 0x75A1,
+ SMSG_QUEST_CONFIRM_ACCEPT = 0x6F07,
+ SMSG_QUEST_FORCE_REMOVE = 0x6605,
+ SMSG_QUEST_POI_QUERY_RESPONSE = 0x6304,
+ SMSG_QUEST_QUERY_RESPONSE = 0x6936,
+ SMSG_RAID_GROUP_ONLY = 0x0837,
+ SMSG_RAID_INSTANCE_INFO = 0x6626,
+ SMSG_RAID_INSTANCE_MESSAGE = 0x6E15,
+ SMSG_RAID_MARKERS_CHANGED = 0x10A1,
+ SMSG_RAID_READY_CHECK_THROTTLED_ERROR = 0x2607,
+ SMSG_RAID_SUMMON_FAILED = 0x18B6,
+ SMSG_RANDOMIZE_CHAR_NAME = 0x38B1,
+ SMSG_RATED_BG_RATING = 0x15A1,
+ SMSG_RATED_BG_STATS = 0x34A1,
+ SMSG_READ_ITEM_FAILED = 0x0F16,
+ SMSG_READ_ITEM_OK = 0x2605,
+ SMSG_REALM_SPLIT = 0x2714,
+ SMSG_REAL_GROUP_UPDATE = 0x0F34,
+ SMSG_RECEIVED_MAIL = 0x2924,
+ SMSG_REDIRECT_CLIENT = 0x0942,
+ SMSG_REFER_A_FRIEND_EXPIRED = 0x4934,
+ SMSG_REFER_A_FRIEND_FAILURE = 0x2037,
+ SMSG_REFORGE_RESULT = 0x58A4,
+ SMSG_REMOVED_SPELL = 0x4804,
+ SMSG_REPORT_PVP_AFK_RESULT = 0x2D06,
+ SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x30A7,
+ SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0x5DA4,
+ SMSG_RESEARCH_COMPLETE = 0x35A6,
+ SMSG_RESEARCH_SETUP_HISTORY = 0x10B6,
+ SMSG_RESET_COMPRESSION_CONTEXT = 0x0142,
+ SMSG_RESET_FAILED_NOTIFY = 0x4616,
+ SMSG_RESISTLOG = 0x0000,
+ SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x15B0,
+ SMSG_RESURRECT_REQUEST = 0x2905,
+ SMSG_RESYNC_RUNES = 0x6224,
+ SMSG_ROLE_POLL_BEGIN = 0x70B0,
+ SMSG_RWHOIS = 0x2437,
+ SMSG_SELL_ITEM = 0x6105,
+ SMSG_SEND_MAIL_RESULT = 0x4927,
+ SMSG_SEND_UNLEARN_SPELLS = 0x4E25,
+ SMSG_SERVERTIME = 0x6327,
+ SMSG_SERVER_FIRST_ACHIEVEMENT = 0x6424,
+ SMSG_SERVER_INFO_RESPONSE = 0x74B5,
+ SMSG_SERVER_MESSAGE = 0x6C04,
+ SMSG_SERVER_PERF = 0x74B6,
+ SMSG_SET_AI_ANIM_KIT = 0x0000,
+ SMSG_SET_DF_FAST_LAUNCH_RESULT = 0x35B6,
+ SMSG_SET_FACTION_ATWAR = 0x4216,
+ SMSG_SET_FACTION_STANDING = 0x0126,
+ SMSG_SET_FACTION_VISIBLE = 0x2525,
+ SMSG_SET_FLAT_SPELL_MODIFIER = 0x2834,
+ SMSG_SET_FORCED_REACTIONS = 0x4615,
+ SMSG_SET_MELEE_ANIM_KIT = 0x0000,
+ SMSG_SET_MOVEMENT_ANIM_KIT = 0x0000,
+ SMSG_SET_PCT_SPELL_MODIFIER = 0x0224,
+ SMSG_SET_PHASE_SHIFT = 0x70A0,
+ SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x2B25,
+ SMSG_SET_PLAY_HOVER_ANIM = 0x30A6,
+ SMSG_SET_PROFICIENCY = 0x6207,
+ SMSG_SET_PROJECTILE_POSITION = 0x2616,
+ SMSG_SHOWTAXINODES = 0x2A36,
+ SMSG_SHOW_BANK = 0x2627,
+ SMSG_SHOW_RATINGS = 0x11B4,
+ SMSG_SOCKET_GEMS_RESULT = 0x6014,
+ SMSG_SOR_START_EXPERIENCE_INCOMPLETE = 0x7CA7,
+ SMSG_SPELLBREAKLOG = 0x6B17,
+ SMSG_SPELLDAMAGESHIELD = 0x2927,
+ SMSG_SPELLDISPELLOG = 0x4516,
+ SMSG_SPELLENERGIZELOG = 0x0414,
+ SMSG_SPELLHEALLOG = 0x2816,
+ SMSG_SPELLINSTAKILLLOG = 0x6216,
+ SMSG_SPELLINTERRUPTLOG = 0x1DA7,
+ SMSG_SPELLLOGEXECUTE = 0x0626,
+ SMSG_SPELLLOGMISS = 0x0625,
+ SMSG_SPELLNONMELEEDAMAGELOG = 0x4315,
+ SMSG_SPELLORDAMAGE_IMMUNE = 0x4507,
+ SMSG_SPELLSTEALLOG = 0x4E26,
+ SMSG_SPELL_CATEGORY_COOLDOWN = 0x71B6,
+ SMSG_SPELL_COOLDOWN = 0x4B16,
+ SMSG_SPELL_DELAYED = 0x0715,
+ SMSG_SPELL_FAILED_OTHER = 0x0C34,
+ SMSG_SPELL_FAILURE = 0x4535,
+ SMSG_SPELL_GO = 0x6E16,
+ SMSG_SPELL_START = 0x6415,
+ SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x6006,
+ SMSG_SPIRIT_HEALER_CONFIRM = 0x4917,
+ SMSG_SPLINE_MOVE_COLLISION_DISABLE = 0x35B1,
+ SMSG_SPLINE_MOVE_COLLISION_ENABLE = 0x3CB0,
+ SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x5DB5,
+ SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0x3CA6,
+ SMSG_SPLINE_MOVE_ROOT = 0x51B4,
+ SMSG_SPLINE_MOVE_SET_ANIM = 0x4335,
+ SMSG_SPLINE_MOVE_SET_FEATHER_FALL = 0x3DA5,
+ SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED = 0x38B3,
+ SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED = 0x39A0,
+ SMSG_SPLINE_MOVE_SET_FLYING = 0x31B5,
+ SMSG_SPLINE_MOVE_SET_HOVER = 0x14B6,
+ SMSG_SPLINE_MOVE_SET_LAND_WALK = 0x3DA7,
+ SMSG_SPLINE_MOVE_SET_NORMAL_FALL = 0x38B2,
+ SMSG_SPLINE_MOVE_SET_PITCH_RATE = 0x14B0,
+ SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED = 0x3DB3,
+ SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x75A7,
+ SMSG_SPLINE_MOVE_SET_RUN_SPEED = 0x51B7,
+ SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED = 0x59A1,
+ SMSG_SPLINE_MOVE_SET_SWIM_SPEED = 0x39A4,
+ SMSG_SPLINE_MOVE_SET_TURN_RATE = 0x78B5,
+ SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x54B6,
+ SMSG_SPLINE_MOVE_SET_WALK_SPEED = 0x34A5,
+ SMSG_SPLINE_MOVE_SET_WATER_WALK = 0x0000,
+ SMSG_SPLINE_MOVE_START_SWIM = 0x31A5,
+ SMSG_SPLINE_MOVE_STOP_SWIM = 0x1DA2,
+ SMSG_SPLINE_MOVE_UNROOT = 0x75B6,
+ SMSG_SPLINE_MOVE_UNSET_FLYING = 0x58A6,
+ SMSG_SPLINE_MOVE_UNSET_HOVER = 0x7DA5,
+ SMSG_SPLINE_MOVE_WATER_WALK = 0x50A2,
+ SMSG_STABLE_RESULT = 0x2204,
+ SMSG_STANDSTATE_UPDATE = 0x6F04,
+ SMSG_START_MIRROR_TIMER = 0x6824,
+ SMSG_START_TIMER = 0x59A5,
+ SMSG_STOP_DANCE = 0x4637,
+ SMSG_STOP_MIRROR_TIMER = 0x0B06,
+ SMSG_STREAMING_MOVIE = 0x15B7,
+ SMSG_SUMMON_CANCEL = 0x0B34,
+ SMSG_SUMMON_REQUEST = 0x2A07,
+ SMSG_SUPERCEDED_SPELL = 0x35B0,
+ SMSG_SUPPRESS_NPC_GREETINGS = 0x74B1,
+ SMSG_SUSPEND_COMMS = 0x4140,
+ SMSG_SUSPEND_TOKEN_RESPONSE = 0x14B1,
+ SMSG_TALENTS_ERROR = 0x0916,
+ SMSG_TALENTS_INFO = 0x6F26,
+ SMSG_TALENTS_INVOLUNTARILY_RESET = 0x2C27,
+ SMSG_TAXINODE_STATUS = 0x2936,
+ SMSG_TEST_DROP_RATE_RESULT = 0x6816,
+ SMSG_TEXT_EMOTE = 0x0B05,
+ SMSG_THREAT_CLEAR = 0x6437,
+ SMSG_THREAT_REMOVE = 0x2E05,
+ SMSG_THREAT_UPDATE = 0x4735,
+ SMSG_TIME_ADJUSTMENT = 0x79B7,
+ SMSG_TIME_SYNC_REQ = 0x3CA4,
+ SMSG_TITLE_EARNED = 0x2426,
+ SMSG_TOGGLE_XP_GAIN = 0x6704,
+ SMSG_TOTEM_CREATED = 0x2414,
+ SMSG_TRADE_STATUS = 0x5CA3,
+ SMSG_TRADE_STATUS_EXTENDED = 0x70A2,
+ SMSG_TRAINER_BUY_FAILED = 0x0004,
+ SMSG_TRAINER_BUY_SUCCEEDED = 0x6A05,
+ SMSG_TRAINER_LIST = 0x4414,
+ SMSG_TRANSFER_ABORTED = 0x0537,
+ SMSG_TRANSFER_PENDING = 0x18A6,
+ SMSG_TRIGGER_CINEMATIC = 0x6C27,
+ SMSG_TRIGGER_MOVIE = 0x4625,
+ SMSG_TURN_IN_PETITION_RESULTS = 0x0F07,
+ SMSG_TUTORIAL_FLAGS = 0x0B35,
+ SMSG_UNIT_HEALTH_FREQUENT = 0x2C26,
+ SMSG_UNIT_SPELLCAST_START = 0x2517,
+ SMSG_UPDATE_ACCOUNT_DATA = 0x6837,
+ SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x2015,
+ SMSG_UPDATE_COMBO_POINTS = 0x6B34,
+ SMSG_UPDATE_CURRENCY = 0x59B0,
+ SMSG_UPDATE_CURRENCY_WEEK_LIMIT = 0x70A7,
+ SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT = 0x3CB5,
+ SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT = 0x4007,
+ SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x4915,
+ SMSG_UPDATE_LAST_INSTANCE = 0x0437,
+ SMSG_UPDATE_OBJECT = 0x4715,
+ SMSG_UPDATE_SERVER_PLAYER_POSITION = 0x74A3,
+ SMSG_UPDATE_WORLD_STATE = 0x4816,
+ SMSG_USERLIST_ADD = 0x0F37,
+ SMSG_USERLIST_REMOVE = 0x2006,
+ SMSG_USERLIST_UPDATE = 0x0135,
+ SMSG_VOICESESSION_FULL = 0x6225,
+ SMSG_VOICE_CHAT_STATUS = 0x0F15,
+ SMSG_VOICE_PARENTAL_CONTROLS = 0x0534,
+ SMSG_VOICE_SESSION_LEAVE = 0x2A24,
+ SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x2A17,
+ SMSG_VOICE_SET_TALKER_MUTED = 0x6E35,
+ SMSG_VOID_ITEM_SWAP_RESPONSE = 0x78A2,
+ SMSG_VOID_STORAGE_CONTENTS = 0x75B4,
+ SMSG_VOID_STORAGE_FAILED = 0x18A7,
+ SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x51A6,
+ SMSG_VOID_TRANSFER_RESULT = 0x1DA6,
+ SMSG_WAIT_QUEUE_FINISH = 0x75B7,
+ SMSG_WAIT_QUEUE_UPDATE = 0x58A1,
+ SMSG_WARDEN_DATA = 0x31A0,
+ SMSG_WARGAME_CHECK_ENTRY = 0x3DA4,
+ SMSG_WARGAME_REQUEST_SENT = 0x59B2,
+ SMSG_WEATHER = 0x2904,
+ SMSG_WEEKLY_LAST_RESET = 0x50A5,
+ SMSG_WEEKLY_RESET_CURRENCY = 0x3CA1,
+ SMSG_WEEKLY_SPELL_USAGE = 0x39B7,
+ SMSG_WEEKLY_SPELL_USAGE_UPDATE = 0x11B5,
+ SMSG_WHO = 0x6907,
+ SMSG_WHOIS = 0x6917,
+ SMSG_WORLD_SERVER_INFO = 0x31A2,
+ SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4A14,
+ SMSG_XP_GAIN_ABORTED = 0x50B4,
+ SMSG_ZONE_UNDER_ATTACK = 0x0A06,
};
/// Player state
@@ -1367,29 +1405,80 @@ enum PacketProcessing
};
class WorldPacket;
+class WorldSession;
+
+typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket);
struct OpcodeHandler
{
- char const* name;
- SessionStatus status;
- PacketProcessing packetProcessing;
- void (WorldSession::*handler)(WorldPacket& recvPacket);
-};
+ OpcodeHandler() {}
+ OpcodeHandler(char const* _name, SessionStatus _status, PacketProcessing _processing, pOpcodeHandler _handler)
+ : Handler(_handler), Name(_name), Status(_status), ProcessingPlace(_processing) {}
-extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
+ pOpcodeHandler Handler;
+ char const* Name;
+ SessionStatus Status;
+ PacketProcessing ProcessingPlace;
+};
-/// Lookup opcode name for human understandable logging
-inline const char* LookupOpcodeName(uint16 id)
+class OpcodeTable
{
- if (id >= NUM_MSG_TYPES)
- return "Received unknown opcode, it's more than max!";
- return opcodeTable[id].name;
-}
+ public:
+ OpcodeTable()
+ {
+ memset(_internalTable, 0, sizeof(_internalTable));
+ }
+
+ ~OpcodeTable()
+ {
+ for (uint16 i = 0; i < NUM_OPCODE_HANDLERS; ++i)
+ delete _internalTable[i];
+ }
+
+ void Initialize();
+
+ OpcodeHandler const* operator[](uint32 index) const
+ {
+ return _internalTable[index];
+ }
-inline std::string GetOpcodeNameForLogging(uint16 opcode)
+ private:
+ template<bool isInValidRange, bool isNonZero>
+ void ValidateAndSetOpcode(uint16 opcode, char const* name, SessionStatus status, PacketProcessing processing, pOpcodeHandler handler);
+
+ // Prevent copying this structure
+ OpcodeTable(OpcodeTable const&);
+ OpcodeTable& operator=(OpcodeTable const&);
+
+ OpcodeHandler* _internalTable[NUM_OPCODE_HANDLERS];
+};
+
+extern OpcodeTable opcodeTable;
+
+void InitOpcodes();
+
+/// Lookup opcode name for human understandable logging
+inline std::string GetOpcodeNameForLogging(Opcodes id)
{
+ uint32 opcode = uint32(id);
std::ostringstream ss;
- ss << '[' << LookupOpcodeName(opcode) << " 0x" << std::hex << std::uppercase << opcode << std::nouppercase << " (" << std::dec << opcode << ")]";
+ ss << '[';
+
+ if (id < UNKNOWN_OPCODE)
+ {
+ if (OpcodeHandler const* handler = opcodeTable[uint32(id) & 0x7FFF])
+ {
+ ss << handler->Name;
+ if (opcode & COMPRESSED_OPCODE_MASK)
+ ss << "_COMPRESSED";
+ }
+ else
+ ss << "UNKNOWN OPCODE";
+ }
+ else
+ ss << "INVALID OPCODE";
+
+ ss << " 0x" << std::hex << std::uppercase << opcode << std::nouppercase << " (" << std::dec << opcode << ")]";
return ss.str();
}
diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp
new file mode 100644
index 00000000000..8efcb4909ac
--- /dev/null
+++ b/src/server/game/Server/WorldPacket.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <zlib.h>
+#include "WorldPacket.h"
+#include "World.h"
+
+//! Compresses packet in place
+void WorldPacket::Compress(z_stream* compressionStream)
+{
+ Opcodes uncompressedOpcode = GetOpcode();
+ if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
+ return;
+ }
+
+ Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
+ uint32 size = wpos();
+ uint32 destsize = compressBound(size);
+
+ std::vector<uint8> storage(destsize);
+
+ _compressionStream = compressionStream;
+ Compress(static_cast<void*>(&storage[0]), &destsize, static_cast<const void*>(contents()), size);
+ if (destsize == 0)
+ return;
+
+ clear();
+ reserve(destsize + sizeof(uint32));
+ *this << uint32(size);
+ append(&storage[0], destsize);
+ SetOpcode(opcode);
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
+}
+
+//! Compresses another packet and stores it in self (source left intact)
+void WorldPacket::Compress(z_stream* compressionStream, WorldPacket const* source)
+{
+ ASSERT(source != this);
+
+ Opcodes uncompressedOpcode = source->GetOpcode();
+ if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
+ return;
+ }
+
+ Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
+ uint32 size = source->size();
+ uint32 destsize = compressBound(size);
+
+ size_t sizePos = 0;
+ resize(destsize + sizeof(uint32));
+
+ _compressionStream = compressionStream;
+ Compress(static_cast<void*>(&_storage[0] + sizeof(uint32)), &destsize, static_cast<const void*>(source->contents()), size);
+ if (destsize == 0)
+ return;
+
+ put<uint32>(sizePos, size);
+ resize(destsize + sizeof(uint32));
+
+ SetOpcode(opcode);
+
+ TC_LOG_INFO(LOG_FILTER_NETWORKIO, "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
+}
+
+void WorldPacket::Compress(void* dst, uint32 *dst_size, const void* src, int src_size)
+{
+ _compressionStream->next_out = (Bytef*)dst;
+ _compressionStream->avail_out = *dst_size;
+ _compressionStream->next_in = (Bytef*)src;
+ _compressionStream->avail_in = (uInt)src_size;
+
+ int32 z_res = deflate(_compressionStream, Z_SYNC_FLUSH);
+ if (z_res != Z_OK)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Can't compress packet (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
+ *dst_size = 0;
+ return;
+ }
+
+ if (_compressionStream->avail_in != 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Can't compress packet (zlib: deflate not greedy)");
+ *dst_size = 0;
+ return;
+ }
+
+ *dst_size -= _compressionStream->avail_out;
+}
diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/game/Server/WorldPacket.h
index 7ec2b5d1e1e..46b5c583eb8 100644
--- a/src/server/shared/Packets/WorldPacket.h
+++ b/src/server/game/Server/WorldPacket.h
@@ -20,33 +20,43 @@
#define TRINITYCORE_WORLDPACKET_H
#include "Common.h"
+#include "Opcodes.h"
#include "ByteBuffer.h"
+struct z_stream_s;
+
class WorldPacket : public ByteBuffer
{
public:
// just container for later use
- WorldPacket() : ByteBuffer(0), m_opcode(0)
+ WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE)
+ {
+ }
+
+ WorldPacket(Opcodes opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode)
{
}
- explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
// copy constructor
- WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
+ WorldPacket(WorldPacket const& packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
{
}
- void Initialize(uint16 opcode, size_t newres=200)
+ void Initialize(Opcodes opcode, size_t newres = 200)
{
clear();
_storage.reserve(newres);
m_opcode = opcode;
}
- uint16 GetOpcode() const { return m_opcode; }
- void SetOpcode(uint16 opcode) { m_opcode = opcode; }
+ Opcodes GetOpcode() const { return m_opcode; }
+ void SetOpcode(Opcodes opcode) { m_opcode = opcode; }
+ void Compress(z_stream_s* compressionStream);
+ void Compress(z_stream_s* compressionStream, WorldPacket const* source);
protected:
- uint16 m_opcode;
+ Opcodes m_opcode;
+ void Compress(void* dst, uint32 *dst_size, const void* src, int src_size);
+ z_stream_s* _compressionStream;
};
#endif
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index b5e22f011a1..fc624b93448 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -21,6 +21,7 @@
*/
#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it
+#include <zlib.h>
#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
@@ -55,14 +56,15 @@ std::string const DefaultPlayerName = "<none>";
bool MapSessionFilter::Process(WorldPacket* packet)
{
- OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
+ Opcodes opcode = DropHighBytes(packet->GetOpcode());
+ OpcodeHandler const* opHandle = opcodeTable[opcode];
//let's check if our opcode can be really processed in Map::Update()
- if (opHandle.packetProcessing == PROCESS_INPLACE)
+ if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//we do not process thread-unsafe packets
- if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
+ if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return false;
Player* player = m_pSession->GetPlayer();
@@ -77,13 +79,14 @@ bool MapSessionFilter::Process(WorldPacket* packet)
//OR packet handler is not thread-safe!
bool WorldSessionFilter::Process(WorldPacket* packet)
{
- OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
+ Opcodes opcode = DropHighBytes(packet->GetOpcode());
+ OpcodeHandler const* opHandle = opcodeTable[opcode];
//check if packet handler is supposed to be safe
- if (opHandle.packetProcessing == PROCESS_INPLACE)
+ if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//thread-unsafe packets should be processed in World::UpdateSessions()
- if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
+ if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return true;
//no player attached? -> our client! ^^
@@ -115,6 +118,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
m_sessionDbLocaleIndex(locale),
m_latency(0),
m_TutorialsChanged(false),
+ _filterAddonMessages(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
timeLastWhoCommand(0),
@@ -129,6 +133,19 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
}
InitializeQueryCallbackParameters();
+
+ _compressionStream = new z_stream();
+ _compressionStream->zalloc = (alloc_func)NULL;
+ _compressionStream->zfree = (free_func)NULL;
+ _compressionStream->opaque = (voidpf)NULL;
+ _compressionStream->avail_in = 0;
+ _compressionStream->next_in = NULL;
+ int32 z_res = deflateInit(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION));
+ if (z_res != Z_OK)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
+ return;
+ }
}
/// WorldSession destructor
@@ -155,6 +172,15 @@ WorldSession::~WorldSession()
delete packet;
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
+
+ int32 z_res = deflateEnd(_compressionStream);
+ if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
+ return;
+ }
+
+ delete _compressionStream;
}
std::string const & WorldSession::GetPlayerName() const
@@ -180,11 +206,32 @@ uint32 WorldSession::GetGuidLow() const
}
/// Send a packet to the client
-void WorldSession::SendPacket(WorldPacket const* packet)
+void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
{
if (!m_Socket)
return;
+ if (packet->GetOpcode() == NULL_OPCODE)
+ {
+ TC_LOG_ERROR(LOG_FILTER_OPCODES, "Prevented sending of NULL_OPCODE to %s", GetPlayerInfo().c_str());
+ return;
+ }
+ else if (packet->GetOpcode() == UNKNOWN_OPCODE)
+ {
+ TC_LOG_ERROR(LOG_FILTER_OPCODES, "Prevented sending of UNKNOWN_OPCODE to %s", GetPlayerInfo().c_str());
+ return;
+ }
+
+ if (!forced)
+ {
+ OpcodeHandler const* handler = opcodeTable[packet->GetOpcode()];
+ if (!handler || handler->Status == STATUS_UNHANDLED)
+ {
+ TC_LOG_ERROR(LOG_FILTER_OPCODES, "Prevented sending disabled opcode %s to %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str(), GetPlayerInfo().c_str());
+ return;
+ }
+ }
+
#ifdef TRINITY_DEBUG
// Code for network use statistic
static uint64 sendPacketCount = 0;
@@ -274,104 +321,96 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
!_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket &&
_recvQueue.next(packet, updater))
{
- if (packet->GetOpcode() >= NUM_MSG_TYPES)
- {
- TC_LOG_ERROR(LOG_FILTER_OPCODES, "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
- , GetPlayerInfo().c_str());
- sScriptMgr->OnUnknownPacketReceive(m_Socket, WorldPacket(*packet));
- }
- else
+ OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()];
+
+ try
{
- OpcodeHandler &opHandle = opcodeTable[packet->GetOpcode()];
- try
+ switch (opHandle->Status)
{
- switch (opHandle.status)
- {
- case STATUS_LOGGEDIN:
- if (!_player)
+ case STATUS_LOGGEDIN:
+ if (!_player)
+ {
+ // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
+ //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
+ //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
+ if (!m_playerRecentlyLogout)
{
- // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
- //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
- //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
- if (!m_playerRecentlyLogout)
- {
- //! Prevent infinite loop
- if (!firstDelayedPacket)
- firstDelayedPacket = packet;
- //! Because checking a bool is faster than reallocating memory
- deletePacket = false;
- QueuePacket(packet);
- //! Log
+ //! Prevent infinite loop
+ if (!firstDelayedPacket)
+ firstDelayedPacket = packet;
+ //! Because checking a bool is faster than reallocating memory
+ deletePacket = false;
+ QueuePacket(packet);
+ //! Log
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str());
- }
- }
- else if (_player->IsInWorld())
- {
- sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
- }
- // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
- break;
- case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
- if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
- LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
- "the player has not logged in yet and not recently logout");
- else
- {
- // not expected _player or must checked in packet handler
- sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
- }
- break;
- case STATUS_TRANSFER:
- if (!_player)
- LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
- else if (_player->IsInWorld())
- LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
- else
- {
- sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
}
- break;
- case STATUS_AUTHED:
- // prevent cheating with skip queue wait
- if (m_inQueue)
- {
- LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet");
- break;
- }
-
- // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
- // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
- if (packet->GetOpcode() == CMSG_CHAR_ENUM)
- m_playerRecentlyLogout = false;
-
+ }
+ else if (_player->IsInWorld())
+ {
+ sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ }
+ // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
+ break;
+ case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
+ if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
+ LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
+ "the player has not logged in yet and not recently logout");
+ else
+ {
+ // not expected _player or must checked in packet hanlder
sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
- (this->*opHandle.handler)(*packet);
+ (this->*opHandle->Handler)(*packet);
LogUnprocessedTail(packet);
+ }
+ break;
+ case STATUS_TRANSFER:
+ if (!_player)
+ LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
+ else if (_player->IsInWorld())
+ LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
+ else
+ {
+ sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ }
+ break;
+ case STATUS_AUTHED:
+ // prevent cheating with skip queue wait
+ if (m_inQueue)
+ {
+ LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet");
break;
- case STATUS_NEVER:
+ }
+
+ // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
+ // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
+ if (packet->GetOpcode() == CMSG_CHAR_ENUM)
+ m_playerRecentlyLogout = false;
+
+ sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ break;
+ case STATUS_NEVER:
TC_LOG_ERROR(LOG_FILTER_OPCODES, "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
- break;
- case STATUS_UNHANDLED:
- TC_LOG_DEBUG(LOG_FILTER_OPCODES, "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
+ break;
+ case STATUS_UNHANDLED:
+ TC_LOG_ERROR(LOG_FILTER_OPCODES, "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
- break;
- }
- }
- catch(ByteBufferException &)
- {
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
- packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
- packet->hexlike();
+ break;
}
}
+ catch(ByteBufferException &)
+ {
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
+ packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
+ packet->hexlike();
+ }
if (deletePacket)
delete packet;
@@ -568,8 +607,11 @@ void WorldSession::SendNotification(const char *format, ...)
vsnprintf(szStr, 1024, format, ap);
va_end(ap);
- WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1));
- data << szStr;
+ size_t len = strlen(szStr);
+ WorldPacket data(SMSG_NOTIFICATION, 2 + len);
+ data.WriteBits(len, 13);
+ data.FlushBits();
+ data.append(szStr, len);
SendPacket(&data);
}
}
@@ -586,8 +628,11 @@ void WorldSession::SendNotification(uint32 string_id, ...)
vsnprintf(szStr, 1024, format, ap);
va_end(ap);
- WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1));
- data << szStr;
+ size_t len = strlen(szStr);
+ WorldPacket data(SMSG_NOTIFICATION, 2 + len);
+ data.WriteBits(len, 13);
+ data.FlushBits();
+ data.append(szStr, len);
SendPacket(&data);
}
}
@@ -626,15 +671,21 @@ void WorldSession::SendAuthWaitQue(uint32 position)
if (position == 0)
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet.WriteBit(0); // has queue info
+ packet.WriteBit(0); // has account info
+ packet.FlushBits();
packet << uint8(AUTH_OK);
SendPacket(&packet);
}
else
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 6);
+ packet.WriteBit(1); // has queue info
+ packet.WriteBit(0); // unk queue bool
+ packet.WriteBit(0); // has account info
+ packet.FlushBits();
packet << uint8(AUTH_WAIT_QUEUE);
packet << uint32(position);
- packet << uint8(0); // unk
SendPacket(&packet);
}
}
@@ -760,156 +811,6 @@ void WorldSession::SaveTutorialsData(SQLTransaction &trans)
m_TutorialsChanged = false;
}
-void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
-{
- data >> mi->flags;
- data >> mi->flags2;
- data >> mi->time;
- data >> mi->pos.PositionXYZOStream();
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- {
- data.readPackGUID(mi->t_guid);
-
- data >> mi->t_pos.PositionXYZOStream();
- data >> mi->t_time;
- data >> mi->t_seat;
-
- if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT))
- data >> mi->t_time2;
-
- if (mi->pos.m_positionX != mi->t_pos.m_positionX)
- if (GetPlayer()->GetTransport())
- GetPlayer()->GetTransport()->UpdatePosition(mi);
- }
-
- if (mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)))
- data >> mi->pitch;
-
- data >> mi->fallTime;
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
- {
- data >> mi->j_zspeed;
- data >> mi->j_sinAngle;
- data >> mi->j_cosAngle;
- data >> mi->j_xyspeed;
- }
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION))
- data >> mi->splineElevation;
-
- //! Anti-cheat checks. Please keep them in seperate if () blocks to maintain a clear overview.
- //! Might be subject to latency, so just remove improper flags.
- #ifdef TRINITY_DEBUG
- #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
- { \
- if (check) \
- { \
- TC_LOG_DEBUG(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
- "MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
- STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
- mi->RemoveMovementFlag((maskToRemove)); \
- } \
- }
- #else
- #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
- if (check) \
- mi->RemoveMovementFlag((maskToRemove));
- #endif
-
-
- /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
- in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
- It will freeze clients that receive this player's movement info.
- */
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
- MOVEMENTFLAG_ROOT);
-
- //! Cannot hover without SPELL_AURA_HOVER
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
- MOVEMENTFLAG_HOVER);
-
- //! Cannot ascend and descend at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
- MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
-
- //! Cannot move left and right at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
- MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
-
- //! Cannot strafe left and right at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
- MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
-
- //! Cannot pitch up and down at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
- MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
-
- //! Cannot move forwards and backwards at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
- MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
-
- //! Cannot walk on water without SPELL_AURA_WATER_WALK
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK),
- MOVEMENTFLAG_WATERWALKING);
-
- //! Cannot feather fall without SPELL_AURA_FEATHER_FALL
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL),
- MOVEMENTFLAG_FALLING_SLOW);
-
- /*! Cannot fly if no fly auras present. Exception is being a GM.
- Note that we check for account level instead of Player::IsGameMaster() because in some
- situations it may be feasable to use .gm fly on as a GM without having .gm on,
- e.g. aerial combat.
- */
-
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
- !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
- !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
- MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
-
- #undef REMOVE_VIOLATING_FLAGS
-}
-
-void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
-{
- data->appendPackGUID(mi->guid);
-
- *data << mi->flags;
- *data << mi->flags2;
- *data << mi->time;
- *data << mi->pos.PositionXYZOStream();
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- {
- data->appendPackGUID(mi->t_guid);
-
- *data << mi->t_pos.PositionXYZOStream();
- *data << mi->t_time;
- *data << mi->t_seat;
-
- if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT))
- *data << mi->t_time2;
- }
-
- if (mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
- *data << mi->pitch;
-
- *data << mi->fallTime;
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
- {
- *data << mi->j_zspeed;
- *data << mi->j_sinAngle;
- *data << mi->j_cosAngle;
- *data << mi->j_xyspeed;
- }
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION))
- *data << mi->splineElevation;
-}
-
void WorldSession::ReadAddonsInfo(WorldPacket &data)
{
if (data.rpos() + 4 > data.size())
@@ -1050,6 +951,57 @@ void WorldSession::SendAddonsInfo()
SendPacket(&data);
}
+bool WorldSession::IsAddonRegistered(const std::string& prefix) const
+{
+ if (!_filterAddonMessages) // if we have hit the softcap (64) nothing should be filtered
+ return true;
+
+ if (_registeredAddonPrefixes.empty())
+ return false;
+
+ std::vector<std::string>::const_iterator itr = std::find(_registeredAddonPrefixes.begin(), _registeredAddonPrefixes.end(), prefix);
+ return itr != _registeredAddonPrefixes.end();
+}
+
+void WorldSession::HandleUnregisterAddonPrefixesOpcode(WorldPacket& /*recvPacket*/) // empty packet
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UNREGISTER_ALL_ADDON_PREFIXES");
+
+ _registeredAddonPrefixes.clear();
+}
+
+void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADDON_REGISTERED_PREFIXES");
+
+ // This is always sent after CMSG_UNREGISTER_ALL_ADDON_PREFIXES
+
+ uint32 count = recvPacket.ReadBits(25);
+
+ if (count > REGISTERED_ADDON_PREFIX_SOFTCAP)
+ {
+ // if we have hit the softcap (64) nothing should be filtered
+ _filterAddonMessages = false;
+ recvPacket.rfinish();
+ return;
+ }
+
+ std::vector<uint8> lengths(count);
+ for (uint32 i = 0; i < count; ++i)
+ lengths[i] = recvPacket.ReadBits(5);
+
+ for (uint32 i = 0; i < count; ++i)
+ _registeredAddonPrefixes.push_back(recvPacket.ReadString(lengths[i]));
+
+ if (_registeredAddonPrefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP) // shouldn't happen
+ {
+ _filterAddonMessages = false;
+ return;
+ }
+
+ _filterAddonMessages = true;
+}
+
void WorldSession::SetPlayer(Player* player)
{
_player = player;
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index bf79b34822d..133d0e7e761 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -30,6 +30,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
+#include "Opcodes.h"
class Creature;
class GameObject;
@@ -79,6 +80,8 @@ enum AccountDataType
#define GLOBAL_CACHE_MASK 0x15
#define PER_CHARACTER_CACHE_MASK 0xEA
+#define REGISTERED_ADDON_PREFIX_SOFTCAP 64
+
struct AccountData
{
AccountData() : Time(0), Data("") {}
@@ -114,12 +117,15 @@ enum ChatRestrictionType
enum CharterTypes
{
- GUILD_CHARTER_TYPE = 9,
+ GUILD_CHARTER_TYPE = 4,
ARENA_TEAM_CHARTER_2v2_TYPE = 2,
ARENA_TEAM_CHARTER_3v3_TYPE = 3,
- ARENA_TEAM_CHARTER_5v5_TYPE = 5
+ ARENA_TEAM_CHARTER_5v5_TYPE = 5,
};
+#define DB2_REPLY_SPARSE 2442913102
+#define DB2_REPLY_ITEM 1344507586
+
//class to deal with packet processing
//allows to determine if next packet is safe to be processed
class PacketFilter
@@ -130,6 +136,7 @@ public:
virtual bool Process(WorldPacket* /*packet*/) { return true; }
virtual bool ProcessLogout() const { return true; }
+ static Opcodes DropHighBytes(Opcodes opcode) { return Opcodes(opcode & 0xFFFF); }
protected:
WorldSession* const m_pSession;
@@ -201,20 +208,18 @@ class WorldSession
void ReadAddonsInfo(WorldPacket& data);
void SendAddonsInfo();
+ bool IsAddonRegistered(const std::string& prefix) const;
- void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
- void WriteMovementInfo(WorldPacket* data, MovementInfo* mi);
-
- void SendPacket(WorldPacket const* packet);
+ void SendPacket(WorldPacket const* packet, bool forced = false);
void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3);
void SendNotification(uint32 string_id, ...);
void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName *declinedName);
void SendPartyResult(PartyOperation operation, std::string const& member, PartyResult res, uint32 val = 0);
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3);
- void SendSetPhaseShift(uint32 phaseShift);
+ void SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps);
void SendQueryTimeResponse();
- void SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos = 0);
+ void SendAuthResponse(uint8 code, bool queued, uint32 queuePos = 0);
void SendClientCacheVersion(uint32 version);
RBACData* GetRBACData();
@@ -317,9 +322,10 @@ class WorldSession
bool SendItemInfo(uint32 itemid, WorldPacket data);
//auction
void SendAuctionHello(uint64 guid, Creature* unit);
- void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
+ void SendAuctionCommandResult(AuctionEntry* auction, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template);
void SendAuctionOwnerNotification(AuctionEntry* auction);
+ void SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId);
//Item Enchantment
void SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId);
@@ -361,19 +367,15 @@ class WorldSession
else
m_timeOutTime -= diff;
}
- void ResetTimeOutTime()
- {
- m_timeOutTime = sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME);
- }
- bool IsConnectionIdle() const
- {
- return (m_timeOutTime <= 0 && !m_inQueue);
- }
+ void ResetTimeOutTime() { m_timeOutTime = sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME); }
+ bool IsConnectionIdle() const { return (m_timeOutTime <= 0 && !m_inQueue); }
// Recruit-A-Friend Handling
uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; }
+ z_stream_s* GetCompressionStream() { return _compressionStream; }
+
public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used
@@ -386,9 +388,13 @@ class WorldSession
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
+ void HandleLoadScreenOpcode(WorldPacket& recvPacket);
void HandleCharEnum(PreparedQueryResult result);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
+ void HandleRandomizeCharNameOpcode(WorldPacket& recvData);
+ void HandleReorderCharacters(WorldPacket& recvData);
+ void HandleOpeningCinematic(WorldPacket& recvData);
// played time
void HandlePlayedTime(WorldPacket& recvPacket);
@@ -397,6 +403,7 @@ class WorldSession
void HandleMoveUnRootAck(WorldPacket& recvPacket);
void HandleMoveRootAck(WorldPacket& recvPacket);
void HandleLookingForGroup(WorldPacket& recvPacket);
+ void HandleReturnToGraveyard(WorldPacket& recvPacket);
// new inspect
void HandleInspectOpcode(WorldPacket& recvPacket);
@@ -423,6 +430,7 @@ class WorldSession
void HandleMoveTeleportAck(WorldPacket& recvPacket);
void HandleForceSpeedChangeAck(WorldPacket& recvData);
+ void HandleSetCollisionHeightAck(WorldPacket& recvPacket);
void HandlePingOpcode(WorldPacket& recvPacket);
void HandleAuthSessionOpcode(WorldPacket& recvPacket);
@@ -462,8 +470,6 @@ class WorldSession
void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
void HandleBugOpcode(WorldPacket& recvPacket);
- void HandleSetAmmoOpcode(WorldPacket& recvPacket);
- void HandleItemNameQueryOpcode(WorldPacket& recvPacket);
void HandleAreaTriggerOpcode(WorldPacket& recvPacket);
@@ -506,11 +512,11 @@ class WorldSession
void HandleGroupInviteOpcode(WorldPacket& recvPacket);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
- void HandleGroupAcceptOpcode(WorldPacket& recvPacket);
- void HandleGroupDeclineOpcode(WorldPacket& recvPacket);
+ void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket);
void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
+ void HandleGroupSetRolesOpcode(WorldPacket& recvData);
void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
void HandleOptOutOfLootOpcode(WorldPacket& recvData);
void HandleLootMethodOpcode(WorldPacket& recvPacket);
@@ -521,6 +527,7 @@ class WorldSession
void HandleRaidReadyCheckFinishedOpcode(WorldPacket& recvData);
void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
+ void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
void HandlePartyAssignmentOpcode(WorldPacket& recvData);
@@ -534,27 +541,41 @@ class WorldSession
void HandleTurnInPetitionOpcode(WorldPacket& recvData);
void HandleGuildQueryOpcode(WorldPacket& recvPacket);
- void HandleGuildCreateOpcode(WorldPacket& recvPacket);
void HandleGuildInviteOpcode(WorldPacket& recvPacket);
void HandleGuildRemoveOpcode(WorldPacket& recvPacket);
void HandleGuildAcceptOpcode(WorldPacket& recvPacket);
void HandleGuildDeclineOpcode(WorldPacket& recvPacket);
- void HandleGuildInfoOpcode(WorldPacket& recvPacket);
void HandleGuildEventLogQueryOpcode(WorldPacket& recvPacket);
void HandleGuildRosterOpcode(WorldPacket& recvPacket);
+ void HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket);
void HandleGuildPromoteOpcode(WorldPacket& recvPacket);
void HandleGuildDemoteOpcode(WorldPacket& recvPacket);
+ void HandleGuildAssignRankOpcode(WorldPacket& recvPacket);
void HandleGuildLeaveOpcode(WorldPacket& recvPacket);
void HandleGuildDisbandOpcode(WorldPacket& recvPacket);
- void HandleGuildLeaderOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetGuildMaster(WorldPacket& recvPacket);
void HandleGuildMOTDOpcode(WorldPacket& recvPacket);
- void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket);
- void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket);
- void HandleGuildRankOpcode(WorldPacket& recvPacket);
+ void HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetNoteOpcode(WorldPacket& recvPacket);
+ void HandleGuildQueryRanksOpcode(WorldPacket& recvPacket);
+ void HandleGuildQueryNewsOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket);
void HandleGuildAddRankOpcode(WorldPacket& recvPacket);
void HandleGuildDelRankOpcode(WorldPacket& recvPacket);
void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket);
void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket);
+ void HandleGuildRequestPartyState(WorldPacket& recvPacket);
+ void HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket);
+ void HandleAutoDeclineGuildInvites(WorldPacket& recvPacket);
+
+ void HandleGuildFinderAddRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderBrowse(WorldPacket& recvPacket);
+ void HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderGetApplications(WorldPacket& recvPacket);
+ void HandleGuildFinderGetRecruits(WorldPacket& recvPacket);
+ void HandleGuildFinderPostRequest(WorldPacket& recvPacket);
+ void HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderSetGuildPost(WorldPacket& recvPacket);
void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
@@ -583,6 +604,7 @@ class WorldSession
void HandleStableRevivePet(WorldPacket& recvPacket);
void HandleStableSwapPet(WorldPacket& recvPacket);
void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
+ void SendTrainerBuyFailed(uint64 guid, uint32 spellId, uint32 reason);
void HandleDuelAcceptedOpcode(WorldPacket& recvPacket);
void HandleDuelCancelledOpcode(WorldPacket& recvPacket);
@@ -624,7 +646,6 @@ class WorldSession
void HandleSwapInvItemOpcode(WorldPacket& recvPacket);
void HandleDestroyItemOpcode(WorldPacket& recvPacket);
void HandleAutoEquipItemOpcode(WorldPacket& recvPacket);
- void HandleItemQuerySingleOpcode(WorldPacket& recvPacket);
void HandleSellItemOpcode(WorldPacket& recvPacket);
void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket);
void HandleBuyItemOpcode(WorldPacket& recvPacket);
@@ -673,6 +694,7 @@ class WorldSession
void HandleQuestPushResult(WorldPacket& recvPacket);
void HandleMessagechatOpcode(WorldPacket& recvPacket);
+ void HandleAddonMessagechatOpcode(WorldPacket& recvPacket);
void SendPlayerNotFoundNotice(std::string const& name);
void SendPlayerAmbiguousNotice(std::string const& name);
void SendWrongFactionNotice();
@@ -680,6 +702,9 @@ class WorldSession
void HandleTextEmoteOpcode(WorldPacket& recvPacket);
void HandleChatIgnoredOpcode(WorldPacket& recvPacket);
+ void HandleUnregisterAddonPrefixesOpcode(WorldPacket& recvPacket);
+ void HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket);
+
void HandleReclaimCorpseOpcode(WorldPacket& recvPacket);
void HandleCorpseQueryOpcode(WorldPacket& recvPacket);
void HandleCorpseMapPositionQuery(WorldPacket& recvPacket);
@@ -710,7 +735,6 @@ class WorldSession
void HandleCompleteCinematic(WorldPacket& recvPacket);
void HandleNextCinematicCamera(WorldPacket& recvPacket);
- void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket);
void HandlePageTextQueryOpcode(WorldPacket& recvPacket);
void HandleTutorialFlag (WorldPacket& recvData);
@@ -720,7 +744,7 @@ class WorldSession
//Pet
void HandlePetAction(WorldPacket& recvData);
void HandlePetStopAttack(WorldPacket& recvData);
- void HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2);
+ void HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2, float x, float y, float z);
void HandlePetNameQuery(WorldPacket& recvData);
void HandlePetSetAction(WorldPacket& recvData);
void HandlePetAbandon(WorldPacket& recvData);
@@ -750,6 +774,10 @@ class WorldSession
void HandleBattlefieldLeaveOpcode(WorldPacket& recvData);
void HandleBattlemasterJoinArena(WorldPacket& recvData);
void HandleReportPvPAFK(WorldPacket& recvData);
+ void HandleRequestRatedBgInfo(WorldPacket& recvData);
+ void HandleRequestPvpOptions(WorldPacket& recvData);
+ void HandleRequestPvpReward(WorldPacket& recvData);
+ void HandleRequestRatedBgStats(WorldPacket& recvData);
void HandleWardenDataOpcode(WorldPacket& recvData);
void HandleWorldTeleportOpcode(WorldPacket& recvData);
@@ -768,11 +796,11 @@ class WorldSession
void HandleInstanceLockResponse(WorldPacket& recvPacket);
// Battlefield
- void SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 time);
- void SendBfInvitePlayerToQueue(uint32 battleId);
- void SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue = true, bool full = false);
- void SendBfEntered(uint32 battleId);
- void SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason = BF_LEAVE_REASON_EXITED);
+ void SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 time);
+ void SendBfInvitePlayerToQueue(uint64 guid);
+ void SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue = true, bool full = false);
+ void SendBfEntered(uint64 guid);
+ void SendBfLeaveMessage(uint64 guid, BFLeaveReason reason = BF_LEAVE_REASON_EXITED);
void HandleBfQueueInviteResponse(WorldPacket& recvData);
void HandleBfEntryInviteResponse(WorldPacket& recvData);
void HandleBfExitRequest(WorldPacket& recvData);
@@ -809,6 +837,7 @@ class WorldSession
void HandleInspectArenaTeamsOpcode(WorldPacket& recvData);
void HandleArenaTeamQueryOpcode(WorldPacket& recvData);
void HandleArenaTeamRosterOpcode(WorldPacket& recvData);
+ void HandleArenaTeamCreateOpcode(WorldPacket& recvData);
void HandleArenaTeamInviteOpcode(WorldPacket& recvData);
void HandleArenaTeamAcceptOpcode(WorldPacket& recvData);
void HandleArenaTeamDeclineOpcode(WorldPacket& recvData);
@@ -851,6 +880,7 @@ class WorldSession
void HandleGuildBankBuyTab(WorldPacket& recvData);
void HandleQueryGuildBankTabText(WorldPacket& recvData);
void HandleSetGuildBankTabText(WorldPacket& recvData);
+ void HandleGuildQueryXPOpcode(WorldPacket& recvData);
// Refer-a-Friend
void HandleGrantLevel(WorldPacket& recvData);
@@ -878,12 +908,28 @@ class WorldSession
void SendCalendarRaidLockoutUpdated(InstanceSave const* save);
void HandleSetSavedInstanceExtend(WorldPacket& recvData);
+ // Void Storage
+ void HandleVoidStorageUnlock(WorldPacket& recvData);
+ void HandleVoidStorageQuery(WorldPacket& recvData);
+ void HandleVoidStorageTransfer(WorldPacket& recvData);
+ void HandleVoidSwapItem(WorldPacket& recvData);
+ void SendVoidStorageTransferResult(VoidTransferError result);
+
+ // Transmogrification
+ void HandleTransmogrifyItems(WorldPacket& recvData);
+
+ // Reforge
+ void HandleReforgeItemOpcode(WorldPacket& recvData);
+ void SendReforgeResult(bool success);
+
+ // Miscellaneous
void HandleSpellClick(WorldPacket& recvData);
void HandleMirrorImageDataRequest(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleRemoveGlyph(WorldPacket& recvData);
void HandleCharCustomize(WorldPacket& recvData);
void HandleQueryInspectAchievements(WorldPacket& recvData);
+ void HandleGuildAchievementProgressQuery(WorldPacket& recvData);
void HandleEquipmentSetSave(WorldPacket& recvData);
void HandleEquipmentSetDelete(WorldPacket& recvData);
void HandleEquipmentSetUse(WorldPacket& recvData);
@@ -894,7 +940,16 @@ class WorldSession
void HandleEjectPassenger(WorldPacket& data);
void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
+ void HandleRequestHotfix(WorldPacket& recvPacket);
void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
+ void HandleViolenceLevel(WorldPacket& recvPacket);
+ void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket);
+ void HandleRequestCategoryCooldowns(WorldPacket& recvPacket);
+ int32 HandleEnableNagleAlgorithm();
+
+ // Compact Unit Frames (4.x)
+ void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void SendLoadCUFProfiles();
private:
void InitializeQueryCallbackParameters();
@@ -956,10 +1011,13 @@ class WorldSession
uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
bool m_TutorialsChanged;
AddonsList m_addonsList;
+ std::vector<std::string> _registeredAddonPrefixes;
+ bool _filterAddonMessages;
uint32 recruiterId;
bool isRecruiter;
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
time_t timeLastWhoCommand;
+ z_stream_s* _compressionStream;
RBACData* _RBACData;
};
#endif
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 08da34b9ace..2b5c22c1b14 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -165,6 +165,13 @@ int WorldSocket::SendPacket(WorldPacket const& pct)
WorldPacket const* pkt = &pct;
+ // Empty buffer used in case packet should be compressed
+ WorldPacket buff;
+ if (m_Session && pkt->size() > 0x400)
+ {
+ buff.Compress(m_Session->GetCompressionStream(), pkt);
+ pkt = &buff;
+ }
if (m_Session)
TC_LOG_TRACE(LOG_FILTER_OPCODES, "S->C: %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pkt->GetOpcode()).c_str());
@@ -247,7 +254,12 @@ int WorldSocket::open (void *a)
m_Address = remote_addr.get_host_addr();
- if (HandleSendAuthSession() == -1)
+ // not an opcode. this packet sends raw string WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT"
+ // because of our implementation, bytes "WO" become the opcode
+ WorldPacket packet(MSG_VERIFY_CONNECTIVITY);
+ packet << "RLD OF WARCRAFT CONNECTION - SERVER TO CLIENT";
+
+ if (SendPacket(packet) == -1)
return -1;
// Register with ACE Reactor
@@ -469,7 +481,7 @@ int WorldSocket::handle_input_header (void)
EndianConvertReverse(header.size);
EndianConvert(header.cmd);
- if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240))
+ if ((header.size < 4) || (header.size > 10240) || (header.cmd > 0xFFFF && (header.cmd >> 16) != 0x4C52)) // LR (from MSG_VERIFY_CONNECTIVITY)
{
Player* _player = m_Session ? m_Session->GetPlayer() : NULL;
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WorldSocket::handle_input_header(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %d, cmd: %d)",
@@ -484,7 +496,7 @@ int WorldSocket::handle_input_header (void)
header.size -= 4;
- ACE_NEW_RETURN(m_RecvWPct, WorldPacket ((uint16)header.cmd, header.size), -1);
+ ACE_NEW_RETURN(m_RecvWPct, WorldPacket (PacketFilter::DropHighBytes(Opcodes(header.cmd)), header.size), -1);
if (header.size > 0)
{
@@ -657,7 +669,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
// manage memory ;)
ACE_Auto_Ptr<WorldPacket> aptr(new_pct);
- const ACE_UINT16 opcode = new_pct->GetOpcode();
+ Opcodes opcode = PacketFilter::DropHighBytes(new_pct->GetOpcode());
if (closing_)
return -1;
@@ -689,6 +701,29 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
return 0;
+ case CMSG_LOG_DISCONNECT:
+ new_pct->rfinish(); // contains uint32 disconnectReason;
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
+ return 0;
+ // not an opcode, client sends string "WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER" without opcode
+ // first 4 bytes become the opcode (2 dropped)
+ case MSG_VERIFY_CONNECTIVITY:
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
+ std::string str;
+ *new_pct >> str;
+ if (str != "D OF WARCRAFT CONNECTION - CLIENT TO SERVER")
+ return -1;
+ return HandleSendAuthSession();
+ }
+ case CMSG_ENABLE_NAGLE:
+ {
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
+ return m_Session ? m_Session->HandleEnableNagleAlgorithm() : -1;
+ }
default:
{
ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1);
@@ -698,6 +733,17 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
return -1;
}
+ // prevent invalid memory access/crash with custom opcodes
+ if (opcode >= NUM_OPCODE_HANDLERS)
+ return 0;
+
+ OpcodeHandler const* handler = opcodeTable[opcode];
+ if (!handler || handler->Status == STATUS_UNHANDLED)
+ {
+ TC_LOG_ERROR(LOG_FILTER_OPCODES, "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(new_pct->GetOpcode()).c_str(), m_Session->GetPlayerInfo().c_str());
+ return 0;
+ }
+
// Our Idle timer will reset on any non PING opcodes.
// Catches people idling on the login screen and any lingering ingame connections.
m_Session->ResetTimeOutTime();
@@ -725,9 +771,6 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
int WorldSocket::HandleSendAuthSession()
{
WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
- packet << uint32(1); // 1...31
- packet << uint32(m_Seed);
-
BigNumber seed1;
seed1.SetRand(16 * 8);
packet.append(seed1.AsByteArray(16), 16); // new encryption seeds
@@ -735,6 +778,9 @@ int WorldSocket::HandleSendAuthSession()
BigNumber seed2;
seed2.SetRand(16 * 8);
packet.append(seed2.AsByteArray(16), 16); // new encryption seeds
+
+ packet << m_Seed;
+ packet << uint8(1);
return SendPacket(packet);
}
@@ -743,15 +789,52 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint8 digest[20];
uint32 clientSeed;
uint8 security;
+ uint16 clientBuild;
uint32 id;
+ uint32 addonSize;
LocaleConstant locale;
std::string account;
SHA1Hash sha;
- uint32 clientBuild;
- uint32 unk2, unk3, unk5, unk6, unk7;
- uint64 unk4;
- WorldPacket packet, SendAddonPacked;
BigNumber k;
+ WorldPacket addonsData;
+
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint8>();
+ recvPacket >> digest[10];
+ recvPacket >> digest[18];
+ recvPacket >> digest[12];
+ recvPacket >> digest[5];
+ recvPacket.read_skip<uint64>();
+ recvPacket >> digest[15];
+ recvPacket >> digest[9];
+ recvPacket >> digest[19];
+ recvPacket >> digest[4];
+ recvPacket >> digest[7];
+ recvPacket >> digest[16];
+ recvPacket >> digest[3];
+ recvPacket >> clientBuild;
+ recvPacket >> digest[8];
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint8>();
+ recvPacket >> digest[17];
+ recvPacket >> digest[6];
+ recvPacket >> digest[0];
+ recvPacket >> digest[1];
+ recvPacket >> digest[11];
+ recvPacket >> clientSeed;
+ recvPacket >> digest[2];
+ recvPacket.read_skip<uint32>();
+ recvPacket >> digest[14];
+ recvPacket >> digest[13];
+
+ recvPacket >> addonSize;
+ addonsData.resize(addonSize);
+ recvPacket.read((uint8*)addonsData.contents(), addonSize);
+
+ recvPacket.ReadBit();
+ uint32 accountNameLength = recvPacket.ReadBits(12);
+ account = recvPacket.ReadString(accountNameLength);
if (sWorld->IsClosed())
{
@@ -760,23 +843,6 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return -1;
}
- // Read the content of the packet
- recvPacket >> clientBuild;
- recvPacket >> unk2;
- recvPacket >> account;
- recvPacket >> unk3;
- recvPacket >> clientSeed;
- recvPacket >> unk5 >> unk6 >> unk7;
- recvPacket >> unk4;
- recvPacket.read(digest, 20);
-
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
- clientBuild,
- unk2,
- account.c_str(),
- unk3,
- clientSeed);
-
// Get the account information from the realmd database
// 0 1 2 3 4 5 6 7 8
// SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
@@ -937,7 +1003,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
m_Session->LoadGlobalAccountData();
m_Session->LoadTutorialsData();
- m_Session->ReadAddonsInfo(recvPacket);
+ m_Session->ReadAddonsInfo(addonsData);
m_Session->LoadPermissions();
// Initialize Warden system only if it is enabled by config
@@ -958,8 +1024,8 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
uint32 latency;
// Get the ping packet content
- recvPacket >> ping;
recvPacket >> latency;
+ recvPacket >> ping;
if (m_LastPingTime == ACE_Time_Value::zero)
m_LastPingTime = ACE_OS::gettimeofday(); // for 1st ping
@@ -1017,6 +1083,8 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
void WorldSocket::SendAuthResponseError(uint8 code)
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet.WriteBit(0); // has queue info
+ packet.WriteBit(0); // has account info
packet << uint8(code);
SendPacket(packet);
}
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 2d5762ef60e..9ad27694867 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -161,6 +161,7 @@ class WorldSocket : public WorldHandler
/// Called by ProcessIncoming() on CMSG_PING.
int HandlePing(WorldPacket& recvPacket);
+ /// Called by CMSG_VERIFY_CONNECTIVITY_RESPONSE
int HandleSendAuthSession();
private:
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 3969dfbab98..64290d0c883 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -200,7 +200,7 @@ enum AuraType
SPELL_AURA_MOD_MELEE_HASTE = 138,
SPELL_AURA_FORCE_REACTION = 139,
SPELL_AURA_MOD_RANGED_HASTE = 140,
- SPELL_AURA_MOD_RANGED_AMMO_HASTE = 141,
+ SPELL_AURA_141 = 141, // old SPELL_AURA_MOD_RANGED_AMMO_HASTE, unused now
SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142,
SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143,
SPELL_AURA_SAFE_FALL = 144,
@@ -212,14 +212,14 @@ enum AuraType
SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150,
SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed
SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range
- SPELL_AURA_SPLIT_DAMAGE_FLAT = 153, // Split Damage Flat
+ SPELL_AURA_153 = 153, // old SPELL_AURA_SPLIT_DAMAGE_FLAT. unused 4.3.4
SPELL_AURA_MOD_STEALTH_LEVEL = 154, // Stealth Level Modifier
SPELL_AURA_MOD_WATER_BREATHING = 155, // Mod Water Breathing
SPELL_AURA_MOD_REPUTATION_GAIN = 156, // Mod Reputation Gain
SPELL_AURA_PET_DAMAGE_MULTI = 157, // Mod Pet Damage
SPELL_AURA_MOD_SHIELD_BLOCKVALUE = 158,
SPELL_AURA_NO_PVP_CREDIT = 159,
- SPELL_AURA_MOD_AOE_AVOIDANCE = 160,
+ SPELL_AURA_160 = 160, // old SPELL_AURA_MOD_AOE_AVOIDANCE. Unused 4.3.4
SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161,
SPELL_AURA_POWER_BURN = 162,
SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163,
@@ -228,7 +228,7 @@ enum AuraType
SPELL_AURA_MOD_ATTACK_POWER_PCT = 166,
SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167,
SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168,
- SPELL_AURA_MOD_CRIT_PERCENT_VERSUS = 169,
+ SPELL_AURA_169 = 169, // old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS. unused 4.3.4
SPELL_AURA_DETECT_AMORE = 170,
SPELL_AURA_MOD_SPEED_NOT_STACK = 171,
SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172,
@@ -237,7 +237,7 @@ enum AuraType
SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT = 175,
SPELL_AURA_SPIRIT_OF_REDEMPTION = 176,
SPELL_AURA_AOE_CHARM = 177,
- SPELL_AURA_MOD_DEBUFF_RESISTANCE = 178,
+ SPELL_AURA_178 = 178, // old SPELL_AURA_MOD_DEBUFF_RESISTANCE, unused
SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179,
SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS = 180,
SPELL_AURA_181 = 181, // old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS - possible flat spell crit damage versus
@@ -258,7 +258,7 @@ enum AuraType
SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath
SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197,
SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
- SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT = 199,
+ SPELL_AURA_199 = 199, // old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT. unused 4.3.4
SPELL_AURA_MOD_XP_PCT = 200,
SPELL_AURA_FLY = 201,
SPELL_AURA_IGNORE_COMBAT_RESULT = 202,
@@ -271,12 +271,12 @@ enum AuraType
SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS = 209,
SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS = 210,
SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK = 211,
- SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT = 212,
+ SPELL_AURA_212 = 212, // old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT. unused 4.3.4
SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT = 213,
SPELL_AURA_214 = 214,
SPELL_AURA_ARENA_PREPARATION = 215,
SPELL_AURA_HASTE_SPELLS = 216,
- SPELL_AURA_MOD_MELEE_HASTE_2 = 217, // NYI
+ SPELL_AURA_MOD_MELEE_HASTE_2 = 217,
SPELL_AURA_HASTE_RANGED = 218,
SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219,
SPELL_AURA_MOD_RATING_FROM_STAT = 220,
@@ -289,7 +289,7 @@ enum AuraType
SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227,
SPELL_AURA_DETECT_STEALTH = 228,
SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229,
- SPELL_AURA_230 = 230,
+ SPELL_AURA_MOD_MAX_HEALTH = 230,
SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231,
SPELL_AURA_MECHANIC_DURATION_MOD = 232,
SPELL_AURA_CHANGE_MODEL_FOR_ALL_HUMANOIDS = 233, // client-side only
@@ -318,7 +318,7 @@ enum AuraType
SPELL_AURA_NO_REAGENT_USE = 256,
SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257,
SPELL_AURA_258 = 258,
- SPELL_AURA_MOD_HOT_PCT = 259,
+ SPELL_AURA_259 = 259, // old SPELL_AURA_MOD_HOT_PCT, unused 4.3.4
SPELL_AURA_SCREEN_EFFECT = 260,
SPELL_AURA_PHASE = 261,
SPELL_AURA_ABILITY_IGNORE_AURASTATE = 262,
@@ -327,19 +327,19 @@ enum AuraType
SPELL_AURA_265 = 265,
SPELL_AURA_266 = 266,
SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267,
- SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268,
+ SPELL_AURA_268 = 268, // old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT. unused 4.3.4
SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269,
- SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
+ SPELL_AURA_270 = 270, // old SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST, unused 4.3.4
SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
SPELL_AURA_IGNORE_MELEE_RESET = 272,
SPELL_AURA_X_RAY = 273,
- SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274,
+ SPELL_AURA_274 = 274, // old SPELL_AURA_ABILITY_CONSUME_NO_AMMO, unused 4.3.4
SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
- SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC = 276, // NYI
- SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
+ SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC = 276,
+ SPELL_AURA_277 = 277, // old SPELL_AURA_MOD_MAX_AFFECTED_TARGETS. unused 4.3.4
SPELL_AURA_MOD_DISARM_RANGED = 278,
SPELL_AURA_INITIALIZE_IMAGES = 279,
- SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280,
+ SPELL_AURA_280 = 280, // old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT unused 4.3.4
SPELL_AURA_MOD_HONOR_GAIN_PCT = 281,
SPELL_AURA_MOD_BASE_HEALTH_PCT = 282,
SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells
@@ -367,16 +367,70 @@ enum AuraType
SPELL_AURA_MOD_MINIMUM_SPEED = 305,
SPELL_AURA_306 = 306,
SPELL_AURA_HEAL_ABSORB_TEST = 307,
- SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 308, // NYI
- SPELL_AURA_309 = 309,
+ SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 308,
+ SPELL_AURA_309 = 309, // Not used in 4.3.4
SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE = 310,
SPELL_AURA_311 = 311,
- SPELL_AURA_312 = 312,
- SPELL_AURA_313 = 313,
+ SPELL_AURA_ANIM_REPLACEMENT_SET = 312,
+ SPELL_AURA_313 = 313, // Not used in 4.3.4 - related to mounts
SPELL_AURA_PREVENT_RESURRECTION = 314,
SPELL_AURA_UNDERWATER_WALKING = 315,
- SPELL_AURA_PERIODIC_HASTE = 316,
- TOTAL_AURAS = 317
+ SPELL_AURA_PERIODIC_HASTE = 316, // Not used in 4.3.4 (name from 3.3.5a)
+ SPELL_AURA_MOD_SPELL_POWER_PCT = 317,
+ SPELL_AURA_MASTERY = 318,
+ SPELL_AURA_MOD_MELEE_HASTE_3 = 319,
+ SPELL_AURA_MOD_RANGED_HASTE_2 = 320,
+ SPELL_AURA_321 = 321,
+ SPELL_AURA_INTERFERE_TARGETTING = 322, // NYI
+ SPELL_AURA_323 = 323, // Not used in 4.3.4
+ SPELL_AURA_324 = 324, // spell critical chance (probably by school mask)
+ SPELL_AURA_325 = 325, // Not used in 4.3.4
+ SPELL_AURA_326 = 326, // phase related
+ SPELL_AURA_327 = 327, // Not used in 4.3.4
+ SPELL_AURA_PROC_ON_POWER_AMOUNT = 328,
+ SPELL_AURA_MOD_RUNE_REGEN_SPEED = 329, // NYI
+ SPELL_AURA_CAST_WHILE_WALKING = 330,
+ SPELL_AURA_FORCE_WEATHER = 331,
+ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS = 332,
+ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 = 333,
+ SPELL_AURA_MOD_BLIND = 334, // NYI
+ SPELL_AURA_335 = 335,
+ SPELL_AURA_MOD_FLYING_RESTRICTIONS = 336, // NYI
+ SPELL_AURA_MOD_VENDOR_ITEMS_PRICES = 337,
+ SPELL_AURA_MOD_DURABILITY_LOSS = 338,
+ SPELL_AURA_INCREASE_SKILL_GAIN_CHANCE = 339, // NYI
+ SPELL_AURA_MOD_RESURRECTED_HEALTH_BY_GUILD_MEMBER = 340, // Increases health gained when resurrected by a guild member by X
+ SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN = 341, // Modifies cooldown of all spells using affected category
+ SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 = 342,
+ SPELL_AURA_343 = 343,
+ SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, // NYI
+ SPELL_AURA_BYPASS_ARMOR_FOR_CASTER = 345,
+ SPELL_AURA_ENABLE_ALT_POWER = 346, // NYI
+ SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE = 347, // NYI
+ SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT = 348, // NYI
+ SPELL_AURA_MOD_CURRENCY_GAIN = 349,
+ SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT = 350, // NYI
+ SPELL_AURA_351 = 351,
+ SPELL_AURA_352 = 352,
+ SPELL_AURA_MOD_CAMOUFLAGE = 353, // NYI
+ SPELL_AURA_354 = 354, // Restoration Shaman mastery - mod healing based on target's health (less = more healing)
+ SPELL_AURA_355 = 355,
+ SPELL_AURA_356 = 356, // Arcane Mage mastery - mod damage based on current mana
+ SPELL_AURA_ENABLE_BOSS1_UNIT_FRAME = 357,
+ SPELL_AURA_WORGEN_ALTERED_FORM = 358,
+ SPELL_AURA_359 = 359,
+ SPELL_AURA_PROC_TRIGGER_SPELL_COPY = 360, // Procs the same spell that caused this proc (Dragonwrath, Tarecgosa's Rest)
+ SPELL_AURA_PROC_TRIGGER_SPELL_2 = 361,
+ SPELL_AURA_362 = 362, // Not used in 4.3.4
+ SPELL_AURA_MOD_NEXT_SPELL = 363, // Used by 101601 Throw Totem - causes the client to initialize spell cast with specified spell
+ SPELL_AURA_364 = 364, // Not used in 4.3.4
+ SPELL_AURA_MAX_FAR_CLIP_PLANE = 365, // Overrides client's View Distance setting to max("Fair", current_setting) and turns off terrain display
+ SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT = 366, // NYI - Sets spellpower equal to % of attack power, discarding all other bonuses (from gear and buffs)
+ SPELL_AURA_367 = 367,
+ SPELL_AURA_368 = 368, // Not used in 4.3.4
+ SPELL_AURA_ENABLE_POWER_BAR_TIMER = 369,
+ SPELL_AURA_SET_FAIR_FAR_CLIP = 370, // Overrides client's View Distance setting to max("Fair", current_setting)
+ TOTAL_AURAS = 371 // 4.3.4
};
enum AuraObjectType
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6deea0da7fd..6b2e67df095 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -38,6 +38,7 @@
#include "Vehicle.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "WeatherMgr.h"
#include "Pet.h"
#include "ReputationMgr.h"
@@ -120,7 +121,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&AuraEffect::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
&AuraEffect::HandleNoImmediateEffect, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL implemented in AuraEffect::PeriodicTick
- &AuraEffect::HandleUnused, // 63 unused (3.2.0) old SPELL_AURA_PERIODIC_MANA_FUNNEL
+ &AuraEffect::HandleUnused, // 63 unused (4.3.4) old SPELL_AURA_PERIODIC_MANA_FUNNEL
&AuraEffect::HandleNoImmediateEffect, // 64 SPELL_AURA_PERIODIC_MANA_LEECH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
&AuraEffect::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
@@ -147,7 +148,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth
&AuraEffect::HandleNoImmediateEffect, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
- &AuraEffect::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE
+ &AuraEffect::HandleUnused, // 90 unused (4.3.4) old SPELL_AURA_MOD_RESIST_CHANCE
&AuraEffect::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
&AuraEffect::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
@@ -176,7 +177,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
&AuraEffect::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
- &AuraEffect::HandleUnused, //119 unused (3.2.0) old SPELL_AURA_SHARE_PET_TRACKING
+ &AuraEffect::HandleUnused, //119 unused (4.3.4) old SPELL_AURA_SHARE_PET_TRACKING
&AuraEffect::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
&AuraEffect::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
&AuraEffect::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
@@ -198,7 +199,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleModMeleeSpeedPct, //138 SPELL_AURA_MOD_MELEE_HASTE
&AuraEffect::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
&AuraEffect::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
- &AuraEffect::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
+ &AuraEffect::HandleUnused, //141 SPELL_AURA_141
&AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
@@ -210,14 +211,14 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
- &AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
+ &AuraEffect::HandleUnused, //153 Unused (4.3.4) old SPELL_AURA_SPLIT_DAMAGE_FLAT
&AuraEffect::HandleModStealthLevel, //154 SPELL_AURA_MOD_STEALTH_LEVEL
&AuraEffect::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
&AuraEffect::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
&AuraEffect::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
&AuraEffect::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
&AuraEffect::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
- &AuraEffect::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //160 Unused (4.3.4) old SPELL_AURA_MOD_AOE_AVOIDANCE
&AuraEffect::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
&AuraEffect::HandleNoImmediateEffect, //162 SPELL_AURA_POWER_BURN implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
@@ -226,19 +227,19 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
&AuraEffect::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
&AuraEffect::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
- &AuraEffect::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
+ &AuraEffect::HandleUnused, //169 Unused (4.3.4) old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
&AuraEffect::HandleNULL, //170 SPELL_AURA_DETECT_AMORE various spells that change visual of units for aura target (clientside?)
&AuraEffect::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
&AuraEffect::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
- &AuraEffect::HandleUnused, //173 unused (3.2.0) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
+ &AuraEffect::HandleUnused, //173 unused (4.3.4) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
&AuraEffect::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
&AuraEffect::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
&AuraEffect::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
&AuraEffect::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM
- &AuraEffect::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //178 old SPELL_AURA_MOD_DEBUFF_RESISTANCE unused 4.3.4
&AuraEffect::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
&AuraEffect::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
- &AuraEffect::HandleUnused, //181 unused (3.2.0) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
+ &AuraEffect::HandleUnused, //181 unused (4.3.4) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
&AuraEffect::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
&AuraEffect::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school
&AuraEffect::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
@@ -255,8 +256,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns
&AuraEffect::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
- &AuraEffect::HandleUnused, //198 unused (3.2.0) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
- &AuraEffect::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //198 unused (4.3.4) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
+ &AuraEffect::HandleUnused, //199 unused (4.3.4) old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT
&AuraEffect::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill
&AuraEffect::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
&AuraEffect::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
@@ -269,19 +270,19 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
- &AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
+ &AuraEffect::HandleUnused, //212 Unused (4.3.4) old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
&AuraEffect::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
&AuraEffect::HandleNULL, //214 Tamed Pet Passive
&AuraEffect::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
&AuraEffect::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
- &AuraEffect::HandleNULL, //217 69106 - killing spree helper - unknown use
+ &AuraEffect::HandleModMeleeSpeedPct, //217 SPELL_AURA_MOD_MELEE_HASTE_2
&AuraEffect::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&AuraEffect::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
&AuraEffect::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&AuraEffect::HandleNULL, //221 SPELL_AURA_MOD_DETAUNT
&AuraEffect::HandleUnused, //222 unused (3.2.0) only for spell 44586 that not used in real spell cast
&AuraEffect::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE
- &AuraEffect::HandleUnused, //224 unused (3.0.8a)
+ &AuraEffect::HandleUnused, //224 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
&AuraEffect::HandleNoImmediateEffect, //226 SPELL_AURA_PERIODIC_DUMMY implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE implemented in AuraEffect::PeriodicTick
@@ -316,28 +317,28 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
- &AuraEffect::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus
+ &AuraEffect::HandleUnused, //259 unused (4.3.4) old SPELL_AURA_MOD_HOT_PCT
&AuraEffect::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
&AuraEffect::HandlePhase, //261 SPELL_AURA_PHASE
&AuraEffect::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast
&AuraEffect::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
&AuraEffect::HandleUnused, //264 unused (3.2.0)
- &AuraEffect::HandleUnused, //265 unused (3.2.0)
- &AuraEffect::HandleUnused, //266 unused (3.2.0)
+ &AuraEffect::HandleUnused, //265 unused (4.3.4)
+ &AuraEffect::HandleUnused, //266 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
- &AuraEffect::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
+ &AuraEffect::HandleUnused, //268 unused (4.3.4) old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT.
&AuraEffect::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
- &AuraEffect::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
+ &AuraEffect::HandleUnused, //270 unused (4.3.4) old SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST
&AuraEffect::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, //272 SPELL_AURA_IGNORE_MELEE_RESET
&AuraEffect::HandleUnused, //273 clientside
- &AuraEffect::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets
+ &AuraEffect::HandleUnused, //274 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //276 mod damage % mechanic?
- &AuraEffect::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
+ &AuraEffect::HandleUnused, //277 unused (4.3.4) old SPELL_AURA_MOD_MAX_AFFECTED_TARGETS
&AuraEffect::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
- &AuraEffect::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
+ &AuraEffect::HandleUnused, //280 unused (4.3.4) old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
&AuraEffect::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
&AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
@@ -352,28 +353,82 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE
&AuraEffect::HandleAuraOverrideSpells, //293 auras which probably add set of abilities to their target based on it's miscvalue
&AuraEffect::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
- &AuraEffect::HandleUnused, //295 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //295 unused (4.3.4)
&AuraEffect::HandleAuraSetVehicle, //296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target
&AuraEffect::HandleNULL, //297 Spirit Burst spells
&AuraEffect::HandleNULL, //298 70569 - Strangulating, maybe prevents talk or cast
- &AuraEffect::HandleUnused, //299 unused
+ &AuraEffect::HandleUnused, //299 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //300 SPELL_AURA_SHARE_DAMAGE_PCT implemented in Unit::DealDamage
&AuraEffect::HandleNoImmediateEffect, //301 SPELL_AURA_SCHOOL_HEAL_ABSORB implemented in Unit::CalcHealAbsorb
- &AuraEffect::HandleUnused, //302 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //302 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //303 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModFakeInebriation, //304 SPELL_AURA_MOD_DRUNK
&AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
- &AuraEffect::HandleUnused, //306 0 spells in 3.3.5
- &AuraEffect::HandleUnused, //307 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //306 unused (4.3.4)
+ &AuraEffect::HandleUnused, //307 unused (4.3.4)
&AuraEffect::HandleNULL, //308 new aura for hunter traps
- &AuraEffect::HandleUnused, //309 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //309 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //310 SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE implemented in Spell::CalculateDamageDone
&AuraEffect::HandleNULL, //311 0 spells in 3.3.5
&AuraEffect::HandleNULL, //312 0 spells in 3.3.5
- &AuraEffect::HandleUnused, //313 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //313 unused (4.3.4)
&AuraEffect::HandlePreventResurrection, //314 SPELL_AURA_PREVENT_RESURRECTION todo
&AuraEffect::HandleNoImmediateEffect, //315 SPELL_AURA_UNDERWATER_WALKING todo
- &AuraEffect::HandleNoImmediateEffect, //316 SPELL_AURA_PERIODIC_HASTE implemented in AuraEffect::CalculatePeriodic
+ &AuraEffect::HandleNoImmediateEffect, //316 unused (4.3.4) old SPELL_AURA_PERIODIC_HASTE
+ &AuraEffect::HandleNULL, //317 SPELL_AURA_MOD_SPELL_POWER_PCT
+ &AuraEffect::HandleMastery, //318 SPELL_AURA_MASTERY
+ &AuraEffect::HandleModMeleeSpeedPct, //319 SPELL_AURA_MOD_MELEE_HASTE_3
+ &AuraEffect::HandleAuraModRangedHaste, //320 SPELL_AURA_MOD_RANGED_HASTE_2
+ &AuraEffect::HandleNULL, //321 SPELL_AURA_321
+ &AuraEffect::HandleNULL, //322 SPELL_AURA_INTERFERE_TARGETTING
+ &AuraEffect::HandleUnused, //323 unused (4.3.4)
+ &AuraEffect::HandleNULL, //324 SPELL_AURA_324
+ &AuraEffect::HandleUnused, //325 unused (4.3.4)
+ &AuraEffect::HandleNULL, //326 SPELL_AURA_326
+ &AuraEffect::HandleUnused, //327 unused (4.3.4)
+ &AuraEffect::HandleNoImmediateEffect, //328 SPELL_AURA_PROC_ON_POWER_AMOUNT implemented in Unit::HandleAuraProcOnPowerAmount
+ &AuraEffect::HandleNULL, //329 SPELL_AURA_MOD_RUNE_REGEN_SPEED
+ &AuraEffect::HandleNoImmediateEffect, //330 SPELL_AURA_CAST_WHILE_WALKING
+ &AuraEffect::HandleAuraForceWeather, //331 SPELL_AURA_FORCE_WEATHER
+ &AuraEffect::HandleNoImmediateEffect, //332 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS implemented in WorldSession::HandleCastSpellOpcode
+ &AuraEffect::HandleNoImmediateEffect, //333 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 implemented in WorldSession::HandleCastSpellOpcode
+ &AuraEffect::HandleNULL, //334 SPELL_AURA_MOD_BLIND
+ &AuraEffect::HandleNULL, //335 SPELL_AURA_335
+ &AuraEffect::HandleNULL, //336 SPELL_AURA_MOD_FLYING_RESTRICTIONS
+ &AuraEffect::HandleNoImmediateEffect, //337 SPELL_AURA_MOD_VENDOR_ITEMS_PRICES
+ &AuraEffect::HandleNoImmediateEffect, //338 SPELL_AURA_MOD_DURABILITY_LOSS
+ &AuraEffect::HandleNULL, //339 SPELL_AURA_INCREASE_SKILL_GAIN_CHANCE
+ &AuraEffect::HandleNULL, //340 SPELL_AURA_MOD_RESURRECTED_HEALTH_BY_GUILD_MEMBER
+ &AuraEffect::HandleNULL, //341 SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN
+ &AuraEffect::HandleModMeleeRangedSpeedPct, //342 SPELL_AURA_MOD_MELEE_RANGED_HASTE_2
+ &AuraEffect::HandleNULL, //343 SPELL_AURA_343
+ &AuraEffect::HandleNULL, //344 SPELL_AURA_MOD_AUTOATTACK_DAMAGE
+ &AuraEffect::HandleNoImmediateEffect, //345 SPELL_AURA_BYPASS_ARMOR_FOR_CASTER
+ &AuraEffect::HandleEnableAltPower, //346 SPELL_AURA_ENABLE_ALT_POWER
+ &AuraEffect::HandleNULL, //347 SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE
+ &AuraEffect::HandleNoImmediateEffect, //348 SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT implemented in WorldSession::HandleLootMoneyOpcode
+ &AuraEffect::HandleNoImmediateEffect, //349 SPELL_AURA_MOD_CURRENCY_GAIN implemented in Player::ModifyCurrency
+ &AuraEffect::HandleNULL, //350 SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT
+ &AuraEffect::HandleNULL, //351 SPELL_AURA_351
+ &AuraEffect::HandleNULL, //352 SPELL_AURA_352
+ &AuraEffect::HandleNULL, //353 SPELL_AURA_MOD_CAMOUFLAGE
+ &AuraEffect::HandleNULL, //354 SPELL_AURA_354
+ &AuraEffect::HandleUnused, //355 unused (4.3.4)
+ &AuraEffect::HandleNULL, //356 SPELL_AURA_356
+ &AuraEffect::HandleNULL, //357 SPELL_AURA_ENABLE_BOSS1_UNIT_FRAME
+ &AuraEffect::HandleNULL, //358 SPELL_AURA_358
+ &AuraEffect::HandleNULL, //359 SPELL_AURA_359
+ &AuraEffect::HandleNULL, //360 SPELL_AURA_PROC_TRIGGER_SPELL_COPY
+ &AuraEffect::HandleNULL, //361 SPELL_AURA_PROC_TRIGGER_SPELL_2 implemented in Unit::ProcDamageAndSpellFor
+ &AuraEffect::HandleUnused, //362 unused (4.3.4)
+ &AuraEffect::HandleNULL, //363 SPELL_AURA_MOD_NEXT_SPELL
+ &AuraEffect::HandleUnused, //364 unused (4.3.4)
+ &AuraEffect::HandleNULL, //365 SPELL_AURA_MAX_FAR_CLIP_PLANE
+ &AuraEffect::HandleNULL, //366 SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT
+ &AuraEffect::HandleNULL, //367 SPELL_AURA_367
+ &AuraEffect::HandleUnused, //368 unused (4.3.4)
+ &AuraEffect::HandleNULL, //369 SPELL_AURA_ENABLE_POWER_BAR_TIMER
+ &AuraEffect::HandleNULL, //370 SPELL_AURA_SET_FAIR_FAR_CLIP
};
AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster):
@@ -418,7 +473,12 @@ void AuraEffect::GetApplicationList(std::list<AuraApplication*> & applicationLis
int32 AuraEffect::CalculateAmount(Unit* caster)
{
// default amount calculation
- int32 amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, NULL);
+ int32 amount = 0;
+
+ if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(m_spellInfo->Effects[m_effIndex].BonusMultiplier, 0.0f))
+ amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit());
+ else if (caster && caster->GetTypeId() == TYPEID_PLAYER)
+ amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * m_spellInfo->Effects[m_effIndex].BonusMultiplier);
// check item enchant aura cast
if (!amount && caster)
@@ -468,9 +528,9 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
Unit::AuraEffectList const& overrideClassScripts = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr)
{
- if ((*itr)->IsAffectedOnSpell(m_spellInfo))
+ if ((*itr)->IsAffectingSpell(m_spellInfo))
{
- // Glyph of Fear, Glyph of Frost nova and similar auras
+ // Glyph of Frost nova and similar auras
if ((*itr)->GetMiscValue() == 7801)
{
AddPct(amount, (*itr)->GetAmount());
@@ -484,6 +544,45 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
case SPELL_AURA_MANA_SHIELD:
m_canBeRecalculated = false;
break;
+ case SPELL_AURA_MOUNTED:
+ if (MountCapabilityEntry const* mountCapability = GetBase()->GetUnitOwner()->GetMountCapability(uint32(GetMiscValueB())))
+ {
+ amount = mountCapability->Id;
+ m_canBeRecalculated = false;
+ }
+ break;
+ case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE:
+ {
+ if (caster)
+ {
+ // if Level <= 70 resist = player level
+ int32 resist = caster->getLevel();
+
+ if (resist > 70 && resist < 81)
+ resist += (resist - 70) * 5;
+ else if (resist > 80)
+ resist += ((resist-70) * 5 + (resist - 80) * 7);
+
+ switch (GetId())
+ {
+ case 20043: // Aspect of the Wild
+ case 8185: // Elemental Resistance
+ case 19891: // Resistance Aura
+ case 79106: // Shadow Protection
+ case 79107: // Shadow Protection
+ amount = resist;
+ break;
+ case 79060: // Mark of the Wild
+ case 79061: // Mark of the Wild
+ case 79062: // Blessing of Kings
+ case 79063: // Blessing of Kings
+ case 90363: // Embrace of the Shale Spider
+ amount = resist / 2;
+ break;
+ }
+ break;
+ }
+ }
default:
break;
}
@@ -493,7 +592,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
return amount;
}
-void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
+void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/)
{
m_amplitude = m_spellInfo->Effects[m_effIndex].Amplitude;
@@ -544,8 +643,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
caster->ModSpellCastTime(m_spellInfo, m_amplitude);
}
- // and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ else if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
m_amplitude = int32(m_amplitude * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
}
}
@@ -563,9 +661,6 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
// reset periodic timer on aura create or on reapply when aura isn't dot
// possibly we should not reset periodic timers only when aura is triggered by proc
// or maybe there's a spell attribute somewhere
- bool resetPeriodicTimer = create
- || ((GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE) && (GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE_PERCENT));
-
if (resetPeriodicTimer)
{
m_periodicTimer = 0;
@@ -795,6 +890,16 @@ void AuraEffect::UpdatePeriodic(Unit* caster)
case 49472: // Drink Coffee
case 57073:
case 61830:
+ case 69176:
+ case 72623:
+ case 80166:
+ case 80167:
+ case 87958:
+ case 87959:
+ case 92736:
+ case 92797:
+ case 92800:
+ case 92803:
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
// Get SPELL_AURA_MOD_POWER_REGEN aura from spell
@@ -894,21 +999,10 @@ void AuraEffect::UpdatePeriodic(Unit* caster)
bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const
{
ASSERT(caster);
- Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT);
- for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr)
- {
- if ((*itr)->IsAffectedOnSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask()))
- return true;
- }
-
- // Rupture - since 3.3.3 can crit
- if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
- return caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask());
-
- return false;
+ return caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask());
}
-bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const
+bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const
{
if (!spell)
return false;
@@ -1057,11 +1151,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
spellId2 = 21178;
HotWSpellId = 24899;
break;
- case FORM_DIREBEAR:
- spellId = 9635;
- spellId2 = 21178;
- HotWSpellId = 24899;
- break;
case FORM_BATTLESTANCE:
spellId = 21156;
break;
@@ -1127,7 +1216,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (target->GetTypeId() == TYPEID_PLAYER)
{
- const PlayerSpellMap& sp_list = target->ToPlayer()->GetSpellMap();
+ Player* plrTarget = target->ToPlayer();
+
+ PlayerSpellMap const& sp_list = plrTarget->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
@@ -1140,6 +1231,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
+ if ((spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) && !plrTarget->IsCurrentSpecMasterySpell(spellInfo))
+ continue;
+
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
@@ -1147,13 +1241,14 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Also do it for Glyphs
for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyphId = target->ToPlayer()->GetGlyph(i))
+ if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
+
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, glyph->SpellId, true, NULL, this);
}
@@ -1161,19 +1256,21 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
}
// Leader of the Pack
- if (target->ToPlayer()->HasSpell(17007))
+ if (plrTarget->HasSpell(17007))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932);
if (spellInfo && spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, 24932, true, NULL, this);
}
+
// Improved Barkskin - apply/remove armor bonus due to shapeshift
- if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
+ if (plrTarget->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
{
target->RemoveAurasDueToSpell(66530);
if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted"
target->CastSpell(target, 66530, true);
}
+
// Heart of the Wild
if (HotWSpellId)
{ // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
@@ -1218,7 +1315,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true);
}
break;
- case FORM_DIREBEAR:
case FORM_BEAR:
// Master Shapeshifter - Bear
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
@@ -1229,7 +1325,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Survival of the Fittest
if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0))
{
- int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue();
+ int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster());
target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this);
}
break;
@@ -1531,27 +1627,21 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
Unit* target = aurApp->GetTarget();
- // no-phase is also phase state so same code for apply and remove
- uint32 newPhase = 0;
- Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
-
if (Player* player = target->ToPlayer())
{
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
-
- // GM-mode have mask 0xFFFFFFFF
- if (player->isGameMaster())
- newPhase = 0xFFFFFFFF;
-
- player->SetPhaseMask(newPhase, false);
- player->GetSession()->SendSetPhaseShift(newPhase);
+ if (apply)
+ player->GetPhaseMgr().RegisterPhasingAuraEffect(this);
+ else
+ player->GetPhaseMgr().UnRegisterPhasingAuraEffect(this);
}
else
{
+ uint32 newPhase = 0;
+ Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
+ if (!phases.empty())
+ for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
+ newPhase |= (*itr)->GetMiscValue();
+
if (!newPhase)
{
newPhase = PHASEMASK_NORMAL;
@@ -1599,7 +1689,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
break;
case FORM_BEAR: // 0x05
- case FORM_DIREBEAR: // 0x08
case FORM_BATTLESTANCE: // 0x11
case FORM_DEFENSIVESTANCE: // 0x12
@@ -1649,7 +1738,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
case FORM_TRAVEL:
case FORM_AQUA:
case FORM_BEAR:
- case FORM_DIREBEAR:
case FORM_FLIGHT_EPIC:
case FORM_FLIGHT:
case FORM_MOONKIN:
@@ -1678,7 +1766,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (PowerType != POWER_MANA)
{
- uint32 oldPower = target->GetPower(PowerType);
+ int32 oldPower = target->GetPower(PowerType);
// reset power to default values only at power change
if (target->getPowerType() != PowerType)
target->setPowerType(PowerType);
@@ -1687,10 +1775,9 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
{
case FORM_CAT:
case FORM_BEAR:
- case FORM_DIREBEAR:
{
// get furor proc chance
- uint32 FurorChance = 0;
+ int32 FurorChance = 0;
if (AuraEffect const* dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0))
FurorChance = std::max(dummy->GetAmount(), 0);
@@ -1698,19 +1785,17 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
{
case FORM_CAT:
{
- int32 basePoints = int32(std::min(oldPower, FurorChance));
+ int32 basePoints = std::min<int32>(oldPower, FurorChance);
target->SetPower(POWER_ENERGY, 0);
target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
break;
}
case FORM_BEAR:
- case FORM_DIREBEAR:
- if (urand(0, 99) < FurorChance)
- target->CastSpell(target, 17057, true);
- break;
+ if (urand(0, 99) < FurorChance)
+ target->CastSpell(target, 17057, true);
default:
{
- uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance);
+ int32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance);
target->SetPower(POWER_ENERGY, newEnergy);
break;
}
@@ -1749,7 +1834,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
{
// Nordrassil Harness - bonus
case FORM_BEAR:
- case FORM_DIREBEAR:
case FORM_CAT:
if (AuraEffect* dummy = target->GetAuraEffect(37315, 0))
target->CastSpell(target, 37316, true, NULL, dummy);
@@ -1763,7 +1847,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
case FORM_DEFENSIVESTANCE:
case FORM_BERSERKERSTANCE:
{
- uint32 Rage_val = 0;
+ int32 Rage_val = 0;
// Defensive Tactics
if (form == FORM_DEFENSIVESTANCE)
{
@@ -1824,7 +1908,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (target->GetTypeId() == TYPEID_PLAYER)
{
- SpellShapeshiftEntry const* shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
// Learn spells for shapeshift form - no need to send action bars or add spells to spellbook
for (uint8 i = 0; i<MAX_SHAPESHIFT_SPELLS; ++i)
{
@@ -2116,9 +2200,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
if (apply)
{
/*
- WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
- data<<target->GetGUID();
- data<<uint8(0);
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 0);
target->SendMessageToSet(&data, true);
*/
@@ -2164,9 +2246,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
else
{
/*
- WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
- data<<target->GetGUID();
- data<<uint8(1);
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 0);
target->SendMessageToSet(&data, true);
*/
// blizz like 2.0.x
@@ -2478,17 +2558,18 @@ void AuraEffect::HandleAuraModSkill(AuraApplication const* aurApp, uint8 mode, b
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_SKILL)))
return;
- Unit* target = aurApp->GetTarget();
- if (target->GetTypeId() != TYPEID_PLAYER)
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
return;
uint32 prot = GetMiscValue();
int32 points = GetAmount();
- target->ToPlayer()->ModifySkillBonus(prot, ((apply) ? points: -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
if (prot == SKILL_DEFENSE)
- target->ToPlayer()->UpdateDefenseBonusesMod();
+ return;
+
+ target->ModifySkillBonus(prot, (apply ? points : -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
}
/****************************/
@@ -2532,6 +2613,10 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
}
target->Mount(displayId, vehicleId, creatureEntry);
+
+ // cast speed aura
+ if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
+ target->CastSpell(target, mountCapability->SpeedModSpell, true);
}
else
{
@@ -2540,7 +2625,13 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
// need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount
if (mode & AURA_EFFECT_HANDLE_REAL)
+ {
target->RemoveAurasByType(SPELL_AURA_MOUNTED);
+
+ // remove speed aura
+ if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
+ target->RemoveAurasDueToSpell(mountCapability->SpeedModSpell, target->GetGUID());
+ }
}
}
@@ -3724,19 +3815,13 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
Unit* target = aurApp->GetTarget();
- if (GetMiscValue() < -1 || GetMiscValue() > 4)
- {
- TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
- return;
- }
-
// save current health state
float healthPct = target->GetHealthPct();
bool alive = target->isAlive();
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
- if (GetMiscValue() == i || GetMiscValue() == -1)
+ if (GetMiscValueB() & 1 << i || !GetMiscValueB()) // 0 is also used for all stats
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
@@ -3746,7 +3831,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
// recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
// this check is total bullshit i think
- if (GetMiscValue() == STAT_STAMINA && (m_spellInfo->Attributes & SPELL_ATTR0_ABILITY))
+ if (GetMiscValueB() & 1 << STAT_STAMINA && (m_spellInfo->Attributes & SPELL_ATTR0_ABILITY))
target->SetHealth(std::max<uint32>(uint32(healthPct * target->GetMaxHealth() * 0.01f), (alive ? 1 : 0)));
}
@@ -3802,7 +3887,7 @@ void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode,
// Update manaregen value
if (GetMiscValue() == POWER_MANA)
target->ToPlayer()->UpdateManaRegen();
- else if (GetMiscValue() == POWER_RUNE)
+ else if (GetMiscValue() == POWER_RUNES)
target->ToPlayer()->UpdateRuneRegen(RuneType(GetMiscValueB()));
// other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate
}
@@ -4123,6 +4208,7 @@ void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const* aurApp, uin
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
@@ -4159,6 +4245,7 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
@@ -4170,24 +4257,12 @@ void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 m
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
}
-void AuraEffect::HandleRangedAmmoHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const
-{
- if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
- return;
-
- Unit* target = aurApp->GetTarget();
-
- if (target->GetTypeId() != TYPEID_PLAYER)
- return;
-
- target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
-}
-
/********************************/
/*** COMBAT RATING ***/
/********************************/
@@ -4275,23 +4350,6 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
}
-void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
-{
- if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
- return;
-
- Unit* target = aurApp->GetTarget();
-
- // Recalculate bonus
- if (target->GetTypeId() == TYPEID_PLAYER && !(target->getClassMask() & CLASSMASK_WAND_USERS))
- target->ToPlayer()->UpdateAttackPowerAndDamage(true);
-}
-
-void AuraEffect::HandleAuraModAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
-{
- HandleAuraModAttackPowerOfArmor(aurApp, mode, apply);
-}
-
void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
@@ -4635,22 +4693,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
}
break;
}
- case 55198: // Tidal Force
- {
- target->CastSpell(target, 55166, true, NULL, this);
- // set 3 stacks and 3 charges (to make all auras not disappear at once)
- Aura* owner_aura = target->GetAura(55166, GetCasterGUID());
- if (owner_aura)
- {
- // This aura lasts 2 sec, need this hack to properly proc spells
- /// @todo drop aura charges for ApplySpellMod in ProcDamageAndSpell
- GetBase()->SetDuration(owner_aura->GetDuration());
- // Make aura be not charged-this prevents removing charge on not crit spells
- owner_aura->SetCharges(0);
- owner_aura->SetStackAmount(owner_aura->GetSpellInfo()->StackAmount);
- }
- break;
- }
case 39850: // Rocket Blast
if (roll_chance_i(20)) // backfire stun
target->CastSpell(target, 51581, true, NULL, this);
@@ -4676,10 +4718,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (caster)
target->GetMotionMaster()->MoveFall();
break;
- case 46699: // Requires No Ammo
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
- break;
case 52916: // Honor Among Thieves
if (target->GetTypeId() == TYPEID_PLAYER)
if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
@@ -4772,8 +4810,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case 60244: // Blood Parrot Despawn Aura
target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this);
break;
- case 58600: // Restricted Flight Area
- case 58730: // Restricted Flight Area
+ case 91604: // Restricted Flight Area
if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
target->CastSpell(target, 58601, true);
break;
@@ -4981,15 +5018,6 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod
if (!plCaster->isHonorOrXPTarget(target) ||
(target->GetTypeId() == TYPEID_UNIT && !target->ToCreature()->isTappedBy(plCaster)))
return;
-
- // If this is Drain Soul, check for Glyph of Drain Soul
- if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
- {
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, true, 0, aur); // We _could_ simply do ++count here, but Blizz does it this way :)
- }
}
//Adding items
@@ -5275,7 +5303,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
+ if (!target->IsInWorld())
return;
uint32 vehicleId = GetMiscValue();
@@ -5288,6 +5316,9 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
else if (target->GetVehicleKit())
target->RemoveVehicleKit();
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, target->GetPackGUID().size()+4);
data.appendPackGUID(target->GetGUID());
data << uint32(apply ? vehicleId : 0);
@@ -5311,6 +5342,18 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8
aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER);
}
+void AuraEffect::HandleMastery(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ target->UpdateMastery();
+}
+
void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
{
switch (GetSpellInfo()->SpellFamilyName)
@@ -5892,16 +5935,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
{
if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
- {
- if (roll_chance_i(20))
- {
- caster->CastSpell(caster, 43836, true, 0, this);
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, true, 0, aur);
- }
- }
+ caster->CastSpell(caster, 95810, true, 0, this);
}
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC)
{
@@ -5926,7 +5960,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, &dmg, crit);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
@@ -5993,7 +6027,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
}
int32 dmg = damage;
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, &dmg, crit);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
@@ -6096,15 +6130,6 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
if (maxval)
AddPct(TakenTotalMod, maxval);
- // Healing over time taken percent
- float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (minval_hot)
- AddPct(TakenTotalMod, minval_hot);
-
- float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (maxval_hot)
- AddPct(TakenTotalMod, maxval_hot);
-
TakenTotalMod = std::max(TakenTotalMod, 0.0f);
damage = uint32(target->CountPctFromMaxHealth(damage));
@@ -6205,10 +6230,6 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
TC_LOG_INFO(LOG_FILTER_SPELLS_AURAS, "PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), drainAmount, GetId());
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- drainAmount -= target->GetSpellCritDamageReduction(drainAmount);
-
int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount);
float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
@@ -6323,10 +6344,6 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
// ignore negative values (can be result apply spellmods to aura damage
int32 damage = std::max(m_amount, 0);
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- damage -= target->GetSpellCritDamageReduction(damage);
-
uint32 gain = uint32(-target->ModifyPower(powerType, -damage));
float dmgMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
@@ -6486,3 +6503,52 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandleRaidProcFromChargeWithValueAuraProc: Triggering spell %u from aura %u proc", triggerSpellId, GetId());
target->CastCustomSpell(target, triggerSpellId, &value, NULL, NULL, true, NULL, this, GetCasterGUID());
}
+
+void AuraEffect::HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+
+ if (!target)
+ return;
+
+ if (apply)
+ {
+ WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
+
+ data << uint32(GetMiscValue()) << 1.0f << uint8(0);
+ target->GetSession()->SendPacket(&data);
+ }
+ else
+ {
+ // send weather for current zone
+ if (Weather* weather = WeatherMgr::FindWeather(target->GetZoneId()))
+ weather->SendWeatherUpdateToPlayer(target);
+ else
+ {
+ if (!WeatherMgr::AddWeather(target->GetZoneId()))
+ {
+ // send fine weather packet to remove old weather
+ WeatherMgr::SendFineWeatherUpdateToPlayer(target);
+ }
+ }
+ }
+}
+
+void AuraEffect::HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ uint32 altPowerId = GetMiscValue();
+ UnitPowerBarEntry const* powerEntry = sUnitPowerBarStore.LookupEntry(altPowerId);
+ if (!powerEntry)
+ return;
+
+ if (apply)
+ aurApp->GetTarget()->SetMaxPower(POWER_ALTERNATE_POWER, powerEntry->MaxPower);
+ else
+ aurApp->GetTarget()->SetMaxPower(POWER_ALTERNATE_POWER, 0);
+}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 7cfb1e04850..9e551837c96 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -59,7 +59,7 @@ class AuraEffect
void SetPeriodicTimer(int32 periodicTimer) { m_periodicTimer = periodicTimer; }
int32 CalculateAmount(Unit* caster);
- void CalculatePeriodic(Unit* caster, bool create = false, bool load = false);
+ void CalculatePeriodic(Unit* caster, bool resetPeriodicTimer = true, bool load = false);
void CalculateSpellMod();
void ChangeAmount(int32 newAmount, bool mark = true, bool onStackOrReapply = false);
void RecalculateAmount() { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(GetCaster()), false); }
@@ -79,7 +79,7 @@ class AuraEffect
bool IsPeriodic() const { return m_isPeriodic; }
void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; }
- bool IsAffectedOnSpell(SpellInfo const* spell) const;
+ bool IsAffectingSpell(SpellInfo const* spell) const;
bool HasSpellClassMask() const { return m_spellInfo->Effects[m_effIndex].SpellClassMask; }
void SendTickImmune(Unit* target, Unit* caster) const;
@@ -242,7 +242,6 @@ class AuraEffect
void HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleRangedAmmoHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// combat rating
void HandleModRating(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModRatingFromStat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -251,8 +250,6 @@ class AuraEffect
void HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleAuraModAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// damage bonus
void HandleModDamageDone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -280,6 +277,9 @@ class AuraEffect
void HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleMastery(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// aura effect periodic tick handlers
void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index e9c456c4c7b..12cd3c93c98 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -147,6 +147,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask)
}
_flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE;
}
+
+ if (GetBase()->GetSpellInfo()->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT)
+ _flags |= AFLAG_ANY_EFFECT_AMOUNT_SENT;
}
void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
@@ -192,7 +195,7 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
uint32 flags = _flags;
if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION))
flags |= AFLAG_DURATION;
- data << uint8(flags);
+ data << uint16(flags);
data << uint8(aura->GetCasterLevel());
// send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges
// stack amount has priority over charges (checked on retail with spell 50262)
@@ -206,6 +209,12 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
data << uint32(aura->GetMaxDuration());
data << uint32(aura->GetDuration());
}
+
+ if (flags & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = aura->GetEffect(i))
+ if (HasEffect(i)) // Not all of aura's effects have to be applied on every target
+ data << int32(eff->GetAmount());
}
void AuraApplication::ClientUpdate(bool remove)
@@ -337,7 +346,7 @@ m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false)
{
- if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
+ if (m_spellInfo->ManaPerSecond)
m_timeCla = 1 * IN_MILLISECONDS;
m_maxDuration = CalcMaxDuration(caster);
@@ -672,7 +681,7 @@ void Aura::Update(uint32 diff, Unit* caster)
m_timeCla -= diff;
else if (caster)
{
- if (int32 manaPerSecond = m_spellInfo->ManaPerSecond + m_spellInfo->ManaPerSecondPerLevel * caster->getLevel())
+ if (int32 manaPerSecond = m_spellInfo->ManaPerSecond)
{
m_timeCla += 1000 - diff;
@@ -741,18 +750,35 @@ void Aura::RefreshDuration()
{
SetDuration(GetMaxDuration());
- if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
+ if (m_spellInfo->ManaPerSecond)
m_timeCla = 1 * IN_MILLISECONDS;
}
void Aura::RefreshTimers()
{
m_maxDuration = CalcMaxDuration();
+ bool resetPeriodic = true;
+ if (m_spellInfo->AttributesEx8 & SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER)
+ {
+ int32 minAmplitude = m_maxDuration;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = GetEffect(i))
+ if (int32 ampl = eff->GetAmplitude())
+ minAmplitude = std::min(ampl, minAmplitude);
+
+ // If only one tick remaining, roll it over into new duration
+ if (GetDuration() <= minAmplitude)
+ {
+ m_maxDuration += GetDuration();
+ resetPeriodic = false;
+ }
+ }
+
RefreshDuration();
Unit* caster = GetCaster();
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (HasEffect(i))
- GetEffect(i)->CalculatePeriodic(caster, false, false);
+ GetEffect(i)->CalculatePeriodic(caster, resetPeriodic, false);
}
void Aura::SetCharges(uint8 charges)
@@ -773,7 +799,7 @@ uint8 Aura::CalcMaxCharges(Unit* caster) const
if (caster)
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, maxProcCharges);
- return maxProcCharges;
+ return uint8(maxProcCharges);
}
bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode)
@@ -925,6 +951,10 @@ bool Aura::CanBeSaved() const
break;
}
+ // When a druid logins, he doesnt have either eclipse power, nor the marker auras, nor the eclipse buffs. Dont save them.
+ if (GetId() == 67483 || GetId() == 67484 || GetId() == 48517 || GetId() == 48518)
+ return false;
+
// don't save auras removed by proc system
if (IsUsingCharges() && !GetCharges())
return false;
@@ -934,7 +964,7 @@ bool Aura::CanBeSaved() const
bool Aura::CanBeSentToClient() const
{
- return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
+ return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING);
}
void Aura::UnregisterSingleTarget()
@@ -1154,20 +1184,8 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_MAGE:
if (!caster)
break;
- if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001 && GetSpellInfo()->SpellFamilyFlags[2] & 0x00000008)
- {
- // Glyph of Fireball
- if (caster->HasAura(56368))
- SetDuration(0);
- }
- else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000020 && GetSpellInfo()->SpellVisual[0] == 13)
- {
- // Glyph of Frostbolt
- if (caster->HasAura(56370))
- SetDuration(0);
- }
/// @todo This should be moved to similar function in spell::hit
- else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x01000000)
+ if (GetSpellInfo()->SpellFamilyFlags[0] & 0x01000000)
{
// Polymorph Sound - Sheep && Penguin
if (GetSpellInfo()->SpellIconID == 82 && GetSpellInfo()->SpellVisual[0] == 12978)
@@ -1199,18 +1217,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
caster->CastSpell(caster, spellId, true);
}
break;
- case 44544: // Fingers of Frost
- {
- // See if we already have the indicator aura. If not, create one.
- if (Aura* aur = target->GetAura(74396))
- {
- // Aura already there. Refresh duration and set original charges
- aur->SetCharges(2);
- aur->RefreshDuration();
- }
- else
- target->AddAura(74396, target);
- }
default:
break;
}
@@ -1222,7 +1228,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (GetSpellInfo()->SpellFamilyFlags[0] & 0x02000000 && GetEffect(0))
{
// Improved Devouring Plague
- if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
+ if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 0))
{
uint32 damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), DOT);
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
@@ -1252,49 +1258,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (target->HasAura(58039)) // Glyph of Blurred Speed
target->CastSpell(target, 61922, true); // Sprint (waterwalk)
break;
- case SPELLFAMILY_DEATHKNIGHT:
- if (!caster)
- break;
- // Frost Fever and Blood Plague
- if (GetSpellInfo()->SpellFamilyFlags[2] & 0x2)
- {
- // Can't proc on self
- if (GetCasterGUID() == target->GetGUID())
- break;
-
- AuraEffect* aurEff = NULL;
- // Ebon Plaguebringer / Crypt Fever
- Unit::AuraEffectList const& TalentAuras = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (Unit::AuraEffectList::const_iterator itr = TalentAuras.begin(); itr != TalentAuras.end(); ++itr)
- {
- if ((*itr)->GetMiscValue() == 7282)
- {
- aurEff = *itr;
- // Ebon Plaguebringer - end search if found
- if ((*itr)->GetSpellInfo()->SpellIconID == 1766)
- break;
- }
- }
- if (aurEff)
- {
- uint32 spellId = 0;
- switch (aurEff->GetId())
- {
- // Ebon Plague
- case 51161: spellId = 51735; break;
- case 51160: spellId = 51734; break;
- case 51099: spellId = 51726; break;
- // Crypt Fever
- case 49632: spellId = 50510; break;
- case 49631: spellId = 50509; break;
- case 49032: spellId = 50508; break;
- default:
- TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "Aura::HandleAuraSpecificMods: Unknown rank of Crypt Fever/Ebon Plague (%d) found", aurEff->GetId());
- }
- caster->CastSpell(target, spellId, true, 0, GetEffect(0));
- }
- }
- break;
}
}
// mods at aura remove
@@ -1333,54 +1296,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
target->CastSpell(target, 32612, true, NULL, GetEffect(1));
target->CombatStop();
break;
- case 74396: // Fingers of Frost
- // Remove the IGNORE_AURASTATE aura
- target->RemoveAurasDueToSpell(44544);
- break;
- case 44401: //Missile Barrage
- case 48108: //Hot Streak
- case 57761: //Fireball!
- if (removeMode != AURA_REMOVE_BY_EXPIRE || aurApp->GetBase()->IsExpired())
- break;
- if (target->HasAura(70752)) //Item - Mage T10 2P Bonus
- target->CastSpell(target, 70753, true);
- break;
default:
break;
}
- if (!caster)
- break;
- // Ice barrier - dispel/absorb remove
- if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[1] & 0x1)
- {
- // Shattered Barrier
- if (AuraEffect* dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 2945, 0))
- if (roll_chance_i(dummy->GetSpellInfo()->ProcChance))
- caster->CastSpell(target, 55080, true, NULL, GetEffect(0));
- }
- break;
- case SPELLFAMILY_WARRIOR:
- if (!caster)
- break;
- // Spell Reflection
- if (GetSpellInfo()->SpellFamilyFlags[1] & 0x2)
- {
- if (removeMode != AURA_REMOVE_BY_DEFAULT)
- {
- // Improved Spell Reflection
- if (caster->GetDummyAuraEffect(SPELLFAMILY_WARRIOR, 1935, 1))
- {
- // aura remove - remove auras from all party members
- std::list<Unit*> PartyMembers;
- target->GetPartyMembers(PartyMembers);
- for (std::list<Unit*>::iterator itr = PartyMembers.begin(); itr != PartyMembers.end(); ++itr)
- {
- if ((*itr)!= target)
- (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, 0, 0x2, 0, GetCasterGUID());
- }
- }
- }
- }
break;
case SPELLFAMILY_WARLOCK:
if (!caster)
@@ -1406,18 +1324,8 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_PRIEST:
if (!caster)
break;
- // Shadow word: Pain // Vampiric Touch
- if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00008000 || GetSpellInfo()->SpellFamilyFlags[1] & 0x00000400))
- {
- // Shadow Affinity
- if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 178, 1))
- {
- int32 basepoints0 = aurEff->GetAmount() * caster->GetCreateMana() / 100;
- caster->CastCustomSpell(caster, 64103, &basepoints0, NULL, NULL, true, NULL, GetEffect(0));
- }
- }
// Power word: shield
- else if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
+ if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
{
// Rapture
if (Aura const* aura = caster->GetAuraOfRankedSpell(47535))
@@ -1439,68 +1347,12 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// effect on caster
if (AuraEffect const* aurEff = aura->GetEffect(0))
{
- float multiplier = (float)aurEff->GetAmount();
- if (aurEff->GetId() == 47535)
- multiplier -= 0.5f;
- else if (aurEff->GetId() == 47537)
- multiplier += 0.5f;
-
+ float multiplier = float(aurEff->GetAmount());
int32 basepoints0 = int32(CalculatePct(caster->GetMaxPower(POWER_MANA), multiplier));
caster->CastCustomSpell(caster, 47755, &basepoints0, NULL, NULL, true);
}
- // effect on aura target
- if (AuraEffect const* aurEff = aura->GetEffect(1))
- {
- if (!roll_chance_i(aurEff->GetAmount()))
- break;
-
- int32 triggeredSpellId = 0;
- switch (target->getPowerType())
- {
- case POWER_MANA:
- {
- int32 basepoints0 = int32(CalculatePct(target->GetMaxPower(POWER_MANA), 2));
- caster->CastCustomSpell(target, 63654, &basepoints0, NULL, NULL, true);
- break;
- }
- case POWER_RAGE: triggeredSpellId = 63653; break;
- case POWER_ENERGY: triggeredSpellId = 63655; break;
- case POWER_RUNIC_POWER: triggeredSpellId = 63652; break;
- default:
- break;
- }
- if (triggeredSpellId)
- caster->CastSpell(target, triggeredSpellId, true);
- }
}
}
- switch (GetId())
- {
- case 47788: // Guardian Spirit
- if (removeMode != AURA_REMOVE_BY_EXPIRE)
- break;
- if (caster->GetTypeId() != TYPEID_PLAYER)
- break;
-
- Player* player = caster->ToPlayer();
- // Glyph of Guardian Spirit
- if (AuraEffect* aurEff = player->GetAuraEffect(63231, 0))
- {
- if (!player->HasSpellCooldown(47788))
- break;
-
- player->RemoveSpellCooldown(GetSpellInfo()->Id, true);
- player->AddSpellCooldown(GetSpellInfo()->Id, 0, uint32(time(NULL) + aurEff->GetAmount()));
-
- WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4);
- data << uint64(player->GetGUID());
- data << uint8(0x0); // flags (0x1, 0x2)
- data << uint32(GetSpellInfo()->Id);
- data << uint32(aurEff->GetAmount()*IN_MILLISECONDS);
- player->SendDirectMessage(&data);
- }
- break;
- }
break;
case SPELLFAMILY_ROGUE:
// Remove Vanish on stealth remove
@@ -1556,7 +1408,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00400000)
{
// Master of subtlety
- if (AuraEffect const* aurEff = target->GetAuraEffectOfRankedSpell(31221, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(31223, 0))
{
if (!apply)
target->CastSpell(target, 31666, true);
@@ -1566,14 +1418,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
target->CastCustomSpell(target, 31665, &basepoints0, NULL, NULL, true);
}
}
- // Overkill
- if (target->HasAura(58426))
- {
- if (!apply)
- target->CastSpell(target, 58428, true);
- else
- target->CastSpell(target, 58427, true);
- }
break;
}
break;
@@ -1599,19 +1443,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_PALADIN:
switch (GetId())
{
- case 19746:
- if (!caster)
- break;
-
- // Improved concentration aura - linked aura
- if (caster->HasAura(20254) || caster->HasAura(20255) || caster->HasAura(20256))
- {
- if (apply)
- target->CastSpell(target, 63510, true);
- else
- target->RemoveAura(63510);
- }
- break;
case 31821:
// Aura Mastery Triggered Spell Handler
// If apply Concentration Aura -> trigger -> apply Aura Mastery Immunity
@@ -1629,7 +1460,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
else
target->RemoveAurasDueToSpell(64364, GetCasterGUID());
break;
- case 31842: // Divine Illumination
+ case 31842: // Divine Favor
// Item - Paladin T10 Holy 2P Bonus
if (target->HasAura(70755))
{
@@ -1640,118 +1471,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
}
break;
}
- if (GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_AURA)
- {
- if (!caster)
- break;
-
- // Improved devotion aura
- if (caster->HasAura(20140) || caster->HasAura(20138) || caster->HasAura(20139))
- {
- if (apply)
- caster->CastSpell(target, 63514, true);
- else
- target->RemoveAura(63514);
- }
- // 63531 - linked aura for both Sanctified Retribution and Swift Retribution talents
- // Not allow for Retribution Aura (prevent stacking)
- if ((GetSpellInfo()->SpellIconID != 555) && (caster->HasAura(53648) || caster->HasAura(53484) || caster->HasAura(53379) || caster->HasAura(31869)))
- {
- if (apply)
- caster->CastSpell(target, 63531, true);
- else
- target->RemoveAura(63531);
- }
- }
- break;
- case SPELLFAMILY_DEATHKNIGHT:
- if (GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_PRESENCE)
- {
- AuraEffect* bloodPresenceAura=0; // healing by damage done
- AuraEffect* frostPresenceAura=0; // increased health
- AuraEffect* unholyPresenceAura=0; // increased movement speed, faster rune recovery
-
- // Improved Presences
- Unit::AuraEffectList const& vDummyAuras = target->GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr)
- {
- switch ((*itr)->GetId())
- {
- // Improved Blood Presence
- case 50365:
- case 50371:
- {
- bloodPresenceAura = (*itr);
- break;
- }
- // Improved Frost Presence
- case 50384:
- case 50385:
- {
- frostPresenceAura = (*itr);
- break;
- }
- // Improved Unholy Presence
- case 50391:
- case 50392:
- {
- unholyPresenceAura = (*itr);
- break;
- }
- }
- }
-
- uint32 presence = GetId();
- if (apply)
- {
- // Blood Presence bonus
- if (presence == 48266)
- target->CastSpell(target, 63611, true);
- else if (bloodPresenceAura)
- {
- int32 basePoints1 = bloodPresenceAura->GetAmount();
- target->CastCustomSpell(target, 63611, NULL, &basePoints1, NULL, true, 0, bloodPresenceAura);
- }
- // Frost Presence bonus
- if (presence == 48263)
- target->CastSpell(target, 61261, true);
- else if (frostPresenceAura)
- {
- int32 basePoints0 = frostPresenceAura->GetAmount();
- target->CastCustomSpell(target, 61261, &basePoints0, NULL, NULL, true, 0, frostPresenceAura);
- }
- // Unholy Presence bonus
- if (presence == 48265)
- {
- if (unholyPresenceAura)
- {
- // Not listed as any effect, only base points set
- int32 basePoints0 = unholyPresenceAura->GetSpellInfo()->Effects[EFFECT_1].CalcValue();
- target->CastCustomSpell(target, 63622, &basePoints0, &basePoints0, &basePoints0, true, 0, unholyPresenceAura);
- }
- target->CastSpell(target, 49772, true);
- }
- else if (unholyPresenceAura)
- {
- int32 basePoints0 = unholyPresenceAura->GetAmount();
- target->CastCustomSpell(target, 49772, &basePoints0, NULL, NULL, true, 0, unholyPresenceAura);
- }
- }
- else
- {
- // Remove passive auras
- if (presence == 48266 || bloodPresenceAura)
- target->RemoveAurasDueToSpell(63611);
- if (presence == 48263 || frostPresenceAura)
- target->RemoveAurasDueToSpell(61261);
- if (presence == 48265 || unholyPresenceAura)
- {
- if (presence == 48265 && unholyPresenceAura)
- target->RemoveAurasDueToSpell(63622);
- target->RemoveAurasDueToSpell(49772);
- }
- }
- }
break;
case SPELLFAMILY_WARLOCK:
// Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage
@@ -2604,4 +2323,3 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster*
}
}
}
-
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index e7f7ea69611..4e0c0e0f831 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -53,6 +53,7 @@
#include "SpellScript.h"
#include "InstanceScript.h"
#include "SpellInfo.h"
+#include "DB2Stores.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
@@ -532,7 +533,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
// wand case
if ((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId() == TYPEID_PLAYER)
if (Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
- m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->Damage[0].DamageType);
+ m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->DamageType);
if (originalCasterGUID)
m_originalCasterGUID = originalCasterGUID;
@@ -795,7 +796,10 @@ void Spell::SelectSpellTargets()
else if (m_spellInfo->Speed > 0.0f)
{
float dist = m_caster->GetDistance(*m_targets.GetDstPos());
- m_delayMoment = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ m_delayMoment = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ m_delayMoment = uint64(m_spellInfo->Speed * 1000.0f);
}
}
}
@@ -1067,14 +1071,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
{
// Other special target selection goes here
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
Trinity::Containers::RandomResizeList(targets, maxTargets);
- }
// for compability with older code - add only unit and go targets
/// @todo remove this
@@ -1349,14 +1346,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
// Other special target selection goes here
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
Trinity::Containers::RandomResizeList(unitTargets, maxTargets);
- }
for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
AddUnitTarget(*itr, effMask, false);
@@ -1365,14 +1355,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
if (!gObjTargets.empty())
{
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
Trinity::Containers::RandomResizeList(gObjTargets, maxTargets);
- }
for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
AddGOTarget(*itr, effMask);
@@ -1766,6 +1749,9 @@ void Spell::SelectImplicitTrajTargets()
trajDst.Relocate(x, y, z, m_caster->GetOrientation());
m_targets.ModDst(trajDst);
}
+
+ if (Vehicle* veh = m_caster->GetVehicleKit())
+ veh->SetLastShootPos(*m_targets.GetDstPos());
}
void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
@@ -2200,7 +2186,11 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
if (dist < 5.0f)
dist = 5.0f;
- targetInfo.timeDelay = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);
+
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ targetInfo.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ targetInfo.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
// Calculate minimum incoming time
if (m_delayMoment == 0 || m_delayMoment > targetInfo.timeDelay)
@@ -2279,7 +2269,12 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask)
float dist = m_caster->GetDistance(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
if (dist < 5.0f)
dist = 5.0f;
- target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ target.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
+
if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
m_delayMoment = target.timeDelay;
}
@@ -2523,6 +2518,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
}
+
m_damage = damageInfo.damage;
caster->DealSpellDamage(&damageInfo, true);
@@ -2596,25 +2592,9 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
// disable effects to which unit is immune
SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
- {
if (effectMask & (1 << effectNumber))
- {
if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber))
effectMask &= ~(1 << effectNumber);
- else if (m_spellInfo->Effects[effectNumber].IsAura() && !m_spellInfo->IsPositiveEffect(effectNumber))
- {
- int32 debuff_resist_chance = unit->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel));
- debuff_resist_chance += unit->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel));
-
- if (debuff_resist_chance > 0)
- if (irand(0, 10000) <= (debuff_resist_chance * 100))
- {
- effectMask &= ~(1 << effectNumber);
- returnVal = SPELL_MISS_RESIST;
- }
- }
- }
- }
if (!effectMask)
return returnVal;
@@ -2625,14 +2605,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (Player* player = unit->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, m_caster);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
}
if (Player* player = m_caster->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
}
if (m_caster != unit)
@@ -2750,15 +2730,28 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask);
- // Haste modifies duration of channeled spells
- if (m_spellInfo->IsChanneled())
+ if (duration > 0)
{
- if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
- m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
+ // Haste modifies duration of channeled spells
+ if (m_spellInfo->IsChanneled())
+ {
+ if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
+ }
+ else if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ {
+ int32 origDuration = duration;
+ duration = 0;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = m_spellAura->GetEffect(i))
+ if (int32 amplitude = eff->GetAmplitude()) // amplitude is hastened by UNIT_MOD_CAST_SPEED
+ duration = std::max(std::max(origDuration / amplitude, 1) * amplitude, duration);
+
+ // if there is no periodic effect
+ if (!duration)
+ duration = int32(origDuration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ }
}
- // and duration of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
- duration = int32(duration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
if (duration != m_spellAura->GetMaxDuration())
{
@@ -2839,11 +2832,15 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
// trigger linked auras remove/apply
/// @todo remove/cleanup this, as this table is not documented and people are doing stupid things with it
if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id + SPELL_LINK_HIT))
+ {
for (std::vector<int32>::const_iterator i = spellTriggered->begin(); i != spellTriggered->end(); ++i)
+ {
if (*i < 0)
unit->RemoveAurasDueToSpell(-(*i));
else
unit->CastSpell(unit, *i, true, 0, 0, m_caster->GetGUID());
+ }
+ }
}
void Spell::DoAllEffectOnTarget(GOTargetInfo* target)
@@ -3019,6 +3016,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
m_needComboPoints = false;
SpellCastResult result = CheckCast(true);
+ // target is checked in too many locations and with different results to handle each of them
+ // handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks
+ if (_triggeredCastFlags & TRIGGERED_IGNORE_TARGET_CHECK && result == SPELL_FAILED_BAD_TARGETS)
+ result = SPELL_CAST_OK;
if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
{
// Periodic auras should be interrupted when aura triggers a spell which can't be cast
@@ -3055,7 +3056,9 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
// don't allow channeled spells / spells with cast time to be casted while moving
// (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
- if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)
+ // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() &&
+ m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
@@ -3402,7 +3405,7 @@ void Spell::handle_immediate()
// Remove used for cast item if need (it can be already NULL after TakeReagents call
TakeCastItem();
- // handle ammo consumption for Hunter's volley spell
+ // handle ammo consumption for thrown weapons
if (m_spellInfo->IsRangedWeaponSpell() && m_spellInfo->IsChanneled())
TakeAmmo();
@@ -3532,6 +3535,9 @@ void Spell::_handle_finish_phase()
// Real add combo points from effects
if (m_comboPointGain)
m_caster->m_movedPlayer->GainSpellComboPoints(m_comboPointGain);
+
+ if (m_spellInfo->PowerType == POWER_HOLY_POWER && m_caster->m_movedPlayer->getClass() == CLASS_PALADIN)
+ HandleHolyPower(m_caster->m_movedPlayer);
}
if (m_caster->m_extraAttacks && GetSpellInfo()->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
@@ -3575,9 +3581,11 @@ void Spell::update(uint32 difftime)
}
// check if the player caster has moved before the spell finished
+ // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
- (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
+ (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) &&
+ !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
// don't cancel for melee, autorepeat, triggered and instant spells
if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered())
@@ -3718,7 +3726,7 @@ void Spell::finish(bool ok)
Unit::AuraEffectList const& vIgnoreReset = m_caster->GetAuraEffectsByType(SPELL_AURA_IGNORE_MELEE_RESET);
for (Unit::AuraEffectList::const_iterator i = vIgnoreReset.begin(); i != vIgnoreReset.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(m_spellInfo))
+ if ((*i)->IsAffectingSpell(m_spellInfo))
{
found = true;
break;
@@ -3779,6 +3787,9 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
data << uint8(result); // problem
switch (result)
{
+ case SPELL_FAILED_NOT_READY:
+ data << uint32(0); // unknown (value 1 update cooldowns on client flag)
+ break;
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
break;
@@ -3831,9 +3842,29 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
data << uint32(proto->ItemLimitCategory);
break;
}
+ case SPELL_FAILED_PREVENTED_BY_MECHANIC:
+ data << uint32(spellInfo->GetAllEffectsMechanicMask()); // SpellMechanic.dbc id
+ break;
+ case SPELL_FAILED_NEED_EXOTIC_AMMO:
+ data << uint32(spellInfo->EquippedItemSubClassMask); // seems correct...
+ break;
+ case SPELL_FAILED_NEED_MORE_ITEMS:
+ data << uint32(0); // Item id
+ data << uint32(0); // Item count?
+ break;
+ case SPELL_FAILED_MIN_SKILL:
+ data << uint32(0); // SkillLine.dbc id
+ data << uint32(0); // required skill value
+ break;
+ case SPELL_FAILED_FISHING_TOO_LOW:
+ data << uint32(0); // required fishing skill
+ break;
case SPELL_FAILED_CUSTOM_ERROR:
data << uint32(customError);
break;
+ case SPELL_FAILED_SILENCED:
+ data << uint32(0); // Unknown
+ break;
case SPELL_FAILED_REAGENTS:
{
uint32 missingItem = 0;
@@ -3855,23 +3886,7 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
data << uint32(missingItem); // first missing item
break;
}
- case SPELL_FAILED_PREVENTED_BY_MECHANIC:
- data << uint32(spellInfo->Mechanic);
- break;
- case SPELL_FAILED_NEED_EXOTIC_AMMO:
- data << uint32(spellInfo->EquippedItemSubClassMask);
- break;
- case SPELL_FAILED_NEED_MORE_ITEMS:
- data << uint32(0); // Item entry
- data << uint32(0); // Count
- break;
- case SPELL_FAILED_MIN_SKILL:
- data << uint32(0); // SkillLine.dbc Id
- data << uint32(0); // Amount
- break;
- case SPELL_FAILED_FISHING_TOO_LOW:
- data << uint32(0); // Skill level
- break;
+ // TODO: SPELL_FAILED_NOT_STANDING
default:
break;
}
@@ -3885,19 +3900,17 @@ void Spell::SendSpellStart()
//TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
- uint32 castFlags = CAST_FLAG_UNKNOWN_2;
+ uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
- castFlags |= CAST_FLAG_AMMO;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
- if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
+ if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNES)
castFlags |= CAST_FLAG_UNKNOWN_19;
WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
@@ -3910,20 +3923,56 @@ void Spell::SendSpellStart()
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
- data << int32(m_timer); // delay?
+ data << uint32(m_timer); // delay?
+ data << uint32(m_casttime);
m_targets.Write(data);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
data << uint32(m_caster->GetPower((Powers)m_spellInfo->PowerType));
- if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
+ {
+ //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature
+ //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
+ if (Player* player = m_caster->ToPlayer())
+ {
+ data << uint8(m_runesState); // runes state before
+ data << uint8(player->GetRunesState()); // runes state after
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ }
+ }
+ else
+ {
+ data << uint8(0);
+ data << uint8(0);
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ data << uint8(0);
+ }
+ }
- if (castFlags & CAST_FLAG_UNKNOWN_23)
+ if (castFlags & CAST_FLAG_PROJECTILE)
{
+ data << uint32(0); // Ammo display ID
+ data << uint32(0); // Inventory Type
+ }
+
+ if (castFlags & CAST_FLAG_IMMUNITY)
+ {
+ data << uint32(0);
data << uint32(0);
+ }
+
+ if (castFlags & CAST_FLAG_HEAL_PREDICTION)
+ {
data << uint32(0);
+ data << uint8(0); // unkByte
+ // if (unkByte == 2)
+ // data.append(0);
}
m_caster->SendMessageToSet(&data, true);
@@ -3943,9 +3992,6 @@ void Spell::SendSpellGo()
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
- castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
-
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
@@ -3954,7 +4000,7 @@ void Spell::SendSpellGo()
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
&& m_spellInfo->RuneCostID
- && m_spellInfo->PowerType == POWER_RUNE)
+ && m_spellInfo->PowerType == POWER_RUNES)
{
castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START
castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
@@ -3980,6 +4026,7 @@ void Spell::SendSpellGo()
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
+ data << uint32(m_timer);
data << uint32(getMSTime()); // timestamp
WriteSpellGoTargets(&data);
@@ -3995,30 +4042,28 @@ void Spell::SendSpellGo()
//The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
if (Player* player = m_caster->ToPlayer())
{
- uint8 runeMaskInitial = m_runesState;
- uint8 runeMaskAfterCast = player->GetRunesState();
- data << uint8(runeMaskInitial); // runes state before
- data << uint8(runeMaskAfterCast); // runes state after
+ data << uint8(m_runesState); // runes state before
+ data << uint8(player->GetRunesState()); // runes state after
for (uint8 i = 0; i < MAX_RUNES; ++i)
{
- uint8 mask = (1 << i);
- if (mask & runeMaskInitial && !(mask & runeMaskAfterCast)) // usable before andon cooldown now...
- {
- // float casts ensure the division is performed on floats as we need float result
- float baseCd = float(player->GetRuneBaseCooldown(i));
- data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
- }
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
}
}
}
+
if (castFlags & CAST_FLAG_ADJUST_MISSILE)
{
data << m_targets.GetElevation();
data << uint32(m_delayMoment);
}
- if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ if (castFlags & CAST_FLAG_PROJECTILE)
+ {
+ data << uint32(0); // Ammo display ID
+ data << uint32(0); // Inventory Type
+ }
if (castFlags & CAST_FLAG_VISUAL_CHAIN)
{
@@ -4031,79 +4076,21 @@ void Spell::SendSpellGo()
data << uint8(0);
}
- m_caster->SendMessageToSet(&data, true);
-}
-
-void Spell::WriteAmmoToPacket(WorldPacket* data)
-{
- uint32 ammoInventoryType = 0;
- uint32 ammoDisplayID = 0;
-
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ if (m_targets.GetTargetMask() & TARGET_FLAG_EXTRA_TARGETS)
{
- Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK);
- if (pItem)
+ data << uint32(0); // Extra targets count
+ /*
+ for (uint8 i = 0; i < count; ++i)
{
- ammoInventoryType = pItem->GetTemplate()->InventoryType;
- if (ammoInventoryType == INVTYPE_THROWN)
- ammoDisplayID = pItem->GetTemplate()->DisplayInfoID;
- else
- {
- uint32 ammoID = m_caster->ToPlayer()->GetUInt32Value(PLAYER_AMMO_ID);
- if (ammoID)
- {
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(ammoID);
- if (pProto)
- {
- ammoDisplayID = pProto->DisplayInfoID;
- ammoInventoryType = pProto->InventoryType;
- }
- }
- else if (m_caster->HasAura(46699)) // Requires No Ammo
- {
- ammoDisplayID = 5996; // normal arrow
- ammoInventoryType = INVTYPE_AMMO;
- }
- }
- }
- }
- else
- {
- for (uint8 i = 0; i < 3; ++i)
- {
- if (uint32 item_id = m_caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i))
- {
- if (ItemEntry const* itemEntry = sItemStore.LookupEntry(item_id))
- {
- if (itemEntry->Class == ITEM_CLASS_WEAPON)
- {
- switch (itemEntry->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_THROWN:
- ammoDisplayID = itemEntry->DisplayId;
- ammoInventoryType = itemEntry->InventoryType;
- break;
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- ammoDisplayID = 5996; // is this need fixing?
- ammoInventoryType = INVTYPE_AMMO;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- ammoDisplayID = 5998; // is this need fixing?
- ammoInventoryType = INVTYPE_AMMO;
- break;
- }
-
- if (ammoDisplayID)
- break;
- }
- }
- }
+ data << float(0); // Target Position X
+ data << float(0); // Target Position Y
+ data << float(0); // Target Position Z
+ data << uint64(0); // Target Guid
}
+ */
}
- *data << uint32(ammoDisplayID);
- *data << uint32(ammoInventoryType);
+ m_caster->SendMessageToSet(&data, true);
}
/// Writes miss and hit targets for a SMSG_SPELL_GO packet
@@ -4309,7 +4296,25 @@ void Spell::SendChannelStart(uint32 duration)
data.append(m_caster->GetPackGUID());
data << uint32(m_spellInfo->Id);
data << uint32(duration);
-
+ data << uint8(0); // immunity (castflag & 0x04000000)
+ /*
+ if (immunity)
+ {
+ data << uint32(); // CastSchoolImmunities
+ data << uint32(); // CastImmunities
+ }
+ */
+ data << uint8(0); // healPrediction (castflag & 0x40000000)
+ /*
+ if (healPrediction)
+ {
+ data.appendPackGUID(channelTarget); // target packguid
+ data << uint32(); // spellid
+ data << uint8(0); // unk3
+ if (unk3 == 2)
+ data.append(); // unk packed guid (unused ?)
+ }
+ */
m_caster->SendMessageToSet(&data, true);
m_timer = duration;
@@ -4336,8 +4341,8 @@ void Spell::SendResurrectRequest(Player* target)
data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness"
// override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)
- data << uint32(0);
+ // 4.2.2 edit : id of the spell used to resurect. (used client-side for Mass Resurect)
+ data << uint32(m_spellInfo->Id);
target->GetSession()->SendPacket(&data);
}
@@ -4419,7 +4424,7 @@ void Spell::TakePower()
bool hit = true;
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
- if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNE)
+ if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNES)
if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetGUID)
@@ -4435,7 +4440,7 @@ void Spell::TakePower()
}
}
- if (powerType == POWER_RUNE)
+ if (powerType == POWER_RUNES)
{
TakeRunePower(hit);
return;
@@ -4461,10 +4466,6 @@ void Spell::TakePower()
m_caster->ModifyPower(powerType, -m_powerCost);
else
m_caster->ModifyPower(powerType, -irand(0, m_powerCost/4));
-
- // Set the five second timer
- if (powerType == POWER_MANA && m_powerCost > 0)
- m_caster->SetLastManaUse(getMSTime());
}
void Spell::TakeAmmo()
@@ -4491,14 +4492,12 @@ void Spell::TakeAmmo()
m_caster->ToPlayer()->DestroyItemCount(pItem, count, true);
}
}
- else if (uint32 ammo = m_caster->ToPlayer()->GetUInt32Value(PLAYER_AMMO_ID))
- m_caster->ToPlayer()->DestroyItemCount(ammo, 1, true);
}
}
SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
{
- if (m_spellInfo->PowerType != POWER_RUNE || !runeCostID)
+ if (m_spellInfo->PowerType != POWER_RUNES || !runeCostID)
return SPELL_CAST_OK;
if (m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -4707,6 +4706,41 @@ void Spell::HandleThreatSpells()
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
}
+void Spell::HandleHolyPower(Player* caster)
+{
+ if (!caster)
+ return;
+
+ bool hit = true;
+ Player* modOwner = caster->GetSpellModOwner();
+
+ m_powerCost = caster->GetPower(POWER_HOLY_POWER); // Always use all the holy power we have
+
+ if (!m_powerCost || !modOwner)
+ return;
+
+ if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
+ {
+ for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ {
+ if (ihit->targetGUID == targetGUID)
+ {
+ if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS)
+ hit = false;
+
+ break;
+ }
+ }
+
+ // The spell did hit the target, apply aura cost mods if there are any.
+ if (hit)
+ {
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, m_powerCost);
+ m_caster->ModifyPower(POWER_HOLY_POWER, -m_powerCost);
+ }
+ }
+}
+
void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode)
{
effectHandleMode = mode;
@@ -4719,8 +4753,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "Spell: %u Effect : %u", m_spellInfo->Id, eff);
- // we do not need DamageMultiplier here.
- damage = CalculateDamage(i, NULL);
+ damage = CalculateDamage(i, unitTarget);
bool preventDefault = CallScriptEffectHandlers((SpellEffIndex)i, mode);
@@ -4788,7 +4821,7 @@ SpellCastResult Spell::CheckCast(bool strict)
Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT);
for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!(*i)->IsAffectingSpell(m_spellInfo))
continue;
checkForm = false;
break;
@@ -4814,7 +4847,7 @@ SpellCastResult Spell::CheckCast(bool strict)
Unit::AuraEffectList const& stateAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
for (Unit::AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
{
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ if ((*j)->IsAffectingSpell(m_spellInfo))
{
m_needComboPoints = false;
if ((*j)->GetMiscValue() == 1)
@@ -4846,7 +4879,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// cancel autorepeat spells if cast start when moving
// (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving())
+ // Do not cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
// skip stuck spell to allow use it in falling case and apply spell limitations at movement
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) &&
@@ -4947,14 +4981,14 @@ SpellCastResult Spell::CheckCast(bool strict)
if (!m_caster->ToPlayer()->InBattleground())
return SPELL_FAILED_ONLY_BATTLEGROUNDS;
- // do not allow spells to be cast in arenas
- // - with greater than 10 min CD without SPELL_ATTR4_USABLE_IN_ARENA flag
- // - with SPELL_ATTR4_NOT_USABLE_IN_ARENA flag
- if ((m_spellInfo->AttributesEx4 & SPELL_ATTR4_NOT_USABLE_IN_ARENA) ||
- (m_spellInfo->GetRecoveryTime() > 10 * MINUTE * IN_MILLISECONDS && !(m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)))
- if (MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId()))
- if (mapEntry->IsBattleArena())
- return SPELL_FAILED_NOT_IN_ARENA;
+ // do not allow spells to be cast in arenas or rated battlegrounds
+ if (Player* player = m_caster->ToPlayer())
+ if (player->InArena()/* || player->InRatedBattleGround() NYI*/)
+ {
+ SpellCastResult castResult = CheckArenaAndRatedBattlegroundCastRules();
+ if (castResult != SPELL_CAST_OK)
+ return castResult;
+ }
// zone check
if (m_caster->GetTypeId() == TYPEID_UNIT || !m_caster->ToPlayer()->isGameMaster())
@@ -5017,6 +5051,7 @@ SpellCastResult Spell::CheckCast(bool strict)
bool hasNonDispelEffect = false;
uint32 dispelMask = 0;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL)
{
if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->AttributesEx & SPELL_ATTR1_MELEE_COMBAT_START)
@@ -5032,16 +5067,6 @@ SpellCastResult Spell::CheckCast(bool strict)
hasNonDispelEffect = true;
break;
}
-
- if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered())
- {
- if (Unit* target = m_targets.GetUnitTarget())
- {
- DispelChargesList dispelList;
- target->GetDispellableAuraList(m_caster, dispelMask, dispelList);
- if (dispelList.empty())
- return SPELL_FAILED_NOTHING_TO_DISPEL;
- }
}
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -5049,6 +5074,26 @@ SpellCastResult Spell::CheckCast(bool strict)
// for effects of spells that have only one target
switch (m_spellInfo->Effects[i].Effect)
{
+ case SPELL_EFFECT_DUMMY:
+ {
+ if (m_spellInfo->Id == 19938) // Awaken Peon
+ {
+ Unit* unit = m_targets.GetUnitTarget();
+ if (!unit || !unit->HasAura(17743))
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ else if (m_spellInfo->Id == 31789) // Righteous Defense
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_DONT_REPORT;
+
+ Unit* target = m_targets.GetUnitTarget();
+ if (!target || !target->IsFriendlyTo(m_caster) || target->getAttackers().empty())
+ return SPELL_FAILED_BAD_TARGETS;
+
+ }
+ break;
+ }
case SPELL_EFFECT_LEARN_SPELL:
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -5616,8 +5661,9 @@ SpellCastResult Spell::CheckCasterAuras() const
bool usableInStun = m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_STUNNED;
// Glyph of Pain Suppression
+ // Allow Pain Suppression and Guardian Spirit to be cast while stunned
// there is no other way to handle it
- if (m_spellInfo->Id == 33206 && !m_caster->HasAura(63248))
+ if ((m_spellInfo->Id == 33206 || m_spellInfo->Id == 47788) && !m_caster->HasAura(63248))
usableInStun = false;
// Check whether the cast should be prevented by any state you might have.
@@ -5713,6 +5759,37 @@ SpellCastResult Spell::CheckCasterAuras() const
return SPELL_CAST_OK;
}
+SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules()
+{
+ bool isRatedBattleground = false; // NYI
+ bool isArena = !isRatedBattleground;
+
+ // check USABLE attributes
+ // USABLE takes precedence over NOT_USABLE
+ if (isRatedBattleground && m_spellInfo->AttributesEx9 & SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS)
+ return SPELL_CAST_OK;
+
+ if (isArena && m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)
+ return SPELL_CAST_OK;
+
+ // check NOT_USABLE attributes
+ if (m_spellInfo->AttributesEx4 & SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG)
+ return isArena ? SPELL_FAILED_NOT_IN_ARENA : SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND;
+
+ if (isArena && m_spellInfo->AttributesEx9 & SPELL_ATTR9_NOT_USABLE_IN_ARENA)
+ return SPELL_FAILED_NOT_IN_ARENA;
+
+ // check cooldowns
+ uint32 spellCooldown = m_spellInfo->GetRecoveryTime();
+ if (isArena && spellCooldown > 10 * MINUTE * IN_MILLISECONDS) // not sure if still needed
+ return SPELL_FAILED_NOT_IN_ARENA;
+
+ if (isRatedBattleground && spellCooldown > 15 * MINUTE * IN_MILLISECONDS)
+ return SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND;
+
+ return SPELL_CAST_OK;
+}
+
bool Spell::CanAutoCast(Unit* target)
{
uint64 targetguid = target->GetGUID();
@@ -5833,8 +5910,8 @@ SpellCastResult Spell::CheckPower()
return SPELL_FAILED_UNKNOWN;
}
- //check rune cost only if a spell has PowerType == POWER_RUNE
- if (m_spellInfo->PowerType == POWER_RUNE)
+ //check rune cost only if a spell has PowerType == POWER_RUNES
+ if (m_spellInfo->PowerType == POWER_RUNES)
{
SpellCastResult failReason = CheckRuneCost(m_spellInfo->RuneCostID);
if (failReason != SPELL_CAST_OK)
@@ -6026,25 +6103,7 @@ SpellCastResult Spell::CheckItems()
totems -= 1;
}
if (totems != 0)
- return SPELL_FAILED_TOTEMS; //0x7C
-
- // Check items for TotemCategory (items presence in inventory)
- uint32 TotemCategory = 2;
- for (int i= 0; i < 2; ++i)
- {
- if (m_spellInfo->TotemCategory[i] != 0)
- {
- if (p_caster->HasItemTotemCategory(m_spellInfo->TotemCategory[i]))
- {
- TotemCategory -= 1;
- continue;
- }
- }
- else
- TotemCategory -= 1;
- }
- if (TotemCategory != 0)
- return SPELL_FAILED_TOTEM_CATEGORY; //0x7B
+ return SPELL_FAILED_TOTEMS;
}
// special checks for spell effects
@@ -6084,7 +6143,7 @@ SpellCastResult Spell::CheckItems()
}
case SPELL_EFFECT_ENCHANT_ITEM:
if (m_spellInfo->Effects[i].ItemType && m_targets.GetItemTarget()
- && (m_targets.GetItemTarget()->IsWeaponVellum() || m_targets.GetItemTarget()->IsArmorVellum()))
+ && (m_targets.GetItemTarget()->IsVellum()))
{
// cannot enchant vellum for other player
if (m_targets.GetItemTarget()->GetOwner() != m_caster)
@@ -6258,46 +6317,6 @@ SpellCastResult Spell::CheckItems()
case ITEM_SUBCLASS_WEAPON_GUN:
case ITEM_SUBCLASS_WEAPON_BOW:
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- {
- uint32 ammo = m_caster->ToPlayer()->GetUInt32Value(PLAYER_AMMO_ID);
- if (!ammo)
- {
- // Requires No Ammo
- if (m_caster->HasAura(46699))
- break; // skip other checks
-
- return SPELL_FAILED_NO_AMMO;
- }
-
- ItemTemplate const* ammoProto = sObjectMgr->GetItemTemplate(ammo);
- if (!ammoProto)
- return SPELL_FAILED_NO_AMMO;
-
- if (ammoProto->Class != ITEM_CLASS_PROJECTILE)
- return SPELL_FAILED_NO_AMMO;
-
- // check ammo ws. weapon compatibility
- switch (pItem->GetTemplate()->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- if (ammoProto->SubClass != ITEM_SUBCLASS_ARROW)
- return SPELL_FAILED_NO_AMMO;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- if (ammoProto->SubClass != ITEM_SUBCLASS_BULLET)
- return SPELL_FAILED_NO_AMMO;
- break;
- default:
- return SPELL_FAILED_NO_AMMO;
- }
-
- if (!m_caster->ToPlayer()->HasItemCount(ammo))
- {
- m_caster->ToPlayer()->SetUInt32Value(PLAYER_AMMO_ID, 0);
- return SPELL_FAILED_NO_AMMO;
- }
- }; break;
case ITEM_SUBCLASS_WEAPON_WAND:
break;
default:
@@ -6574,7 +6593,7 @@ bool Spell::IsAutoActionResetSpell() const
bool Spell::IsNeedSendToClient() const
{
return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || m_spellInfo->IsChanneled() ||
- m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered());
+ (m_spellInfo->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered());
}
bool Spell::HaveTargetsForEffect(uint8 effect) const
@@ -6742,12 +6761,6 @@ void Spell::HandleLaunchPhase()
multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this);
bool usesAmmo = m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE;
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- {
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- usesAmmo=false;
- }
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
@@ -7220,7 +7233,7 @@ void Spell::PrepareTriggersExecutedOnHit()
Unit::AuraEffectList const& targetTriggers = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_TARGET_TRIGGER);
for (Unit::AuraEffectList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!(*i)->IsAffectingSpell(m_spellInfo))
continue;
SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo();
uint32 auraSpellIdx = (*i)->GetEffIndex();
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 191a7461fe9..1fd130a29ef 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -40,11 +40,11 @@ enum SpellCastFlags
{
CAST_FLAG_NONE = 0x00000000,
CAST_FLAG_PENDING = 0x00000001, // aoe combat log?
- CAST_FLAG_UNKNOWN_2 = 0x00000002,
+ CAST_FLAG_HAS_TRAJECTORY = 0x00000002,
CAST_FLAG_UNKNOWN_3 = 0x00000004,
CAST_FLAG_UNKNOWN_4 = 0x00000008, // ignore AOE visual
CAST_FLAG_UNKNOWN_5 = 0x00000010,
- CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
+ CAST_FLAG_PROJECTILE = 0x00000020,
CAST_FLAG_UNKNOWN_7 = 0x00000040,
CAST_FLAG_UNKNOWN_8 = 0x00000080,
CAST_FLAG_UNKNOWN_9 = 0x00000100,
@@ -69,7 +69,7 @@ enum SpellCastFlags
CAST_FLAG_UNKNOWN_28 = 0x08000000,
CAST_FLAG_UNKNOWN_29 = 0x10000000,
CAST_FLAG_UNKNOWN_30 = 0x20000000,
- CAST_FLAG_UNKNOWN_31 = 0x40000000,
+ CAST_FLAG_HEAL_PREDICTION = 0x40000000,
CAST_FLAG_UNKNOWN_32 = 0x80000000
};
@@ -253,7 +253,7 @@ class Spell
void EffectQuestClear(SpellEffIndex effIndex);
void EffectTeleUnitsFaceCaster(SpellEffIndex effIndex);
void EffectLearnSkill(SpellEffIndex effIndex);
- void EffectAddHonor(SpellEffIndex effIndex);
+ void EffectPlayMovie(SpellEffIndex effIndex);
void EffectTradeSkill(SpellEffIndex effIndex);
void EffectEnchantItemPerm(SpellEffIndex effIndex);
void EffectEnchantItemTmp(SpellEffIndex effIndex);
@@ -336,8 +336,12 @@ class Spell
void EffectActivateSpec(SpellEffIndex effIndex);
void EffectPlaySound(SpellEffIndex effIndex);
void EffectRemoveAura(SpellEffIndex effIndex);
+ void EffectDamageFromMaxHealthPCT(SpellEffIndex effIndex);
void EffectCastButtons(SpellEffIndex effIndex);
void EffectRechargeManaGem(SpellEffIndex effIndex);
+ void EffectGiveCurrency(SpellEffIndex effIndex);
+ void EffectResurrectWithAura(SpellEffIndex effIndex);
+ void EffectCreateAreaTrigger(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
@@ -397,6 +401,7 @@ class Spell
SpellCastResult CheckPower();
SpellCastResult CheckRuneCost(uint32 runeCostID);
SpellCastResult CheckCasterAuras() const;
+ SpellCastResult CheckArenaAndRatedBattlegroundCastRules();
int32 CalculateDamage(uint8 i, Unit const* target) const { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i]); }
@@ -408,7 +413,6 @@ class Spell
void DoCreateItem(uint32 i, uint32 itemtype);
void WriteSpellGoTargets(WorldPacket* data);
- void WriteAmmoToPacket(WorldPacket* data);
bool CheckEffectTarget(Unit const* target, uint32 eff) const;
bool CanAutoCast(Unit* target);
@@ -436,6 +440,7 @@ class Spell
void SendChannelStart(uint32 duration);
void SendResurrectRequest(Player* target);
+ void HandleHolyPower(Player* caster);
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode);
void HandleThreatSpells();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index fa82b6436d3..97a06415a9d 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -64,7 +64,10 @@
#include "AccountMgr.h"
#include "InstanceScript.h"
#include "PathGenerator.h"
+#include "Guild.h"
+#include "GuildMgr.h"
#include "ReputationMgr.h"
+#include "AreaTrigger.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@@ -113,14 +116,14 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectJumpDest, // 42 SPELL_EFFECT_JUMP_DEST
&Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
&Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
- &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
+ &Spell::EffectPlayMovie, // 45 SPELL_EFFECT_PLAY_MOVIE
&Spell::EffectUnused, // 46 SPELL_EFFECT_SPAWN clientside, unit appears as if it was just spawned
&Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
&Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
&Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
&Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
&Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
- &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
+ &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT unused
&Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
&Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
&Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
@@ -231,8 +234,26 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534
&Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
&Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
- &Spell::EffectNULL, //163 unused
+ &Spell::EffectUnused, //163 SPELL_EFFECT_163 unused
&Spell::EffectRemoveAura, //164 SPELL_EFFECT_REMOVE_AURA
+ &Spell::EffectDamageFromMaxHealthPCT, //165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
+ &Spell::EffectGiveCurrency, //166 SPELL_EFFECT_GIVE_CURRENCY
+ &Spell::EffectNULL, //167 SPELL_EFFECT_167
+ &Spell::EffectNULL, //168 SPELL_EFFECT_168
+ &Spell::EffectNULL, //169 SPELL_EFFECT_DESTROY_ITEM
+ &Spell::EffectNULL, //170 SPELL_EFFECT_170
+ &Spell::EffectNULL, //171 SPELL_EFFECT_171
+ &Spell::EffectResurrectWithAura, //172 SPELL_EFFECT_RESURRECT_WITH_AURA
+ &Spell::EffectNULL, //173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
+ &Spell::EffectNULL, //174 SPELL_EFFECT_174
+ &Spell::EffectUnused, //175 SPELL_EFFECT_175 unused
+ &Spell::EffectNULL, //176 SPELL_EFFECT_176
+ &Spell::EffectNULL, //177 SPELL_EFFECT_177
+ &Spell::EffectUnused, //178 SPELL_EFFECT_178 unused
+ &Spell::EffectCreateAreaTrigger, //179 SPELL_EFFECT_CREATE_AREATRIGGER
+ &Spell::EffectUnused, //180 SPELL_EFFECT_180 unused
+ &Spell::EffectUnused, //181 SPELL_EFFECT_181 unused
+ &Spell::EffectNULL, //182 SPELL_EFFECT_182
};
void Spell::EffectNULL(SpellEffIndex /*effIndex*/)
@@ -261,13 +282,13 @@ void Spell::EffectResurrectNew(SpellEffIndex effIndex)
Player* target = unitTarget->ToPlayer();
- if (target->isRessurectRequested()) // already have one active request
+ if (target->IsRessurectRequested()) // already have one active request
return;
uint32 health = damage;
uint32 mana = m_spellInfo->Effects[effIndex].MiscValue;
ExecuteLogEffectResurrect(effIndex, target);
- target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
+ target->SetResurrectRequestData(m_caster, health, mana, 0);
SendResurrectRequest(target);
}
@@ -370,15 +391,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
}
case SPELLFAMILY_WARRIOR:
{
- // Shield Slam
- if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 1209)
- {
- uint8 level = m_caster->getLevel();
- uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 24.5f), uint32(float(level) * 34.5f));
- damage += int32(m_caster->ApplyEffectModifiers(m_spellInfo, effIndex, float(block_value)));
- }
// Victory Rush
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x100)
+ if (m_spellInfo->Id == 34428)
ApplyPct(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
// Shockwave
else if (m_spellInfo->Id == 46968)
@@ -395,73 +409,12 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Incinerate Rank 1 & 2
if ((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID == 2128)
{
- // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
+ // Incinerate does more dmg (dmg/6) if the target have Immolate debuff.
// Check aura state for speed but aura state set not only for Immolate spell
if (unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
{
if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0))
- damage += damage/4;
- }
- }
- // Conflagrate - consumes Immolate or Shadowflame
- else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
- {
- AuraEffect const* aura = NULL; // found req. aura for damage calculation
-
- Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
- for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
- {
- // for caster applied auras only
- if ((*i)->GetSpellInfo()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
- (*i)->GetCasterGUID() != m_caster->GetGUID())
- continue;
-
- // Immolate
- if ((*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x4)
- {
- aura = *i; // it selected always if exist
- break;
- }
-
- // Shadowflame
- if ((*i)->GetSpellInfo()->SpellFamilyFlags[2] & 0x00000002)
- aura = *i; // remember but wait possible Immolate as primary priority
- }
-
- // found Immolate or Shadowflame
- if (aura)
- {
- uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
- pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
- uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
- damage += int32(CalculatePct(pdamage * baseTotalTicks, pct_dir));
-
- uint32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 2)) / 3;
- m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(int32(CalculatePct(pdamage * baseTotalTicks, pct_dot)));
-
- apply_direct_bonus = false;
- // Glyph of Conflagrate
- if (!m_caster->HasAura(56235))
- unitTarget->RemoveAurasDueToSpell(aura->GetId(), m_caster->GetGUID());
-
- break;
- }
- }
- // Shadow Bite
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000)
- {
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet())
- {
- if (Player* owner = m_caster->GetOwner()->ToPlayer())
- {
- if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 214, 0))
- {
- int32 bp0 = aurEff->GetId() == 54037 ? 4 : 8;
- m_caster->CastCustomSpell(m_caster, 54425, &bp0, NULL, NULL, true);
- }
- }
+ damage += damage / 6;
}
}
break;
@@ -492,20 +445,10 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Ferocious Bite
if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0] == 6587)
{
- // converts each extra point of energy into ($f1+$AP/410) additional damage
- float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
- float multiple = ap / 410 + m_spellInfo->Effects[effIndex].DamageMultiplier;
- int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -30));
- damage += int32(energy * multiple);
- damage += int32(CalculatePct(m_caster->ToPlayer()->GetComboPoints() * ap, 7));
- }
- // Wrath
- else if (m_spellInfo->SpellFamilyFlags[0] & 0x00000001)
- {
- // Improved Insect Swarm
- if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
- if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000, 0, 0))
- AddPct(damage, aurEff->GetAmount());
+ // converts each extra point of energy ( up to 25 energy ) into additional damage
+ int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -25));
+ // 25 energy = 100% more damage
+ AddPct(damage, energy * 4);
}
break;
}
@@ -585,62 +528,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
damage *= 2;
}
- // Steady Shot
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x1)
- {
- bool found = false;
- // check dazed affect
- Unit::AuraEffectList const& decSpeedList = unitTarget->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
- for (Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
- {
- if ((*iter)->GetSpellInfo()->SpellIconID == 15 && (*iter)->GetSpellInfo()->Dispel == 0)
- {
- found = true;
- break;
- }
- }
-
- /// @todo should this be put on taken but not done?
- if (found)
- damage += m_spellInfo->Effects[EFFECT_1].CalcValue();
-
- if (Player* caster = m_caster->ToPlayer())
- {
- // Add Ammo and Weapon damage plus RAP * 0.1
- if (Item* item = caster->GetWeaponForAttack(RANGED_ATTACK))
- {
- ItemTemplate const* weaponTemplate = item->GetTemplate();
- float dmg_min = weaponTemplate->Damage[0].DamageMin;
- float dmg_max = weaponTemplate->Damage[0].DamageMax;
- if (dmg_max == 0.0f && dmg_min > dmg_max)
- damage += int32(dmg_min);
- else
- damage += irand(int32(dmg_min), int32(dmg_max));
- damage += int32(caster->GetAmmoDPS() * weaponTemplate->Delay * 0.001f);
- }
- }
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Hammer of the Righteous
- if (m_spellInfo->SpellFamilyFlags[1]&0x00040000)
- {
- // Add main hand dps * effect[2] amount
- float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
- int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
- damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
- break;
- }
- // Shield of Righteousness
- if (m_spellInfo->SpellFamilyFlags[EFFECT_1] & 0x100000)
- {
- uint8 level = m_caster->getLevel();
- uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 29.5f), uint32(float(level) * 39.5f));
- damage += CalculatePct(block_value, m_spellInfo->Effects[EFFECT_1].CalcValue());
- break;
- }
break;
}
case SPELLFAMILY_DEATHKNIGHT:
@@ -815,15 +702,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
// special cases
switch (triggered_spell_id)
{
- // Mirror Image
- case 58832:
- {
- // Glyph of Mirror Image
- if (m_caster->HasAura(63093))
- m_caster->CastSpell(m_caster, 65047, true); // Mirror Image
-
- break;
- }
// Vanish (not exist)
case 18461:
{
@@ -856,10 +734,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
unitTarget->CastSpell(unitTarget, 7870, true);
return;
}
- // just skip
- case 23770: // Sayge's Dark Fortune of *
- // not exist, common cooldown can be implemented in scripts if need.
- return;
// Brittle Armor - (need add max stack of 24575 Brittle Armor)
case 29284:
{
@@ -1329,16 +1203,11 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- int32 power = damage;
- if (powerType == POWER_MANA)
- power -= unitTarget->GetSpellCritDamageReduction(power);
-
- int32 newDamage = -(unitTarget->ModifyPower(powerType, -int32(power)));
+ int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage));
float gainMultiplier = 0.0f;
- // Don`t restore from self drain
+ // Don't restore from self drain
if (m_caster != unitTarget)
{
gainMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
@@ -1412,12 +1281,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
damage = std::min(damage, maxDamage);
}
- int32 power = damage;
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- power -= unitTarget->GetSpellCritDamageReduction(power);
-
- int32 newDamage = -(unitTarget->ModifyPower(powerType, -power));
+ int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage));
// NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier
float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
@@ -1511,22 +1375,6 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
//addhealth += tickheal * tickcount;
//addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
}
- // Nourish
- else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
- {
- addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
-
- // Glyph of Nourish
- if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
- {
- Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
- for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i)
- {
- if (m_caster->GetGUID() == (*i)->GetCasterGUID())
- AddPct(addhealth, aurEff->GetAmount());
- }
- }
- }
// Death Pact - return pct of max health to caster
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
@@ -1672,7 +1520,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
if (msg != EQUIP_ERR_OK)
{
// convert to possible store amount
- if (msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ if (msg == EQUIP_ERR_INV_FULL || msg == EQUIP_ERR_ITEM_MAX_COUNT)
num_to_add -= no_space;
else
{
@@ -1701,6 +1549,11 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
// send info to the client
player->SendNewItem(pItem, num_to_add, true, bgType == 0);
+ if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = player->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_CRAFTED, player->GetGUID(), 0, pProto->ItemId);
+
+
// we succeeded in creating at least one item, so a levelup is possible
if (bgType == 0)
player->UpdateCraftSkill(m_spellInfo->Id);
@@ -1789,7 +1642,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
if (!caster->IsInWorld())
return;
DynamicObject* dynObj = new DynamicObject(false);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
{
delete dynObj;
return;
@@ -1841,13 +1694,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
level_multiplier = 4;
break;
case 31930: // Judgements of the Wise
- case 63375: // Improved Stormstrike
+ case 63375: // Primal Wisdom
case 68082: // Glyph of Seal of Command
damage = int32(CalculatePct(unitTarget->GetCreateMana(), damage));
break;
- case 48542: // Revitalize
- damage = int32(CalculatePct(unitTarget->GetMaxPower(power), damage));
- break;
case 67490: // Runic Mana Injector (mana gain increased by 25% for engineers - 3.2.0 patch change)
{
if (Player* player = m_caster->ToPlayer())
@@ -1855,9 +1705,6 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
AddPct(damage, 25);
break;
}
- case 71132: // Glyph of Shadow Word: Pain
- damage = int32(CalculatePct(unitTarget->GetCreateMana(), 1)); // set 1 as value, missing in dbc
- break;
default:
break;
}
@@ -1865,7 +1712,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
if (level_diff > 0)
damage -= level_multiplier * level_diff;
- if (damage < 0)
+ if (damage < 0 && power != POWER_ECLIPSE)
return;
if (unitTarget->GetMaxPower(power) == 0)
@@ -2199,9 +2046,9 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true);
- if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CANT_DO_RIGHT_NOW)
+ if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CLIENT_LOCKED_OUT)
{
- if (msg == EQUIP_ERR_CANT_DO_RIGHT_NOW) dest = EQUIPMENT_SLOT_MAINHAND;
+ if (msg == EQUIP_ERR_CLIENT_LOCKED_OUT) dest = EQUIPMENT_SLOT_MAINHAND;
// prevent crash at access and unexpected charges counting with item update queue corrupt
if (m_CastItem == m_targets.GetItemTarget())
@@ -2540,7 +2387,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
// Devour Magic
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
{
- int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue();
+ int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue(m_caster);
m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
// Glyph of Felhunter
if (Unit* owner = m_caster->GetOwner())
@@ -2617,7 +2464,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)
return;
DynamicObject* dynObj = new DynamicObject(true);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
{
delete dynObj;
return;
@@ -2674,7 +2521,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex)
unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), skillval?skillval:1, damage*75);
}
-void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
+void Spell::EffectPlayMovie(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
@@ -2682,27 +2529,11 @@ void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- // not scale value for item based reward (/10 value expected)
- if (m_CastItem)
- {
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage/10);
- TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUIDLow());
+ uint32 movieId = GetSpellInfo()->Effects[effIndex].MiscValue;
+ if (!sMovieStore.LookupEntry(movieId))
return;
- }
- // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
- if (damage <= 50)
- {
- uint32 honor_reward = Trinity::Honor::hk_honor_at_level(unitTarget->getLevel(), float(damage));
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, honor_reward);
- TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUIDLow());
- }
- else
- {
- //maybe we have correct honor_gain in damage already
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage);
- TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
- }
+ unitTarget->ToPlayer()->SendMovieStart(movieId);
}
void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/)
@@ -2730,7 +2561,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
Player* p_caster = (Player*)m_caster;
// Handle vellums
- if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum())
+ if (itemTarget->IsVellum())
{
// destroy one vellum from stack
uint32 count = 1;
@@ -2855,58 +2686,6 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
Player* p_caster = (Player*)m_caster;
- // Rockbiter Weapon apply to both weapon
- if (!itemTarget)
- return;
- if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x400000)
- {
- uint32 spell_id = 0;
-
- // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
- // Note: damage calculated (correctly) with rounding int32(float(v)) but
- // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
- switch (damage)
- {
- // Rank 1
- case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
- // Rank 2
- case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
- case 5: spell_id = 36751; break; // 20%
- // Rank 3
- case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
- case 7: spell_id = 36755; break; // 20%
- // Rank 4
- case 9: spell_id = 36761; break; // 0% [ 7% == 6]
- case 10: spell_id = 36758; break; // 14%
- case 11: spell_id = 36760; break; // 20%
- default:
- TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", damage);
- return;
- }
-
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
- if (!spellInfo)
- {
- TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
- return;
-
- }
-
- for (int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
- {
- if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
- {
- if (item->IsFitToSpellRequirements(m_spellInfo))
- {
- Spell* spell = new Spell(m_caster, spellInfo, TRIGGERED_FULL_MASK);
- SpellCastTargets targets;
- targets.SetItemTarget(item);
- spell->prepare(&targets);
- }
- }
- }
- return;
- }
if (!itemTarget)
return;
@@ -3157,9 +2936,6 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
return;
}
- if (m_spellInfo->Id == 62124)
- m_caster->CastSpell(unitTarget, 67485, true);
-
// Also use this effect to set the taunter's threat to the taunted creature's highest value
if (unitTarget->getThreatManager().getCurrentVictim())
{
@@ -3221,74 +2997,26 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID()))
{
- // 58388 - Glyph of Devastate dummy aura.
- if (int32 num = (needCast ? 0 : 1) + (m_caster->HasAura(58388) ? 1 : 0))
+ if (int32 num = (needCast ? 0 : 1))
aur->ModStackAmount(num);
fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget);
}
}
- if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow
- {
- if (unitTarget->IsImmunedToSpellEffect(m_spellInfo, EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER)
- {
- m_damage = 0;
- return;
- }
- }
break;
}
case SPELLFAMILY_ROGUE:
{
- // Fan of Knives, Hemorrhage, Ghostly Strike
- if ((m_spellInfo->SpellFamilyFlags[1] & 0x40000)
- || (m_spellInfo->SpellFamilyFlags[0] & 0x6000000))
+ // Hemorrhage
+ if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
{
- // Hemorrhage
- if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
- {
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
- }
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
// 50% more damage with daggers
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (Item* item = m_caster->ToPlayer()->GetWeaponForAttack(m_attackType, true))
if (item->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
totalDamagePercentMod *= 1.5f;
}
- // Mutilate (for each hand)
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x6)
- {
- bool found = false;
- // fast check
- if (unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON, m_spellInfo, m_caster))
- found = true;
- // full aura scan
- else
- {
- Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras();
- for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- if (itr->second->GetBase()->GetSpellInfo()->Dispel == DISPEL_POISON)
- {
- found = true;
- break;
- }
- }
- }
-
- if (found)
- totalDamagePercentMod *= 1.2f; // 120% if poisoned
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Seal of Command Unleashed
- if (m_spellInfo->Id == 20467)
- {
- spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
- spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
- }
break;
}
case SPELLFAMILY_SHAMAN:
@@ -3319,54 +3047,35 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
{
// Kill Shot - bonus damage from Ranged Attack Power
if (m_spellInfo->SpellFamilyFlags[1] & 0x800000)
- spell_bonus += int32(0.4f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
+ spell_bonus += int32(0.45f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
- // Plague Strike
- if (m_spellInfo->SpellFamilyFlags[0] & 0x1)
- {
- // Glyph of Plague Strike
- if (AuraEffect const* aurEff = m_caster->GetAuraEffect(58657, EFFECT_0))
- AddPct(totalDamagePercentMod, aurEff->GetAmount());
- break;
- }
// Blood Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
{
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
AddPct(totalDamagePercentMod, bonusPct);
-
- // Glyph of Blood Strike
- if (m_caster->GetAuraEffect(59332, EFFECT_0))
- if (unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
- AddPct(totalDamagePercentMod, 20);
break;
}
// Death Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x10)
{
// Glyph of Death Strike
+ // 2% more damage per 5 runic power, up to a maximum of 40%
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0))
- if (uint32 runic = std::min<uint32>(m_caster->GetPower(POWER_RUNIC_POWER), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()))
+ if (uint32 runic = std::min<uint32>(uint32(m_caster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster)))
AddPct(totalDamagePercentMod, runic);
break;
}
// Obliterate (12.5% more damage per disease)
if (m_spellInfo->SpellFamilyFlags[1] & 0x20000)
{
- bool consumeDiseases = true;
- // Annihilation
- if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2710, EFFECT_0))
- // Do not consume diseases if roll sucesses
- if (roll_chance_i(aurEff->GetAmount()))
- consumeDiseases = false;
-
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f;
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false) / 2.0f;
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
@@ -3382,7 +3091,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Heart Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000)
{
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
@@ -3526,7 +3235,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex)
// check if we can interrupt spell
if ((spell->getState() == SPELL_STATE_CASTING
|| (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f))
- && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE
+ && (curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE || curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_UNK)
&& ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT)
|| (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT)))
{
@@ -4469,12 +4178,16 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
switch (m_glyphIndex)
{
case 0:
- case 1: minLevel = 15; break;
- case 2: minLevel = 50; break;
- case 3: minLevel = 30; break;
- case 4: minLevel = 70; break;
- case 5: minLevel = 80; break;
+ case 1:
+ case 6: minLevel = 25; break;
+ case 2:
+ case 3:
+ case 7: minLevel = 50; break;
+ case 4:
+ case 5:
+ case 8: minLevel = 75; break;
}
+
if (minLevel && m_caster->getLevel() < minLevel)
{
SendCastResult(SPELL_FAILED_GLYPH_SOCKET_LOCKED);
@@ -4482,13 +4195,13 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
}
// apply new one
- if (uint32 glyph = m_spellInfo->Effects[effIndex].MiscValue)
+ if (uint32 newGlyph = m_spellInfo->Effects[effIndex].MiscValue)
{
- if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
+ if (GlyphPropertiesEntry const* newGlyphProperties = sGlyphPropertiesStore.LookupEntry(newGlyph))
{
- if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
+ if (GlyphSlotEntry const* newGlyphSlot = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
{
- if (gp->TypeFlags != gs->TypeFlags)
+ if (newGlyphProperties->TypeFlags != newGlyphSlot->TypeFlags)
{
SendCastResult(SPELL_FAILED_INVALID_GLYPH);
return; // glyph slot mismatch
@@ -4496,17 +4209,26 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
}
// remove old glyph
- if (uint32 oldglyph = player->GetGlyph(m_glyphIndex))
+ if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex))
{
- if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
+ if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
- player->RemoveAurasDueToSpell(old_gp->SpellId);
+ player->RemoveAurasDueToSpell(oldGlyphProperties->SpellId);
player->SetGlyph(m_glyphIndex, 0);
}
}
- player->CastSpell(m_caster, gp->SpellId, true);
- player->SetGlyph(m_glyphIndex, glyph);
+ player->CastSpell(m_caster, newGlyphProperties->SpellId, true);
+ player->SetGlyph(m_glyphIndex, newGlyph);
+ player->SendTalentsInfoData(false);
+ }
+ }
+ else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex)) // Removing the glyph, get the old one
+ {
+ if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
+ {
+ player->RemoveAurasDueToSpell(oldGlyphProperties->SpellId);
+ player->SetGlyph(m_glyphIndex, 0);
player->SendTalentsInfoData(false);
}
}
@@ -4722,7 +4444,7 @@ void Spell::EffectResurrect(SpellEffIndex effIndex)
Player* target = unitTarget->ToPlayer();
- if (target->isRessurectRequested()) // already have one active request
+ if (target->IsRessurectRequested()) // already have one active request
return;
uint32 health = target->CountPctFromMaxHealth(damage);
@@ -4730,7 +4452,7 @@ void Spell::EffectResurrect(SpellEffIndex effIndex)
ExecuteLogEffectResurrect(effIndex, target);
- target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
+ target->SetResurrectRequestData(m_caster, health, mana, 0);
SendResurrectRequest(target);
}
@@ -4878,6 +4600,7 @@ void Spell::EffectSelfResurrect(SpellEffIndex effIndex)
player->SetPower(POWER_MANA, mana);
player->SetPower(POWER_RAGE, 0);
player->SetPower(POWER_ENERGY, player->GetMaxPower(POWER_ENERGY));
+ player->SetPower(POWER_FOCUS, 0);
player->SpawnCorpseBones();
}
@@ -5719,6 +5442,11 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
if (!pet)
return;
+ // relocate
+ float px, py, pz;
+ unitTarget->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle());
+ pet->Relocate(px, py, pz, unitTarget->GetOrientation());
+
// add to world
pet->GetMap()->AddToMap(pet->ToCreature());
@@ -5902,6 +5630,7 @@ void Spell::EffectPlayMusic(SpellEffIndex effIndex)
WorldPacket data(SMSG_PLAY_MUSIC, 4);
data << uint32(soundid);
+ data << uint64(unitTarget->GetGUID());
unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
}
@@ -5937,8 +5666,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex)
switch (m_spellInfo->Id)
{
- case 58730: // Restricted Flight Area
- case 58600: // Restricted Flight Area
+ case 91604: // Restricted Flight Area
unitTarget->ToPlayer()->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
break;
default:
@@ -5955,6 +5683,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex)
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(soundId);
+ data << uint64(m_caster->GetGUID());
unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
}
@@ -5969,6 +5698,28 @@ void Spell::EffectRemoveAura(SpellEffIndex effIndex)
unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell);
}
+void Spell::EffectDamageFromMaxHealthPCT(SpellEffIndex /*effIndex*/)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget)
+ return;
+
+ m_damage += unitTarget->CountPctFromMaxHealth(damage);
+}
+
+void Spell::EffectGiveCurrency(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ unitTarget->ToPlayer()->ModifyCurrency(m_spellInfo->Effects[effIndex].MiscValue, damage);
+}
+
void Spell::EffectCastButtons(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
@@ -6000,10 +5751,10 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex)
if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
continue;
- if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
+ if (!(spellInfo->AttributesEx9 & SPELL_ATTR9_SUMMON_PLAYER_TOTEM))
continue;
- uint32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
+ int32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
if (m_caster->GetPower(POWER_MANA) < cost)
continue;
@@ -6097,3 +5848,54 @@ void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex)
m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true);
}
+
+void Spell::EffectResurrectWithAura(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || !unitTarget->IsInWorld())
+ return;
+
+ Player* target = unitTarget->ToPlayer();
+ if (!target)
+ return;
+
+ if (unitTarget->isAlive())
+ return;
+
+ if (target->IsRessurectRequested()) // already have one active request
+ return;
+
+ uint32 health = target->CountPctFromMaxHealth(damage);
+ uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
+ uint32 resurrectAura = 0;
+ if (sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[effIndex].TriggerSpell))
+ resurrectAura = GetSpellInfo()->Effects[effIndex].TriggerSpell;
+
+ if (resurrectAura && target->HasAura(resurrectAura))
+ return;
+
+ ExecuteLogEffectResurrect(effIndex, target);
+ target->SetResurrectRequestData(m_caster, health, mana, resurrectAura);
+ SendResurrectRequest(target);
+}
+
+void Spell::EffectCreateAreaTrigger(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ Position pos;
+ if (!m_targets.HasDst())
+ GetCaster()->GetPosition(&pos);
+ else
+ destTarget->GetPosition(&pos);
+
+ // trigger entry/miscvalue relation is currently unknown, for now use MiscValue as trigger entry
+ uint32 triggerEntry = GetSpellInfo()->Effects[effIndex].MiscValue;
+
+ AreaTrigger * areaTrigger = new AreaTrigger;
+ if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GenerateLowGuid(HIGHGUID_AREATRIGGER), triggerEntry, GetCaster(), GetSpellInfo(), pos))
+ delete areaTrigger;
+}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 6a4fe9abbdd..88cda9d5db9 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "SpellAuraDefines.h"
#include "SpellInfo.h"
+#include "SpellAuraDefines.h"
#include "SpellMgr.h"
#include "Spell.h"
#include "DBCStores.h"
@@ -317,34 +317,57 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
{TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 111
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 112
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 113
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 114
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 115
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 116
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 117
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 118
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 119
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 120
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 121
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 122
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 123
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 124
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 125
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 126
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 127
};
-SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
+SpellEffectInfo::SpellEffectInfo(SpellEntry const* /*spellEntry*/, SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* _effect)
{
+ SpellScalingEntry const* scaling = spellInfo->GetSpellScaling();
+
_spellInfo = spellInfo;
- _effIndex = effIndex;
- Effect = spellEntry->Effect[effIndex];
- ApplyAuraName = spellEntry->EffectApplyAuraName[effIndex];
- Amplitude = spellEntry->EffectAmplitude[effIndex];
- DieSides = spellEntry->EffectDieSides[effIndex];
- RealPointsPerLevel = spellEntry->EffectRealPointsPerLevel[effIndex];
- BasePoints = spellEntry->EffectBasePoints[effIndex];
- PointsPerComboPoint = spellEntry->EffectPointsPerComboPoint[effIndex];
- ValueMultiplier = spellEntry->EffectValueMultiplier[effIndex];
- DamageMultiplier = spellEntry->EffectDamageMultiplier[effIndex];
- BonusMultiplier = spellEntry->EffectBonusMultiplier[effIndex];
- MiscValue = spellEntry->EffectMiscValue[effIndex];
- MiscValueB = spellEntry->EffectMiscValueB[effIndex];
- Mechanic = Mechanics(spellEntry->EffectMechanic[effIndex]);
- TargetA = SpellImplicitTargetInfo(spellEntry->EffectImplicitTargetA[effIndex]);
- TargetB = SpellImplicitTargetInfo(spellEntry->EffectImplicitTargetB[effIndex]);
- RadiusEntry = spellEntry->EffectRadiusIndex[effIndex] ? sSpellRadiusStore.LookupEntry(spellEntry->EffectRadiusIndex[effIndex]) : NULL;
- ChainTarget = spellEntry->EffectChainTarget[effIndex];
- ItemType = spellEntry->EffectItemType[effIndex];
- TriggerSpell = spellEntry->EffectTriggerSpell[effIndex];
- SpellClassMask = spellEntry->EffectSpellClassMask[effIndex];
+ _effIndex = _effect ? _effect->EffectIndex : effIndex;
+ Effect = _effect ? _effect->Effect : 0;
+ ApplyAuraName = _effect ? _effect->EffectApplyAuraName : 0;
+ Amplitude = _effect ? _effect->EffectAmplitude : 0;
+ DieSides = _effect ? _effect->EffectDieSides : 0;
+ RealPointsPerLevel = _effect ? _effect->EffectRealPointsPerLevel : 0.0f;
+ BasePoints = _effect ? _effect->EffectBasePoints : 0;
+ PointsPerComboPoint = _effect ? _effect->EffectPointsPerComboPoint : 0.0f;
+ ValueMultiplier = _effect ? _effect->EffectValueMultiplier : 0.0f;
+ DamageMultiplier = _effect ? _effect->EffectDamageMultiplier : 0.0f;
+ BonusMultiplier = _effect ? _effect->EffectBonusMultiplier : 0.0f;
+ MiscValue = _effect ? _effect->EffectMiscValue : 0;
+ MiscValueB = _effect ? _effect->EffectMiscValueB : 0;
+ Mechanic = Mechanics(_effect ? _effect->EffectMechanic : 0);
+ TargetA = SpellImplicitTargetInfo(_effect ? _effect->EffectImplicitTargetA : 0);
+ TargetB = SpellImplicitTargetInfo(_effect ? _effect->EffectImplicitTargetB : 0);
+ RadiusEntry = _effect && _effect->EffectRadiusIndex ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex) : NULL;
+ MaxRadiusEntry = _effect && _effect->EffectRadiusMaxIndex ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusMaxIndex) : NULL;
+ ChainTarget = _effect ? _effect->EffectChainTarget : 0;
+ ItemType = _effect ? _effect->EffectItemType : 0;
+ TriggerSpell = _effect ? _effect->EffectTriggerSpell : 0;
+ SpellClassMask = _effect ? _effect->EffectSpellClassMask : flag96(0);
ImplicitTargetConditions = NULL;
+ ScalingMultiplier = scaling ? scaling->Multiplier[_effIndex] : 0.0f;
+ DeltaScalingMultiplier = scaling ? scaling->RandomMultiplier[_effIndex] : 0.0f;
+ ComboScalingMultiplier = scaling ? scaling->OtherMultiplier[_effIndex] : 0.0f;
}
bool SpellEffectInfo::IsEffect() const
@@ -403,37 +426,73 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const
return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA;
}
-int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const* /*target*/) const
+int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const* target) const
{
float basePointsPerLevel = RealPointsPerLevel;
int32 basePoints = bp ? *bp : BasePoints;
- int32 randomPoints = int32(DieSides);
+ float comboDamage = PointsPerComboPoint;
// base amount modification based on spell lvl vs caster lvl
- if (caster)
+ if (ScalingMultiplier != 0.0f)
{
- int32 level = int32(caster->getLevel());
- if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
- level = int32(_spellInfo->MaxLevel);
- else if (level < int32(_spellInfo->BaseLevel))
- level = int32(_spellInfo->BaseLevel);
- level -= int32(_spellInfo->SpellLevel);
- basePoints += int32(level * basePointsPerLevel);
- }
+ if (caster)
+ {
+ int32 level = caster->getLevel();
+ if (target && _spellInfo->IsPositiveEffect(_effIndex) && (Effect == SPELL_EFFECT_APPLY_AURA))
+ level = target->getLevel();
- // roll in a range <1;EffectDieSides> as of patch 3.3.3
- switch (randomPoints)
+ if (GtSpellScalingEntry const* gtScaling = sGtSpellScalingStore.LookupEntry((_spellInfo->ScalingClass != -1 ? _spellInfo->ScalingClass - 1 : MAX_CLASSES - 1) * 100 + level - 1))
+ {
+ float multiplier = gtScaling->value;
+ if (_spellInfo->CastTimeMax > 0 && _spellInfo->CastTimeMaxLevel > level)
+ multiplier *= float(_spellInfo->CastTimeMin + (level - 1) * (_spellInfo->CastTimeMax - _spellInfo->CastTimeMin) / (_spellInfo->CastTimeMaxLevel - 1)) / float(_spellInfo->CastTimeMax);
+ if (_spellInfo->CoefLevelBase > level)
+ multiplier *= (1.0f - _spellInfo->CoefBase) * (float)(level - 1) / (float)(_spellInfo->CoefLevelBase - 1) + _spellInfo->CoefBase;
+
+ float preciseBasePoints = ScalingMultiplier * multiplier;
+ if (DeltaScalingMultiplier)
+ {
+ float delta = DeltaScalingMultiplier * ScalingMultiplier * multiplier * 0.5f;
+ preciseBasePoints += frand(-delta, delta);
+ }
+
+ basePoints = int32(preciseBasePoints);
+
+ if (ComboScalingMultiplier)
+ comboDamage = ComboScalingMultiplier * multiplier;
+ }
+ }
+ }
+ else
{
- case 0: break;
- case 1: basePoints += 1; break; // range 1..1
- default:
- // range can have positive (1..rand) and negative (rand..1) values, so order its for irand
- int32 randvalue = (randomPoints >= 1)
- ? irand(1, randomPoints)
- : irand(randomPoints, 1);
+ if (caster)
+ {
+ int32 level = int32(caster->getLevel());
+ if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
+ level = int32(_spellInfo->MaxLevel);
+ else if (level < int32(_spellInfo->BaseLevel))
+ level = int32(_spellInfo->BaseLevel);
+ level -= int32(_spellInfo->SpellLevel);
+ basePoints += int32(level * basePointsPerLevel);
+ }
- basePoints += randvalue;
- break;
+ // roll in a range <1;EffectDieSides> as of patch 3.3.3
+ int32 randomPoints = int32(DieSides);
+ switch (randomPoints)
+ {
+ case 0: break;
+ case 1: basePoints += 1; break; // range 1..1
+ default:
+ {
+ // range can have positive (1..rand) and negative (rand..1) values, so order its for irand
+ int32 randvalue = (randomPoints >= 1)
+ ? irand(1, randomPoints)
+ : irand(randomPoints, 1);
+
+ basePoints += randvalue;
+ break;
+ }
+ }
}
float value = float(basePoints);
@@ -442,14 +501,26 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
if (caster)
{
// bonus amount from combo points
- if (caster->m_movedPlayer)
+ if (caster->m_movedPlayer && comboDamage)
if (uint8 comboPoints = caster->m_movedPlayer->GetComboPoints())
- if (float comboDamage = PointsPerComboPoint)
- value += comboDamage* comboPoints;
+ value += comboDamage * comboPoints;
value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value);
// amount multiplication based on caster's level
+/* REVIEW - MERGE <<<<<<< HEAD
+ if (!_spellInfo->GetSpellScaling() && !basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) &&
+ Effect != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE &&
+ Effect != SPELL_EFFECT_KNOCK_BACK &&
+ Effect != SPELL_EFFECT_ADD_EXTRA_ATTACKS &&
+ ApplyAuraName != SPELL_AURA_MOD_SPEED_ALWAYS &&
+ ApplyAuraName != SPELL_AURA_MOD_SPEED_NOT_STACK &&
+ ApplyAuraName != SPELL_AURA_MOD_INCREASE_SPEED &&
+ ApplyAuraName != SPELL_AURA_MOD_DECREASE_SPEED)
+ //there are many more: slow speed, -healing pct
+ value *= 0.25f * exp(caster->getLevel() * (70 - _spellInfo->SpellLevel) / 1000.0f);
+ //value = int32(value * (int32)getLevel() / (int32)(_spellInfo->spellLevel ? _spellInfo->spellLevel : 1));
+======= */
if (!caster->IsControlledByPlayer() &&
_spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() &&
!basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
@@ -500,6 +571,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
value *= casterScaler->ratio / spellScaler->ratio;
}
}
+// REVIEW - MERGE >>>>>>> master
}
return int32(value);
@@ -534,10 +606,23 @@ bool SpellEffectInfo::HasRadius() const
return RadiusEntry != NULL;
}
+bool SpellEffectInfo::HasMaxRadius() const
+{
+ return MaxRadiusEntry != NULL;
+}
+
float SpellEffectInfo::CalcRadius(Unit* caster, Spell* spell) const
{
if (!HasRadius())
+ {
+ if (HasMaxRadius())
+ {
+ //! Still not sure which to pick. Anyway at the current time (Patch 4.3.4) most of the spell effects
+ //! have no radius mod per level, and RadiusMin is equal to RadiusMax.
+ return MaxRadiusEntry->RadiusMin;
+ }
return 0.0f;
+ }
float radius = RadiusEntry->RadiusMin;
if (caster)
@@ -590,7 +675,7 @@ SpellTargetObjectTypes SpellEffectInfo::GetUsedTargetObjectType() const
return _data[Effect].UsedTargetObjectType;
}
-SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
+SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{
// implicit target type used target object type
{EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 0
@@ -758,14 +843,29 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 164 SPELL_EFFECT_REMOVE_AURA
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 165 SPELL_EFFECT_165
+ {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 166 SPELL_EFFECT_GIVE_CURRENCY
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 167 SPELL_EFFECT_167
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 168 SPELL_EFFECT_168
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_ITEM}, // 169 SPELL_EFFECT_DESTROY_ITEM
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 170 SPELL_EFFECT_170
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_171
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 172 SPELL_EFFECT_172
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 174 SPELL_EFFECT_174
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 175 SPELL_EFFECT_175
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 176 SPELL_EFFECT_176
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 177 SPELL_EFFECT_177
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 178 SPELL_EFFECT_178
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 179 SPELL_EFFECT_CREATE_AREATRIGGER
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_180
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 181 SPELL_EFFECT_181
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 182 SPELL_EFFECT_182
};
-SpellInfo::SpellInfo(SpellEntry const* spellEntry)
+SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects)
{
Id = spellEntry->Id;
- Category = spellEntry->Category;
- Dispel = spellEntry->Dispel;
- Mechanic = spellEntry->Mechanic;
Attributes = spellEntry->Attributes;
AttributesEx = spellEntry->AttributesEx;
AttributesEx2 = spellEntry->AttributesEx2;
@@ -774,75 +874,147 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
AttributesEx5 = spellEntry->AttributesEx5;
AttributesEx6 = spellEntry->AttributesEx6;
AttributesEx7 = spellEntry->AttributesEx7;
+ AttributesEx8 = spellEntry->AttributesEx8;
+ AttributesEx9 = spellEntry->AttributesEx9;
+ AttributesEx10 = spellEntry->AttributesEx10;
AttributesCu = 0;
- Stances = spellEntry->Stances;
- StancesNot = spellEntry->StancesNot;
- Targets = spellEntry->Targets;
- TargetCreatureType = spellEntry->TargetCreatureType;
- RequiresSpellFocus = spellEntry->RequiresSpellFocus;
- FacingCasterFlags = spellEntry->FacingCasterFlags;
- CasterAuraState = spellEntry->CasterAuraState;
- TargetAuraState = spellEntry->TargetAuraState;
- CasterAuraStateNot = spellEntry->CasterAuraStateNot;
- TargetAuraStateNot = spellEntry->TargetAuraStateNot;
- CasterAuraSpell = spellEntry->casterAuraSpell;
- TargetAuraSpell = spellEntry->targetAuraSpell;
- ExcludeCasterAuraSpell = spellEntry->excludeCasterAuraSpell;
- ExcludeTargetAuraSpell = spellEntry->excludeTargetAuraSpell;
CastTimeEntry = spellEntry->CastingTimeIndex ? sSpellCastTimesStore.LookupEntry(spellEntry->CastingTimeIndex) : NULL;
- RecoveryTime = spellEntry->RecoveryTime;
- CategoryRecoveryTime = spellEntry->CategoryRecoveryTime;
- StartRecoveryCategory = spellEntry->StartRecoveryCategory;
- StartRecoveryTime = spellEntry->StartRecoveryTime;
- InterruptFlags = spellEntry->InterruptFlags;
- AuraInterruptFlags = spellEntry->AuraInterruptFlags;
- ChannelInterruptFlags = spellEntry->ChannelInterruptFlags;
- ProcFlags = spellEntry->procFlags;
- ProcChance = spellEntry->procChance;
- ProcCharges = spellEntry->procCharges;
- MaxLevel = spellEntry->maxLevel;
- BaseLevel = spellEntry->baseLevel;
- SpellLevel = spellEntry->spellLevel;
DurationEntry = spellEntry->DurationIndex ? sSpellDurationStore.LookupEntry(spellEntry->DurationIndex) : NULL;
PowerType = spellEntry->powerType;
- ManaCost = spellEntry->manaCost;
- ManaCostPerlevel = spellEntry->manaCostPerlevel;
- ManaPerSecond = spellEntry->manaPerSecond;
- ManaPerSecondPerLevel = spellEntry->manaPerSecondPerLevel;
- ManaCostPercentage = spellEntry->ManaCostPercentage;
- RuneCostID = spellEntry->runeCostID;
RangeEntry = spellEntry->rangeIndex ? sSpellRangeStore.LookupEntry(spellEntry->rangeIndex) : NULL;
Speed = spellEntry->speed;
- StackAmount = spellEntry->StackAmount;
- for (uint8 i = 0; i < 2; ++i)
- Totem[i] = spellEntry->Totem[i];
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- Reagent[i] = spellEntry->Reagent[i];
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- ReagentCount[i] = spellEntry->ReagentCount[i];
- EquippedItemClass = spellEntry->EquippedItemClass;
- EquippedItemSubClassMask = spellEntry->EquippedItemSubClassMask;
- EquippedItemInventoryTypeMask = spellEntry->EquippedItemInventoryTypeMask;
- for (uint8 i = 0; i < 2; ++i)
- TotemCategory[i] = spellEntry->TotemCategory[i];
for (uint8 i = 0; i < 2; ++i)
SpellVisual[i] = spellEntry->SpellVisual[i];
SpellIconID = spellEntry->SpellIconID;
ActiveIconID = spellEntry->activeIconID;
- for (uint8 i = 0; i < 16; ++i)
- SpellName[i] = spellEntry->SpellName[i];
- for (uint8 i = 0; i < 16; ++i)
- Rank[i] = spellEntry->Rank[i];
- MaxTargetLevel = spellEntry->MaxTargetLevel;
- MaxAffectedTargets = spellEntry->MaxAffectedTargets;
- SpellFamilyName = spellEntry->SpellFamilyName;
- SpellFamilyFlags = spellEntry->SpellFamilyFlags;
- DmgClass = spellEntry->DmgClass;
- PreventionType = spellEntry->PreventionType;
- AreaGroupId = spellEntry->AreaGroupId;
+ SpellName = spellEntry->SpellName;
+ Rank = spellEntry->Rank;
SchoolMask = spellEntry->SchoolMask;
+ RuneCostID = spellEntry->runeCostID;
+ SpellDifficultyId = spellEntry->SpellDifficultyId;
+ SpellScalingId = spellEntry->SpellScalingId;
+ SpellAuraOptionsId = spellEntry->SpellAuraOptionsId;
+ SpellAuraRestrictionsId = spellEntry->SpellAuraRestrictionsId;
+ SpellCastingRequirementsId = spellEntry->SpellCastingRequirementsId;
+ SpellCategoriesId = spellEntry->SpellCategoriesId;
+ SpellClassOptionsId = spellEntry->SpellClassOptionsId;
+ SpellCooldownsId = spellEntry->SpellCooldownsId;
+ SpellEquippedItemsId = spellEntry->SpellEquippedItemsId;
+ SpellInterruptsId = spellEntry->SpellInterruptsId;
+ SpellLevelsId = spellEntry->SpellLevelsId;
+ SpellPowerId = spellEntry->SpellPowerId;
+ SpellReagentsId = spellEntry->SpellReagentsId;
+ SpellShapeshiftId = spellEntry->SpellShapeshiftId;
+ SpellTargetRestrictionsId = spellEntry->SpellTargetRestrictionsId;
+ SpellTotemsId = spellEntry->SpellTotemsId;
+
+ // SpellDifficultyEntry
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- Effects[i] = SpellEffectInfo(spellEntry, this, i);
+ Effects[i] = SpellEffectInfo(spellEntry, this, i, effects[i]);
+
+ // SpellScalingEntry
+ SpellScalingEntry const* _scaling = GetSpellScaling();
+ CastTimeMin = _scaling ? _scaling->CastTimeMin : 0;
+ CastTimeMax = _scaling ?_scaling->CastTimeMax : 0;
+ CastTimeMaxLevel = _scaling ? _scaling->CastTimeMaxLevel : 0;
+ ScalingClass = _scaling ? _scaling->ScalingClass : 0;
+ CoefBase = _scaling ? _scaling->CoefBase : 0;
+ CoefLevelBase = _scaling ? _scaling->CoefLevelBase : 0;
+
+ // SpellAuraOptionsEntry
+ SpellAuraOptionsEntry const* _options = GetSpellAuraOptions();
+ ProcFlags = _options ? _options->procFlags : 0;
+ ProcChance = _options ? _options->procChance : 0;
+ ProcCharges = _options ? _options->procCharges : 0;
+ StackAmount = _options ? _options->StackAmount : 0;
+
+ // SpellAuraRestrictionsEntry
+ SpellAuraRestrictionsEntry const* _aura = GetSpellAuraRestrictions();
+ CasterAuraState = _aura ? _aura->CasterAuraState : 0;
+ TargetAuraState = _aura ? _aura->TargetAuraState : 0;
+ CasterAuraStateNot = _aura ? _aura->CasterAuraStateNot : 0;
+ TargetAuraStateNot = _aura ? _aura->TargetAuraStateNot : 0;
+ CasterAuraSpell = _aura ? _aura->casterAuraSpell : 0;
+ TargetAuraSpell = _aura ? _aura->targetAuraSpell : 0;
+ ExcludeCasterAuraSpell = _aura ? _aura->excludeCasterAuraSpell : 0;
+ ExcludeTargetAuraSpell = _aura ? _aura->excludeTargetAuraSpell : 0;
+
+ // SpellCastingRequirementsEntry
+ SpellCastingRequirementsEntry const* _castreq = GetSpellCastingRequirements();
+ RequiresSpellFocus = _castreq ? _castreq->RequiresSpellFocus : 0;
+ FacingCasterFlags = _castreq ? _castreq->FacingCasterFlags : 0;
+ AreaGroupId = _castreq ? _castreq->AreaGroupId : -1;
+
+ // SpellCategoriesEntry
+ SpellCategoriesEntry const* _categorie = GetSpellCategories();
+ Category = _categorie ? _categorie->Category : 0;
+ Dispel = _categorie ? _categorie->Dispel : 0;
+ Mechanic = _categorie ? _categorie->Mechanic : 0;
+ StartRecoveryCategory = _categorie ? _categorie->StartRecoveryCategory : 0;
+ DmgClass = _categorie ? _categorie->DmgClass : 0;
+ PreventionType = _categorie ? _categorie->PreventionType : 0;
+
+ // SpellClassOptionsEntry
+ SpellClassOptionsEntry const* _class = GetSpellClassOptions();
+ SpellFamilyName = _class ? _class->SpellFamilyName : 0;
+ SpellFamilyFlags = _class ? _class->SpellFamilyFlags : flag96(0);
+
+ // SpellCooldownsEntry
+ SpellCooldownsEntry const* _cooldowns = GetSpellCooldowns();
+ RecoveryTime = _cooldowns ? _cooldowns->RecoveryTime : 0;
+ CategoryRecoveryTime = _cooldowns ? _cooldowns->CategoryRecoveryTime : 0;
+ StartRecoveryTime = _cooldowns ? _cooldowns->StartRecoveryTime : 0;
+
+ // SpellEquippedItemsEntry
+ SpellEquippedItemsEntry const* _equipped = GetSpellEquippedItems();
+ EquippedItemClass = _equipped ? _equipped->EquippedItemClass : -1;
+ EquippedItemSubClassMask = _equipped ?_equipped->EquippedItemSubClassMask : -1;
+ EquippedItemInventoryTypeMask = _equipped ? _equipped->EquippedItemInventoryTypeMask : -1;
+
+ // SpellInterruptsEntry
+ SpellInterruptsEntry const* _interrupt = GetSpellInterrupts();
+ InterruptFlags = _interrupt ? _interrupt->InterruptFlags : 0;
+ AuraInterruptFlags = _interrupt ? _interrupt->AuraInterruptFlags : 0;
+ ChannelInterruptFlags = _interrupt ? _interrupt->ChannelInterruptFlags : 0;
+
+ // SpellLevelsEntry
+ SpellLevelsEntry const* _levels = GetSpellLevels();
+ MaxLevel = _levels ? _levels->maxLevel : 0;
+ BaseLevel = _levels ? _levels->baseLevel : 0;
+ SpellLevel = _levels ? _levels->spellLevel : 0;
+
+ // SpellPowerEntry
+ SpellPowerEntry const* _power = GetSpellPower();
+ ManaCost = _power ? _power->manaCost : 0;
+ ManaCostPerlevel = _power ? _power->manaCostPerlevel : 0;
+ ManaCostPercentage = _power ? _power->ManaCostPercentage : 0;
+ ManaPerSecond = _power ? _power->manaPerSecond : 0;
+
+ // SpellReagentsEntry
+ SpellReagentsEntry const* _reagents = GetSpellReagents();
+ for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
+ Reagent[i] = _reagents ? _reagents->Reagent[i] : 0;
+ for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
+ ReagentCount[i] = _reagents ? _reagents->ReagentCount[i] : 0;
+
+ // SpellShapeshiftEntry
+ SpellShapeshiftEntry const* _shapeshift = GetSpellShapeshift();
+ Stances = _shapeshift ? _shapeshift->Stances : 0;
+ StancesNot = _shapeshift ? _shapeshift->StancesNot : 0;
+
+ // SpellTargetRestrictionsEntry
+ SpellTargetRestrictionsEntry const* _target = GetSpellTargetRestrictions();
+ Targets = _target ? _target->Targets : 0;
+ TargetCreatureType = _target ? _target->TargetCreatureType : 0;
+ MaxAffectedTargets = _target ? _target->MaxAffectedTargets : 0;
+
+ // SpellTotemsEntry
+ SpellTotemsEntry const* _totem = GetSpellTotems();
+ for (uint8 i = 0; i < 2; ++i)
+ TotemCategory[i] = _totem ? _totem->TotemCategory[i] : 0;
+ for (uint8 i = 0; i < 2; ++i)
+ Totem[i] = _totem ? _totem->Totem[i] : 0;
+
ExplicitTargetMask = _GetExplicitTargetMask();
ChainEntry = NULL;
}
@@ -1277,6 +1449,7 @@ bool SpellInfo::IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInf
case SPELL_SPECIFIC_AURA:
case SPELL_SPECIFIC_STING:
case SPELL_SPECIFIC_CURSE:
+ case SPELL_SPECIFIC_BANE:
case SPELL_SPECIFIC_ASPECT:
case SPELL_SPECIFIC_JUDGEMENT:
case SPELL_SPECIFIC_WARLOCK_CORRUPTION:
@@ -1303,10 +1476,10 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const
return SPELL_CAST_OK;
bool actAsShifted = false;
- SpellShapeshiftEntry const* shapeInfo = NULL;
+ SpellShapeshiftFormEntry const* shapeInfo = NULL;
if (form > 0)
{
- shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
+ shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
if (!shapeInfo)
{
TC_LOG_ERROR(LOG_FILTER_SPELLS_AURAS, "GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
@@ -1458,17 +1631,27 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
}
// aura limitations
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (player)
{
- if (!Effects[i].IsAura())
- continue;
- switch (Effects[i].ApplyAuraName)
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED:
- case SPELL_AURA_FLY:
+ if (!Effects[i].IsAura())
+ continue;
+
+ switch (Effects[i].ApplyAuraName)
{
- if (player && !player->IsKnowHowFlyIn(map_id, zone_id))
- return SPELL_FAILED_INCORRECT_AREA;
+ case SPELL_AURA_FLY:
+ {
+ if (!player->IsKnowHowFlyIn(map_id, zone_id))
+ return SPELL_FAILED_INCORRECT_AREA;
+ break;
+ }
+ case SPELL_AURA_MOUNTED:
+ {
+ if (Effects[i].MiscValueB && !player->GetMountCapability(Effects[i].MiscValueB))
+ return SPELL_FAILED_NOT_HERE;
+ break;
+ }
}
}
}
@@ -1668,8 +1851,8 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
{
if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
{
- SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(Effects[effIndex].MiscValue);
- if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag
+ SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(Effects[effIndex].MiscValue);
+ if (shapeShiftFromEntry && (shapeShiftFromEntry->flags1 & 1) == 0) // unk flag
checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
break;
}
@@ -1935,6 +2118,10 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const
}
case SPELLFAMILY_WARLOCK:
{
+ // Warlock (Bane of Doom | Bane of Agony | Bane of Havoc)
+ if (Id == 603 || Id == 980 || Id == 80240)
+ return SPELL_SPECIFIC_BANE;
+
// only warlock curses have this
if (Dispel == DISPEL_CURSE)
return SPELL_SPECIFIC_CURSE;
@@ -2069,11 +2256,20 @@ int32 SpellInfo::GetMaxDuration() const
uint32 SpellInfo::CalcCastTime(Unit* caster, Spell* spell) const
{
+ int32 castTime = 0;
+
// not all spells have cast time index and this is all is pasiive abilities
- if (!CastTimeEntry)
- return 0;
+ if (caster && CastTimeMax > 0)
+ {
+ castTime = CastTimeMax;
+ if (CastTimeMaxLevel > int32(caster->getLevel()))
+ castTime = CastTimeMin + int32(caster->getLevel() - 1) * (CastTimeMax - CastTimeMin) / (CastTimeMaxLevel - 1);
+ }
+ else if (CastTimeEntry)
+ castTime = CastTimeEntry->CastTime;
- int32 castTime = CastTimeEntry->CastTime;
+ if (!castTime)
+ return 0;
if (caster)
caster->ModSpellCastTime(this, castTime, spell);
@@ -2148,10 +2344,9 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
case POWER_RAGE:
case POWER_FOCUS:
case POWER_ENERGY:
- case POWER_HAPPINESS:
powerCost += int32(CalculatePct(caster->GetMaxPower(Powers(PowerType)), ManaCostPercentage));
break;
- case POWER_RUNE:
+ case POWER_RUNES:
case POWER_RUNIC_POWER:
TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "CalculateManaCost: Not implemented yet!");
break;
@@ -2160,17 +2355,27 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
return 0;
}
}
- SpellSchools school = GetFirstSchoolInMask(schoolMask);
- // Flat mod from caster auras by spell school
- powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
+
+ // Flat mod from caster auras by spell school and power type
+ Unit::AuraEffectList const& auras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL);
+ for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
+ {
+ if (!((*i)->GetMiscValue() & schoolMask))
+ continue;
+ if (!((*i)->GetMiscValueB() & (1 << PowerType)))
+ continue;
+ powerCost += (*i)->GetAmount();
+ }
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
if (AttributesEx4 & SPELL_ATTR4_SPELL_VS_EXTEND_COST)
{
uint32 speed = 0;
+/* REVIEW - MERGE
if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm()))
speed = ss->attackSpeed;
else
+*/
{
WeaponAttackType slot = BASE_ATTACK;
if (AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
@@ -2197,8 +2402,16 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
}
}
- // PCT mod from user auras by school
- powerCost = int32(powerCost * (1.0f + caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
+ // PCT mod from user auras by spell school and power type
+ Unit::AuraEffectList const& aurasPct = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
+ for (Unit::AuraEffectList::const_iterator i = aurasPct.begin(); i != aurasPct.end(); ++i)
+ {
+ if (!((*i)->GetMiscValue() & schoolMask))
+ continue;
+ if (!((*i)->GetMiscValueB() & (1 << PowerType)))
+ continue;
+ powerCost += CalculatePct(powerCost, (*i)->GetAmount());
+ }
if (powerCost < 0)
powerCost = 0;
return powerCost;
@@ -2253,7 +2466,8 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const
if (IsPositiveEffect(i) &&
(Effects[i].Effect == SPELL_EFFECT_APPLY_AURA ||
Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
- Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID))
+ Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) &&
+ !Effects[i].ScalingMultiplier)
{
needRankSelection = true;
break;
@@ -2616,6 +2830,81 @@ bool SpellInfo::_IsPositiveTarget(uint32 targetA, uint32 targetB)
return true;
}
+SpellTargetRestrictionsEntry const* SpellInfo::GetSpellTargetRestrictions() const
+{
+ return SpellTargetRestrictionsId ? sSpellTargetRestrictionsStore.LookupEntry(SpellTargetRestrictionsId) : NULL;
+}
+
+SpellEquippedItemsEntry const* SpellInfo::GetSpellEquippedItems() const
+{
+ return SpellEquippedItemsId ? sSpellEquippedItemsStore.LookupEntry(SpellEquippedItemsId) : NULL;
+}
+
+SpellInterruptsEntry const* SpellInfo::GetSpellInterrupts() const
+{
+ return SpellInterruptsId ? sSpellInterruptsStore.LookupEntry(SpellInterruptsId) : NULL;
+}
+
+SpellLevelsEntry const* SpellInfo::GetSpellLevels() const
+{
+ return SpellLevelsId ? sSpellLevelsStore.LookupEntry(SpellLevelsId) : NULL;
+}
+
+SpellPowerEntry const* SpellInfo::GetSpellPower() const
+{
+ return SpellPowerId ? sSpellPowerStore.LookupEntry(SpellPowerId) : NULL;
+}
+
+SpellReagentsEntry const* SpellInfo::GetSpellReagents() const
+{
+ return SpellReagentsId ? sSpellReagentsStore.LookupEntry(SpellReagentsId) : NULL;
+}
+
+SpellScalingEntry const* SpellInfo::GetSpellScaling() const
+{
+ return SpellScalingId ? sSpellScalingStore.LookupEntry(SpellScalingId) : NULL;
+}
+
+SpellShapeshiftEntry const* SpellInfo::GetSpellShapeshift() const
+{
+ return SpellShapeshiftId ? sSpellShapeshiftStore.LookupEntry(SpellShapeshiftId) : NULL;
+}
+
+SpellTotemsEntry const* SpellInfo::GetSpellTotems() const
+{
+ return SpellTotemsId ? sSpellTotemsStore.LookupEntry(SpellTotemsId) : NULL;
+}
+
+SpellAuraOptionsEntry const* SpellInfo::GetSpellAuraOptions() const
+{
+ return SpellAuraOptionsId ? sSpellAuraOptionsStore.LookupEntry(SpellAuraOptionsId) : NULL;
+}
+
+SpellAuraRestrictionsEntry const* SpellInfo::GetSpellAuraRestrictions() const
+{
+ return SpellAuraRestrictionsId ? sSpellAuraRestrictionsStore.LookupEntry(SpellAuraRestrictionsId) : NULL;
+}
+
+SpellCastingRequirementsEntry const* SpellInfo::GetSpellCastingRequirements() const
+{
+ return SpellCastingRequirementsId ? sSpellCastingRequirementsStore.LookupEntry(SpellCastingRequirementsId) : NULL;
+}
+
+SpellCategoriesEntry const* SpellInfo::GetSpellCategories() const
+{
+ return SpellCategoriesId ? sSpellCategoriesStore.LookupEntry(SpellCategoriesId) : NULL;
+}
+
+SpellClassOptionsEntry const* SpellInfo::GetSpellClassOptions() const
+{
+ return SpellClassOptionsId ? sSpellClassOptionsStore.LookupEntry(SpellClassOptionsId) : NULL;
+}
+
+SpellCooldownsEntry const* SpellInfo::GetSpellCooldowns() const
+{
+ return SpellCooldownsId ? sSpellCooldownsStore.LookupEntry(SpellCooldownsId) : NULL;
+}
+
void SpellInfo::_UnloadImplicitTargetConditionLists()
{
// find the same instances of ConditionList and delete them.
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 3e6ba0023b1..4be90e5c100 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -29,6 +29,7 @@ class Player;
class Item;
class Spell;
class SpellInfo;
+class WorldObject;
struct SpellChainNode;
struct SpellTargetPosition;
struct SpellDurationEntry;
@@ -61,7 +62,7 @@ enum SpellCastTargetFlags
TARGET_FLAG_UNIT_MINIPET = 0x00010000, // pguid, used to validate target (if non combat pet)
TARGET_FLAG_GLYPH_SLOT = 0x00020000, // used in glyph spells
TARGET_FLAG_DEST_TARGET = 0x00040000, // sometimes appears with DEST_TARGET spells (may appear or not for a given spell)
- TARGET_FLAG_UNUSED20 = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far
+ TARGET_FLAG_EXTRA_TARGETS = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far
TARGET_FLAG_UNIT_PASSENGER = 0x00100000, // guessed, used to validate target (if vehicle passenger)
TARGET_FLAG_UNIT_MASK = TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY
@@ -166,7 +167,9 @@ enum SpellSpecificType
SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE = 25,
SPELL_SPECIFIC_WARRIOR_ENRAGE = 26,
SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT = 27,
- SPELL_SPECIFIC_HAND = 28
+ SPELL_SPECIFIC_HAND = 28,
+ SPELL_SPECIFIC_PHASE = 29,
+ SPELL_SPECIFIC_BANE = 30
};
enum SpellCustomAttributes
@@ -198,7 +201,7 @@ class SpellImplicitTargetInfo
private:
Targets _target;
public:
- SpellImplicitTargetInfo() {}
+ SpellImplicitTargetInfo() : _target(Targets(0)) {}
SpellImplicitTargetInfo(uint32 target);
bool IsArea() const;
@@ -245,14 +248,19 @@ public:
SpellImplicitTargetInfo TargetA;
SpellImplicitTargetInfo TargetB;
SpellRadiusEntry const* RadiusEntry;
+ SpellRadiusEntry const* MaxRadiusEntry;
uint32 ChainTarget;
uint32 ItemType;
uint32 TriggerSpell;
flag96 SpellClassMask;
std::list<Condition*>* ImplicitTargetConditions;
+ // SpellScalingEntry
+ float ScalingMultiplier;
+ float DeltaScalingMultiplier;
+ float ComboScalingMultiplier;
SpellEffectInfo() {}
- SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex);
+ SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* effect);
bool IsEffect() const;
bool IsEffect(SpellEffects effectName) const;
@@ -270,6 +278,7 @@ public:
float CalcDamageMultiplier(Unit* caster, Spell* spell = NULL) const;
bool HasRadius() const;
+ bool HasMaxRadius() const;
float CalcRadius(Unit* caster = NULL, Spell* = NULL) const;
uint32 GetProvidedTargetMask() const;
@@ -302,6 +311,9 @@ public:
uint32 AttributesEx5;
uint32 AttributesEx6;
uint32 AttributesEx7;
+ uint32 AttributesEx8;
+ uint32 AttributesEx9;
+ uint32 AttributesEx10;
uint32 AttributesCu;
uint32 Stances;
uint32 StancesNot;
@@ -336,7 +348,6 @@ public:
uint32 ManaCost;
uint32 ManaCostPerlevel;
uint32 ManaPerSecond;
- uint32 ManaPerSecondPerLevel;
uint32 ManaCostPercentage;
uint32 RuneCostID;
SpellRangeEntry const* RangeEntry;
@@ -352,8 +363,8 @@ public:
uint32 SpellVisual[2];
uint32 SpellIconID;
uint32 ActiveIconID;
- char* SpellName[16];
- char* Rank[16];
+ char* SpellName;
+ char* Rank;
uint32 MaxTargetLevel;
uint32 MaxAffectedTargets;
uint32 SpellFamilyName;
@@ -362,11 +373,51 @@ public:
uint32 PreventionType;
int32 AreaGroupId;
uint32 SchoolMask;
+ uint32 SpellDifficultyId;
+ uint32 SpellScalingId;
+ uint32 SpellAuraOptionsId;
+ uint32 SpellAuraRestrictionsId;
+ uint32 SpellCastingRequirementsId;
+ uint32 SpellCategoriesId;
+ uint32 SpellClassOptionsId;
+ uint32 SpellCooldownsId;
+ uint32 SpellEquippedItemsId;
+ uint32 SpellInterruptsId;
+ uint32 SpellLevelsId;
+ uint32 SpellPowerId;
+ uint32 SpellReagentsId;
+ uint32 SpellShapeshiftId;
+ uint32 SpellTargetRestrictionsId;
+ uint32 SpellTotemsId;
+ // SpellScalingEntry
+ int32 CastTimeMin;
+ int32 CastTimeMax;
+ int32 CastTimeMaxLevel;
+ int32 ScalingClass;
+ float CoefBase;
+ int32 CoefLevelBase;
SpellEffectInfo Effects[MAX_SPELL_EFFECTS];
uint32 ExplicitTargetMask;
SpellChainNode const* ChainEntry;
- SpellInfo(SpellEntry const* spellEntry);
+ // struct access functions
+ SpellTargetRestrictionsEntry const* GetSpellTargetRestrictions() const;
+ SpellAuraOptionsEntry const* GetSpellAuraOptions() const;
+ SpellAuraRestrictionsEntry const* GetSpellAuraRestrictions() const;
+ SpellCastingRequirementsEntry const* GetSpellCastingRequirements() const;
+ SpellCategoriesEntry const* GetSpellCategories() const;
+ SpellClassOptionsEntry const* GetSpellClassOptions() const;
+ SpellCooldownsEntry const* GetSpellCooldowns() const;
+ SpellEquippedItemsEntry const* GetSpellEquippedItems() const;
+ SpellInterruptsEntry const* GetSpellInterrupts() const;
+ SpellLevelsEntry const* GetSpellLevels() const;
+ SpellPowerEntry const* GetSpellPower() const;
+ SpellReagentsEntry const* GetSpellReagents() const;
+ SpellScalingEntry const* GetSpellScaling() const;
+ SpellShapeshiftEntry const* GetSpellShapeshift() const;
+ SpellTotemsEntry const* GetSpellTotems() const;
+
+ SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects);
~SpellInfo();
bool HasEffect(SpellEffects effect) const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 9cedfdf922f..3ee6266b0d2 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -37,13 +37,13 @@
bool IsPrimaryProfessionSkill(uint32 skill)
{
SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
- if (!pSkill)
- return false;
-
- if (pSkill->categoryId != SKILL_CATEGORY_PROFESSION)
- return false;
+ return pSkill && pSkill->categoryId == SKILL_CATEGORY_PROFESSION;
+}
- return true;
+bool IsWeaponSkill(uint32 skill)
+{
+ SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
+ return pSkill && pSkill->categoryId == SKILL_CATEGORY_WEAPON;
}
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)
@@ -315,7 +315,7 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const
break;
}
- return 10 * IN_MILLISECONDS;
+ return 8 * IN_MILLISECONDS;
}
bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group)
@@ -1105,19 +1105,7 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
// Extra conditions -- leaving the possibility add extra conditions...
switch (spellId)
{
- case 58600: // No fly Zone - Dalaran
- {
- if (!player)
- return false;
-
- AreaTableEntry const* pArea = GetAreaEntryByAreaID(player->GetAreaId());
- if (!(pArea && pArea->flags & AREA_FLAG_NO_FLY_ZONE))
- return false;
- if (!player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY))
- return false;
- break;
- }
- case 58730: // No fly Zone - Wintergrasp
+ case 91604: // No fly Zone - Wintergrasp
{
if (!player)
return false;
@@ -1144,24 +1132,24 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
}
case 56618: // Horde Controls Factory Phase Shift
case 56617: // Alliance Controls Factory Phase Shift
- {
- if (!player)
- return false;
+ {
+ if (!player)
+ return false;
- Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetZoneId());
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetZoneId());
- if (!bf || bf->GetTypeId() != BATTLEFIELD_WG)
- return false;
+ if (!bf || bf->GetTypeId() != BATTLEFIELD_WG)
+ return false;
- // team that controls the workshop in the specified area
- uint32 team = bf->GetData(newArea);
+ // team that controls the workshop in the specified area
+ uint32 team = bf->GetData(newArea);
- if (team == TEAM_HORDE)
- return spellId == 56618;
- else if (team == TEAM_ALLIANCE)
- return spellId == 56617;
- }
+ if (team == TEAM_HORDE)
+ return spellId == 56618;
+ else if (team == TEAM_ALLIANCE)
+ return spellId == 56617;
break;
+ }
case 57940: // Essence of Wintergrasp - Northrend
case 58045: // Essence of Wintergrasp - Wintergrasp
{
@@ -1287,6 +1275,7 @@ void SpellMgr::LoadSpellRanks()
mSpellInfoMap[addedSpell]->ChainEntry = &mSpellChains[addedSpell];
prevRank = addedSpell;
++itr;
+
if (itr == rankChain.end())
{
mSpellChains[addedSpell].next = NULL;
@@ -1419,10 +1408,10 @@ void SpellMgr::LoadSpellLearnSpells()
{
Field* fields = result->Fetch();
- uint32 spell_id = fields[0].GetUInt16();
+ uint32 spell_id = fields[0].GetUInt32();
SpellLearnSpellNode node;
- node.spell = fields[1].GetUInt16();
+ node.spell = fields[1].GetUInt32();
node.active = fields[2].GetBool();
node.autoLearned = false;
@@ -1449,6 +1438,9 @@ void SpellMgr::LoadSpellLearnSpells()
++count;
} while (result->NextRow());
+ // copy state loaded from db
+ SpellLearnSpellMap dbSpellLearnSpells = mSpellLearnSpells;
+
// search auto-learned spells and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
for (uint32 spell = 0; spell < GetSpellInfoStoreSize(); ++spell)
@@ -1475,7 +1467,7 @@ void SpellMgr::LoadSpellLearnSpells()
// other required explicit dependent learning
dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentSpellCost(spell) > 0 || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP);
- SpellLearnSpellMapBounds db_node_bounds = GetSpellLearnSpellMapBounds(spell);
+ SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell);
bool found = false;
for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
@@ -1498,7 +1490,68 @@ void SpellMgr::LoadSpellLearnSpells()
}
}
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell learn spells + %u found in DBC in %u ms", count, dbc_count, GetMSTimeDiffToNow(oldMSTime));
+ uint32 mastery_count = 0;
+ for (uint32 i = 0; i < sTalentTabStore.GetNumRows(); ++i)
+ {
+ TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(i);
+ if (!talentTab)
+ continue;
+
+ for (uint32 c = CLASS_WARRIOR; c < MAX_CLASSES; ++c)
+ {
+ if (!(talentTab->ClassMask & (1 << (c - 1))))
+ continue;
+
+ uint32 masteryMainSpell = MasterySpells[c];
+
+ for (uint32 m = 0; m < MAX_MASTERY_SPELLS; ++m)
+ {
+ uint32 mastery = talentTab->MasterySpellId[m];
+ if (!mastery)
+ continue;
+
+ SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(masteryMainSpell);
+ bool found = false;
+ for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
+ {
+ if (itr->second.spell == mastery)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from TalentTab.dbc", masteryMainSpell, mastery);
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ // Check if it is already found in Spell.dbc, ignore silently if yes
+ SpellLearnSpellMapBounds dbc_node_bounds = GetSpellLearnSpellMapBounds(masteryMainSpell);
+ found = false;
+ for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr)
+ {
+ if (itr->second.spell == mastery)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SpellLearnSpellNode masteryNode;
+ masteryNode.spell = mastery;
+ masteryNode.active = true;
+ masteryNode.autoLearned = false;
+
+ mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(masteryMainSpell, masteryNode));
+ ++mastery_count;
+ }
+ }
+ }
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell learn spells, %u found in Spell.dbc and %u from TalentTab.dbc in %u ms", count, dbc_count, mastery_count, GetMSTimeDiffToNow(oldMSTime));
}
void SpellMgr::LoadSpellTargetPositions()
@@ -2588,6 +2641,19 @@ void SpellMgr::LoadSpellAreas()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell area requirements in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+// Temporary structure to hold spell effect entries for faster loading
+struct SpellEffectArray
+{
+ SpellEffectArray()
+ {
+ effects[0] = NULL;
+ effects[1] = NULL;
+ effects[2] = NULL;
+ }
+
+ SpellEffectEntry const* effects[MAX_SPELL_EFFECTS];
+};
+
void SpellMgr::LoadSpellInfoStore()
{
uint32 oldMSTime = getMSTime();
@@ -2595,13 +2661,22 @@ void SpellMgr::LoadSpellInfoStore()
UnloadSpellInfoStore();
mSpellInfoMap.resize(sSpellStore.GetNumRows(), NULL);
- for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
+ std::map<uint32, SpellEffectArray> effectsBySpell;
+
+ for (uint32 i = 0; i < sSpellEffectStore.GetNumRows(); ++i)
{
- if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i))
- mSpellInfoMap[i] = new SpellInfo(spellEntry);
+ SpellEffectEntry const* effect = sSpellEffectStore.LookupEntry(i);
+ if (!effect)
+ continue;
+
+ effectsBySpell[effect->EffectSpellId].effects[effect->EffectIndex] = effect;
}
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded spell custom attributes in %u ms", GetMSTimeDiffToNow(oldMSTime));
+ for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
+ if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i))
+ mSpellInfoMap[i] = new SpellInfo(spellEntry, effectsBySpell[i].effects);
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded spell info store in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
void SpellMgr::UnloadSpellInfoStore()
@@ -2920,33 +2995,33 @@ void SpellMgr::LoadSpellCustomAttr()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded spell custom attributes in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
-void SpellMgr::LoadDbcDataCorrections()
+void SpellMgr::LoadSpellInfoCorrections()
{
uint32 oldMSTime = getMSTime();
- SpellEntry* spellInfo = NULL;
- for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
+ SpellInfo* spellInfo = NULL;
+ for (uint32 i = 0; i < mSpellInfoMap.size(); ++i)
{
- spellInfo = (SpellEntry*)sSpellStore.LookupEntry(i);
+ spellInfo = (SpellInfo*)mSpellInfoMap[i];
if (!spellInfo)
continue;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
- switch (spellInfo->Effect[j])
+ switch (spellInfo->Effects[j].Effect)
{
case SPELL_EFFECT_CHARGE:
case SPELL_EFFECT_CHARGE_DEST:
case SPELL_EFFECT_JUMP:
case SPELL_EFFECT_JUMP_DEST:
case SPELL_EFFECT_LEAP_BACK:
- if (!spellInfo->speed && !spellInfo->SpellFamilyName)
- spellInfo->speed = SPEED_CHARGE;
+ if (!spellInfo->Speed && !spellInfo->SpellFamilyName)
+ spellInfo->Speed = SPEED_CHARGE;
break;
}
}
- if (spellInfo->activeIconID == 2158) // flight
+ if (spellInfo->ActiveIconID == 2158) // flight
spellInfo->Attributes |= SPELL_ATTR0_PASSIVE;
switch (spellInfo->Id)
@@ -2955,28 +3030,28 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->MaxAffectedTargets = 1;
break;
case 42730:
- spellInfo->EffectTriggerSpell[EFFECT_1] = 42739;
+ spellInfo->Effects[EFFECT_1].TriggerSpell = 42739;
break;
case 59735:
- spellInfo->EffectTriggerSpell[EFFECT_1] = 59736;
+ spellInfo->Effects[EFFECT_1].TriggerSpell = 59736;
break;
case 52611: // Summon Skeletons
case 52612: // Summon Skeletons
- spellInfo->EffectMiscValueB[0] = 64;
+ spellInfo->Effects[EFFECT_0].MiscValueB = 64;
break;
case 40244: // Simon Game Visual
case 40245: // Simon Game Visual
case 40246: // Simon Game Visual
case 40247: // Simon Game Visual
case 42835: // Spout, remove damage effect, only anim is needed
- spellInfo->Effect[0] = 0;
+ spellInfo->Effects[EFFECT_0].Effect = 0;
break;
case 30657: // Quake
- spellInfo->EffectTriggerSpell[0] = 30571;
+ spellInfo->Effects[EFFECT_0].TriggerSpell = 30571;
break;
case 30541: // Blaze (needs conditions entry)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ENEMY;
- spellInfo->EffectImplicitTargetB[0] = 0;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY);
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo();
break;
case 63665: // Charge (Argent Tournament emote on riders)
case 31298: // Sleep (needs target selection script)
@@ -2984,18 +3059,18 @@ void SpellMgr::LoadDbcDataCorrections()
case 2895: // Wrath of Air Totem rank 1 (Aura)
case 68933: // Wrath of Air Totem rank 2 (Aura)
case 29200: // Purify Helboar Meat
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
- spellInfo->EffectImplicitTargetB[0] = 0;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo();
break;
case 31344: // Howl of Azgalor
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_100_YARDS; // 100yards instead of 50000?!
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yards instead of 50000?!
break;
case 42818: // Headless Horseman - Wisp Flight Port
case 42821: // Headless Horseman - Wisp Flight Missile
- spellInfo->rangeIndex = 6; // 100 yards
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100 yards
break;
case 36350: //They Must Burn Bomb Aura (self)
- spellInfo->EffectTriggerSpell[0] = 36325; // They Must Burn Bomb Drop (DND)
+ spellInfo->Effects[EFFECT_0].TriggerSpell = 36325; // They Must Burn Bomb Drop (DND)
break;
case 49838: // Stop Time
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO;
@@ -3004,15 +3079,15 @@ void SpellMgr::LoadDbcDataCorrections()
case 62136: // Energize Cores
case 54069: // Energize Cores
case 56251: // Energize Cores
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_SRC_AREA_ENTRY;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY);
break;
case 50785: // Energize Cores
case 59372: // Energize Cores
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_SRC_AREA_ENEMY;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENEMY);
break;
case 8494: // Mana Shield (rank 2)
// because of bug in dbc
- spellInfo->procChance = 0;
+ spellInfo->ProcChance = 0;
break;
case 20335: // Heart of the Crusader
case 20336:
@@ -3023,8 +3098,8 @@ void SpellMgr::LoadDbcDataCorrections()
break;
case 59725: // Improved Spell Reflection - aoe aura
// Target entry seems to be wrong for this spell :/
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER_AREA_PARTY;
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_10_YARDS_2;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER_AREA_PARTY);
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS_2);
break;
case 44978: // Wild Magic
case 45001:
@@ -3095,7 +3170,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 33711: // Murmur's Touch
case 38794:
spellInfo->MaxAffectedTargets = 1;
- spellInfo->EffectTriggerSpell[0] = 33760;
+ spellInfo->Effects[EFFECT_0].TriggerSpell = 33760;
break;
case 17941: // Shadow Trance
case 22008: // Netherwind Focus
@@ -3110,17 +3185,17 @@ void SpellMgr::LoadDbcDataCorrections()
case 64823: // Item - Druid T8 Balance 4P Bonus
case 34477: // Misdirection
case 44401: // Missile Barrage
- spellInfo->procCharges = 1;
+ spellInfo->ProcCharges = 1;
break;
case 44544: // Fingers of Frost
- spellInfo->EffectSpellClassMask[0] = flag96(685904631, 1151048, 0);
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(685904631, 1151048, 0);
break;
case 74396: // Fingers of Frost visual buff
- spellInfo->procCharges = 2;
+ spellInfo->ProcCharges = 2;
spellInfo->StackAmount = 0;
break;
case 28200: // Ascendance (Talisman of Ascendance trinket)
- spellInfo->procCharges = 6;
+ spellInfo->ProcCharges = 6;
break;
case 47201: // Everlasting Affliction
case 47202:
@@ -3128,16 +3203,16 @@ void SpellMgr::LoadDbcDataCorrections()
case 47204:
case 47205:
// add corruption to affected spells
- spellInfo->EffectSpellClassMask[1][0] |= 2;
+ spellInfo->Effects[1].SpellClassMask[0] |= 2;
break;
case 51852: // The Eye of Acherus (no spawn in phase 2 in db)
- spellInfo->EffectMiscValue[0] |= 1;
+ spellInfo->Effects[0].MiscValue |= 1;
break;
case 51912: // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster
- spellInfo->EffectAmplitude[0] = 3000;
+ spellInfo->Effects[0].Amplitude = 3000;
break;
case 29809: // Desecration Arm - 36 instead of 37 - typo? :/
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_7_YARDS;
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_7_YARDS);
break;
// Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data
// To prevent aura staying on target after talent unlearned
@@ -3152,37 +3227,30 @@ void SpellMgr::LoadDbcDataCorrections()
break;
case 51466: // Elemental Oath (Rank 1)
case 51470: // Elemental Oath (Rank 2)
- spellInfo->Effect[EFFECT_1] = SPELL_EFFECT_APPLY_AURA;
- spellInfo->EffectApplyAuraName[EFFECT_1] = SPELL_AURA_ADD_FLAT_MODIFIER;
- spellInfo->EffectMiscValue[EFFECT_1] = SPELLMOD_EFFECT2;
- spellInfo->EffectSpellClassMask[EFFECT_1] = flag96(0x00000000, 0x00004000, 0x00000000);
+ spellInfo->Effects[EFFECT_1].Effect = SPELL_EFFECT_APPLY_AURA;
+ spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
+ spellInfo->Effects[EFFECT_1].MiscValue = SPELLMOD_EFFECT2;
+ spellInfo->Effects[EFFECT_1].SpellClassMask = flag96(0x00000000, 0x00004000, 0x00000000);
break;
case 47569: // Improved Shadowform (Rank 1)
// with this spell atrribute aura can be stacked several times
spellInfo->Attributes &= ~SPELL_ATTR0_NOT_SHAPESHIFT;
break;
case 64904: // Hymn of Hope
- spellInfo->EffectApplyAuraName[EFFECT_1] = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT;
- break;
- case 19465: // Improved Stings (Rank 2)
- spellInfo->EffectImplicitTargetA[EFFECT_2] = TARGET_UNIT_CASTER;
+ spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT;
break;
case 30421: // Nether Portal - Perseverence
- spellInfo->EffectBasePoints[2] += 30000;
- break;
- case 16834: // Natural shapeshifter
- case 16835:
- spellInfo->DurationIndex = 21;
+ spellInfo->Effects[2].BasePoints += 30000;
break;
case 51735: // Ebon Plague
case 51734:
case 51726:
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
spellInfo->SpellFamilyFlags[2] = 0x10;
- spellInfo->EffectApplyAuraName[1] = SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN;
+ spellInfo->Effects[1].ApplyAuraName = SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN;
break;
case 41913: // Parasitic Shadowfiend Passive
- spellInfo->EffectApplyAuraName[0] = SPELL_AURA_DUMMY; // proc debuff, and summon infinite fiends
+ spellInfo->Effects[0].ApplyAuraName = SPELL_AURA_DUMMY; // proc debuff, and summon infinite fiends
break;
case 27892: // To Anchor 1
case 27928: // To Anchor 1
@@ -3190,18 +3258,14 @@ void SpellMgr::LoadDbcDataCorrections()
case 27915: // Anchor to Skulls
case 27931: // Anchor to Skulls
case 27937: // Anchor to Skulls
- spellInfo->rangeIndex = 13;
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13);
break;
// target allys instead of enemies, target A is src_caster, spells with effect like that have ally target
// this is the only known exception, probably just wrong data
case 29214: // Wrath of the Plaguebringer
case 54836: // Wrath of the Plaguebringer
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_SRC_AREA_ALLY;
- spellInfo->EffectImplicitTargetB[1] = TARGET_UNIT_SRC_AREA_ALLY;
- break;
- case 57994: // Wind Shear - improper data for EFFECT_1 in 3.3.5 DBC, but is correct in 4.x
- spellInfo->Effect[EFFECT_1] = SPELL_EFFECT_MODIFY_THREAT_PERCENT;
- spellInfo->EffectBasePoints[EFFECT_1] = -6; // -5%
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
+ spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
break;
case 63675: // Improved Devouring Plague
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
@@ -3210,73 +3274,56 @@ void SpellMgr::LoadDbcDataCorrections()
case 6474: // Earthbind Totem (instant pulse)
spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY;
break;
- case 52109: // Flametongue Totem rank 1 (Aura)
- case 52110: // Flametongue Totem rank 2 (Aura)
- case 52111: // Flametongue Totem rank 3 (Aura)
- case 52112: // Flametongue Totem rank 4 (Aura)
- case 52113: // Flametongue Totem rank 5 (Aura)
- case 58651: // Flametongue Totem rank 6 (Aura)
- case 58654: // Flametongue Totem rank 7 (Aura)
- case 58655: // Flametongue Totem rank 8 (Aura)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
- spellInfo->EffectImplicitTargetA[1] = TARGET_UNIT_CASTER;
- spellInfo->EffectImplicitTargetB[0] = 0;
- spellInfo->EffectImplicitTargetB[1] = 0;
- break;
case 53241: // Marked for Death (Rank 1)
case 53243: // Marked for Death (Rank 2)
case 53244: // Marked for Death (Rank 3)
case 53245: // Marked for Death (Rank 4)
case 53246: // Marked for Death (Rank 5)
- spellInfo->EffectSpellClassMask[0] = flag96(0x00067801, 0x10820001, 0x00000801);
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00067801, 0x10820001, 0x00000801);
+ break;
+ case 5176: // Wrath
+ case 2912: // Starfire
+ case 78674: // Starsurge
+ spellInfo->Effects[1].Effect = SPELL_EFFECT_DUMMY;
+ spellInfo->Effects[1].TargetA = TARGET_UNIT_CASTER;
break;
case 70728: // Exploit Weakness (needs target selection script)
case 70840: // Devious Minds (needs target selection script)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_PET;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_PET);
break;
case 70893: // Culling The Herd (needs target selection script)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_MASTER;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_MASTER);
break;
case 54800: // Sigil of the Frozen Conscience - change class mask to custom extended flags of Icy Touch
// this is done because another spell also uses the same SpellFamilyFlags as Icy Touch
// SpellFamilyFlags[0] & 0x00000040 in SPELLFAMILY_DEATHKNIGHT is currently unused (3.3.5a)
// this needs research on modifier applying rules, does not seem to be in Attributes fields
- spellInfo->EffectSpellClassMask[0] = flag96(0x00000040, 0x00000000, 0x00000000);
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000040, 0x00000000, 0x00000000);
break;
case 64949: // Idol of the Flourishing Life
- spellInfo->EffectSpellClassMask[EFFECT_0] = flag96(0x00000000, 0x02000000, 0x00000000);
- spellInfo->EffectApplyAuraName[EFFECT_0] = SPELL_AURA_ADD_FLAT_MODIFIER;
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000000, 0x02000000, 0x00000000);
+ spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
break;
case 34231: // Libram of the Lightbringer
case 60792: // Libram of Tolerance
case 64956: // Libram of the Resolute
- spellInfo->EffectSpellClassMask[EFFECT_0] = flag96(0x80000000, 0x00000000, 0x00000000);
- spellInfo->EffectApplyAuraName[EFFECT_0] = SPELL_AURA_ADD_FLAT_MODIFIER;
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x80000000, 0x00000000, 0x00000000);
+ spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
break;
case 28851: // Libram of Light
case 28853: // Libram of Divinity
case 32403: // Blessed Book of Nagrand
- spellInfo->EffectSpellClassMask[EFFECT_0] = flag96(0x40000000, 0x00000000, 0x00000000);
- spellInfo->EffectApplyAuraName[EFFECT_0] = SPELL_AURA_ADD_FLAT_MODIFIER;
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x40000000, 0x00000000, 0x00000000);
+ spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
break;
case 45602: // Ride Carpet
- spellInfo->EffectBasePoints[EFFECT_0] = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)"
+ spellInfo->Effects[EFFECT_0].BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)"
break;
case 64745: // Item - Death Knight T8 Tank 4P Bonus
case 64936: // Item - Warrior T8 Protection 4P Bonus
- spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
- break;
- case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
- case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
- case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
- case 19973: // Entangling Roots (Rank 3) -- Nature's Grasp Proc
- case 19974: // Entangling Roots (Rank 2) -- Nature's Grasp Proc
- case 19975: // Entangling Roots (Rank 1) -- Nature's Grasp Proc
- case 27010: // Entangling Roots (Rank 7) -- Nature's Grasp Proc
- case 53313: // Entangling Roots (Rank 8) -- Nature's Grasp Proc
- spellInfo->CastingTimeIndex = 1;
+ spellInfo->Effects[0].BasePoints = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
break;
case 59414: // Pulsing Shockwave Aura (Loken)
// this flag breaks movement, remove it
@@ -3286,7 +3333,7 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE;
break;
case 70650: // Death Knight T10 Tank 2P Bonus
- spellInfo->EffectApplyAuraName[0] = SPELL_AURA_ADD_PCT_MODIFIER;
+ spellInfo->Effects[0].ApplyAuraName = SPELL_AURA_ADD_PCT_MODIFIER;
break;
case 71838: // Drain Life - Bryntroll Normal
case 71839: // Drain Life - Bryntroll Heroic
@@ -3298,7 +3345,7 @@ void SpellMgr::LoadDbcDataCorrections()
// ULDUAR SPELLS
//
case 62374: // Pursued (Flame Leviathan)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 63342: // Focused Eyebeam Summon Trigger (Kologarn)
spellInfo->MaxAffectedTargets = 1;
@@ -3320,12 +3367,12 @@ void SpellMgr::LoadDbcDataCorrections()
// then EFFECT_1, etc - instead of applying each effect on target1, then target2, etc.
// The above situation causes the visual for this spell to be bugged, so we remove the instakill
// effect and implement a script hack for that.
- spellInfo->Effect[EFFECT_1] = 0;
+ spellInfo->Effects[EFFECT_1].Effect = 0;
break;
case 64386: // Terrifying Screech (Auriaya)
case 64389: // Sentinel Blast (Auriaya)
case 64678: // Sentinel Blast (Auriaya)
- spellInfo->DurationIndex = 28; // 5 seconds, wrong DBC data?
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds, wrong DBC data?
break;
case 64321: // Potent Pheromones (Freya)
// spell should dispel area aura, but doesn't have the attribute
@@ -3335,7 +3382,7 @@ void SpellMgr::LoadDbcDataCorrections()
break;
case 61791: // Ride Vehicle (Yogg-Saron)
// TODO: remove this when basepoints of all Ride Vehicle auras are calculated correctly
- spellInfo->EffectBasePoints[0] = 1;
+ spellInfo->Effects[EFFECT_0].BasePoints = 1;
break;
case 64468: // Empowering Shadows (Yogg-Saron)
case 64486: // Empowering Shadows (Yogg-Saron)
@@ -3348,11 +3395,11 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->MaxAffectedTargets = 3;
break;
case 62293: // Cosmic Smash (Algalon the Observer)
- spellInfo->EffectImplicitTargetB[0] = TARGET_DEST_CASTER;
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_DEST_CASTER);
break;
case 62311: // Cosmic Smash (Algalon the Observer)
case 64596: // Cosmic Smash (Algalon the Observer)
- spellInfo->rangeIndex = 6; // 100yd
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100yd
break;
case 64014: // Expedition Base Camp Teleport
case 64024: // Conservatory Teleport
@@ -3363,7 +3410,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 64031: // Scrapyard Teleport
case 64032: // Formation Grounds Teleport
case 65042: // Prison of Yogg-Saron Teleport
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DB;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
// ENDOF ULDUAR SPELLS
//
@@ -3373,7 +3420,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 67901: // Infernal Eruption (25N)
// increase duration from 15 to 18 seconds because caster is already
// unsummoned when spell missile hits the ground so nothing happen in result
- spellInfo->DurationIndex = 85;
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(85);
break;
// ENDOF TRIAL OF THE CRUSADER SPELLS
//
@@ -3389,11 +3436,11 @@ void SpellMgr::LoadDbcDataCorrections()
case 70859: // Upper Spire Teleport
case 70860: // Frozen Throne Teleport
case 70861: // Sindragosa's Lair Teleport
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DB;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
- case 69055: // Bone Slice (Lord Marrowgar)
- case 70814: // Bone Slice (Lord Marrowgar)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_8_YARDS; // 5yd
+ case 69055: // Saber Lash (Lord Marrowgar)
+ case 70814: // Saber Lash (Lord Marrowgar)
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_8_YARDS); // 8yd
break;
case 69075: // Bone Storm (Lord Marrowgar)
case 70834: // Bone Storm (Lord Marrowgar)
@@ -3403,62 +3450,62 @@ void SpellMgr::LoadDbcDataCorrections()
case 71160: // Plague Stench (Stinky)
case 71161: // Plague Stench (Stinky)
case 71123: // Decimate (Stinky & Precious)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_100_YARDS; // 100yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd
break;
case 71169: // Shadow's Fate
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
break;
case 72378: // Blood Nova (Deathbringer Saurfang)
case 73058: // Blood Nova (Deathbringer Saurfang)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS;
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_200_YARDS;
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
break;
case 72769: // Scent of Blood (Deathbringer Saurfang)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS;
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
// no break
case 72771: // Scent of Blood (Deathbringer Saurfang)
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_200_YARDS;
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
break;
case 72723: // Resistant Skin (Deathbringer Saurfang adds)
// this spell initially granted Shadow damage immunity, however it was removed but the data was left in client
- spellInfo->Effect[2] = 0;
+ spellInfo->Effects[EFFECT_2].Effect = 0;
break;
case 70460: // Coldflame Jets (Traps after Saurfang)
- spellInfo->DurationIndex = 1; // 10 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(1); // 10 seconds
break;
case 71412: // Green Ooze Summon (Professor Putricide)
case 71415: // Orange Ooze Summon (Professor Putricide)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
case 71159: // Awaken Plagued Zombies
- spellInfo->DurationIndex = 21;
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(21);
break;
case 70530: // Volatile Ooze Beam Protection (Professor Putricide)
- spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AURA; // for an unknown reason this was SPELL_EFFECT_APPLY_AREA_AURA_RAID
+ spellInfo->Effects[EFFECT_0].Effect = SPELL_EFFECT_APPLY_AURA; // for an unknown reason this was SPELL_EFFECT_APPLY_AREA_AURA_RAID
break;
// THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS IS NOT IMPLEMENTED
case 71604: // Mutated Strength (Professor Putricide)
case 72673: // Mutated Strength (Professor Putricide)
case 72674: // Mutated Strength (Professor Putricide)
case 72675: // Mutated Strength (Professor Putricide)
- spellInfo->Effect[1] = 0;
+ spellInfo->Effects[EFFECT_1].Effect = 0;
break;
case 72454: // Mutated Plague (Professor Putricide)
case 72464: // Mutated Plague (Professor Putricide)
case 72506: // Mutated Plague (Professor Putricide)
case 72507: // Mutated Plague (Professor Putricide)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 70911: // Unbound Plague (Professor Putricide) (needs target selection script)
case 72854: // Unbound Plague (Professor Putricide) (needs target selection script)
case 72855: // Unbound Plague (Professor Putricide) (needs target selection script)
case 72856: // Unbound Plague (Professor Putricide) (needs target selection script)
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY;
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY);
break;
case 71518: // Unholy Infusion Quest Credit (Professor Putricide)
case 72934: // Blood Infusion Quest Credit (Blood-Queen Lana'thel)
case 72289: // Frost Infusion Quest Credit (Sindragosa)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // another missing radius
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // another missing radius
break;
case 71708: // Empowered Flare (Blood Prince Council)
case 72785: // Empowered Flare (Blood Prince Council)
@@ -3475,98 +3522,98 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
break;
case 70715: // Column of Frost (visual marker)
- spellInfo->DurationIndex = 32; // 6 seconds (missing)
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(32); // 6 seconds (missing)
break;
case 71085: // Mana Void (periodic aura)
- spellInfo->DurationIndex = 9; // 30 seconds (missing)
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(9); // 30 seconds (missing)
break;
case 72015: // Frostbolt Volley (only heroic)
case 72016: // Frostbolt Volley (only heroic)
- spellInfo->EffectRadiusIndex[2] = EFFECT_RADIUS_40_YARDS;
+ spellInfo->Effects[EFFECT_2].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_40_YARDS);
break;
case 70936: // Summon Suppressor (needs target selection script)
- spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
- spellInfo->EffectImplicitTargetB[0] = 0;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo();
break;
case 72706: // Achievement Check (Valithria Dreamwalker)
case 71357: // Order Whelp
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
case 70598: // Sindragosa's Fury
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DEST;
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DEST);
break;
case 69846: // Frost Bomb
- spellInfo->speed = 0.0f; // This spell's summon happens instantly
+ spellInfo->Speed = 0.0f; // This spell's summon happens instantly
break;
case 71614: // Ice Lock
spellInfo->Mechanic = MECHANIC_STUN;
break;
case 72762: // Defile
- spellInfo->DurationIndex = 559; // 53 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(559); // 53 seconds
break;
case 72743: // Defile
- spellInfo->DurationIndex = 22; // 45 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(22); // 45 seconds
break;
case 72754: // Defile
case 73708: // Defile
case 73709: // Defile
case 73710: // Defile
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
case 69030: // Val'kyr Target Search
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
case 69198: // Raging Spirit Visual
- spellInfo->rangeIndex = 13; // 50000yd
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd
break;
case 73654: // Harvest Souls
case 74295: // Harvest Souls
case 74296: // Harvest Souls
case 74297: // Harvest Souls
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_50000_YARDS; // 50000yd
- spellInfo->EffectRadiusIndex[2] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
+ spellInfo->Effects[EFFECT_2].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 73655: // Harvest Soul
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
break;
case 73540: // Summon Shadow Trap
- spellInfo->DurationIndex = 23; // 90 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(23); // 90 seconds
break;
case 73530: // Shadow Trap (visual)
- spellInfo->DurationIndex = 28; // 5 seconds
+ spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds
break;
case 73529: // Shadow Trap
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_10_YARDS; // 10yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd
break;
case 74282: // Shadow Trap (searcher)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_3_YARDS; // 3yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); // 3yd
break;
case 72595: // Restore Soul
case 73650: // Restore Soul
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
case 74086: // Destroy Soul
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
case 74302: // Summon Spirit Bomb
case 74342: // Summon Spirit Bomb
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
spellInfo->MaxAffectedTargets = 1;
break;
case 74341: // Summon Spirit Bomb
case 74343: // Summon Spirit Bomb
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
spellInfo->MaxAffectedTargets = 3;
break;
case 73579: // Summon Spirit Bomb
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_25_YARDS; // 25yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd
break;
case 72350: // Fury of Frostmourne
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 75127: // Kill Frostmourne Players
case 72351: // Fury of Frostmourne
@@ -3574,18 +3621,18 @@ void SpellMgr::LoadDbcDataCorrections()
case 72429: // Mass Resurrection
case 73159: // Play Movie
case 73582: // Trigger Vile Spirit (Inside, Heroic)
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 72376: // Raise Dead
spellInfo->MaxAffectedTargets = 3;
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // 50000yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
break;
case 71809: // Jump
- spellInfo->rangeIndex = 3; // 20yd
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_25_YARDS; // 25yd
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(3); // 20yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd
break;
case 72405: // Broken Frostmourne
- spellInfo->EffectRadiusIndex[1] = EFFECT_RADIUS_200_YARDS; // 200yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
// ENDOF ICECROWN CITADEL SPELLS
//
@@ -3595,7 +3642,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 77844: // Twilight Cutter
case 77845: // Twilight Cutter
case 77846: // Twilight Cutter
- spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_100_YARDS; // 100yd
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd
break;
case 75509: // Twilight Mending
spellInfo->AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE;
@@ -3632,7 +3679,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 49462: // Call Ruby Drake
case 49461: // Call Amber Drake
case 49345: // Call Emerald Drake
- spellInfo->Effect[1] = 0;
+ spellInfo->Effects[EFFECT_1].Effect = 0;
break;
// ENDOF OCULUS SPELLS
//
@@ -3642,15 +3689,27 @@ void SpellMgr::LoadDbcDataCorrections()
case 40167: // Introspection
spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
break;
- case 45524: // Chains of Ice
- spellInfo->EffectImplicitTargetA[EFFECT_2] = 0;
- break;
case 2378: // Minor Fortitude
- spellInfo->manaCost = 0;
- spellInfo->manaPerSecond = 0;
+ spellInfo->ManaCost = 0;
+ spellInfo->ManaPerSecond = 0;
+ break;
+ // Halls Of Origination spells
+ // Temple Guardian Anhuur
+ case 76606: // Disable Beacon Beams L
+ case 76608: // Disable Beacon Beams R
+ // Little hack, Increase the radius so it can hit the Cave In Stalkers in the platform.
+ spellInfo->Effects[EFFECT_0].MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_45_YARDS);
+ break;
+ case 75323: // Reverberating Hymn
+ // Aura is refreshed at 3 seconds, and the tick should happen at the fourth.
+ spellInfo->AttributesEx8 |= SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER;
break;
case 24314: // Threatening Gaze
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP;
+ break;
+ case 5420: // Tree of Life (Passive)
+ spellInfo->Stances = 1 << (FORM_TREE - 1);
+ break;
default:
break;
}
@@ -3660,7 +3719,7 @@ void SpellMgr::LoadDbcDataCorrections()
case SPELLFAMILY_PALADIN:
// Seals of the Pure should affect Seal of Righteousness
if (spellInfo->SpellIconID == 25 && spellInfo->Attributes & SPELL_ATTR0_PASSIVE)
- spellInfo->EffectSpellClassMask[0][1] |= 0x20000000;
+ spellInfo->Effects[EFFECT_0].SpellClassMask[1] |= 0x20000000;
break;
case SPELLFAMILY_DEATHKNIGHT:
// Icy Touch - extend FamilyFlags (unused value) for Sigil of the Frozen Conscience to use
@@ -3675,5 +3734,5 @@ void SpellMgr::LoadDbcDataCorrections()
properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(647)); // 52893
properties->Type = SUMMON_TYPE_TOTEM;
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded spell dbc data corrections in %u ms", GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded SpellInfo corrections in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index b7a3294efe3..69eedf25186 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -581,6 +581,8 @@ typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
bool IsPrimaryProfessionSkill(uint32 skill);
+bool IsWeaponSkill(uint32 skill);
+
inline bool IsProfessionSkill(uint32 skill)
{
return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID;
@@ -719,7 +721,7 @@ class SpellMgr
void UnloadSpellInfoStore();
void UnloadSpellInfoImplicitTargetConditionLists();
void LoadSpellCustomAttr();
- void LoadDbcDataCorrections();
+ void LoadSpellInfoCorrections();
private:
SpellDifficultySearcherMap mSpellDifficultySearcherMap;
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 5844a120e47..0887af332b1 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -53,6 +53,11 @@ class CreatureTextBuilder
*data << uint32(text.length() + 1);
*data << text;
*data << uint8(0); // ChatTag
+ if (_msgType == CHAT_MSG_RAID_BOSS_EMOTE || _msgType == CHAT_MSG_RAID_BOSS_WHISPER)
+ {
+ *data << float(0);
+ *data << uint8(0);
+ }
return whisperGUIDpos;
}
@@ -93,7 +98,11 @@ class PlayerTextBuilder
*data << uint32(text.length() + 1);
*data << text;
*data << uint8(0); // ChatTag
-
+ if (_msgType == CHAT_MSG_RAID_BOSS_EMOTE || _msgType == CHAT_MSG_RAID_BOSS_WHISPER)
+ {
+ *data << float(0);
+ *data << uint8(0);
+ }
return whisperGUIDpos;
}
@@ -344,6 +353,7 @@ void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType,
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound);
+ data << uint64(source->GetGUID());
SendNonChatPacket(source, &data, msgType, whisperGuid, range, team, gmOnly);
}
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index ccfeb35e5b8..4e6da3ba3f5 100644
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -134,6 +134,11 @@ void GmTicket::WritePacket(WorldPacket& data) const
data << uint8(std::min(_escalatedStatus, TICKET_IN_ESCALATION_QUEUE)); // escalated data
data << uint8(_viewed ? GMTICKET_OPENEDBYGM_STATUS_OPENED : GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED); // whether or not it has been viewed
+
+ // TODO: implement these
+ std::string waitTimeOverrideMessage = "";
+ data << waitTimeOverrideMessage;
+ data << uint32(0); // waitTimeOverrideMinutes
}
void GmTicket::SendResponse(WorldSession* session) const
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index f7c7414fb6f..a9026dcc880 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -24,7 +24,7 @@
#include "AccountMgr.h"
#include "World.h"
-#define DUMP_TABLE_COUNT 27
+#define DUMP_TABLE_COUNT 29
struct DumpTable
{
char const* name;
@@ -39,6 +39,8 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_achievement_progress", DTT_CHAR_TABLE },
{ "character_action", DTT_CHAR_TABLE },
{ "character_aura", DTT_CHAR_TABLE },
+ { "character_currency", DTT_CHAR_TABLE },
+ { "character_cuf_profiles", DTT_CHAR_TABLE },
{ "character_declinedname", DTT_CHAR_TABLE },
{ "character_equipmentsets", DTT_EQSET_TABLE},
{ "character_gifts", DTT_ITEM_GIFT },
@@ -320,10 +322,13 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
break;
case DTT_CHARACTER:
{
- if (result->GetFieldCount() <= 68) // avoid crashes on next check
+ if (result->GetFieldCount() <= 64) // avoid crashes on next check
+ {
TC_LOG_FATAL(LOG_FILTER_GENERAL, "PlayerDumpWriter::DumpTable - Trying to access non-existing or wrong positioned field (`deleteInfos_Account`) in `characters` table.");
+ return false;
+ }
- if (result->Fetch()[68].GetUInt32()) // characters.deleteInfos_Account - if filled error
+ if (result->Fetch()[64].GetUInt32()) // characters.deleteInfos_Account - if filled error
return false;
break;
}
@@ -543,18 +548,18 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login"
+ if (!changenth(line, 38, "1")) // characters.at_login set to "rename on login"
ROLLBACK(DUMP_FILE_BROKEN);
}
else if (!changenth(line, 3, name.c_str())) // characters.name
ROLLBACK(DUMP_FILE_BROKEN);
const char null[5] = "NULL";
- if (!changenth(line, 69, null)) // characters.deleteInfos_Account
+ if (!changenth(line, 63, null)) // characters.deleteInfos_Account
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 70, null)) // characters.deleteInfos_Name
+ if (!changenth(line, 64, null)) // characters.deleteInfos_Name
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 71, null)) // characters.deleteDate
+ if (!changenth(line, 65, null)) // characters.deleteDate
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h
index 895676eb5db..c9b763febae 100644
--- a/src/server/game/Tools/PlayerDump.h
+++ b/src/server/game/Tools/PlayerDump.h
@@ -30,7 +30,8 @@ enum DumpTableType
DTT_CHAR_TABLE, // // character_achievement, character_achievement_progress,
// character_action, character_aura, character_homebind,
// character_queststatus, character_queststatus_rewarded, character_reputation,
- // character_spell, character_spell_cooldown, character_ticket, character_talent
+ // character_spell, character_spell_cooldown, character_ticket, character_talent.
+ // character_cuf_profiles, character_currency
DTT_EQSET_TABLE, // <- guid // character_equipmentsets
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index 38d64eedd5c..ae04feb894b 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -29,6 +29,7 @@
#include "Util.h"
#include "ScriptMgr.h"
#include "Opcodes.h"
+#include "WorldSession.h"
/// Create the Weather object
Weather::Weather(uint32 zone, WeatherData const* weatherChances)
diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h
index 2645d3f2067..bde4280cb25 100644
--- a/src/server/game/Weather/Weather.h
+++ b/src/server/game/Weather/Weather.h
@@ -46,7 +46,7 @@ struct WeatherData
enum WeatherState
{
WEATHER_STATE_FINE = 0,
- WEATHER_STATE_FOG = 1,
+ WEATHER_STATE_FOG = 1, // Used in some instance encounters.
WEATHER_STATE_LIGHT_RAIN = 3,
WEATHER_STATE_MEDIUM_RAIN = 4,
WEATHER_STATE_HEAVY_RAIN = 5,
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index 0a09d8a5dff..799ea569ab5 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -28,6 +28,7 @@
#include "Player.h"
#include "WorldPacket.h"
#include "Opcodes.h"
+#include "WorldSession.h"
namespace WeatherMgr
{
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 645c14b8758..bde496a9c5d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -40,12 +40,13 @@
#include "ObjectMgr.h"
#include "ArenaTeamMgr.h"
#include "GuildMgr.h"
+#include "GuildFinderMgr.h"
#include "TicketMgr.h"
-#include "CreatureEventAIMgr.h"
#include "SpellMgr.h"
#include "GroupMgr.h"
#include "Chat.h"
#include "DBCStores.h"
+#include "DB2Stores.h"
#include "LootMgr.h"
#include "ItemEnchantmentMgr.h"
#include "MapManager.h"
@@ -109,6 +110,7 @@ World::World()
m_MaxPlayerCount = 0;
m_NextDailyQuestReset = 0;
m_NextWeeklyQuestReset = 0;
+ m_NextCurrencyReset = 0;
m_defaultDbcLocale = LOCALE_enUS;
m_availableDbcLocaleMask = 0;
@@ -275,7 +277,7 @@ void World::AddSession_(WorldSession* s)
return;
}
- s->SendAuthResponse(AUTH_OK, true);
+ s->SendAuthResponse(AUTH_OK, false);
s->SendAddonsInfo();
s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
s->SendTutorialsData();
@@ -331,7 +333,7 @@ void World::AddQueuedPlayer(WorldSession* sess)
m_QueuedPlayer.push_back(sess);
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
- sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess));
+ sess->SendAuthResponse(AUTH_WAIT_QUEUE, true, GetQueuePos(sess));
}
bool World::RemoveQueuedPlayer(WorldSession* sess)
@@ -405,6 +407,16 @@ void World::LoadConfigSettings(bool reload)
sLog->LoadFromConfig();
}
+ m_defaultDbcLocale = LocaleConstant(ConfigMgr::GetIntDefault("DBC.Locale", 0));
+
+ if (m_defaultDbcLocale >= TOTAL_LOCALES)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", TOTAL_LOCALES);
+ m_defaultDbcLocale = LOCALE_enUS;
+ }
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Using %s DBC Locale", localeNames[m_defaultDbcLocale]);
+
///- Read the player limit and the Message of the day from the config file
SetPlayerAmountLimit(ConfigMgr::GetIntDefault("PlayerLimit", 100));
SetMotd(ConfigMgr::GetStringDefault("Motd", "Welcome to a Trinity Core Server."));
@@ -766,57 +778,84 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_START_PLAYER_MONEY] = ConfigMgr::GetIntDefault("StartPlayerMoney", 0);
if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0.." UI64FMTD ". Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], uint64(MAX_MONEY_AMOUNT), 0);
m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
}
- else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT)
+ else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > 0x7FFFFFFF-1) // TODO: (See MAX_MONEY_AMOUNT)
{
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",
- m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, MAX_MONEY_AMOUNT);
- m_int_configs[CONFIG_START_PLAYER_MONEY] = MAX_MONEY_AMOUNT;
+ m_int_configs[CONFIG_START_PLAYER_MONEY], 0x7FFFFFFF-1, 0x7FFFFFFF-1);
+ m_int_configs[CONFIG_START_PLAYER_MONEY] = 0x7FFFFFFF-1;
}
- m_int_configs[CONFIG_MAX_HONOR_POINTS] = ConfigMgr::GetIntDefault("MaxHonorPoints", 75000);
- if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = ConfigMgr::GetIntDefault("Currency.ResetHour", 3);
+ if (m_int_configs[CONFIG_CURRENCY_RESET_HOUR] > 23)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "MaxHonorPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_HONOR_POINTS]);
- m_int_configs[CONFIG_MAX_HONOR_POINTS] = 0;
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_CURRENCY_RESET_HOUR]);
+ m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = 3;
+ }
+ m_int_configs[CONFIG_CURRENCY_RESET_DAY] = ConfigMgr::GetIntDefault("Currency.ResetDay", 3);
+ if (m_int_configs[CONFIG_CURRENCY_RESET_DAY] > 6)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.ResetDay (%i) can't be load. Set to 3.", m_int_configs[CONFIG_CURRENCY_RESET_DAY]);
+ m_int_configs[CONFIG_CURRENCY_RESET_DAY] = 3;
+ }
+ m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = ConfigMgr::GetIntDefault("Currency.ResetInterval", 7);
+ if (int32(m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]) <= 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.ResetInterval (%i) must be > 0, set to default 7.", m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]);
+ m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = 7;
}
- m_int_configs[CONFIG_START_HONOR_POINTS] = ConfigMgr::GetIntDefault("StartHonorPoints", 0);
- if (int32(m_int_configs[CONFIG_START_HONOR_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = ConfigMgr::GetIntDefault("Currency.StartHonorPoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]) < 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], 0);
- m_int_configs[CONFIG_START_HONOR_POINTS] = 0;
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.StartHonorPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = 0;
}
- else if (m_int_configs[CONFIG_START_HONOR_POINTS] > m_int_configs[CONFIG_MAX_HONOR_POINTS])
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = ConfigMgr::GetIntDefault("Currency.MaxHonorPoints", 4000);
+ if (int32(m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]) < 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS]);
- m_int_configs[CONFIG_START_HONOR_POINTS] = m_int_configs[CONFIG_MAX_HONOR_POINTS];
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.MaxHonorPoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = 4000;
}
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] *= 100; //precision mod
- m_int_configs[CONFIG_MAX_ARENA_POINTS] = ConfigMgr::GetIntDefault("MaxArenaPoints", 10000);
- if (int32(m_int_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = ConfigMgr::GetIntDefault("Currency.StartJusticePoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]) < 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.StartJusticePoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = 0;
+ }
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = ConfigMgr::GetIntDefault("Currency.MaxJusticePoints", 4000);
+ if (int32(m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]) < 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "MaxArenaPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_ARENA_POINTS]);
- m_int_configs[CONFIG_MAX_ARENA_POINTS] = 0;
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.MaxJusticePoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = 4000;
}
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] *= 100; //precision mod
- m_int_configs[CONFIG_START_ARENA_POINTS] = ConfigMgr::GetIntDefault("StartArenaPoints", 0);
- if (int32(m_int_configs[CONFIG_START_ARENA_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = ConfigMgr::GetIntDefault("Currency.StartConquestPoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]) < 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], 0);
- m_int_configs[CONFIG_START_ARENA_POINTS] = 0;
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.StartConquestPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = 0;
}
- else if (m_int_configs[CONFIG_START_ARENA_POINTS] > m_int_configs[CONFIG_MAX_ARENA_POINTS])
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = ConfigMgr::GetIntDefault("Currency.ConquestPointsWeekCap", 1650);
+ if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]) <= 0)
{
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS]);
- m_int_configs[CONFIG_START_ARENA_POINTS] = m_int_configs[CONFIG_MAX_ARENA_POINTS];
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.ConquestPointsWeekCap (%i) must be > 0, set to default 1650.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]);
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = 1650;
}
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] *= 100; //precision mod
+
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = ConfigMgr::GetIntDefault("Currency.ConquestPointsArenaReward", 180);
+ if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]) <= 0)
+ {
+ TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Currency.ConquestPointsArenaReward (%i) must be > 0, set to default 180.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]);
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = 180;
+ }
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] *= 100; //precision mod
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = ConfigMgr::GetIntDefault("RecruitAFriend.MaxLevel", 60);
if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
@@ -913,12 +952,8 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = ConfigMgr::GetIntDefault("SkillGain.Crafting", 1);
- m_int_configs[CONFIG_SKILL_GAIN_DEFENSE] = ConfigMgr::GetIntDefault("SkillGain.Defense", 1);
-
m_int_configs[CONFIG_SKILL_GAIN_GATHERING] = ConfigMgr::GetIntDefault("SkillGain.Gathering", 1);
- m_int_configs[CONFIG_SKILL_GAIN_WEAPON] = ConfigMgr::GetIntDefault("SkillGain.Weapon", 1);
-
m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = ConfigMgr::GetIntDefault("MaxOverspeedPings", 2);
if (m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
{
@@ -931,7 +966,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_DISABLE_BREATHING] = ConfigMgr::GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
- m_bool_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = ConfigMgr::GetBoolDefault("AlwaysMaxSkillForLevel", false);
if (reload)
{
@@ -1022,8 +1056,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = ConfigMgr::GetIntDefault ("Arena.MaxRatingDifference", 150);
m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = ConfigMgr::GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = ConfigMgr::GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS);
- m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = ConfigMgr::GetBoolDefault("Arena.AutoDistributePoints", false);
- m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = ConfigMgr::GetIntDefault ("Arena.AutoDistributeInterval", 7);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = ConfigMgr::GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = ConfigMgr::GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false);
m_int_configs[CONFIG_ARENA_SEASON_ID] = ConfigMgr::GetIntDefault ("Arena.ArenaSeason.ID", 1);
@@ -1047,6 +1079,9 @@ void World::LoadConfigSettings(bool reload)
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
}
+ m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = ConfigMgr::GetIntDefault("Guild.NewsLogRecordsCount", GUILD_NEWSLOG_MAX_RECORDS);
+ if (m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] > GUILD_NEWSLOG_MAX_RECORDS)
+ m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = GUILD_NEWSLOG_MAX_RECORDS;
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = ConfigMgr::GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
if (m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] > GUILD_EVENTLOG_MAX_RECORDS)
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
@@ -1208,6 +1243,15 @@ void World::LoadConfigSettings(bool reload)
// MySQL ping time interval
m_int_configs[CONFIG_DB_PING_INTERVAL] = ConfigMgr::GetIntDefault("MaxPingTime", 30);
+ // Guild save interval
+ m_bool_configs[CONFIG_GUILD_LEVELING_ENABLED] = ConfigMgr::GetBoolDefault("Guild.LevelingEnabled", true);
+ m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = ConfigMgr::GetIntDefault("Guild.SaveInterval", 15);
+ m_int_configs[CONFIG_GUILD_MAX_LEVEL] = ConfigMgr::GetIntDefault("Guild.MaxLevel", 25);
+ m_int_configs[CONFIG_GUILD_UNDELETABLE_LEVEL] = ConfigMgr::GetIntDefault("Guild.UndeletableLevel", 4);
+ rate_values[RATE_XP_GUILD_MODIFIER] = ConfigMgr::GetFloatDefault("Guild.XPModifier", 0.25f);
+ m_int_configs[CONFIG_GUILD_DAILY_XP_CAP] = ConfigMgr::GetIntDefault("Guild.DailyXPCap", 7807500);
+ m_int_configs[CONFIG_GUILD_WEEKLY_REP_CAP] = ConfigMgr::GetIntDefault("Guild.WeeklyReputationCap", 4375);
+
// misc
m_bool_configs[CONFIG_PDUMP_NO_PATHS] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowPaths", true);
m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowOverwrite", true);
@@ -1301,14 +1345,14 @@ void World::SetInitialWorldSettings()
///- Load the DBC files
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Initialize data stores...");
LoadDBCStores(m_dataPath);
- DetectDBCLang();
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading spell dbc data corrections...");
- sSpellMgr->LoadDbcDataCorrections();
+ LoadDB2Stores(m_dataPath);
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading SpellInfo store...");
sSpellMgr->LoadSpellInfoStore();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading SpellInfo corrections...");
+ sSpellMgr->LoadSpellInfoCorrections();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading SkillLineAbilityMultiMap Data...");
sSpellMgr->LoadSkillLineAbilityMap();
@@ -1333,7 +1377,6 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadCreatureLocales();
sObjectMgr->LoadGameObjectLocales();
sObjectMgr->LoadItemLocales();
- sObjectMgr->LoadItemSetNameLocales();
sObjectMgr->LoadQuestLocales();
sObjectMgr->LoadNpcTextLocales();
sObjectMgr->LoadPageTextLocales();
@@ -1382,6 +1425,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Spell Group Stack Rules...");
sSpellMgr->LoadSpellGroupStackRules();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Spell Phase Dbc Info...");
+ sObjectMgr->LoadSpellPhaseInfo();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading NPC Texts...");
sObjectMgr->LoadGossipText();
@@ -1398,7 +1444,10 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadItemTemplates();
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Item set names..."); // must be after LoadItemPrototypes
- sObjectMgr->LoadItemSetNames();
+ sObjectMgr->LoadItemTemplateAddon();
+
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Loading Item Scripts..."); // must be after LoadItemPrototypes
+ sObjectMgr->LoadItemScriptNames();
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Creature Model Based Info Data...");
sObjectMgr->LoadCreatureModelInfo();
@@ -1508,6 +1557,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Graveyard-zone links...");
sObjectMgr->LoadGraveyardZones();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Graveyard Orientations...");
+ sObjectMgr->LoadGraveyardOrientations();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading spell pet auras...");
sSpellMgr->LoadSpellPetAuras();
@@ -1579,9 +1631,17 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Auctions...");
sAuctionMgr->LoadAuctions();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Guild XP for level...");
+ sGuildMgr->LoadGuildXpForLevel();
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Guild rewards...");
+ sGuildMgr->LoadGuildRewards();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Guilds...");
sGuildMgr->LoadGuilds();
+ sGuildFinderMgr->LoadFromDB();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading ArenaTeams...");
sArenaTeamMgr->LoadArenaTeams();
@@ -1624,6 +1684,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
LoadWorldStates();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Phase definitions...");
+ sObjectMgr->LoadPhaseDefinitions();
+
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Conditions...");
sConditionMgr->LoadConditions();
@@ -1666,12 +1729,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading Scripts text locales..."); // must be after Load*Scripts calls
sObjectMgr->LoadDbScriptStrings();
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading CreatureEventAI Texts...");
- sEventAIMgr->LoadCreatureEventAI_Texts();
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading CreatureEventAI Scripts...");
- sEventAIMgr->LoadCreatureEventAI_Scripts();
-
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading spell script names...");
sObjectMgr->LoadSpellScriptNames();
@@ -1715,6 +1772,8 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes
+ m_timers[WUPDATE_GUILDSAVE].SetInterval(getIntConfig(CONFIG_GUILD_SAVE_INTERVAL) * MINUTE * IN_MILLISECONDS);
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -1749,7 +1808,6 @@ void World::SetInitialWorldSettings()
///- Initialize Battlegrounds
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Starting Battleground System");
sBattlegroundMgr->CreateInitialBattlegrounds();
- sBattlegroundMgr->InitAutomaticArenaPointDistribution();
///- Initialize outdoor pvp
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Starting Outdoor PvP System");
@@ -1790,8 +1848,20 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Calculate guild limitation(s) reset time...");
InitGuildResetTime();
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Calculate next currency reset time...");
+ InitCurrencyResetTime();
+
LoadCharacterNameData();
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Initializing Opcodes...");
+ opcodeTable.Initialize();
+
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Loading hotfix info...");
+ sObjectMgr->LoadHotfixData();
+
+ TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading missing KeyChains...");
+ sObjectMgr->LoadMissingKeyChains();
+
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
TC_LOG_INFO(LOG_FILTER_WORLDSERVER, "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
@@ -1800,49 +1870,6 @@ void World::SetInitialWorldSettings()
sLog->SetRealmId(realmId);
}
-void World::DetectDBCLang()
-{
- uint8 m_lang_confid = ConfigMgr::GetIntDefault("DBC.Locale", 255);
-
- if (m_lang_confid != 255 && m_lang_confid >= TOTAL_LOCALES)
- {
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", TOTAL_LOCALES);
- m_lang_confid = LOCALE_enUS;
- }
-
- ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1);
-
- std::string availableLocalsStr;
-
- uint8 default_locale = TOTAL_LOCALES;
- for (uint8 i = default_locale-1; i < TOTAL_LOCALES; --i) // -1 will be 255 due to uint8
- {
- if (race->name[i][0] != '\0') // check by race names
- {
- default_locale = i;
- m_availableDbcLocaleMask |= (1 << i);
- availableLocalsStr += localeNames[i];
- availableLocalsStr += " ";
- }
- }
-
- if (default_locale != m_lang_confid && m_lang_confid < TOTAL_LOCALES &&
- (m_availableDbcLocaleMask & (1 << m_lang_confid)))
- {
- default_locale = m_lang_confid;
- }
-
- if (default_locale >= TOTAL_LOCALES)
- {
- TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Unable to determine your DBC Locale! (corrupt DBC?)");
- exit(1);
- }
-
- m_defaultDbcLocale = LocaleConstant(default_locale);
-
- TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
-}
-
void World::RecordTimeDiff(const char *text, ...)
{
if (m_updateTimeCount != 1)
@@ -1956,6 +1983,9 @@ void World::Update(uint32 diff)
if (m_gameTime > m_NextGuildReset)
ResetGuildCap();
+ if (m_gameTime > m_NextCurrencyReset)
+ ResetCurrencyWeekCap();
+
/// <ul><li> Handle auctions when the timer has passed
if (m_timers[WUPDATE_AUCTIONS].Passed())
{
@@ -2083,6 +2113,12 @@ void World::Update(uint32 diff)
WorldDatabase.KeepAlive();
}
+ if (m_timers[WUPDATE_GUILDSAVE].Passed())
+ {
+ m_timers[WUPDATE_GUILDSAVE].Reset();
+ sGuildMgr->SaveGuilds();
+ }
+
// update the instance reset times
sInstanceSaveMgr->Update();
@@ -2684,16 +2720,20 @@ void World::SendAutoBroadcast()
sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
else if (abcenter == 1)
{
- WorldPacket data(SMSG_NOTIFICATION, (msg.size()+1));
- data << msg;
+ WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
+ data.WriteBits(msg.length(), 13);
+ data.FlushBits();
+ data.WriteString(msg);
sWorld->SendGlobalMessage(&data);
}
else if (abcenter == 2)
{
sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
- WorldPacket data(SMSG_NOTIFICATION, (msg.size()+1));
- data << msg;
+ WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
+ data.WriteBits(msg.length(), 13);
+ data.FlushBits();
+ data.WriteString(msg);
sWorld->SendGlobalMessage(&data);
}
@@ -2831,6 +2871,35 @@ void World::InitGuildResetTime()
sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
}
+void World::InitCurrencyResetTime()
+{
+ time_t currencytime = uint64(sWorld->getWorldState(WS_CURRENCY_RESET_TIME));
+ if (!currencytime)
+ m_NextCurrencyReset = time_t(time(NULL)); // game time not yet init
+
+ // generate time by config
+ time_t curTime = time(NULL);
+ tm localTm = *localtime(&curTime);
+
+ localTm.tm_wday = getIntConfig(CONFIG_CURRENCY_RESET_DAY);
+ localTm.tm_hour = getIntConfig(CONFIG_CURRENCY_RESET_HOUR);
+ localTm.tm_min = 0;
+ localTm.tm_sec = 0;
+
+ // current week reset time
+ time_t nextWeekResetTime = mktime(&localTm);
+
+ // next reset time before current moment
+ if (curTime >= nextWeekResetTime)
+ nextWeekResetTime += getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY;
+
+ // normalize reset time
+ m_NextCurrencyReset = currencytime < curTime ? nextWeekResetTime - getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY : nextWeekResetTime;
+
+ if (!currencytime)
+ sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
+}
+
void World::ResetDailyQuests()
{
TC_LOG_INFO(LOG_FILTER_GENERAL, "Daily quests reset for all characters.");
@@ -2846,6 +2915,18 @@ void World::ResetDailyQuests()
sPoolMgr->ChangeDailyQuests();
}
+void World::ResetCurrencyWeekCap()
+{
+ CharacterDatabase.Execute("UPDATE `character_currency` SET `week_count` = 0");
+
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (itr->second->GetPlayer())
+ itr->second->GetPlayer()->ResetCurrencyWeekCap();
+
+ m_NextCurrencyReset = time_t(m_NextCurrencyReset + DAY * getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL));
+ sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
+}
+
void World::LoadDBAllowedSecurityLevel()
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL);
@@ -2954,11 +3035,14 @@ void World::ResetRandomBG()
void World::ResetGuildCap()
{
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Guild Daily Cap reset.");
-
m_NextGuildReset = time_t(m_NextGuildReset + DAY);
sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
- sGuildMgr->ResetTimes();
+ uint32 week = getWorldState(WS_GUILD_WEEKLY_RESET_TIME);
+ week = week < 7 ? week + 1 : 1;
+
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Guild Daily Cap reset. Week: %u", week == 1);
+ sWorld->setWorldState(WS_GUILD_WEEKLY_RESET_TIME, week);
+ sGuildMgr->ResetTimes(week == 1);
}
void World::UpdateMaxSessionCounters()
@@ -3170,6 +3254,14 @@ CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
return NULL;
}
+void World::UpdatePhaseDefinitions()
+{
+ SessionMap::const_iterator itr;
+ for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld())
+ itr->second->GetPlayer()->GetPhaseMgr().NotifyStoresReloaded();
+}
+
void World::ReloadRBAC()
{
// Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 12586ed4969..cf57a178a2c 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -45,11 +45,19 @@ class SystemMgr;
// ServerMessages.dbc
enum ServerMessageType
{
- SERVER_MSG_SHUTDOWN_TIME = 1,
- SERVER_MSG_RESTART_TIME = 2,
- SERVER_MSG_STRING = 3,
- SERVER_MSG_SHUTDOWN_CANCELLED = 4,
- SERVER_MSG_RESTART_CANCELLED = 5
+ SERVER_MSG_SHUTDOWN_TIME = 1,
+ SERVER_MSG_RESTART_TIME = 2,
+ SERVER_MSG_STRING = 3,
+ SERVER_MSG_SHUTDOWN_CANCELLED = 4,
+ SERVER_MSG_RESTART_CANCELLED = 5,
+ SERVER_MSG_BG_SHUTDOWN_TIME = 6,
+ SERVER_MSG_BG_RESTART_TIME = 7,
+ SERVER_MSG_INSTANCE_SHUTDOWN_TIME = 8,
+ SERVER_MSG_INSTANCE_RESTART_TIME = 9,
+ SERVER_MSG_CONTENT_READY = 10,
+ SERVER_MSG_TICKET_SERVICED_SOON = 11,
+ SERVER_MSG_WAIT_TIME_UNAVAILABLE = 12,
+ SERVER_MSG_TICKET_WAIT_TIME = 13,
};
enum ShutdownMask
@@ -78,6 +86,7 @@ enum WorldTimers
WUPDATE_MAILBOXQUEUE,
WUPDATE_DELETECHARS,
WUPDATE_PINGDB,
+ WUPDATE_GUILDSAVE,
WUPDATE_COUNT
};
@@ -107,7 +116,6 @@ enum WorldBoolConfigs
CONFIG_SKILL_MILLING,
CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
CONFIG_WEATHER,
- CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL,
CONFIG_QUEST_IGNORE_RAID,
CONFIG_DETECT_POS_COLLISION,
CONFIG_RESTRICTED_LFG_CHANNEL,
@@ -123,7 +131,6 @@ enum WorldBoolConfigs
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_BG_XP_FOR_KILL,
- CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_ARENA_SEASON_IN_PROGRESS,
@@ -157,6 +164,7 @@ enum WorldBoolConfigs
CONFIG_WARDEN_ENABLED,
CONFIG_ENABLE_MMAPS,
CONFIG_WINTERGRASP_ENABLE,
+ CONFIG_GUILD_LEVELING_ENABLED,
CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs?
CONFIG_EVENT_ANNOUNCE,
CONFIG_STATS_LIMITS_ENABLE,
@@ -215,10 +223,16 @@ enum WorldIntConfigs
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
- CONFIG_MAX_HONOR_POINTS,
- CONFIG_START_HONOR_POINTS,
- CONFIG_MAX_ARENA_POINTS,
- CONFIG_START_ARENA_POINTS,
+ CONFIG_CURRENCY_START_JUSTICE_POINTS,
+ CONFIG_CURRENCY_MAX_JUSTICE_POINTS,
+ CONFIG_CURRENCY_START_HONOR_POINTS,
+ CONFIG_CURRENCY_MAX_HONOR_POINTS,
+ CONFIG_CURRENCY_START_CONQUEST_POINTS,
+ CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP,
+ CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD,
+ CONFIG_CURRENCY_RESET_HOUR,
+ CONFIG_CURRENCY_RESET_DAY,
+ CONFIG_CURRENCY_RESET_INTERVAL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE,
CONFIG_INSTANCE_RESET_TIME_HOUR,
@@ -243,9 +257,7 @@ enum WorldIntConfigs
CONFIG_SKILL_CHANCE_MINING_STEPS,
CONFIG_SKILL_CHANCE_SKINNING_STEPS,
CONFIG_SKILL_GAIN_CRAFTING,
- CONFIG_SKILL_GAIN_DEFENSE,
CONFIG_SKILL_GAIN_GATHERING,
- CONFIG_SKILL_GAIN_WEAPON,
CONFIG_MAX_OVERSPEED_PINGS,
CONFIG_EXPANSION,
CONFIG_CHATFLOOD_MESSAGE_COUNT,
@@ -279,7 +291,6 @@ enum WorldIntConfigs
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_RATED_UPDATE_TIMER,
- CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_ARENA_SEASON_ID,
CONFIG_ARENA_START_RATING,
CONFIG_ARENA_START_PERSONAL_RATING,
@@ -297,6 +308,7 @@ enum WorldIntConfigs
CONFIG_LOGDB_CLEARINTERVAL,
CONFIG_LOGDB_CLEARTIME,
CONFIG_CLIENTCACHE_VERSION,
+ CONFIG_GUILD_NEWS_LOG_COUNT,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_MIN_LEVEL_STAT_SAVE,
@@ -326,6 +338,11 @@ enum WorldIntConfigs
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
+ CONFIG_GUILD_SAVE_INTERVAL,
+ CONFIG_GUILD_MAX_LEVEL,
+ CONFIG_GUILD_UNDELETABLE_LEVEL,
+ CONFIG_GUILD_DAILY_XP_CAP,
+ CONFIG_GUILD_WEEKLY_REP_CAP,
INT_CONFIG_VALUE_COUNT
};
@@ -353,6 +370,7 @@ enum Rates
RATE_DROP_MONEY,
RATE_XP_KILL,
RATE_XP_QUEST,
+ RATE_XP_GUILD_MODIFIER,
RATE_XP_EXPLORE,
RATE_REPAIRCOST,
RATE_REPUTATION_GAIN,
@@ -471,6 +489,8 @@ enum WorldStates
WS_CLEANING_FLAGS = 20004, // Cleaning Flags
WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time
WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time
+ // Cata specific custom worldstates
+ WS_GUILD_WEEKLY_RESET_TIME = 20050, // Next guild week reset time
};
/// Storage class for commands issued for delayed execution
@@ -603,7 +623,7 @@ class World
/// Get the maximum skill level a player can reach
uint16 GetConfigMaxSkillValue() const
{
- uint16 lvl = uint16(getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
+ uint8 lvl = uint8(getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl * 5;
}
@@ -736,6 +756,7 @@ class World
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
void ResetEventSeasonalQuests(uint16 event_id);
+ void UpdatePhaseDefinitions();
void ReloadRBAC();
protected:
@@ -748,11 +769,13 @@ class World
void InitMonthlyQuestResetTime();
void InitRandomBGResetTime();
void InitGuildResetTime();
+ void InitCurrencyResetTime();
void ResetDailyQuests();
void ResetWeeklyQuests();
void ResetMonthlyQuests();
void ResetRandomBG();
void ResetGuildCap();
+ void ResetCurrencyWeekCap();
private:
static ACE_Atomic_Op<ACE_Thread_Mutex, bool> m_stopEvent;
static uint8 m_ExitCode;
@@ -792,7 +815,6 @@ class World
AccountTypes m_allowedSecurityLevel;
LocaleConstant m_defaultDbcLocale; // from config for one from loaded DBC locales
uint32 m_availableDbcLocaleMask; // by loaded DBC
- void DetectDBCLang();
bool m_allowMovement;
std::string m_motd;
std::string m_dataPath;
@@ -809,12 +831,13 @@ class World
// CLI command holder to be thread safe
ACE_Based::LockedQueue<CliCommandHolder*, ACE_Thread_Mutex> cliCmdQueue;
- // next daily quests and random bg reset time
+ // scheduled reset times
time_t m_NextDailyQuestReset;
time_t m_NextWeeklyQuestReset;
time_t m_NextMonthlyQuestReset;
time_t m_NextRandomBGReset;
time_t m_NextGuildReset;
+ time_t m_NextCurrencyReset;
//Player Queue
Queue m_QueuedPlayer;
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index cf4618022b3..12e68fc5831 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -72,7 +72,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Addons
${CMAKE_SOURCE_DIR}/src/server/game/AI
${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI
- ${CMAKE_SOURCE_DIR}/src/server/game/AI/EventAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
@@ -88,6 +87,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Combat
${CMAKE_SOURCE_DIR}/src/server/game/DataStores
${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding
+ ${CMAKE_SOURCE_DIR}/src/server/game/Entities/AreaTrigger
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature
${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject
diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp
index e51052bc18f..2b316803029 100644
--- a/src/server/scripts/Commands/cs_character.cpp
+++ b/src/server/scripts/Commands/cs_character.cpp
@@ -277,7 +277,7 @@ public:
if (titleInfo && target->HasTitle(titleInfo))
{
- std::string name = titleInfo->name[loc];
+ std::string name = titleInfo->name;
if (name.empty())
continue;
@@ -566,7 +566,7 @@ public:
{
FactionState const& faction = itr->second;
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
- char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#";
+ char const* factionName = factionEntry ? factionEntry->name : "#Not found#";
ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
std::string rankName = handler->GetTrinityString(ReputationRankStrIndex[rank]);
std::ostringstream ss;
diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp
index 9dbc9900e58..aeac475fdb1 100644
--- a/src/server/scripts/Commands/cs_cheat.cpp
+++ b/src/server/scripts/Commands/cs_cheat.cpp
@@ -185,10 +185,11 @@ public:
std::string argstr = (char*)args;
+ Player* target = handler->GetSession()->GetPlayer();
if (!*args)
{
- argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK)) ? "off" : "on";
- if (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK))
+ argstr = (target->GetCommandStatus(CHEAT_WATERWALK)) ? "off" : "on";
+ if (target->GetCommandStatus(CHEAT_WATERWALK))
argstr = "off";
else
argstr = "on";
@@ -196,15 +197,17 @@ public:
if (argstr == "off")
{
- handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_WATERWALK);
- handler->GetSession()->GetPlayer()->SetMovement(MOVE_LAND_WALK); // OFF
+ target->SetCommandStatusOff(CHEAT_WATERWALK);
+ target->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ target->SendMovementWaterWalking(); // OFF
handler->SendSysMessage("Waterwalking is OFF. You can't walk on water.");
return true;
}
else if (argstr == "on")
{
- handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_WATERWALK);
- handler->GetSession()->GetPlayer()->SetMovement(MOVE_WATER_WALK); // ON
+ target->SetCommandStatusOn(CHEAT_WATERWALK);
+ target->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ target->SendMovementWaterWalking(); // ON
handler->SendSysMessage("Waterwalking is ON. You can walk on water.");
return true;
}
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 4719a460c4f..84b317a6ca0 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -91,6 +91,7 @@ public:
{ "areatriggers", SEC_ADMINISTRATOR, false, &HandleDebugAreaTriggersCommand, "", NULL },
{ "los", SEC_MODERATOR, false, &HandleDebugLoSCommand, "", NULL },
{ "moveflags", SEC_ADMINISTRATOR, false, &HandleDebugMoveflagsCommand, "", NULL },
+ { "phase", SEC_MODERATOR, false, &HandleDebugPhaseCommand, "", NULL },
{ NULL, SEC_PLAYER, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
@@ -237,7 +238,7 @@ public:
return false;
SellResult msg = SellResult(atoi(args));
- handler->GetSession()->GetPlayer()->SendSellError(msg, 0, 0, 0);
+ handler->GetSession()->GetPlayer()->SendSellError(msg, 0, 0);
return true;
}
@@ -311,7 +312,7 @@ public:
uint32 opcode;
parsedStream >> opcode;
- WorldPacket data(opcode, 0);
+ WorldPacket data(Opcodes(opcode), 0);
while (!parsedStream.eof())
{
@@ -417,7 +418,7 @@ public:
}
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Sending opcode %u", data.GetOpcode());
data.hexlike();
- player->GetSession()->SendPacket(&data);
+ player->GetSession()->SendPacket(&data, true);
handler->PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName().c_str());
return true;
}
@@ -951,8 +952,21 @@ public:
if (!*args)
return false;
- uint32 PhaseShift = atoi(args);
- handler->GetSession()->SendSetPhaseShift(PhaseShift);
+ char* t = strtok((char*)args, " ");
+ char* p = strtok(NULL, " ");
+
+ if (!t)
+ return false;
+
+ std::set<uint32> terrainswap;
+ std::set<uint32> phaseId;
+
+ terrainswap.insert((uint32)atoi(t));
+
+ if (p)
+ phaseId.insert((uint32)atoi(p));
+
+ handler->GetSession()->SendSetPhaseShift(phaseId, terrainswap);
return true;
}
@@ -1317,7 +1331,15 @@ public:
target->SetExtraUnitMovementFlags(moveFlagsExtra);
}
- target->SendMovementFlagUpdate();
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ target->DestroyForNearbyPlayers(); // Force new SMSG_UPDATE_OBJECT:CreateObject
+ else
+ {
+ WorldPacket data(SMSG_PLAYER_MOVE);
+ target->WriteMovementInfo(data);
+ target->SendMessageToSet(&data, true);
+ }
+
handler->PSendSysMessage(LANG_MOVEFLAGS_SET, target->GetUnitMovementFlags(), target->GetExtraUnitMovementFlags());
}
@@ -1333,6 +1355,17 @@ public:
handler->PSendSysMessage("Waypoint SQL written to SQL Developer log");
return true;
}
+
+ static bool HandleDebugPhaseCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ Unit* unit = handler->getSelectedUnit();
+ Player* player = handler->GetSession()->GetPlayer();
+ if (unit && unit->GetTypeId() == TYPEID_PLAYER)
+ player = unit->ToPlayer();
+
+ player->GetPhaseMgr().SendDebugReportToPlayer(handler->GetSession()->GetPlayer());
+ return true;
+ }
};
void AddSC_debug_commandscript()
diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp
index 168a5ec60b8..e0c338a2dbf 100644
--- a/src/server/scripts/Commands/cs_gm.cpp
+++ b/src/server/scripts/Commands/cs_gm.cpp
@@ -101,19 +101,22 @@ public:
if (!target)
target = handler->GetSession()->GetPlayer();
- WorldPacket data(12);
+ WorldPacket data;
if (strncmp(args, "on", 3) == 0)
- data.SetOpcode(SMSG_MOVE_SET_CAN_FLY);
+ {
+ target->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
+ target->SendMovementCanFlyChange();
+ }
else if (strncmp(args, "off", 4) == 0)
- data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
+ {
+ target->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
+ target->SendMovementCanFlyChange();
+ }
else
{
handler->SendSysMessage(LANG_USE_BOL);
return false;
}
- data.append(target->GetPackGUID());
- data << uint32(0); // unknown
- target->SendMessageToSet(&data, true);
handler->PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, handler->GetNameLink(target).c_str(), args);
return true;
}
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 11aa02ce648..75135199902 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -446,7 +446,7 @@ public:
if (map->Instanceable())
{
- handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[handler->GetSessionDbcLocale()], map->GetId(), map->GetMapName());
+ handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name, map->GetId(), map->GetMapName());
handler->SetSentErrorMessage(true);
return false;
}
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index 18dee2ea324..e20c4a70417 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -152,7 +152,7 @@ public:
GameObject* object = new GameObject;
uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
- if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
+ if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMgr().GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
{
delete object;
return false;
@@ -165,7 +165,7 @@ public:
}
// fill the gameobject data and save to the db
- object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMaskForSpawn());
+ object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMgr().GetPhaseMaskForSpawn());
// this will generate a new guid if the object is in an instance
if (!object->LoadGameObjectFromDB(guidLow, map))
diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp
index 9d2214c82e9..ffaf1360ad5 100644
--- a/src/server/scripts/Commands/cs_guild.cpp
+++ b/src/server/scripts/Commands/cs_guild.cpp
@@ -22,6 +22,7 @@ Comment: All guild related commands
Category: commandscripts
EndScriptData */
+#include "AchievementMgr.h"
#include "Chat.h"
#include "Language.h"
#include "Guild.h"
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 4c01b89a3ae..c1bbfd8affb 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -397,33 +397,14 @@ public:
!skillInfo->canLink) // only prof with recipes have set
continue;
- int locale = handler->GetSessionDbcLocale();
- name = skillInfo->name[locale];
+ name = skillInfo->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, namePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = skillInfo->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, namePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
- {
- targetSkillInfo = skillInfo;
- break;
- }
+ targetSkillInfo = skillInfo;
}
if (!targetSkillInfo)
diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp
index 6b8ce7732c5..364746adae9 100644
--- a/src/server/scripts/Commands/cs_list.cpp
+++ b/src/server/scripts/Commands/cs_list.cpp
@@ -439,7 +439,7 @@ public:
AuraApplication const* aurApp = itr->second;
Aura const* aura = aurApp->GetBase();
- char const* name = aura->GetSpellInfo()->SpellName[handler->GetSessionDbcLocale()];
+ char const* name = aura->GetSpellInfo()->SpellName;
std::ostringstream ss_name;
ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r";
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index b014eb895be..ff5ece84272 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -106,48 +106,30 @@ public:
AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag);
if (areaEntry)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = areaEntry->area_name[locale];
+ std::string name = areaEntry->area_name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = areaEntry->area_name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
+ if (maxResults && count++ == maxResults)
{
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- // send area in "id - [name]" format
- std::ostringstream ss;
- if (handler->GetSession())
- ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << ' ' << localeNames[locale]<< "]|h|r";
- else
- ss << areaEntry->ID << " - " << name << ' ' << localeNames[locale];
+ // send area in "id - [name]" format
+ std::ostringstream ss;
+ if (handler->GetSession())
+ ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name<< "]|h|r";
+ else
+ ss << areaEntry->ID << " - " << name;
- handler->SendSysMessage(ss.str().c_str());
+ handler->SendSysMessage(ss.str().c_str());
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
@@ -313,77 +295,58 @@ public:
for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
{
- FactionEntry const* factionEntry = sFactionStore.LookupEntry(id);
- if (factionEntry)
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(id))
{
FactionState const* factionState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL;
- int locale = handler->GetSessionDbcLocale();
- std::string name = factionEntry->name[locale];
+ std::string name = factionEntry->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = factionEntry->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
+ if (maxResults && count++ == maxResults)
{
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
- // or "id - [faction] [no reputation]" format
- std::ostringstream ss;
- if (handler->GetSession())
- ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << ' ' << localeNames[locale] << "]|h|r";
- else
- ss << id << " - " << name << ' ' << localeNames[locale];
+ // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
+ // or "id - [faction] [no reputation]" format
+ std::ostringstream ss;
+ if (handler->GetSession())
+ ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << "]|h|r";
+ else
+ ss << id << " - " << name;
- if (factionState) // and then target != NULL also
- {
- uint32 index = target->GetReputationMgr().GetReputationRankStrIndex(factionEntry);
- std::string rankName = handler->GetTrinityString(index);
-
- ss << ' ' << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
-
- if (factionState->Flags & FACTION_FLAG_VISIBLE)
- ss << handler->GetTrinityString(LANG_FACTION_VISIBLE);
- if (factionState->Flags & FACTION_FLAG_AT_WAR)
- ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
- if (factionState->Flags & FACTION_FLAG_PEACE_FORCED)
- ss << handler->GetTrinityString(LANG_FACTION_PEACE_FORCED);
- if (factionState->Flags & FACTION_FLAG_HIDDEN)
- ss << handler->GetTrinityString(LANG_FACTION_HIDDEN);
- if (factionState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
- ss << handler->GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
- if (factionState->Flags & FACTION_FLAG_INACTIVE)
- ss << handler->GetTrinityString(LANG_FACTION_INACTIVE);
- }
- else
- ss << handler->GetTrinityString(LANG_FACTION_NOREPUTATION);
+ if (factionState) // and then target != NULL also
+ {
+ uint32 index = target->GetReputationMgr().GetReputationRankStrIndex(factionEntry);
+ std::string rankName = handler->GetTrinityString(index);
+
+ ss << ' ' << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
+
+ if (factionState->Flags & FACTION_FLAG_VISIBLE)
+ ss << handler->GetTrinityString(LANG_FACTION_VISIBLE);
+ if (factionState->Flags & FACTION_FLAG_AT_WAR)
+ ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
+ if (factionState->Flags & FACTION_FLAG_PEACE_FORCED)
+ ss << handler->GetTrinityString(LANG_FACTION_PEACE_FORCED);
+ if (factionState->Flags & FACTION_FLAG_HIDDEN)
+ ss << handler->GetTrinityString(LANG_FACTION_HIDDEN);
+ if (factionState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
+ ss << handler->GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
+ if (factionState->Flags & FACTION_FLAG_INACTIVE)
+ ss << handler->GetTrinityString(LANG_FACTION_INACTIVE);
+ }
+ else
+ ss << handler->GetTrinityString(LANG_FACTION_NOREPUTATION);
- handler->SendSysMessage(ss.str().c_str());
+ handler->SendSysMessage(ss.str().c_str());
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
@@ -498,45 +461,27 @@ public:
ItemSetEntry const* set = sItemSetStore.LookupEntry(id);
if (set)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = set->name[locale];
+ std::string name = set->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = set->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
+ if (maxResults && count++ == maxResults)
{
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- // send item set in "id - [namedlink locale]" format
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_ITEMSET_LIST_CHAT, id, id, name.c_str(), localeNames[locale]);
- else
- handler->PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE, id, name.c_str(), localeNames[locale]);
+ // send item set in "id - [namedlink locale]" format
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_ITEMSET_LIST_CHAT, id, id, name.c_str(), "");
+ else
+ handler->PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE, id, name.c_str(), "");
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
if (!found)
@@ -779,59 +724,41 @@ public:
SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(id);
if (skillInfo)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = skillInfo->name[locale];
+ std::string name = skillInfo->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = skillInfo->name[locale];
- if (name.empty())
- continue;
+ continue;
- if (Utf8FitTo(name, wNamePart))
- break;
- }
+ if (maxResults && count++ == maxResults)
+ {
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
}
- if (locale < TOTAL_LOCALES)
+ char valStr[50] = "";
+ char const* knownStr = "";
+ if (target && target->HasSkill(id))
{
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
-
- char valStr[50] = "";
- char const* knownStr = "";
- if (target && target->HasSkill(id))
- {
- knownStr = handler->GetTrinityString(LANG_KNOWN);
- uint32 curValue = target->GetPureSkillValue(id);
- uint32 maxValue = target->GetPureMaxSkillValue(id);
- uint32 permValue = target->GetSkillPermBonusValue(id);
- uint32 tempValue = target->GetSkillTempBonusValue(id);
-
- char const* valFormat = handler->GetTrinityString(LANG_SKILL_VALUES);
- snprintf(valStr, 50, valFormat, curValue, maxValue, permValue, tempValue);
- }
+ knownStr = handler->GetTrinityString(LANG_KNOWN);
+ uint32 curValue = target->GetPureSkillValue(id);
+ uint32 maxValue = target->GetPureMaxSkillValue(id);
+ uint32 permValue = target->GetSkillPermBonusValue(id);
+ uint32 tempValue = target->GetSkillTempBonusValue(id);
+
+ char const* valFormat = handler->GetTrinityString(LANG_SKILL_VALUES);
+ snprintf(valStr, 50, valFormat, curValue, maxValue, permValue, tempValue);
+ }
- // send skill in "id - [namedlink locale]" format
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_SKILL_LIST_CHAT, id, id, name.c_str(), localeNames[locale], knownStr, valStr);
- else
- handler->PSendSysMessage(LANG_SKILL_LIST_CONSOLE, id, name.c_str(), localeNames[locale], knownStr, valStr);
+ // send skill in "id - [namedlink locale]" format
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_SKILL_LIST_CHAT, id, id, name.c_str(), "", knownStr, valStr);
+ else
+ handler->PSendSysMessage(LANG_SKILL_LIST_CONSOLE, id, name.c_str(), "", knownStr, valStr);
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
if (!found)
@@ -867,83 +794,63 @@ public:
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id);
if (spellInfo)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = spellInfo->SpellName[locale];
+ std::string name = spellInfo->SpellName;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
+ continue;
+
+ if (maxResults && count++ == maxResults)
{
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- name = spellInfo->SpellName[locale];
- if (name.empty())
- continue;
+ bool known = target && target->HasSpell(id);
+ bool learn = (spellInfo->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL);
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell);
- if (locale < TOTAL_LOCALES)
- {
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ uint32 talentCost = GetTalentSpellCost(id);
- bool known = target && target->HasSpell(id);
- bool learn = (spellInfo->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL);
+ bool talent = (talentCost > 0);
+ bool passive = spellInfo->IsPassive();
+ bool active = target && target->HasAura(id);
- SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell);
+ // unit32 used to prevent interpreting uint8 as char at output
+ // find rank of learned spell for learning spell, or talent rank
+ uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank();
- uint32 talentCost = GetTalentSpellCost(id);
+ // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format
+ std::ostringstream ss;
+ if (handler->GetSession())
+ ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name;
+ else
+ ss << id << " - " << name;
- bool talent = (talentCost > 0);
- bool passive = spellInfo->IsPassive();
- bool active = target && target->HasAura(id);
+ // include rank in link name
+ if (rank)
+ ss << handler->GetTrinityString(LANG_SPELL_RANK) << rank;
- // unit32 used to prevent interpreting uint8 as char at output
- // find rank of learned spell for learning spell, or talent rank
- uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank();
+ if (handler->GetSession())
+ ss << "]|h|r";
- // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format
- std::ostringstream ss;
- if (handler->GetSession())
- ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name;
- else
- ss << id << " - " << name;
-
- // include rank in link name
- if (rank)
- ss << handler->GetTrinityString(LANG_SPELL_RANK) << rank;
-
- if (handler->GetSession())
- ss << ' ' << localeNames[locale] << "]|h|r";
- else
- ss << ' ' << localeNames[locale];
-
- if (talent)
- ss << handler->GetTrinityString(LANG_TALENT);
- if (passive)
- ss << handler->GetTrinityString(LANG_PASSIVE);
- if (learn)
- ss << handler->GetTrinityString(LANG_LEARN);
- if (known)
- ss << handler->GetTrinityString(LANG_KNOWN);
- if (active)
- ss << handler->GetTrinityString(LANG_ACTIVE);
+ if (talent)
+ ss << handler->GetTrinityString(LANG_TALENT);
+ if (passive)
+ ss << handler->GetTrinityString(LANG_PASSIVE);
+ if (learn)
+ ss << handler->GetTrinityString(LANG_LEARN);
+ if (known)
+ ss << handler->GetTrinityString(LANG_KNOWN);
+ if (active)
+ ss << handler->GetTrinityString(LANG_ACTIVE);
- handler->SendSysMessage(ss.str().c_str());
+ handler->SendSysMessage(ss.str().c_str());
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
if (!found)
@@ -965,7 +872,7 @@ public:
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id))
{
int locale = handler->GetSessionDbcLocale();
- std::string name = spellInfo->SpellName[locale];
+ std::string name = spellInfo->SpellName;
if (name.empty())
{
handler->SendSysMessage(LANG_COMMAND_NOSPELLFOUND);
@@ -1046,47 +953,29 @@ public:
TaxiNodesEntry const* nodeEntry = sTaxiNodesStore.LookupEntry(id);
if (nodeEntry)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = nodeEntry->name[locale];
+ std::string name = nodeEntry->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = nodeEntry->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
+ if (maxResults && count++ == maxResults)
{
- if (maxResults && count++ == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(), localeNames[locale],
- nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z);
- else
- handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[locale],
- nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z);
+ // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(), "",
+ nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z);
+ else
+ handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), "",
+ nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z);
- if (!found)
- found = true;
- }
+ if (!found)
+ found = true;
}
}
if (!found)
@@ -1183,53 +1072,35 @@ public:
CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
if (titleInfo)
{
- int locale = handler->GetSessionDbcLocale();
- std::string name = titleInfo->name[locale];
+ std::string name = titleInfo->name;
if (name.empty())
continue;
if (!Utf8FitTo(name, wNamePart))
- {
- locale = 0;
- for (; locale < TOTAL_LOCALES; ++locale)
- {
- if (locale == handler->GetSessionDbcLocale())
- continue;
-
- name = titleInfo->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
- }
- }
+ continue;
- if (locale < TOTAL_LOCALES)
+ if (maxResults && counter == maxResults)
{
- if (maxResults && counter == maxResults)
- {
- handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
- return true;
- }
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
+ }
- char const* knownStr = target && target->HasTitle(titleInfo) ? handler->GetTrinityString(LANG_KNOWN) : "";
+ char const* knownStr = target && target->HasTitle(titleInfo) ? handler->GetTrinityString(LANG_KNOWN) : "";
- char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index
- ? handler->GetTrinityString(LANG_ACTIVE)
- : "";
+ char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index
+ ? handler->GetTrinityString(LANG_ACTIVE)
+ : "";
- char titleNameStr[80];
- snprintf(titleNameStr, 80, name.c_str(), targetName);
+ char titleNameStr[80];
+ snprintf(titleNameStr, 80, name.c_str(), targetName);
- // send title in "id (idx:idx) - [namedlink locale]" format
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->bit_index, id, titleNameStr, localeNames[locale], knownStr, activeStr);
- else
- handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->bit_index, titleNameStr, localeNames[locale], knownStr, activeStr);
+ // send title in "id (idx:idx) - [namedlink locale]" format
+ if (handler->GetSession())
+ handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->bit_index, id, titleNameStr, "", knownStr, activeStr);
+ else
+ handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->bit_index, titleNameStr, "", knownStr, activeStr);
- ++counter;
- }
+ ++counter;
}
}
if (counter == 0) // if counter == 0 then we found nth
@@ -1260,7 +1131,7 @@ public:
{
if (MapEntry const* mapInfo = sMapStore.LookupEntry(id))
{
- std::string name = mapInfo->name[locale];
+ std::string name = mapInfo->name;
if (name.empty())
continue;
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index e6a7b096a34..0108bbc1487 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -111,7 +111,6 @@ public:
{ "cometome", SEC_ADMINISTRATOR, false, &HandleComeToMeCommand, "", NULL },
{ "damage", SEC_ADMINISTRATOR, false, &HandleDamageCommand, "", NULL },
{ "combatstop", SEC_GAMEMASTER, true, &HandleCombatStopCommand, "", NULL },
- { "flusharenapoints", SEC_ADMINISTRATOR, false, &HandleFlushArenaPointsCommand, "", NULL },
{ "repairitems", SEC_GAMEMASTER, true, &HandleRepairitemsCommand, "", NULL },
{ "freeze", SEC_MODERATOR, false, &HandleFreezeCommand, "", NULL },
{ "unfreeze", SEC_MODERATOR, false, &HandleUnFreezeCommand, "", NULL },
@@ -228,9 +227,9 @@ public:
handler->PSendSysMessage("no VMAP available for area info");
handler->PSendSysMessage(LANG_MAP_POSITION,
- mapId, (mapEntry ? mapEntry->name[handler->GetSessionDbcLocale()] : "<unknown>"),
- zoneId, (zoneEntry ? zoneEntry->area_name[handler->GetSessionDbcLocale()] : "<unknown>"),
- areaId, (areaEntry ? areaEntry->area_name[handler->GetSessionDbcLocale()] : "<unknown>"),
+ mapId, (mapEntry ? mapEntry->name : "<unknown>"),
+ zoneId, (zoneEntry ? zoneEntry->area_name : "<unknown>"),
+ areaId, (areaEntry ? areaEntry->area_name : "<unknown>"),
object->GetPhaseMask(),
object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation(),
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(),
@@ -1458,7 +1457,7 @@ public:
if (!target->GetSkillValue(skill))
{
- handler->PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, skillLine->name[handler->GetSessionDbcLocale()]);
+ handler->PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, skillLine->name);
handler->SetSentErrorMessage(true);
return false;
}
@@ -1469,7 +1468,7 @@ public:
return false;
target->SetSkill(skill, target->GetSkillStep(skill), level, max);
- handler->PSendSysMessage(LANG_SET_SKILL, skill, skillLine->name[handler->GetSessionDbcLocale()], tNameLink.c_str(), level, max);
+ handler->PSendSysMessage(LANG_SET_SKILL, skill, skillLine->name, tNameLink.c_str(), level, max);
return true;
}
@@ -1818,11 +1817,11 @@ public:
AreaTableEntry const* area = GetAreaEntryByAreaID(areaId);
if (area)
{
- areaName = area->area_name[locale];
+ areaName = area->area_name;
AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
if (zone)
- zoneName = zone->area_name[locale];
+ zoneName = zone->area_name;
}
if (target)
@@ -2328,12 +2327,6 @@ public:
return true;
}
- static bool HandleFlushArenaPointsCommand(ChatHandler* /*handler*/, char const* /*args*/)
- {
- sArenaTeamMgr->DistributeArenaPoints();
- return true;
- }
-
static bool HandleRepairitemsCommand(ChatHandler* handler, char const* args)
{
Player* target;
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index ff4ef587fad..ed933ffd5bc 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -23,6 +23,7 @@ Category: commandscripts
EndScriptData */
#include "Chat.h"
+#include <stdlib.h>
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Pet.h"
@@ -64,11 +65,11 @@ public:
{ "mount", SEC_MODERATOR, false, &HandleModifyMountCommand, "", NULL },
{ "honor", SEC_MODERATOR, false, &HandleModifyHonorCommand, "", NULL },
{ "reputation", SEC_GAMEMASTER, false, &HandleModifyRepCommand, "", NULL },
- { "arenapoints", SEC_MODERATOR, false, &HandleModifyArenaCommand, "", NULL },
{ "drunk", SEC_MODERATOR, false, &HandleModifyDrunkCommand, "", NULL },
{ "standstate", SEC_GAMEMASTER, false, &HandleModifyStandStateCommand, "", NULL },
{ "phase", SEC_ADMINISTRATOR, false, &HandleModifyPhaseCommand, "", NULL },
{ "gender", SEC_GAMEMASTER, false, &HandleModifyGenderCommand, "", NULL },
+ { "currency", SEC_GAMEMASTER, false, &HandleModifyCurrencyCommand, "", NULL },
{ "speed", SEC_MODERATOR, false, NULL, "", modifyspeedCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -963,14 +964,14 @@ public:
target->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP);
target->Mount(mId);
- WorldPacket data(SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+1+4));
+ WorldPacket data(SMSG_MOVE_SET_RUN_SPEED, (8+4+1+4));
data.append(target->GetPackGUID());
data << (uint32)0;
data << (uint8)0; //new 2.1.0
data << float(speed);
target->SendMessageToSet(&data, true);
- data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4));
+ data.Initialize(SMSG_MOVE_SET_SWIM_SPEED, (8+4+4));
data.append(target->GetPackGUID());
data << (uint32)0;
data << float(speed);
@@ -997,19 +998,19 @@ public:
if (handler->HasLowerSecurity(target, 0))
return false;
- int32 moneyToAdd = 0;
+ int64 moneyToAdd = 0;
if (strchr(args, 'g') || strchr(args, 's') || strchr(args, 'c'))
moneyToAdd = MoneyStringToMoney(std::string(args));
else
- moneyToAdd = atoi(args);
+ moneyToAdd = atol(args);
- uint32 targetMoney = target->GetMoney();
+ uint64 targetMoney = target->GetMoney();
if (moneyToAdd < 0)
{
- int32 newmoney = int32(targetMoney) + moneyToAdd;
+ int64 newmoney = int64(targetMoney) + moneyToAdd;
- TC_LOG_DEBUG(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney);
+ TC_LOG_DEBUG(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), uint32(targetMoney), int32(moneyToAdd), uint32(newmoney));
if (newmoney <= 0)
{
handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str());
@@ -1020,31 +1021,32 @@ public:
}
else
{
+ uint32 moneyToAddMsg = moneyToAdd * -1;
if (newmoney > MAX_MONEY_AMOUNT)
newmoney = MAX_MONEY_AMOUNT;
- handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(moneyToAdd), handler->GetNameLink(target).c_str());
+ handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, moneyToAddMsg, handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(moneyToAdd));
+ ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), moneyToAddMsg);
target->SetMoney(newmoney);
}
}
else
{
- handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, moneyToAdd, handler->GetNameLink(target).c_str());
+ handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, uint32(moneyToAdd), handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), moneyToAdd);
+ ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), uint32(moneyToAdd));
if (moneyToAdd >= MAX_MONEY_AMOUNT)
moneyToAdd = MAX_MONEY_AMOUNT;
- if (targetMoney >= uint32(MAX_MONEY_AMOUNT) - moneyToAdd)
+ if (targetMoney >= uint64(MAX_MONEY_AMOUNT) - moneyToAdd)
moneyToAdd -= targetMoney;
target->ModifyMoney(moneyToAdd);
}
- TC_LOG_DEBUG(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), targetMoney, moneyToAdd, target->GetMoney());
+ TC_LOG_DEBUG(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), uint32(targetMoney), int32(moneyToAdd), uint32(target->GetMoney()));
return true;
}
@@ -1104,7 +1106,7 @@ public:
return true;
}
- static bool HandleModifyHonorCommand (ChatHandler* handler, const char* args)
+ static bool HandleModifyHonorCommand(ChatHandler* handler, const char* args)
{
if (!*args)
return false;
@@ -1123,9 +1125,9 @@ public:
int32 amount = (uint32)atoi(args);
- target->ModifyHonorPoints(amount);
+ target->ModifyCurrency(CURRENCY_TYPE_HONOR_POINTS, amount, true, true);
- handler->PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, handler->GetNameLink(target).c_str(), target->GetHonorPoints());
+ handler->PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, handler->GetNameLink(target).c_str(), target->GetCurrency(CURRENCY_TYPE_HONOR_POINTS, false));
return true;
}
@@ -1233,14 +1235,14 @@ public:
if (factionEntry->reputationListID < 0)
{
- handler->PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[handler->GetSessionDbcLocale()], factionId);
+ handler->PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name, factionId);
handler->SetSentErrorMessage(true);
return false;
}
target->GetReputationMgr().SetOneFactionReputation(factionEntry, amount, false);
target->GetReputationMgr().SendState(target->GetReputationMgr().GetState(factionEntry));
- handler->PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[handler->GetSessionDbcLocale()], factionId,
+ handler->PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name, factionId,
handler->GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
return true;
}
@@ -1275,14 +1277,15 @@ public:
uint32 phasemask = (uint32)atoi((char*)args);
Unit* target = handler->getSelectedUnit();
- if (!target)
- target = handler->GetSession()->GetPlayer();
-
- // check online security
- else if (target->GetTypeId() == TYPEID_PLAYER && handler->HasLowerSecurity(target->ToPlayer(), 0))
- return false;
-
- target->SetPhaseMask(phasemask, true);
+ if (target)
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ target->ToPlayer()->GetPhaseMgr().SetCustomPhase(phasemask);
+ else
+ target->SetPhaseMask(phasemask, true);
+ }
+ else
+ handler->GetSession()->GetPlayer()->GetPhaseMgr().SetCustomPhase(phasemask);
return true;
}
@@ -1299,28 +1302,6 @@ public:
return true;
}
- static bool HandleModifyArenaCommand(ChatHandler* handler, const char* args)
- {
- if (!*args)
- return false;
-
- Player* target = handler->getSelectedPlayer();
- if (!target)
- {
- handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- int32 amount = (uint32)atoi(args);
-
- target->ModifyArenaPoints(amount);
-
- handler->PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, handler->GetNameLink(target).c_str(), target->GetArenaPoints());
-
- return true;
- }
-
static bool HandleModifyGenderCommand(ChatHandler* handler, const char* args)
{
if (!*args)
@@ -1396,6 +1377,33 @@ public:
return true;
}
+
+ static bool HandleModifyCurrencyCommand(ChatHandler* handler, const char* args)
+ {
+ if (!*args)
+ return false;
+
+ Player* target = handler->getSelectedPlayer();
+ if (!target)
+ {
+ handler->PSendSysMessage(LANG_PLAYER_NOT_FOUND);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ uint32 currencyId = atoi(strtok((char*)args, " "));
+ const CurrencyTypesEntry* currencyType = sCurrencyTypesStore.LookupEntry(currencyId);
+ if (!currencyType)
+ return false;
+
+ uint32 amount = atoi(strtok(NULL, " "));
+ if (!amount)
+ return false;
+
+ target->ModifyCurrency(currencyId, amount, true, true);
+
+ return true;
+ }
};
void AddSC_modify_commandscript()
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 43c9b294419..eadfd3b8da0 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -191,13 +191,13 @@ public:
}
Creature* creature = new Creature();
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
{
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
uint32 db_guid = creature->GetDBTableGUIDLow();
@@ -218,6 +218,8 @@ public:
if (!*args)
return false;
+ const uint8 type = 1; // FIXME: make type (1 item, 2 currency) an argument
+
char* pitem = handler->extractKeyFromLink((char*)args, "Hitem");
if (!pitem)
{
@@ -254,13 +256,13 @@ public:
uint32 vendor_entry = vendor->GetEntry();
- if (!sObjectMgr->IsVendorItemValid(vendor_entry, itemId, maxcount, incrtime, extendedcost, handler->GetSession()->GetPlayer()))
+ if (!sObjectMgr->IsVendorItemValid(vendor_entry, itemId, maxcount, incrtime, extendedcost, type, handler->GetSession()->GetPlayer()))
{
handler->SetSentErrorMessage(true);
return false;
}
- sObjectMgr->AddVendorItem(vendor_entry, itemId, maxcount, incrtime, extendedcost);
+ sObjectMgr->AddVendorItem(vendor_entry, itemId, maxcount, incrtime, extendedcost, type);
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
@@ -475,7 +477,9 @@ public:
}
uint32 itemId = atol(pitem);
- if (!sObjectMgr->RemoveVendorItem(vendor->GetEntry(), itemId))
+ const uint8 type = 1; // FIXME: make type (1 item, 2 currency) an argument
+
+ if (!sObjectMgr->RemoveVendorItem(vendor->GetEntry(), itemId, type))
{
handler->PSendSysMessage(LANG_ITEM_NOT_IN_LIST, itemId);
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 5351f3edda0..6b846338ea2 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -26,7 +26,6 @@ EndScriptData */
#include "AchievementMgr.h"
#include "AuctionHouseMgr.h"
#include "Chat.h"
-#include "CreatureEventAIMgr.h"
#include "CreatureTextMgr.h"
#include "DisableMgr.h"
#include "Language.h"
@@ -53,7 +52,6 @@ public:
{
{ "achievement", SEC_ADMINISTRATOR, true, &HandleReloadAllAchievementCommand, "", NULL },
{ "area", SEC_ADMINISTRATOR, true, &HandleReloadAllAreaCommand, "", NULL },
- { "eventai", SEC_ADMINISTRATOR, true, &HandleReloadAllEventAICommand, "", NULL },
{ "gossips", SEC_ADMINISTRATOR, true, &HandleReloadAllGossipsCommand, "", NULL },
{ "item", SEC_ADMINISTRATOR, true, &HandleReloadAllItemCommand, "", NULL },
{ "locales", SEC_ADMINISTRATOR, true, &HandleReloadAllLocalesCommand, "", NULL },
@@ -80,8 +78,6 @@ public:
{ "conditions", SEC_ADMINISTRATOR, true, &HandleReloadConditions, "", NULL },
{ "config", SEC_ADMINISTRATOR, true, &HandleReloadConfigCommand, "", NULL },
{ "creature_text", SEC_ADMINISTRATOR, true, &HandleReloadCreatureText, "", NULL },
- { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &HandleReloadEventAIScriptsCommand, "", NULL },
- { "creature_ai_texts", SEC_ADMINISTRATOR, true, &HandleReloadEventAITextsCommand, "", NULL },
{ "creature_involvedrelation", SEC_ADMINISTRATOR, true, &HandleReloadCreatureQuestInvRelationsCommand, "", NULL },
{ "creature_linked_respawn", SEC_GAMEMASTER, true, &HandleReloadLinkedRespawnCommand, "", NULL },
{ "creature_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL },
@@ -104,7 +100,6 @@ public:
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &HandleReloadGossipMenuOptionCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesItemCommand, "", NULL },
- { "item_set_names", SEC_ADMINISTRATOR, true, &HandleReloadItemSetNamesCommand, "", NULL },
{ "lfg_dungeon_rewards", SEC_ADMINISTRATOR, true, &HandleReloadLfgRewardsCommand, "", NULL },
{ "locales_achievement_reward", SEC_ADMINISTRATOR, true, &HandleReloadLocalesAchievementRewardCommand, "", NULL },
{ "locales_creature", SEC_ADMINISTRATOR, true, &HandleReloadLocalesCreatureCommand, "", NULL },
@@ -112,7 +107,6 @@ public:
{ "locales_gameobject", SEC_ADMINISTRATOR, true, &HandleReloadLocalesGameobjectCommand, "", NULL },
{ "locales_gossip_menu_option", SEC_ADMINISTRATOR, true, &HandleReloadLocalesGossipMenuOptionCommand, "", NULL },
{ "locales_item", SEC_ADMINISTRATOR, true, &HandleReloadLocalesItemCommand, "", NULL },
- { "locales_item_set_name", SEC_ADMINISTRATOR, true, &HandleReloadLocalesItemSetNameCommand, "", NULL },
{ "locales_npc_text", SEC_ADMINISTRATOR, true, &HandleReloadLocalesNpcTextCommand, "", NULL },
{ "locales_page_text", SEC_ADMINISTRATOR, true, &HandleReloadLocalesPageTextCommand, "", NULL },
{ "locales_points_of_interest", SEC_ADMINISTRATOR, true, &HandleReloadLocalesPointsOfInterestCommand, "", NULL },
@@ -124,6 +118,7 @@ public:
{ "npc_trainer", SEC_ADMINISTRATOR, true, &HandleReloadNpcTrainerCommand, "", NULL },
{ "npc_vendor", SEC_ADMINISTRATOR, true, &HandleReloadNpcVendorCommand, "", NULL },
{ "page_text", SEC_ADMINISTRATOR, true, &HandleReloadPageTextsCommand, "", NULL },
+ { "phasedefinitions", SEC_ADMINISTRATOR, true, &HandleReloadPhaseDefinitionsCommand, "", NULL },
{ "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesPickpocketingCommand, "", NULL},
{ "points_of_interest", SEC_ADMINISTRATOR, true, &HandleReloadPointsOfInterestCommand, "", NULL },
{ "prospecting_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL },
@@ -182,7 +177,6 @@ public:
HandleReloadAllAchievementCommand(handler, "");
HandleReloadAllAreaCommand(handler, "");
- HandleReloadAllEventAICommand(handler, "");
HandleReloadAllLootCommand(handler, "");
HandleReloadAllNpcCommand(handler, "");
HandleReloadAllQuestCommand(handler, "");
@@ -273,13 +267,6 @@ public:
return true;
}
- static bool HandleReloadAllEventAICommand(ChatHandler* handler, const char* /*args*/)
- {
- HandleReloadEventAITextsCommand(handler, "a");
- HandleReloadEventAIScriptsCommand(handler, "a");
- return true;
- }
-
static bool HandleReloadAllSpellCommand(ChatHandler* handler, const char* /*args*/)
{
HandleReloadSkillDiscoveryTemplateCommand(handler, "a");
@@ -442,11 +429,12 @@ public:
Field* fields = result->Fetch();
- cInfo->DifficultyEntry[0] = fields[0].GetUInt32();
- cInfo->DifficultyEntry[1] = fields[1].GetUInt32();
- cInfo->DifficultyEntry[2] = fields[2].GetUInt32();
- cInfo->KillCredit[0] = fields[3].GetUInt32();
- cInfo->KillCredit[1] = fields[4].GetUInt32();
+ for (uint8 i = 0; i < MAX_DIFFICULTY - 1; ++i)
+ cInfo->DifficultyEntry[i] = fields[0 + i].GetUInt32();
+
+ for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i)
+ cInfo->KillCredit[i] = fields[3 + i].GetUInt32();
+
cInfo->Modelid1 = fields[5].GetUInt32();
cInfo->Modelid2 = fields[6].GetUInt32();
cInfo->Modelid3 = fields[7].GetUInt32();
@@ -458,27 +446,27 @@ public:
cInfo->minlevel = fields[13].GetUInt8();
cInfo->maxlevel = fields[14].GetUInt8();
cInfo->expansion = fields[15].GetUInt16();
- cInfo->faction_A = fields[16].GetUInt16();
- cInfo->faction_H = fields[17].GetUInt16();
- cInfo->npcflag = fields[18].GetUInt32();
- cInfo->speed_walk = fields[19].GetFloat();
- cInfo->speed_run = fields[20].GetFloat();
- cInfo->scale = fields[21].GetFloat();
- cInfo->rank = fields[22].GetUInt8();
- cInfo->mindmg = fields[23].GetFloat();
- cInfo->maxdmg = fields[24].GetFloat();
- cInfo->dmgschool = fields[25].GetUInt8();
- cInfo->attackpower = fields[26].GetUInt32();
- cInfo->dmg_multiplier = fields[27].GetFloat();
- cInfo->baseattacktime = fields[28].GetUInt32();
- cInfo->rangeattacktime = fields[29].GetUInt32();
- cInfo->unit_class = fields[30].GetUInt8();
- cInfo->unit_flags = fields[31].GetUInt32();
- cInfo->unit_flags2 = fields[32].GetUInt32();
- cInfo->dynamicflags = fields[33].GetUInt32();
- cInfo->family = fields[34].GetUInt8();
- cInfo->trainer_type = fields[35].GetUInt8();
- cInfo->trainer_spell = fields[36].GetUInt32();
+ cInfo->expansionUnknown = fields[16].GetUInt16();
+ cInfo->faction_A = fields[17].GetUInt16();
+ cInfo->faction_H = fields[18].GetUInt16();
+ cInfo->npcflag = fields[19].GetUInt32();
+ cInfo->speed_walk = fields[20].GetFloat();
+ cInfo->speed_run = fields[21].GetFloat();
+ cInfo->scale = fields[22].GetFloat();
+ cInfo->rank = fields[23].GetUInt8();
+ cInfo->mindmg = fields[24].GetFloat();
+ cInfo->maxdmg = fields[25].GetFloat();
+ cInfo->dmgschool = fields[26].GetUInt8();
+ cInfo->attackpower = fields[27].GetUInt32();
+ cInfo->dmg_multiplier = fields[28].GetFloat();
+ cInfo->baseattacktime = fields[29].GetUInt32();
+ cInfo->rangeattacktime = fields[30].GetUInt32();
+ cInfo->unit_class = fields[31].GetUInt8();
+ cInfo->unit_flags = fields[32].GetUInt32();
+ cInfo->unit_flags2 = fields[33].GetUInt32();
+ cInfo->dynamicflags = fields[34].GetUInt32();
+ cInfo->family = fields[35].GetUInt8();
+ cInfo->trainer_type = fields[36].GetUInt8();
cInfo->trainer_class = fields[37].GetUInt8();
cInfo->trainer_race = fields[38].GetUInt8();
cInfo->minrangedmg = fields[39].GetFloat();
@@ -486,44 +474,39 @@ public:
cInfo->rangedattackpower = fields[41].GetUInt16();
cInfo->type = fields[42].GetUInt8();
cInfo->type_flags = fields[43].GetUInt32();
- cInfo->lootid = fields[44].GetUInt32();
- cInfo->pickpocketLootId = fields[45].GetUInt32();
- cInfo->SkinLootId = fields[46].GetUInt32();
+ cInfo->type_flags2 = fields[44].GetUInt32();
+ cInfo->lootid = fields[45].GetUInt32();
+ cInfo->pickpocketLootId = fields[46].GetUInt32();
+ cInfo->SkinLootId = fields[47].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- cInfo->resistance[i] = fields[47 + i -1].GetUInt16();
-
- cInfo->spells[0] = fields[53].GetUInt32();
- cInfo->spells[1] = fields[54].GetUInt32();
- cInfo->spells[2] = fields[55].GetUInt32();
- cInfo->spells[3] = fields[56].GetUInt32();
- cInfo->spells[4] = fields[57].GetUInt32();
- cInfo->spells[5] = fields[58].GetUInt32();
- cInfo->spells[6] = fields[59].GetUInt32();
- cInfo->spells[7] = fields[60].GetUInt32();
- cInfo->PetSpellDataId = fields[61].GetUInt32();
- cInfo->VehicleId = fields[62].GetUInt32();
- cInfo->mingold = fields[63].GetUInt32();
- cInfo->maxgold = fields[64].GetUInt32();
- cInfo->AIName = fields[65].GetString();
- cInfo->MovementType = fields[66].GetUInt8();
- cInfo->InhabitType = fields[67].GetUInt8();
- cInfo->HoverHeight = fields[68].GetFloat();
- cInfo->ModHealth = fields[69].GetFloat();
- cInfo->ModMana = fields[70].GetFloat();
- cInfo->ModArmor = fields[71].GetFloat();
- cInfo->RacialLeader = fields[72].GetBool();
- cInfo->questItems[0] = fields[73].GetUInt32();
- cInfo->questItems[1] = fields[74].GetUInt32();
- cInfo->questItems[2] = fields[75].GetUInt32();
- cInfo->questItems[3] = fields[76].GetUInt32();
- cInfo->questItems[4] = fields[77].GetUInt32();
- cInfo->questItems[5] = fields[78].GetUInt32();
- cInfo->movementId = fields[79].GetUInt32();
- cInfo->RegenHealth = fields[80].GetBool();
- cInfo->MechanicImmuneMask = fields[81].GetUInt32();
- cInfo->flags_extra = fields[82].GetUInt32();
- cInfo->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString());
+ cInfo->resistance[i] = fields[48 + i -1].GetUInt16();
+
+ for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ cInfo->spells[i] = fields[54 + i].GetUInt32();
+
+ cInfo->PetSpellDataId = fields[62].GetUInt32();
+ cInfo->VehicleId = fields[63].GetUInt32();
+ cInfo->mingold = fields[64].GetUInt32();
+ cInfo->maxgold = fields[65].GetUInt32();
+ cInfo->AIName = fields[66].GetString();
+ cInfo->MovementType = fields[67].GetUInt8();
+ cInfo->InhabitType = fields[68].GetUInt8();
+ cInfo->HoverHeight = fields[69].GetFloat();
+ cInfo->ModHealth = fields[70].GetFloat();
+ cInfo->ModMana = fields[71].GetFloat();
+ cInfo->ModManaExtra = fields[72].GetFloat();
+ cInfo->ModArmor = fields[73].GetFloat();
+ cInfo->RacialLeader = fields[74].GetBool();
+
+ for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
+ cInfo->questItems[i] = fields[75 + i].GetUInt32();
+
+ cInfo->movementId = fields[81].GetUInt32();
+ cInfo->RegenHealth = fields[82].GetBool();
+ cInfo->MechanicImmuneMask = fields[83].GetUInt32();
+ cInfo->flags_extra = fields[84].GetUInt32();
+ cInfo->ScriptID = sObjectMgr->GetScriptId(fields[85].GetCString());
sObjectMgr->CheckCreatureTemplate(cInfo);
}
@@ -953,14 +936,6 @@ public:
return true;
}
- static bool HandleReloadItemSetNamesCommand(ChatHandler* handler, const char* /*args*/)
- {
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Re-Loading Item set names...");
- sObjectMgr->LoadItemSetNames();
- handler->SendGlobalGMSysMessage("DB table `item_set_names` reloaded.");
- return true;
- }
-
static bool HandleReloadEventScriptsCommand(ChatHandler* handler, const char* args)
{
if (sScriptMgr->IsScriptScheduled())
@@ -1014,23 +989,6 @@ public:
return true;
}
- static bool HandleReloadEventAITextsCommand(ChatHandler* handler, const char* /*args*/)
- {
-
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Re-Loading Texts from `creature_ai_texts`...");
- sEventAIMgr->LoadCreatureEventAI_Texts();
- handler->SendGlobalGMSysMessage("DB table `creature_ai_texts` reloaded.");
- return true;
- }
-
- static bool HandleReloadEventAIScriptsCommand(ChatHandler* handler, const char* /*args*/)
- {
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Re-Loading Scripts from `creature_ai_scripts`...");
- sEventAIMgr->LoadCreatureEventAI_Scripts();
- handler->SendGlobalGMSysMessage("DB table `creature_ai_scripts` reloaded.");
- return true;
- }
-
static bool HandleReloadSpellScriptsCommand(ChatHandler* handler, const char* args)
{
if (sScriptMgr->IsScriptScheduled())
@@ -1147,14 +1105,6 @@ public:
return true;
}
- static bool HandleReloadLocalesItemSetNameCommand(ChatHandler* handler, const char* /*args*/)
- {
- TC_LOG_INFO(LOG_FILTER_GENERAL, "Re-Loading Locales Item set name... ");
- sObjectMgr->LoadItemSetNameLocales();
- handler->SendGlobalGMSysMessage("DB table `locales_item_set_name` reloaded.");
- return true;
- }
-
static bool HandleReloadLocalesNpcTextCommand(ChatHandler* handler, const char* /*args*/)
{
TC_LOG_INFO(LOG_FILTER_GENERAL, "Re-Loading Locales NPC Text ... ");
@@ -1245,6 +1195,16 @@ public:
return true;
}
+
+ static bool HandleReloadPhaseDefinitionsCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ TC_LOG_INFO(LOG_FILTER_GENERAL, "Reloading phase_definitions table...");
+ sObjectMgr->LoadPhaseDefinitions();
+ sWorld->UpdatePhaseDefinitions();
+ handler->SendGlobalGMSysMessage("Phase Definitions reloaded.");
+ return true;
+ }
+
static bool HandleReloadRBACCommand(ChatHandler* handler, const char* /*args*/)
{
TC_LOG_INFO(LOG_FILTER_GENERAL, "Reloading RBAC tables...");
diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp
index bfb3c8aeff1..8e45aa6a855 100644
--- a/src/server/scripts/Commands/cs_reset.cpp
+++ b/src/server/scripts/Commands/cs_reset.cpp
@@ -66,7 +66,7 @@ public:
if (target)
target->ResetAchievements();
else
- AchievementMgr::DeleteFromDB(GUID_LOPART(targetGuid));
+ AchievementMgr<Player>::DeleteFromDB(GUID_LOPART(targetGuid));
return true;
}
@@ -77,11 +77,8 @@ public:
if (!handler->extractPlayerTarget((char*)args, &target))
return false;
- target->SetHonorPoints(0);
target->SetUInt32Value(PLAYER_FIELD_KILLS, 0);
target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0);
- target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0);
- target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL);
return true;
@@ -233,7 +230,7 @@ public:
if (target)
{
- target->resetTalents(true);
+ target->ResetTalents(true);
target->SendTalentsInfoData(false);
ChatHandler(target->GetSession()).SendSysMessage(LANG_RESET_TALENTS);
if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target)
diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp
index 4c80f669312..bad3b8c0318 100644
--- a/src/server/scripts/Commands/cs_titles.cpp
+++ b/src/server/scripts/Commands/cs_titles.cpp
@@ -96,7 +96,7 @@ public:
target->SetTitle(titleInfo); // to be sure that title now known
target->SetUInt32Value(PLAYER_CHOSEN_TITLE, titleInfo->bit_index);
- handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[handler->GetSessionDbcLocale()], tNameLink.c_str());
+ handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name, tNameLink.c_str());
return true;
}
@@ -139,7 +139,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
- snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
+ snprintf(titleNameStr, 80, titleInfo->name, target->GetName().c_str());
target->SetTitle(titleInfo);
handler->PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str());
@@ -187,7 +187,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
- snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
+ snprintf(titleNameStr, 80, titleInfo->name, target->GetName().c_str());
handler->PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str());
diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp
index b7a89ceb325..745cc80ab41 100644
--- a/src/server/scripts/Commands/cs_wp.cpp
+++ b/src/server/scripts/Commands/cs_wp.cpp
@@ -241,40 +241,44 @@ public:
if (!target)
{
- handler->PSendSysMessage("%s%s|r", "|cff33ffff", "You must select target.");
+ handler->PSendSysMessage("%s%s|r", "|cff33ffff", "You must select a target.");
return true;
}
- uint32 guildLow = target->GetDBTableGUIDLow();
+ uint32 guidLow = target->GetDBTableGUIDLow();
+ if (guidLow == 0)
+ {
+ handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target is not saved to DB.");
+ return true;
+ }
- if (target->GetCreatureAddon())
+ CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(guidLow);
+ if (!addon || addon->path_id == 0)
{
- if (target->GetCreatureAddon()->path_id != 0)
- {
- PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
+ handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target does not have a loaded path.");
+ return true;
+ }
- stmt->setUInt32(0, guildLow);
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
- WorldDatabase.Execute(stmt);
+ stmt->setUInt32(0, guidLow);
+
+ WorldDatabase.Execute(stmt);
- target->UpdateWaypointID(0);
+ target->UpdateWaypointID(0);
- stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
+ stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE);
- stmt->setUInt8(0, uint8(IDLE_MOTION_TYPE));
- stmt->setUInt32(1, guildLow);
+ stmt->setUInt8(0, uint8(IDLE_MOTION_TYPE));
+ stmt->setUInt32(1, guidLow);
- WorldDatabase.Execute(stmt);
+ WorldDatabase.Execute(stmt);
- target->LoadPath(0);
- target->SetDefaultMovementType(IDLE_MOTION_TYPE);
- target->GetMotionMaster()->MoveTargetedHome();
- target->GetMotionMaster()->Initialize();
- target->MonsterSay("Path unloaded.", 0, 0);
- return true;
- }
- handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path.");
- }
+ target->LoadPath(0);
+ target->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ target->GetMotionMaster()->MoveTargetedHome();
+ target->GetMotionMaster()->Initialize();
+ target->MonsterSay("Path unloaded.", 0, 0);
return true;
}
@@ -690,7 +694,7 @@ public:
}
// re-create
Creature* wpCreature2 = new Creature;
- if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
+ if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
@@ -698,7 +702,7 @@ public:
return false;
}
- wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
/// @todo Should we first use "Create" then use "LoadFromDB"?
if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetDBTableGUIDLow(), map))
@@ -914,7 +918,7 @@ public:
float o = chr->GetOrientation();
Creature* wpCreature = new Creature;
- if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -930,7 +934,7 @@ public:
WorldDatabase.Execute(stmt);
- wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
if (!wpCreature->LoadCreatureFromDB(wpCreature->GetDBTableGUIDLow(), map))
{
@@ -978,14 +982,14 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature;
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
@@ -1027,14 +1031,14 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature;
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h b/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h
new file mode 100644
index 00000000000..77554d29d15
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 3 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DEF_BARADIN_HOLD_H_
+#define DEF_BARADIN_HOLD_H_
+
+#define MAX_ENCOUNTERS 3
+
+enum Creatures
+{
+ BOSS_ARGALOTH = 47120,
+ BOSS_OCCUTHAR = 52363,
+ BOSS_ALIZABAL = 55869,
+
+ NPC_EYE_OF_OCCUTHAR = 52389,
+ NPC_FOCUS_FIRE_DUMMY = 52369,
+ NPC_OCCUTHAR_EYE = 52368,
+};
+
+enum Objects
+{
+ GO_ARGALOTH_DOOR = 207619,
+ GO_OCCUTHAR_DOOR = 208953,
+};
+
+enum Data
+{
+ DATA_ARGALOTH = 1,
+ DATA_OCCUTHAR = 2,
+ DATA_ALIZABAL = 3,
+};
+
+#endif
diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp
new file mode 100644
index 00000000000..b2f46f3e08a
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_alizabal.cpp
@@ -0,0 +1,271 @@
+/*
+* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "baradin_hold.h"
+#include "InstanceScript.h"
+#include "ScriptMgr.h"
+#include "Player.h"
+#include "ObjectAccessor.h"
+#include "ScriptedCreature.h"
+
+enum Texts
+{
+ SAY_INTRO = 1,
+ SAY_AGGRO = 2,
+ SAY_HATE = 3,
+ SAY_SKEWER = 4,
+ SAY_SKEWER_ANNOUNCE = 5,
+ SAY_BLADE_STORM = 6,
+ SAY_SLAY = 10,
+ SAY_DEATH = 12,
+};
+
+enum Spells
+{
+ SPELL_BLADE_DANCE = 105784,
+ SPELL_BLADE_DANCE_DUMMY = 105828,
+ SPELL_SEETHING_HATE = 105067,
+ SPELL_SKEWER = 104936,
+ SPELL_BERSERK = 47008,
+};
+
+enum Actions
+{
+ ACTION_INTRO = 1,
+};
+
+enum Points
+{
+ POINT_STORM = 1,
+};
+
+enum Events
+{
+ EVENT_RANDOM_CAST = 1,
+ EVENT_STOP_STORM = 2,
+ EVENT_MOVE_STORM = 3,
+ EVENT_CAST_STORM = 4,
+};
+
+class at_alizabal_intro : public AreaTriggerScript
+{
+ public:
+ at_alizabal_intro() : AreaTriggerScript("at_alizabal_intro") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/)
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* alizabal = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_ALIZABAL)))
+ alizabal->AI()->DoAction(ACTION_INTRO);
+ return true;
+ }
+};
+
+class boss_alizabal : public CreatureScript
+{
+ public:
+ boss_alizabal() : CreatureScript("boss_alizabal") { }
+
+ struct boss_alizabalAI : public BossAI
+ {
+ boss_alizabalAI(Creature* creature) : BossAI(creature, DATA_ALIZABAL)
+ {
+ Intro = false;
+ Hate = false;
+ Skewer = false;
+ }
+
+ bool Intro;
+ bool Hate;
+ bool Skewer;
+
+ void Reset()
+ {
+ _Reset();
+ Hate = false;
+ Skewer = false;
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.ScheduleEvent(EVENT_RANDOM_CAST, 10000);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ }
+
+ void KilledUnit(Unit* who)
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
+
+ void EnterEvadeMode()
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ me->GetMotionMaster()->MoveTargetedHome();
+ _DespawnAtEvade();
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_INTRO:
+ if (!Intro)
+ {
+ Talk(SAY_INTRO);
+ Intro = true;
+ }
+ break;
+ }
+ }
+
+ void MovementInform(uint32 /*type*/, uint32 pointId)
+ {
+ switch (pointId)
+ {
+ case POINT_STORM:
+ events.ScheduleEvent(EVENT_CAST_STORM, 1);
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RANDOM_CAST:
+ switch (urand(0, 1))
+ {
+ case 0:
+ if (!Skewer)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
+ {
+ DoCast(target, SPELL_SKEWER, true);
+ Talk(SAY_SKEWER);
+ Talk(SAY_SKEWER_ANNOUNCE, target->GetGUID());
+ }
+ Skewer = true;
+ events.ScheduleEvent(EVENT_RANDOM_CAST, urand(7000, 10000));
+ }
+ else if (!Hate)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
+ {
+ DoCast(target, SPELL_SEETHING_HATE, true);
+ Talk(SAY_HATE);
+ }
+ Hate = true;
+ events.ScheduleEvent(EVENT_RANDOM_CAST, urand(7000, 10000));
+ }
+ else if (Hate && Skewer)
+ {
+ Talk(SAY_BLADE_STORM);
+ DoCastAOE(SPELL_BLADE_DANCE_DUMMY);
+ DoCastAOE(SPELL_BLADE_DANCE);
+ events.ScheduleEvent(EVENT_RANDOM_CAST, 21000);
+ events.ScheduleEvent(EVENT_MOVE_STORM, 4050);
+ events.ScheduleEvent(EVENT_STOP_STORM, 13000);
+ }
+ break;
+ case 1:
+ if (!Hate)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
+ {
+ DoCast(target, SPELL_SEETHING_HATE, true);
+ Talk(SAY_HATE);
+ }
+ Hate = true;
+ events.ScheduleEvent(EVENT_RANDOM_CAST, urand(7000, 10000));
+ }
+ else if (!Skewer)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
+ {
+ DoCast(target, SPELL_SKEWER, true);
+ Talk(SAY_SKEWER);
+ Talk(SAY_SKEWER_ANNOUNCE, target->GetGUID());
+ }
+ Skewer = true;
+ events.ScheduleEvent(EVENT_RANDOM_CAST, urand(7000, 10000));
+ }
+ else if (Hate && Skewer)
+ {
+ Talk(SAY_BLADE_STORM);
+ DoCastAOE(SPELL_BLADE_DANCE_DUMMY);
+ DoCastAOE(SPELL_BLADE_DANCE);
+ events.ScheduleEvent(EVENT_RANDOM_CAST, 21000);
+ events.ScheduleEvent(EVENT_MOVE_STORM, 4050);
+ events.ScheduleEvent(EVENT_STOP_STORM, 13000);
+ }
+ break;
+ }
+ break;
+ case EVENT_MOVE_STORM:
+ me->SetSpeed(MOVE_RUN, 4.0f);
+ me->SetSpeed(MOVE_WALK, 4.0f);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
+ me->GetMotionMaster()->MovePoint(POINT_STORM, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
+ events.ScheduleEvent(EVENT_MOVE_STORM, 4050);
+ break;
+ case EVENT_STOP_STORM:
+ me->RemoveAura(SPELL_BLADE_DANCE);
+ me->RemoveAura(SPELL_BLADE_DANCE_DUMMY);
+ me->SetSpeed(MOVE_WALK, 1.0f);
+ me->SetSpeed(MOVE_RUN, 1.14f);
+ me->GetMotionMaster()->MoveChase(me->getVictim());
+ Hate = false;
+ Skewer = false;
+ break;
+ case EVENT_CAST_STORM:
+ DoCastAOE(SPELL_BLADE_DANCE);
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new boss_alizabalAI(creature);
+ }
+};
+
+void AddSC_boss_alizabal()
+{
+ new boss_alizabal();
+ new at_alizabal_intro();
+}
diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp
new file mode 100644
index 00000000000..0e2b7107548
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 3 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "baradin_hold.h"
+#include "InstanceScript.h"
+#include "ScriptMgr.h"
+
+DoorData const doorData[] =
+{
+ {GO_ARGALOTH_DOOR, DATA_ARGALOTH, DOOR_TYPE_ROOM, BOUNDARY_NONE},
+ {GO_OCCUTHAR_DOOR, DATA_OCCUTHAR, DOOR_TYPE_ROOM, BOUNDARY_NONE},
+};
+
+class instance_baradin_hold: public InstanceMapScript
+{
+public:
+ instance_baradin_hold() : InstanceMapScript("instance_baradin_hold", 757) { }
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const
+ {
+ return new instance_baradin_hold_InstanceMapScript(map);
+ }
+
+ struct instance_baradin_hold_InstanceMapScript: public InstanceScript
+ {
+ instance_baradin_hold_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ {
+ SetBossNumber(MAX_ENCOUNTERS);
+ LoadDoorData(doorData);
+ _argalothGUID = 0;
+ _occutharGUID = 0;
+ _alizabalGUID = 0;
+ _argalothDoor = 0;
+ _occutharDoor = 0;
+ }
+
+ void Initialize()
+ {
+ }
+
+ void OnCreatureCreate(Creature* creature)
+ {
+ switch(creature->GetEntry())
+ {
+ case BOSS_ARGALOTH:
+ _argalothGUID = creature->GetGUID();
+ break;
+ case BOSS_OCCUTHAR:
+ _occutharGUID = creature->GetGUID();
+ break;
+ case BOSS_ALIZABAL:
+ _alizabalGUID = creature->GetGUID();
+ break;
+ }
+ }
+
+ void OnGameObjectCreate(GameObject* go)
+ {
+ switch(go->GetEntry())
+ {
+ case GO_ARGALOTH_DOOR:
+ _argalothDoor = go->GetGUID();
+ AddDoor(go, true);
+ break;
+ case GO_OCCUTHAR_DOOR:
+ _occutharDoor = go->GetGUID();
+ AddDoor(go, true);
+ break;
+ }
+ }
+
+ uint64 GetData64(uint32 data) const
+ {
+ switch (data)
+ {
+ case DATA_ARGALOTH:
+ return _argalothGUID;
+ case DATA_OCCUTHAR:
+ return _occutharGUID;
+ case DATA_ALIZABAL:
+ return _alizabalGUID;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ void OnGameObjectRemove(GameObject* go)
+ {
+ switch(go->GetEntry())
+ {
+ case GO_ARGALOTH_DOOR:
+ AddDoor(go, false);
+ break;
+ case GO_OCCUTHAR_DOOR:
+ AddDoor(go, false);
+ break;
+ }
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "B H " << GetBossSaveData();
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
+ }
+
+ void Load(const char* in)
+ {
+ if (!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(in);
+
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(in);
+ loadStream >> dataHead1 >> dataHead2;
+
+ if (dataHead1 == 'B' && dataHead2 == 'H')
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+
+ SetBossState(i, EncounterState(tmpState));
+ }
+
+ } else OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ private:
+ uint64 _argalothGUID;
+ uint64 _occutharGUID;
+ uint64 _alizabalGUID;
+ uint64 _argalothDoor;
+ uint64 _occutharDoor;
+ };
+};
+
+void AddSC_instance_baradin_hold()
+{
+ new instance_baradin_hold();
+}
diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt
index f581baa31fa..e782711bde2 100644
--- a/src/server/scripts/EasternKingdoms/CMakeLists.txt
+++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt
@@ -17,6 +17,8 @@ set(scripts_STAT_SRCS
EasternKingdoms/AlteracValley/boss_drekthar.cpp
EasternKingdoms/AlteracValley/boss_vanndar.cpp
EasternKingdoms/AlteracValley/alterac_valley.cpp
+ EasternKingdoms/BaradinHold/boss_alizabal.cpp
+ EasternKingdoms/BaradinHold/instance_baradin_hold.cpp
EasternKingdoms/Scholomance/boss_the_ravenian.cpp
EasternKingdoms/Scholomance/boss_instructor_malicia.cpp
EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp
@@ -33,22 +35,17 @@ set(scripts_STAT_SRCS
EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp
EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp
EasternKingdoms/zone_isle_of_queldanas.cpp
- EasternKingdoms/boss_kruul.cpp
- EasternKingdoms/ZulGurub/boss_hakkar.cpp
- EasternKingdoms/ZulGurub/boss_mandokir.cpp
- EasternKingdoms/ZulGurub/boss_marli.cpp
- EasternKingdoms/ZulGurub/boss_hazzarah.cpp
- EasternKingdoms/ZulGurub/boss_jeklik.cpp
EasternKingdoms/ZulGurub/boss_grilek.cpp
- EasternKingdoms/ZulGurub/zulgurub.h
+ EasternKingdoms/ZulGurub/boss_hazzarah.cpp
+ EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp
+ EasternKingdoms/ZulGurub/boss_kilnara.cpp
+ EasternKingdoms/ZulGurub/boss_mandokir.cpp
EasternKingdoms/ZulGurub/boss_renataki.cpp
- EasternKingdoms/ZulGurub/boss_arlokk.cpp
- EasternKingdoms/ZulGurub/boss_gahzranka.cpp
EasternKingdoms/ZulGurub/boss_venoxis.cpp
- EasternKingdoms/ZulGurub/instance_zulgurub.cpp
- EasternKingdoms/ZulGurub/boss_jindo.cpp
EasternKingdoms/ZulGurub/boss_wushoolay.cpp
- EasternKingdoms/ZulGurub/boss_thekal.cpp
+ EasternKingdoms/ZulGurub/boss_zanzil.cpp
+ EasternKingdoms/ZulGurub/instance_zulgurub.cpp
+ EasternKingdoms/ZulGurub/zulgurub.h
EasternKingdoms/zone_wetlands.cpp
EasternKingdoms/zone_arathi_highlands.cpp
EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp
diff --git a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp
index 210fb11a269..d9e355a0a1a 100644
--- a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp
+++ b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp
@@ -242,6 +242,7 @@ class instance_deadmines : public InstanceMapScript
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound);
+ data << uint64(unit->GetGUID());
unit->SendMessageToSet(&data, false);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index fdbbcaf8216..7328c5cecc9 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -1033,6 +1033,8 @@ class npc_scarlet_miner : public CreatureScript
if (Unit* car = ObjectAccessor::GetCreature(*me, carGUID))
{
me->SetFacingToObject(car);
+ car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ() + 1);
+ car->StopMoving();
car->RemoveAura(SPELL_CART_DRAG);
}
Talk(SAY_SCARLET_MINER_1);
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
index 326c02630ac..3f95d8d0aee 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
@@ -99,7 +99,7 @@ public:
FlyBackTimer = 4500;
break;
case 2:
- if (!player->isRessurectRequested())
+ if (!player->IsRessurectRequested())
{
me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOM_SPELL_01);
DoCast(player, SPELL_REVIVE, true);
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
index 32e8af3821b..4a610f6678f 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -443,7 +443,7 @@ public:
{
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_DISABLE_GRAVITY);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
me->SetSpeed(MOVE_WALK, 5.0f, true);
wp_reached = false;
count = 0;
@@ -476,7 +476,7 @@ public:
instance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject
break;
case 19:
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_DISABLE_GRAVITY);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
break;
case 20:
{
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
index 499644ed250..a6aa9457551 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
@@ -254,7 +254,7 @@ public:
{
OrbsEmpowered = 0;
EmpowerCount = 0;
- me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_DISABLE_GRAVITY);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->setActive(true);
@@ -442,7 +442,7 @@ public:
summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false);
break;
case CREATURE_ANVEENA:
- summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_DISABLE_GRAVITY);
+ summoned->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true);
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
index ff6d434fa40..0c2c9597cfe 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
@@ -297,8 +297,7 @@ class npc_harrison_jones : public CreatureScript
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
{
player->CLOSE_GOSSIP_MENU();
- me->SetInFront(player);
- me->SendMovementFlagUpdate(true);
+ me->SetFacingToObject(player);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Talk(SAY_HARRISON_0);
_gongEvent = GONG_EVENT_1;
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
deleted file mode 100644
index 6fe0934191e..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-TCName: Boss_Arlokk
-TC%Complete: 95
-TCComment: Wrong cleave and red aura is missing not yet added.
-TCComment: Prowlers moving through wall hopefully mmaps will fix.
-TCComment: Can't test LOS until mmaps.
-TCCategory: Zul'Gurub
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "SpellInfo.h"
-#include "zulgurub.h"
-
-enum Says
-{
- SAY_AGGRO = 0,
- SAY_FEAST_PROWLER = 1,
- SAY_DEATH = 2
-};
-
-enum Spells
-{
- SPELL_SHADOW_WORD_PAIN = 24212, // Corrected
- SPELL_GOUGE = 12540, // Corrected
- SPELL_MARK_OF_ARLOKK = 24210, // triggered spell 24211 Added to spell_dbc
- SPELL_RAVAGE = 24213, // Corrected
- SPELL_CLEAVE = 25174, // Searching for right spell
- SPELL_PANTHER_TRANSFORM = 24190, // Transform to panther now used
- SPELL_SUMMON_PROWLER = 24246, // Added to Spell_dbc
- SPELL_VANISH_VISUAL = 24222, // Added
- SPELL_VANISH = 24223, // Added
- SPELL_SUPER_INVIS = 24235 // Added to Spell_dbc
-};
-
-enum Events
-{
- EVENT_SHADOW_WORD_PAIN = 1,
- EVENT_GOUGE = 2,
- EVENT_MARK_OF_ARLOKK = 3,
- EVENT_RAVAGE = 4,
- EVENT_TRANSFORM = 5,
- EVENT_VANISH = 6,
- EVENT_VANISH_2 = 7,
- EVENT_TRANSFORM_BACK = 8,
- EVENT_VISIBLE = 9,
- EVENT_SUMMON_PROWLERS = 10
-};
-
-enum Phases
-{
- PHASE_ALL = 0,
- PHASE_ONE = 1,
- PHASE_TWO = 2
-};
-
-enum Weapon
-{
- WEAPON_DAGGER = 10616
-};
-
-enum Misc
-{
- MAX_PROWLERS_PER_SIDE = 15
-};
-
-Position const PosMoveOnSpawn[1] =
-{
- { -11561.9f, -1627.868f, 41.29941f, 0.0f }
-};
-
-class boss_arlokk : public CreatureScript
-{
- public: boss_arlokk() : CreatureScript("boss_arlokk") {}
-
- struct boss_arlokkAI : public BossAI
- {
- boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) { }
-
- void Reset()
- {
- _summonCountA = 0;
- _summonCountB = 0;
- me->RemoveAllAuras();
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
- if (instance)
- {
- if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- gate->SetGoState(GO_STATE_READY);
- me->SetWalk(false);
- me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]);
- }
- }
-
- void JustDied(Unit* /*killer*/)
- {
- Talk(SAY_DEATH);
- me->RemoveAllAuras();
- if (instance)
- {
- if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- gate->SetGoState(GO_STATE_ACTIVE);
- instance->SetBossState(DATA_ARLOKK, DONE);
- }
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
- if (instance)
- events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL);
- events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL);
- events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE);
- Talk(SAY_AGGRO);
-
- // Sets up list of Panther spawners to cast on
- std::list<Creature*> triggerList;
- GetCreatureListWithEntryInGrid(triggerList, me, NPC_PANTHER_TRIGGER, 100.0f);
- if (!triggerList.empty())
- {
- uint8 sideA = 0;
- uint8 sideB = 0;
- for (std::list<Creature*>::const_iterator itr = triggerList.begin(); itr != triggerList.end(); ++itr)
- {
- if (Creature* trigger = *itr)
- {
- if (trigger->GetPositionY() < -1625.0f)
- {
- _triggersSideAGUID[sideA] = trigger->GetGUID();
- ++sideA;
- }
- else
- {
- _triggersSideBGUID[sideB] = trigger->GetGUID();
- ++sideB;
- }
- }
- }
- }
- }
-
- void EnterEvadeMode()
- {
- if (instance)
- {
- if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- object->SetGoState(GO_STATE_ACTIVE);
- if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK)))
- object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- instance->SetBossState(DATA_ARLOKK, NOT_STARTED);
- }
- me->DespawnOrUnsummon(4000);
- }
-
- void SetData(uint32 id, uint32 /*value*/)
- {
- if (id == 1)
- --_summonCountA;
- else if (id == 2)
- --_summonCountB;
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SHADOW_WORD_PAIN:
- DoCastVictim(SPELL_SHADOW_WORD_PAIN, true);
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE);
- break;
- case EVENT_GOUGE:
- DoCastVictim(SPELL_GOUGE, true);
- break;
- case EVENT_SUMMON_PROWLERS:
- if (_summonCountA < MAX_PROWLERS_PER_SIDE)
- {
- if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)]))
- {
- trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
- ++_summonCountA;
- }
- }
- if (_summonCountB < MAX_PROWLERS_PER_SIDE)
- {
- if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)]))
- {
- trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
- ++_summonCountB;
- }
- }
- events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL);
- break;
- case EVENT_MARK_OF_ARLOKK:
- {
- Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1, 3), 0.0f, false, -SPELL_MARK_OF_ARLOKK);
- if (!target)
- target = me->getVictim();
- if (target)
- {
- DoCast(target, SPELL_MARK_OF_ARLOKK, true);
- Talk(SAY_FEAST_PROWLER, target->GetGUID());
- }
- events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000));
- break;
- }
- case EVENT_TRANSFORM:
- {
- DoCast(me, SPELL_PANTHER_TRANSFORM);
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP));
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- me->AttackStop();
- DoResetThreat();
- me->SetReactState(REACT_PASSIVE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- DoCast(me, SPELL_VANISH_VISUAL);
- DoCast(me, SPELL_VANISH);
- events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE);
- break;
- }
- case EVENT_VANISH:
- DoCast(me, SPELL_SUPER_INVIS);
- me->SetWalk(false);
- if (instance)
- me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ());
- events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE);
- break;
- case EVENT_VANISH_2:
- DoCast(me, SPELL_VANISH);
- DoCast(me, SPELL_SUPER_INVIS);
- events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE);
- break;
- case EVENT_VISIBLE:
- me->SetReactState(REACT_AGGRESSIVE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- AttackStart(target);
- me->RemoveAura(SPELL_SUPER_INVIS);
- me->RemoveAura(SPELL_VANISH);
- events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO);
- events.SetPhase(PHASE_TWO);
- break;
- case EVENT_RAVAGE:
- DoCastVictim(SPELL_RAVAGE, true);
- events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
- break;
- case EVENT_TRANSFORM_BACK:
- {
- me->RemoveAura(SPELL_PANTHER_TRANSFORM);
- DoCast(me, SPELL_VANISH_VISUAL);
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg));
- me->UpdateDamagePhysical(BASE_ATTACK);
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE);
- events.SetPhase(PHASE_ONE);
- break;
- }
- default:
- break;
- }
- }
-
- DoMeleeAttackIfReady();
- }
-
- private:
- uint8 _summonCountA;
- uint8 _summonCountB;
- uint64 _triggersSideAGUID[5];
- uint64 _triggersSideBGUID[5];
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return GetZulGurubAI<boss_arlokkAI>(creature);
- }
-};
-
-/*######
-## npc_zulian_prowler
-######*/
-
-enum ZulianProwlerSpells
-{
- SPELL_SNEAK_RANK_1_1 = 22766,
- SPELL_SNEAK_RANK_1_2 = 7939, // Added to Spell_dbc
- SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 // Added to Spell_dbc
-};
-
-enum ZulianProwlerEvents
-{
- EVENT_ATTACK = 1
-};
-
-Position const PosProwlerCenter[1] =
-{
- { -11556.7f, -1631.344f, 41.2994f, 0.0f }
-};
-
-class npc_zulian_prowler : public CreatureScript
-{
- public: npc_zulian_prowler() : CreatureScript("npc_zulian_prowler") {}
-
- struct npc_zulian_prowlerAI : public ScriptedAI
- {
- npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
-
- void Reset()
- {
- if (me->GetPositionY() < -1625.0f)
- _sideData = 1;
- else
- _sideData = 2;
-
- DoCast(me, SPELL_SNEAK_RANK_1_1);
- DoCast(me, SPELL_SNEAK_RANK_1_2);
-
- if (_instance)
- if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK)))
- me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ());
- _events.ScheduleEvent(EVENT_ATTACK, 6000);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- me->GetMotionMaster()->Clear(false);
- me->RemoveAura(SPELL_SNEAK_RANK_1_1);
- me->RemoveAura(SPELL_SNEAK_RANK_1_2);
- }
-
- void SpellHit(Unit* caster, SpellInfo const* spell)
- {
- if (spell->Id == SPELL_MARK_OF_ARLOKK_TRIGGER) // Should only hit if line of sight
- me->Attack(caster, true);
- }
-
- void JustDied(Unit* /*killer*/)
- {
- if (_instance)
- {
- if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK)))
- {
- if (arlokk->isAlive())
- arlokk->GetAI()->SetData(_sideData, 0);
- }
- }
- me->DespawnOrUnsummon(4000);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (UpdateVictim())
- {
- DoMeleeAttackIfReady();
- return;
- }
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_ATTACK:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0.0f, 100, false))
- me->Attack(target, true);
- break;
- default:
- break;
- }
- }
- }
-
- private:
- int32 _sideData;
- EventMap _events;
- InstanceScript* _instance;
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return GetZulGurubAI<npc_zulian_prowlerAI>(creature);
- }
-};
-
-/*######
-## go_gong_of_bethekk
-######*/
-
-Position const PosSummonArlokk[1] =
-{
- { -11507.22f, -1628.062f, 41.38264f, 3.159046f }
-};
-
-class go_gong_of_bethekk : public GameObjectScript
-{
- public: go_gong_of_bethekk() : GameObjectScript("go_gong_of_bethekk") {}
-
- bool OnGossipHello(Player* /*player*/, GameObject* go)
- {
- if (go->GetInstanceScript())
- {
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- go->SendCustomAnim(0);
- go->SummonCreature(NPC_ARLOKK, PosSummonArlokk[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 600000);
- }
- return true;
- }
-};
-
-void AddSC_boss_arlokk()
-{
- new boss_arlokk();
- new npc_zulian_prowler();
- new go_gong_of_bethekk();
-}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp
index c0362397dd5..c3bfa008c08 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp
@@ -16,52 +16,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Grilek
-SD%Complete: 100
-SDComment:
-SDCategory: Zul'Gurub
-EndScriptData */
-
+#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"
+enum Yells
+{
+};
+
enum Spells
{
- SPELL_AVATAR = 24646, // Enrage Spell
- SPELL_GROUND_TREMOR = 6524
};
enum Events
{
- EVENT_AVATAR = 1,
- EVENT_GROUND_TREMOR = 2
};
-class boss_grilek : public CreatureScript // grilek
+class boss_grilek : public CreatureScript
{
- public: boss_grilek() : CreatureScript("boss_grilek") {}
+ public:
+ boss_grilek() : CreatureScript("boss_grilek") { }
struct boss_grilekAI : public BossAI
{
- boss_grilekAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) {}
+ boss_grilekAI(Creature* creature) : BossAI(creature, DATA_GRILEK)
+ {
+ }
void Reset()
{
- _Reset();
}
- void JustDied(Unit* /*killer*/)
+ void EnterCombat(Unit* /*who*/)
{
- _JustDied();
}
- void EnterCombat(Unit* /*who*/)
+ void JustDied(Unit* /*killer*/)
{
- _EnterCombat();
- events.ScheduleEvent(EVENT_AVATAR, urand(15000, 25000));
- events.ScheduleEvent(EVENT_GROUND_TREMOR, urand(15000, 25000));
}
void UpdateAI(uint32 diff)
@@ -73,31 +65,16 @@ class boss_grilek : public CreatureScript // grilek
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
+ /*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
- case EVENT_AVATAR:
- DoCast(me, SPELL_AVATAR);
- if (Unit* victim = me->getVictim())
- {
- if (DoGetThreat(victim))
- DoModifyThreatPercent(victim, -50);
- }
-
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- AttackStart(target);
- events.ScheduleEvent(EVENT_AVATAR, urand(25000, 35000));
- break;
- case EVENT_GROUND_TREMOR:
- DoCastVictim(SPELL_GROUND_TREMOR, true);
- events.ScheduleEvent(EVENT_GROUND_TREMOR, urand(12000, 16000));
- break;
default:
break;
}
}
+ */
DoMeleeAttackIfReady();
}
@@ -113,4 +90,3 @@ void AddSC_boss_grilek()
{
new boss_grilek();
}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
deleted file mode 100644
index 18b1bc21ea3..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-Name: Boss_Hakkar
-%Complete: 95
-Comment: Blood siphon spell buggy cause of Core Issue.
-Category: Zul'Gurub
-*/
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "zulgurub.h"
-
-enum Says
-{
- SAY_AGGRO = 0,
- SAY_FLEEING = 1,
- SAY_MINION_DESTROY = 2, // Where does it belong?
- SAY_PROTECT_ALTAR = 3 // Where does it belong?
-};
-
-enum Spells
-{
- SPELL_BLOOD_SIPHON = 24322, // Buggy ?
- SPELL_CORRUPTED_BLOOD = 24328,
- SPELL_CAUSE_INSANITY = 24327, // Spell needs scripting.
- SPELL_WILL_OF_HAKKAR = 24178,
- SPELL_ENRAGE = 24318,
- // The Aspects of all High Priests spells
- SPELL_ASPECT_OF_JEKLIK = 24687,
- SPELL_ASPECT_OF_VENOXIS = 24688,
- SPELL_ASPECT_OF_MARLI = 24686,
- SPELL_ASPECT_OF_THEKAL = 24689,
- SPELL_ASPECT_OF_ARLOKK = 24690
-};
-
-enum Events
-{
- EVENT_BLOOD_SIPHON = 1,
- EVENT_CORRUPTED_BLOOD = 2,
- EVENT_CAUSE_INSANITY = 3, // Spell needs scripting. Event disabled
- EVENT_WILL_OF_HAKKAR = 4,
- EVENT_ENRAGE = 5,
- // The Aspects of all High Priests events
- EVENT_ASPECT_OF_JEKLIK = 6,
- EVENT_ASPECT_OF_VENOXIS = 7,
- EVENT_ASPECT_OF_MARLI = 8,
- EVENT_ASPECT_OF_THEKAL = 9,
- EVENT_ASPECT_OF_ARLOKK = 10
-};
-
-class boss_hakkar : public CreatureScript
-{
- public: boss_hakkar() : CreatureScript("boss_hakkar") {}
-
- struct boss_hakkarAI : public BossAI
- {
- boss_hakkarAI(Creature* creature) : BossAI(creature, DATA_HAKKAR) {}
-
- void Reset()
- {
- _Reset();
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_BLOOD_SIPHON, 90000);
- events.ScheduleEvent(EVENT_CORRUPTED_BLOOD, 25000);
- events.ScheduleEvent(EVENT_CAUSE_INSANITY, 17000);
- events.ScheduleEvent(EVENT_WILL_OF_HAKKAR, 17000);
- events.ScheduleEvent(EVENT_ENRAGE, 600000);
- if (instance->GetBossState(DATA_JEKLIK) != DONE)
- events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 4000);
- if (instance->GetBossState(DATA_VENOXIS) != DONE)
- events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 7000);
- if (instance->GetBossState(DATA_MARLI) != DONE)
- events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000);
- if (instance->GetBossState(DATA_THEKAL) != DONE)
- events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 8000);
- if (instance->GetBossState(DATA_ARLOKK) != DONE)
- events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 18000);
- Talk(SAY_AGGRO);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_BLOOD_SIPHON:
- DoCastVictim(SPELL_BLOOD_SIPHON, true);
- events.ScheduleEvent(EVENT_BLOOD_SIPHON, 90000);
- break;
- case EVENT_CORRUPTED_BLOOD:
- DoCastVictim(SPELL_CORRUPTED_BLOOD, true);
- events.ScheduleEvent(EVENT_CORRUPTED_BLOOD, urand(30000, 45000));
- break;
- case EVENT_CAUSE_INSANITY:
- // DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CAUSE_INSANITY);
- // events.ScheduleEvent(EVENT_CAUSE_INSANITY, urand(35000, 45000));
- break;
- case EVENT_WILL_OF_HAKKAR:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_WILL_OF_HAKKAR);
- events.ScheduleEvent(EVENT_WILL_OF_HAKKAR, urand(25000, 35000));
- break;
- case EVENT_ENRAGE:
- if (!me->HasAura(SPELL_ENRAGE))
- DoCast(me, SPELL_ENRAGE);
- events.ScheduleEvent(EVENT_ENRAGE, 90000);
- break;
- case EVENT_ASPECT_OF_JEKLIK:
- DoCastVictim(SPELL_ASPECT_OF_JEKLIK, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, urand(10000, 14000));
- break;
- case EVENT_ASPECT_OF_VENOXIS:
- DoCastVictim(SPELL_ASPECT_OF_VENOXIS, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 8000);
- break;
- case EVENT_ASPECT_OF_MARLI:
- DoCastVictim(SPELL_ASPECT_OF_MARLI, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 10000);
- break;
- case EVENT_ASPECT_OF_THEKAL:
- DoCastVictim(SPELL_ASPECT_OF_THEKAL, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 15000);
- break;
- case EVENT_ASPECT_OF_ARLOKK:
- DoCastVictim(SPELL_ASPECT_OF_ARLOKK, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, urand(10000, 15000));
- break;
- default:
- break;
- }
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_hakkarAI(creature);
- }
-};
-
-void AddSC_boss_hakkar()
-{
- new boss_hakkar();
-}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp
index e92d3266c45..8889af46b81 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp
@@ -16,54 +16,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Hazzarah
-SD%Complete: 100
-SDComment:
-SDCategory: Zul'Gurub
-EndScriptData */
-
+#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"
+enum Yells
+{
+};
+
enum Spells
{
- SPELL_MANABURN = 26046,
- SPELL_SLEEP = 24664
};
enum Events
{
- EVENT_MANABURN = 1,
- EVENT_SLEEP = 2,
- EVENT_ILLUSIONS = 3
};
class boss_hazzarah : public CreatureScript
{
- public: boss_hazzarah() : CreatureScript("boss_hazzarah") {}
+ public:
+ boss_hazzarah() : CreatureScript("boss_hazzarah") { }
struct boss_hazzarahAI : public BossAI
{
- boss_hazzarahAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) {}
+ boss_hazzarahAI(Creature* creature) : BossAI(creature, DATA_HAZZARAH)
+ {
+ }
void Reset()
{
- _Reset();
}
- void JustDied(Unit* /*killer*/)
+ void EnterCombat(Unit* /*who*/)
{
- _JustDied();
}
- void EnterCombat(Unit* /*who*/)
+ void JustDied(Unit* /*killer*/)
{
- _EnterCombat();
- events.ScheduleEvent(EVENT_MANABURN, urand(4000, 10000));
- events.ScheduleEvent(EVENT_SLEEP, urand(10000, 18000));
- events.ScheduleEvent(EVENT_ILLUSIONS, urand(10000, 18000));
}
void UpdateAI(uint32 diff)
@@ -75,37 +65,16 @@ class boss_hazzarah : public CreatureScript
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
+ /*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
- case EVENT_MANABURN:
- DoCastVictim(SPELL_MANABURN, true);
- events.ScheduleEvent(EVENT_MANABURN, urand(8000, 16000));
- break;
- case EVENT_SLEEP:
- DoCastVictim(SPELL_SLEEP, true);
- events.ScheduleEvent(EVENT_SLEEP, urand(12000, 20000));
- break;
- case EVENT_ILLUSIONS:
- // We will summon 3 illusions that will spawn on a random gamer and attack this gamer
- // We will just use one model for the beginning
- for (uint8 i = 0; i < 3; ++i)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- Creature* Illusion = me->SummonCreature(NPC_NIGHTMARE_ILLUSION, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
- if (Illusion)
- Illusion->AI()->AttackStart(target);
- }
- }
- events.ScheduleEvent(EVENT_ILLUSIONS, urand(15000, 25000));
- break;
default:
break;
}
}
+ */
DoMeleeAttackIfReady();
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
deleted file mode 100644
index 73d2982aee6..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Boss_Jeklik
-SD%Complete: 85
-SDComment: Problem in finding the right flying batriders for spawning and making them fly.
-SDCategory: Zul'Gurub
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "zulgurub.h"
-
-enum Says
-{
- SAY_AGGRO = 0,
- SAY_RAIN_FIRE = 1,
- SAY_DEATH = 2
-};
-
-enum Spells
-{
- SPELL_CHARGE = 22911,
- SPELL_SONICBURST = 23918,
- SPELL_SCREECH = 6605,
- SPELL_SHADOW_WORD_PAIN = 23952,
- SPELL_MIND_FLAY = 23953,
- SPELL_CHAIN_MIND_FLAY = 26044, // Right ID unknown. So disabled
- SPELL_GREATERHEAL = 23954,
- SPELL_BAT_FORM = 23966,
- // Batriders Spell
- SPELL_BOMB = 40332 // Wrong ID but Magmadars bomb is not working...
-};
-
-class boss_jeklik : public CreatureScript //jeklik
-{
- public: boss_jeklik() : CreatureScript("boss_jeklik") {}
-
- struct boss_jeklikAI : public BossAI
- {
- boss_jeklikAI(Creature* creature) : BossAI(creature, DATA_JEKLIK) {}
-
- uint32 Charge_Timer;
- uint32 SonicBurst_Timer;
- uint32 Screech_Timer;
- uint32 SpawnBats_Timer;
- uint32 ShadowWordPain_Timer;
- uint32 MindFlay_Timer;
- uint32 ChainMindFlay_Timer;
- uint32 GreaterHeal_Timer;
- uint32 SpawnFlyingBats_Timer;
-
- bool PhaseTwo;
-
- void Reset()
- {
- _Reset();
- Charge_Timer = 20000;
- SonicBurst_Timer = 8000;
- Screech_Timer = 13000;
- SpawnBats_Timer = 60000;
- ShadowWordPain_Timer = 6000;
- MindFlay_Timer = 11000;
- ChainMindFlay_Timer = 26000;
- GreaterHeal_Timer = 50000;
- SpawnFlyingBats_Timer = 10000;
-
- PhaseTwo = false;
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
- DoCast(me, SPELL_BAT_FORM);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- if (me->getVictim() && me->isAlive())
- {
- if (HealthAbovePct(50))
- {
- if (Charge_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoCast(target, SPELL_CHARGE);
- AttackStart(target);
- }
-
- Charge_Timer = urand(15000, 30000);
- } else Charge_Timer -= diff;
-
- if (SonicBurst_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SONICBURST);
- SonicBurst_Timer = urand(8000, 13000);
- } else SonicBurst_Timer -= diff;
-
- if (Screech_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SCREECH);
- Screech_Timer = urand(18000, 26000);
- } else Screech_Timer -= diff;
-
- if (SpawnBats_Timer <= diff)
- {
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
-
- Creature* Bat = NULL;
- Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
-
- Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
-
- Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
-
- Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
-
- Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
- Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (target && Bat) Bat ->AI()->AttackStart(target);
-
- SpawnBats_Timer = 60000;
- } else SpawnBats_Timer -= diff;
- }
- else
- {
- if (PhaseTwo)
- {
- if (ShadowWordPain_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoCast(target, SPELL_SHADOW_WORD_PAIN);
- ShadowWordPain_Timer = urand(12000, 18000);
- }
- }ShadowWordPain_Timer -=diff;
-
- if (MindFlay_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_MIND_FLAY);
- MindFlay_Timer = 16000;
- }MindFlay_Timer -=diff;
-
- if (ChainMindFlay_Timer <= diff)
- {
- me->InterruptNonMeleeSpells(false);
- DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY);
- ChainMindFlay_Timer = urand(15000, 30000);
- }ChainMindFlay_Timer -=diff;
-
- if (GreaterHeal_Timer <= diff)
- {
- me->InterruptNonMeleeSpells(false);
- DoCast(me, SPELL_GREATERHEAL);
- GreaterHeal_Timer = urand(25000, 35000);
- }GreaterHeal_Timer -=diff;
-
- if (SpawnFlyingBats_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- if (Creature* FlyingBat = me->SummonCreature(14965, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000))
- FlyingBat->AI()->AttackStart(target);
- }
-
- SpawnFlyingBats_Timer = urand(10000, 15000);
- } else SpawnFlyingBats_Timer -=diff;
- }
- else
- {
- me->SetDisplayId(15219);
- DoResetThreat();
- PhaseTwo = true;
- }
- }
-
- DoMeleeAttackIfReady();
- }
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_jeklikAI(creature);
- }
-};
-
-//Flying Bat
-class mob_batrider : public CreatureScript
-{
- public:
-
- mob_batrider()
- : CreatureScript("mob_batrider")
- {
- }
-
- struct mob_batriderAI : public ScriptedAI
- {
- mob_batriderAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
-
- uint32 Bomb_Timer;
- uint32 Check_Timer;
-
- void Reset()
- {
- Bomb_Timer = 2000;
- Check_Timer = 1000;
-
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- void EnterCombat(Unit* /*who*/) {}
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- //Bomb_Timer
- if (Bomb_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoCast(target, SPELL_BOMB);
- Bomb_Timer = 5000;
- }
- } else Bomb_Timer -= diff;
-
- //Check_Timer
- if (Check_Timer <= diff)
- {
- if (instance)
- {
- if (instance->GetBossState(DATA_JEKLIK) == DONE)
- {
- me->setDeathState(JUST_DIED);
- me->RemoveCorpse();
- return;
- }
- }
-
- Check_Timer = 1000;
- } else Check_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_batriderAI(creature);
- }
-};
-
-void AddSC_boss_jeklik()
-{
- new boss_jeklik();
- new mob_batrider();
-}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
deleted file mode 100644
index 7566c1b2e11..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Boss_Jin'do the Hexxer
-SD%Complete: 85
-SDComment: Mind Control not working because of core bug. Shades visible for all.
-SDCategory: Zul'Gurub
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "zulgurub.h"
-
-enum Say
-{
- SAY_AGGRO = 1
-};
-
-enum Spells
-{
- SPELL_BRAINWASHTOTEM = 24262,
- SPELL_POWERFULLHEALINGWARD = 24309, // HACKED Totem summoned by script because the spell totems will not cast.
- SPELL_HEX = 24053,
- SPELL_DELUSIONSOFJINDO = 24306,
- SPELL_SHADEOFJINDO = 24308, // HACKED
- //Healing Ward Spell
- SPELL_HEAL = 38588, // HACKED Totems are not working right. Right heal spell ID is 24311 but this spell is not casting...
- //Shade of Jindo Spell
- SPELL_SHADOWSHOCK = 19460,
- SPELL_INVISIBLE = 24699
-};
-
-enum Events
-{
- EVENT_BRAINWASHTOTEM = 1,
- EVENT_POWERFULLHEALINGWARD = 2,
- EVENT_HEX = 3,
- EVENT_DELUSIONSOFJINDO = 4,
- EVENT_TELEPORT = 5
-};
-
-Position const TeleportLoc = {-11583.7783f, -1249.4278f, 77.5471f, 4.745f};
-
-class boss_jindo : public CreatureScript
-{
- public: boss_jindo() : CreatureScript("boss_jindo") {}
-
- struct boss_jindoAI : public BossAI
- {
- boss_jindoAI(Creature* creature) : BossAI(creature, DATA_JINDO) {}
-
- void Reset()
- {
- _Reset();
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_BRAINWASHTOTEM, 20000);
- events.ScheduleEvent(EVENT_POWERFULLHEALINGWARD, 16000);
- events.ScheduleEvent(EVENT_HEX, 8000);
- events.ScheduleEvent(EVENT_DELUSIONSOFJINDO, 10000);
- events.ScheduleEvent(EVENT_TELEPORT, 5000);
- Talk(SAY_AGGRO);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_BRAINWASHTOTEM:
- DoCast(me, SPELL_BRAINWASHTOTEM);
- events.ScheduleEvent(EVENT_BRAINWASHTOTEM, urand(18000, 26000));
- break;
- case EVENT_POWERFULLHEALINGWARD: // HACK
- //DoCast(me, SPELL_POWERFULLHEALINGWARD);
- me->SummonCreature(14987, me->GetPositionX()+3, me->GetPositionY()-2, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
- events.ScheduleEvent(EVENT_POWERFULLHEALINGWARD, urand(14000, 20000));
- break;
- case EVENT_HEX:
- if (Unit* target = me->getVictim())
- {
- DoCast(target, SPELL_HEX, true);
- if (DoGetThreat(target))
- DoModifyThreatPercent(target, -80);
- }
- events.ScheduleEvent(EVENT_HEX, urand(12000, 20000));
- break;
- case EVENT_DELUSIONSOFJINDO: // HACK
- // Casting the delusion curse with a shade so shade will attack the same target with the curse.
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoCast(target, SPELL_DELUSIONSOFJINDO);
- Creature* Shade = me->SummonCreature(NPC_SHADE_OF_JINDO, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Shade)
- Shade->AI()->AttackStart(target);
- }
- events.ScheduleEvent(EVENT_DELUSIONSOFJINDO, urand(4000, 12000));
- break;
- case EVENT_TELEPORT: // Possible HACK
- // Teleports a random player and spawns 9 Sacrificed Trolls to attack player
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoTeleportPlayer(target, TeleportLoc.m_positionX, TeleportLoc.m_positionY, TeleportLoc.m_positionZ, TeleportLoc.m_orientation);
- if (DoGetThreat(me->getVictim()))
- DoModifyThreatPercent(target, -100);
- Creature* SacrificedTroll;
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX()+2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX()-2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX()+4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX()-4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY()+2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY()-2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY()+4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX(), target->GetPositionY()-4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, target->GetPositionX()+3, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (SacrificedTroll)
- SacrificedTroll->AI()->AttackStart(target);
- }
- events.ScheduleEvent(EVENT_TELEPORT, urand(15000, 23000));
- break;
- default:
- break;
- }
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_jindoAI(creature);
- }
-};
-
-//Healing Ward
-class mob_healing_ward : public CreatureScript
-{
- public:
-
- mob_healing_ward()
- : CreatureScript("mob_healing_ward")
- {
- }
-
- struct mob_healing_wardAI : public ScriptedAI
- {
- mob_healing_wardAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- uint32 Heal_Timer;
-
- InstanceScript* instance;
-
- void Reset()
- {
- Heal_Timer = 2000;
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- }
-
- void UpdateAI(uint32 diff)
- {
- //Heal_Timer
- if (Heal_Timer <= diff)
- {
- if (instance)
- {
- Unit* pJindo = Unit::GetUnit(*me, instance->GetData64(DATA_JINDO));
- if (pJindo)
- DoCast(pJindo, SPELL_HEAL);
- }
- Heal_Timer = 3000;
- } else Heal_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_healing_wardAI(creature);
- }
-};
-
-//Shade of Jindo
-class mob_shade_of_jindo : public CreatureScript
-{
- public:
-
- mob_shade_of_jindo()
- : CreatureScript("mob_shade_of_jindo")
- {
- }
-
- struct mob_shade_of_jindoAI : public ScriptedAI
- {
- mob_shade_of_jindoAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 ShadowShock_Timer;
-
- void Reset()
- {
- ShadowShock_Timer = 1000;
- DoCast(me, SPELL_INVISIBLE, true);
- }
-
- void EnterCombat(Unit* /*who*/){}
-
- void UpdateAI(uint32 diff)
- {
-
- //ShadowShock_Timer
- if (ShadowShock_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SHADOWSHOCK);
- ShadowShock_Timer = 2000;
- } else ShadowShock_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_shade_of_jindoAI(creature);
- }
-};
-
-void AddSC_boss_jindo()
-{
- new boss_jindo();
- new mob_healing_ward();
- new mob_shade_of_jindo();
-}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp
new file mode 100644
index 00000000000..d3fff5d710e
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "zulgurub.h"
+
+enum Yells
+{
+ // Jin'do the Godbreaker
+ SAY_INTRO = 0,
+ SAY_AGGRO = 1,
+ EMOTE_SHADOWS_OF_HAKKAR = 2, // ID - 97172 Shadows of Hakkar
+ SAY_JINDO_SPIRIT_PHASE = 3,
+ //SAY_PLAYER_KILL = 4, // missing data
+
+ // Spirit of Hakkar
+ SAY_SPIRIT_SPIRIT_PHASE = 0,
+ SAY_SPIRIT_DEFEATED = 1,
+
+ // Jin'do the Godbreaker - Trigger
+ SAY_JINDO_DEFEATED = 0,
+
+ // Shadow of Hakkar
+ SAY_SHADOW_DEFEATED = 0,
+};
+
+enum Spells
+{
+};
+
+enum Events
+{
+};
+
+class boss_jindo_the_godbreaker : public CreatureScript
+{
+ public:
+ boss_jindo_the_godbreaker() : CreatureScript("boss_jindo_the_godbreaker") { }
+
+ struct boss_jindo_the_godbreakerAI : public BossAI
+ {
+ boss_jindo_the_godbreakerAI(Creature* creature) : BossAI(creature, DATA_JINDO) { }
+
+ void Reset()
+ {
+ _Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ /*
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ default:
+ break;
+ }
+ }
+ */
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetZulGurubAI<boss_jindo_the_godbreakerAI>(creature);
+ }
+};
+
+void AddSC_boss_jindo_the_godbreaker()
+{
+ new boss_jindo_the_godbreaker();
+}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_kilnara.cpp
index fe9c0be49aa..eab9722b280 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_kilnara.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,55 +15,60 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Gahz'ranka
-SD%Complete: 85
-SDComment: Massive Geyser with knockback not working. Spell buggy.
-SDCategory: Zul'Gurub
-EndScriptData */
-
+#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
#include "zulgurub.h"
+enum Yells
+{
+ SAY_AGGRO = 0,
+ SAY_WAVE_OF_AGONY = 1, // ID - 96457 Wave of Agony
+ SAY_TRANSFROM_1 = 2,
+ SAY_TRANSFROM_2 = 3,
+ SAY_PLAYER_KILL = 4,
+ SAY_DEATH = 5
+};
+
enum Spells
{
- SPELL_FROSTBREATH = 16099,
- SPELL_MASSIVEGEYSER = 22421, // Not working. (summon)
- SPELL_SLAM = 24326
};
enum Events
{
- EVENT_FROSTBREATH = 1,
- EVENT_MASSIVEGEYSER = 2,
- EVENT_SLAM = 3
};
-class boss_gahzranka : public CreatureScript // gahzranka
+class boss_kilnara : public CreatureScript
{
- public: boss_gahzranka() : CreatureScript("boss_gahzranka") {}
+ public:
+ boss_kilnara() : CreatureScript("boss_kilnara") { }
- struct boss_gahzrankaAI : public BossAI
+ struct boss_kilnaraAI : public BossAI
{
- boss_gahzrankaAI(Creature* creature) : BossAI(creature, DATA_GAHZRANKA) {}
+ boss_kilnaraAI(Creature* creature) : BossAI(creature, DATA_KILNARA) { }
void Reset()
{
_Reset();
}
+ void EnterCombat(Unit* /*who*/)
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ }
+
void JustDied(Unit* /*killer*/)
{
_JustDied();
+ Talk(SAY_DEATH);
}
- void EnterCombat(Unit* /*who*/)
+ void KilledUnit(Unit* victim)
{
- _EnterCombat();
- events.ScheduleEvent(EVENT_FROSTBREATH, 8000);
- events.ScheduleEvent(EVENT_MASSIVEGEYSER, 25000);
- events.ScheduleEvent(EVENT_SLAM, 17000);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_PLAYER_KILL);
}
void UpdateAI(uint32 diff)
@@ -76,27 +80,16 @@ class boss_gahzranka : public CreatureScript // gahzranka
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
+ /*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
- case EVENT_FROSTBREATH:
- DoCastVictim(SPELL_FROSTBREATH, true);
- events.ScheduleEvent(EVENT_FROSTBREATH, urand(7000, 11000));
- break;
- case EVENT_MASSIVEGEYSER:
- DoCastVictim(SPELL_MASSIVEGEYSER, true);
- events.ScheduleEvent(EVENT_MASSIVEGEYSER, urand(22000, 32000));
- break;
- case EVENT_SLAM:
- DoCastVictim(SPELL_SLAM, true);
- events.ScheduleEvent(EVENT_SLAM, urand(12000, 20000));
- break;
default:
break;
}
}
+ */
DoMeleeAttackIfReady();
}
@@ -104,11 +97,11 @@ class boss_gahzranka : public CreatureScript // gahzranka
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_gahzrankaAI(creature);
+ return GetZulGurubAI<boss_kilnaraAI>(creature);
}
};
-void AddSC_boss_gahzranka()
+void AddSC_boss_kilnara()
{
- new boss_gahzranka();
+ new boss_kilnara();
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
index 9a94ab02348..116fd18e458 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
@@ -16,97 +16,94 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Mandokir
-SD%Complete: 90
-SDComment: Ohgan function needs improvements.
-SDCategory: Zul'Gurub
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
-#include "Spell.h"
-#include "SpellAuras.h"
#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "Player.h"
+#include "GridNotifiers.h"
#include "zulgurub.h"
-enum Says
+enum Yells
{
- SAY_AGGRO = 0,
- SAY_DING_KILL = 1,
- SAY_WATCH = 2,
- SAY_WATCH_WHISPER = 3,
- SAY_OHGAN_DEAD = 4,
- SAY_GRATS_JINDO = 0,
+ SAY_AGGRO = 0,
+ SAY_PLAYER_KILL = 1,
+ SAY_DISMOUNT_OHGAN = 2,
+ EMOTE_DEVASTATING_SLAM = 3,
+ SAY_REANIMATE_OHGAN = 4,
+ EMOTE_FRENZY = 5,
+ SAY_FRENZY = 6,
+ SAY_DEATH = 7
};
enum Spells
{
- SPELL_CHARGE = 24408, // seen
- SPELL_OVERPOWER = 24407, // Seen
- SPELL_FEAR = 29321,
- SPELL_WHIRLWIND = 13736, // Triggers 15589
- SPELL_MORTAL_STRIKE = 16856, // Seen
- SPELL_FRENZY = 24318, // seen
- SPELL_WATCH = 24314, // seen 24315, 24316
- SPELL_WATCH_CHARGE = 24315, // Triggers 24316
- SPELL_LEVEL_UP = 24312 //
+ // Bloodlord Mandokir
+ SPELL_BLOODLORD_AURA = 96480,
+ SPELL_SUMMON_OHGAN = 96717,
+ SPELL_REANIMATE_OHGAN = 96724,
+ SPELL_DECAPITATE = 96682,
+ SPELL_BLOODLETTING = 96776,
+ SPELL_BLOODLETTING_DAMAGE = 96777,
+ SPELL_BLOODLETTING_HEAL = 96778,
+ SPELL_FRENZY = 96800,
+ SPELL_LEVEL_UP = 96662,
+ SPELL_DEVASTATING_SLAM = 96740,
+ SPELL_DEVASTATING_SLAM_TRIGGER = 96761,
+ SPELL_DEVASTATING_SLAM_DAMAGE = 97385,
+ SPELL_SPIRIT_VENGEANCE_CANCEL = 96821,
+
+ // Chained Spirit
+ SPELL_REVIVE = 96484,
+
+ // Ohgan
+ SPELL_OHGAN_HEART_VISUAL = 96727,
+ SPELL_PERMANENT_FEIGN_DEATH = 96733,
+ SPELL_CLEAR_ALL = 28471,
+ SPELL_OHGAN_ORDERS = 96721,
+ SPELL_OHGAN_ORDERS_TRIGGER = 96722
};
enum Events
{
- EVENT_CHECK_SPEAKER = 1,
- EVENT_CHECK_START = 2,
- EVENT_STARTED = 3,
- EVENT_OVERPOWER = 4,
- EVENT_MORTAL_STRIKE = 5,
- EVENT_WHIRLWIND = 6,
- EVENT_CHECK_OHGAN = 7,
- EVENT_WATCH_PLAYER = 8,
- EVENT_CHARGE_PLAYER = 9
+ // Bloodlord Mandokir
+ EVENT_SUMMON_OHGAN = 1,
+ EVENT_DECAPITATE = 2,
+ EVENT_BLOODLETTING = 3,
+ EVENT_REANIMATE_OHGAN = 4,
+ EVENT_REANIMATE_OHGAN_COOLDOWN = 5,
+ EVENT_DEVASTATING_SLAM = 6
};
-enum Misc
+enum Action
{
- MODEL_OHGAN_MOUNT = 15271,
- PATH_MANDOKIR = 492861,
- POINT_MANDOKIR_END = 24,
- CHAINED_SPIRT_COUNT = 20
+ // Bloodlord Mandokir
+ ACTION_OHGAN_IS_DEATH = 1,
+ ACTION_START_REVIVE = 2,
+
+ // Chained Spirit
+ ACTION_REVIVE = 1
};
-Position const PosSummonChainedSpirits[CHAINED_SPIRT_COUNT] =
+enum Misc
{
- { -12167.17f, -1979.330f, 133.0992f, 2.268928f },
- { -12262.74f, -1953.394f, 133.5496f, 0.593412f },
- { -12176.89f, -1983.068f, 133.7841f, 2.129302f },
- { -12226.45f, -1977.933f, 132.7982f, 1.466077f },
- { -12204.74f, -1890.431f, 135.7569f, 4.415683f },
- { -12216.70f, -1891.806f, 136.3496f, 4.677482f },
- { -12236.19f, -1892.034f, 134.1041f, 5.044002f },
- { -12248.24f, -1893.424f, 134.1182f, 5.270895f },
- { -12257.36f, -1897.663f, 133.1484f, 5.462881f },
- { -12265.84f, -1903.077f, 133.1649f, 5.654867f },
- { -12158.69f, -1972.707f, 133.8751f, 2.408554f },
- { -12178.82f, -1891.974f, 134.1786f, 3.944444f },
- { -12193.36f, -1890.039f, 135.1441f, 4.188790f },
- { -12275.59f, -1932.845f, 134.9017f, 0.174533f },
- { -12273.51f, -1941.539f, 136.1262f, 0.314159f },
- { -12247.02f, -1963.497f, 133.9476f, 0.872665f },
- { -12238.68f, -1969.574f, 133.6273f, 1.134464f },
- { -12192.78f, -1982.116f, 132.6966f, 1.919862f },
- { -12210.81f, -1979.316f, 133.8700f, 1.797689f },
- { -12283.51f, -1924.839f, 133.5170f, 0.069813f }
+ POINT_START_REVIVE = 1,
+
+ DATA_OHGANOT_SO_FAST = 5762,
+
+ FACTION_NONE = 1665
};
-Position const PosMandokir[2] =
+enum SummonGroups
{
- { -12167.8f, -1927.25f, 153.73f, 3.76991f },
- { -12197.86f, -1949.392f, 130.2745f, 0.0f }
+ SUMMON_GROUP_CHAINED_SPIRIT = 0
};
class boss_mandokir : public CreatureScript
{
- public: boss_mandokir() : CreatureScript("boss_mandokir") {}
+ public:
+
+ boss_mandokir() : CreatureScript("boss_mandokir") { }
struct boss_mandokirAI : public BossAI
{
@@ -114,115 +111,121 @@ class boss_mandokir : public CreatureScript
void Reset()
{
- if (me->GetPositionZ() > 140.0f)
- {
- _Reset();
- killCount = 0;
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
- events.ScheduleEvent(EVENT_CHECK_START, 1000);
- if (Creature* speaker = Creature::GetCreature(*me, instance->GetData64(NPC_VILEBRANCH_SPEAKER)))
- if (!speaker->isAlive())
- speaker->Respawn(true);
- }
- summons.DespawnAll();
- me->Mount(MODEL_OHGAN_MOUNT);
- }
+ DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL);
- void JustDied(Unit* /*killer*/)
- {
- // Do not want to unsummon Ohgan
- for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
- if (Creature* unsummon = Creature::GetCreature(*me, chainedSpirtGUIDs[i]))
- unsummon->DespawnOrUnsummon();
- instance->SetBossState(DATA_MANDOKIR, DONE);
- instance->SaveToDB();
+ _Reset();
+
+ me->SummonCreatureGroup(SUMMON_GROUP_CHAINED_SPIRIT);
+ _ohganotSoFast = true;
+ _reanimateOhganCooldown = false;
+ _reviveGUID = 0;
}
void EnterCombat(Unit* /*who*/)
{
_EnterCombat();
- events.ScheduleEvent(EVENT_OVERPOWER, urand(7000, 9000));
- events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
- events.ScheduleEvent(EVENT_WHIRLWIND, urand(24000, 30000));
- events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
- events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(13000, 15000));
- events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(33000, 38000));
- me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
Talk(SAY_AGGRO);
- me->Dismount();
- // Summon Ohgan (Spell missing) TEMP HACK
- me->SummonCreature(NPC_OHGAN, me->GetPositionX()-3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
- // Summon Chained Spirits
- for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
+
+ DoCastAOE(SPELL_BLOODLORD_AURA);
+
+ if (!summons.empty())
{
- Creature* chainedSpirt = me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
- chainedSpirtGUIDs[i] = chainedSpirt->GetGUID();
+ for (std::list<uint64>::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
+ {
+ if (Creature* chainedSpirit = ObjectAccessor::GetCreature(*me, *itr))
+ if (chainedSpirit->GetEntry() == NPC_CHAINED_SPIRIT && chainedSpirit->AI())
+ chainedSpirit->setFaction(FACTION_NONE);
+ }
}
- DoZoneInCombat();
+
+ events.ScheduleEvent(EVENT_DECAPITATE, 10000);
+ events.ScheduleEvent(EVENT_BLOODLETTING, 15000);
+ events.ScheduleEvent(EVENT_SUMMON_OHGAN, 20000);
+ events.ScheduleEvent(EVENT_DEVASTATING_SLAM, 25000);
}
- void KilledUnit(Unit* victim)
+ void JustDied(Unit* /*killer*/)
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
+ DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL);
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
- if (++killCount == 3)
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
{
- Talk(SAY_DING_KILL);
- if (Creature* jindo = Creature::GetCreature(*me, instance->GetData64(DATA_JINDO)))
- if (jindo->isAlive())
- jindo->AI()->Talk(SAY_GRATS_JINDO);
- DoCast(me, SPELL_LEVEL_UP, true);
- killCount = 0;
+ Talk(SAY_PLAYER_KILL);
+ DoCast(SPELL_LEVEL_UP);
+ _reviveGUID = victim->GetGUID();
+ DoAction(ACTION_START_REVIVE);
}
}
- void MovementInform(uint32 type, uint32 id)
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
{
- if (type == WAYPOINT_MOTION_TYPE)
+ if (me->HealthBelowPctDamaged(20, damage) && !me->HasAura(SPELL_FRENZY))
{
- me->SetWalk(false);
- if (id == POINT_MANDOKIR_END)
- {
- me->SetHomePosition(PosMandokir[0]);
- instance->SetBossState(DATA_MANDOKIR, NOT_STARTED);
- me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe.
- }
+ DoCast(me, SPELL_FRENZY, true);
+ Talk(SAY_FRENZY);
+ Talk(EMOTE_FRENZY);
}
}
- void UpdateAI(uint32 diff)
+ void DoAction(int32 action)
{
- events.Update(diff);
-
- if (!UpdateVictim())
+ switch (action)
{
- if (instance->GetBossState(DATA_MANDOKIR) == NOT_STARTED || instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
+ case ACTION_OHGAN_IS_DEATH:
+ events.ScheduleEvent(EVENT_REANIMATE_OHGAN, 4000);
+ _ohganotSoFast = false;
+ break;
+ case ACTION_START_REVIVE:
{
- while (uint32 eventId = events.ExecuteEvent())
+ std::list<Creature*> creatures;
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_CHAINED_SPIRIT, 200.0f);
+ creatures.remove_if(Trinity::AnyDeadUnitCheck());
+ creatures.remove_if(Trinity::UnitAuraCheck(true, SPELL_OHGAN_ORDERS_TRIGGER));
+ Trinity::Containers::RandomResizeList(creatures, 1);
+ if (creatures.empty())
+ return;
+
+ for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
{
- switch (eventId)
+ if (Creature* chainedSpirit = ObjectAccessor::GetCreature(*me, (*itr)->GetGUID()))
{
- case EVENT_CHECK_START:
- if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
- {
- me->GetMotionMaster()->MovePoint(0, PosMandokir[1].m_positionX, PosMandokir[1].m_positionY, PosMandokir[1].m_positionZ);
- events.ScheduleEvent(EVENT_STARTED, 6000);
- }
- else
- events.ScheduleEvent(EVENT_CHECK_START, 1000);
- break;
- case EVENT_STARTED:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
- me->GetMotionMaster()->MovePath(PATH_MANDOKIR, false);
- break;
- default:
- break;
+ chainedSpirit->AI()->SetGUID(_reviveGUID);
+ chainedSpirit->AI()->DoAction(ACTION_REVIVE);
+ _reviveGUID = 0;
}
}
+ break;
}
- return;
+ default:
+ break;
+
}
+ }
+
+ uint32 GetData(uint32 type) const
+ {
+ if (type == DATA_OHGANOT_SO_FAST)
+ return _ohganotSoFast;
+
+ return 0;
+ }
+
+ void SetGUID(uint64 guid, int32 /*type = 0 */)
+ {
+ _reviveGUID = guid;
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -231,39 +234,40 @@ class boss_mandokir : public CreatureScript
{
switch (eventId)
{
- case EVENT_OVERPOWER:
- DoCastVictim(SPELL_OVERPOWER, true);
- events.ScheduleEvent(EVENT_OVERPOWER, urand(6000, 12000));
- break;
- case EVENT_MORTAL_STRIKE:
- if (me->getVictim() && me->getVictim()->HealthBelowPct(50))
- DoCastVictim(SPELL_MORTAL_STRIKE, true);
- events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
+ case EVENT_SUMMON_OHGAN:
+ me->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
+ DoCast(me, SPELL_SUMMON_OHGAN, true);
break;
- case EVENT_WHIRLWIND:
- DoCast(me, SPELL_WHIRLWIND);
- events.ScheduleEvent(EVENT_WHIRLWIND, urand(22000, 26000));
+ case EVENT_DECAPITATE:
+ DoCastAOE(SPELL_DECAPITATE);
+ events.ScheduleEvent(EVENT_DECAPITATE, me->HasAura(SPELL_FRENZY) ? 17500 : 35000);
break;
- case EVENT_CHECK_OHGAN:
- if (instance->GetBossState(DATA_OHGAN) == DONE)
+ case EVENT_BLOODLETTING:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
{
- DoCast(me, SPELL_FRENZY);
- Talk(SAY_OHGAN_DEAD);
+ DoCast(target, SPELL_BLOODLETTING, true);
+ me->ClearUnitState(UNIT_STATE_CASTING);
}
- else
- events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
+ events.ScheduleEvent(EVENT_BLOODLETTING, 25000);
break;
- case EVENT_WATCH_PLAYER:
- if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ case EVENT_REANIMATE_OHGAN:
+ if (_reanimateOhganCooldown)
+ events.ScheduleEvent(EVENT_REANIMATE_OHGAN, 1000);
+ else
{
- DoCast(player, SPELL_WATCH);
- Talk(SAY_WATCH, player->GetGUID());
+ DoCastAOE(SPELL_REANIMATE_OHGAN);
+ Talk(SAY_REANIMATE_OHGAN);
+ // Cooldown
+ _reanimateOhganCooldown = true;
+ events.ScheduleEvent(EVENT_REANIMATE_OHGAN_COOLDOWN, 20000);
}
- events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 15000));
break;
- case EVENT_CHARGE_PLAYER:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_CHARGE);
- events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(22000, 30000));
+ case EVENT_REANIMATE_OHGAN_COOLDOWN:
+ _reanimateOhganCooldown = false;
+ break;
+ case EVENT_DEVASTATING_SLAM:
+ DoCastAOE(SPELL_DEVASTATING_SLAM_TRIGGER);
+ events.ScheduleEvent(EVENT_DEVASTATING_SLAM, 30000);
break;
default:
break;
@@ -274,8 +278,9 @@ class boss_mandokir : public CreatureScript
}
private:
- uint8 killCount;
- uint64 chainedSpirtGUIDs[CHAINED_SPIRT_COUNT];
+ bool _ohganotSoFast;
+ bool _reanimateOhganCooldown;
+ uint64 _reviveGUID;
};
CreatureAI* GetAI(Creature* creature) const
@@ -284,152 +289,488 @@ class boss_mandokir : public CreatureScript
}
};
-// Ohgan
-
-enum OhganSpells
+class npc_ohgan : public CreatureScript
{
- SPELL_SUNDERARMOR = 24317
+ public:
+ npc_ohgan() : CreatureScript("npc_ohgan") { }
+
+ struct npc_ohganAI : public ScriptedAI
+ {
+ npc_ohganAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ DoCastAOE(SPELL_OHGAN_ORDERS, true);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = 0;
+ me->AttackStop();
+ me->SetHealth(0);
+ me->SetTarget(0);
+ DoCast(me, SPELL_CLEAR_ALL, true);
+ DoCast(me, SPELL_PERMANENT_FEIGN_DEATH);
+
+ if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MANDOKIR)))
+ mandokir->AI()->DoAction(ACTION_OHGAN_IS_DEATH);
+ }
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (Creature* creature = victim->ToCreature())
+ {
+ if (creature->GetEntry() == NPC_CHAINED_SPIRIT)
+ DoCastAOE(SPELL_OHGAN_ORDERS, true);
+ }
+ }
+
+ void UpdateAI(uint32 /*diff*/)
+ {
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetZulGurubAI<npc_ohganAI>(creature);
+ }
};
-class mob_ohgan : public CreatureScript
+class npc_chained_spirit : public CreatureScript
{
- public: mob_ohgan() : CreatureScript("mob_ohgan") {}
+ public:
+ npc_chained_spirit() : CreatureScript("npc_chained_spirit") { }
- struct mob_ohganAI : public ScriptedAI
+ struct npc_chained_spiritAI : public ScriptedAI
{
- mob_ohganAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
+ npc_chained_spiritAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ me->AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
+ me->SetReactState(REACT_PASSIVE); // correct?
+ }
void Reset()
{
- SunderArmor_Timer = 5000;
+ _revivePlayerGUID = 0;
}
- void EnterCombat(Unit* /*who*/) {}
+ void SetGUID(uint64 guid, int32 /*type = 0 */)
+ {
+ _revivePlayerGUID = guid;
+ }
- void JustDied(Unit* /*killer*/)
+ void DoAction(int32 action)
+ {
+ if (action == ACTION_REVIVE)
+ {
+ Position pos;
+ if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
+ {
+ target->GetNearPoint(me, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 5.0f, target->GetAngle(me));
+ me->GetMotionMaster()->MovePoint(POINT_START_REVIVE, pos);
+ }
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 pointId)
{
- instance->SetBossState(DATA_OHGAN, DONE);
+ if (type != POINT_MOTION_TYPE || !_revivePlayerGUID)
+ return;
+
+ if (pointId == POINT_START_REVIVE)
+ {
+ if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
+ DoCast(target, SPELL_REVIVE);
+
+ me->DespawnOrUnsummon(2000);
+ }
}
- void UpdateAI(uint32 diff)
+ void JustDied(Unit* /*killer*/)
{
- // Return since we have no target
- if (!UpdateVictim())
+ Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID);
+ if (!target || target->isAlive())
return;
- if (SunderArmor_Timer <= diff)
+ if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MANDOKIR)))
{
- DoCastVictim(SPELL_SUNDERARMOR, true);
- SunderArmor_Timer = urand(10000, 15000);
- } else SunderArmor_Timer -= diff;
+ mandokir->GetAI()->SetGUID(target->GetGUID());
+ mandokir->GetAI()->DoAction(ACTION_START_REVIVE);
+ }
- DoMeleeAttackIfReady();
+ me->DespawnOrUnsummon();
}
+ void UpdateAI(uint32 /*diff*/) { }
+
private:
- uint32 SunderArmor_Timer;
- InstanceScript* instance;
+ InstanceScript* _instance;
+ uint64 _revivePlayerGUID;
};
CreatureAI* GetAI(Creature* creature) const
{
- return GetZulGurubAI<mob_ohganAI>(creature);
+ return GetZulGurubAI<npc_chained_spiritAI>(creature);
}
};
-enum VilebranchSpells
+class spell_mandokir_decapitate : public SpellScriptLoader
{
- SPELL_DEMORALIZING_SHOUT = 13730,
- SPELL_CLEAVE = 15284
+ public:
+ spell_mandokir_decapitate() : SpellScriptLoader("spell_mandokir_decapitate") { }
+
+ class spell_mandokir_decapitate_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mandokir_decapitate_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.empty())
+ return;
+
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Player* target = GetHitPlayer())
+ caster->CastSpell(target, uint32(GetEffectValue()), true);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_decapitate_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_decapitate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mandokir_decapitate_SpellScript();
+ }
};
-class mob_vilebranch_speaker : public CreatureScript
+class spell_mandokir_bloodletting : public SpellScriptLoader
{
- public: mob_vilebranch_speaker() : CreatureScript("mob_vilebranch_speaker") {}
+ public:
+ spell_mandokir_bloodletting() : SpellScriptLoader("spell_mandokir_bloodletting") { }
- struct mob_vilebranch_speakerAI : public ScriptedAI
+ class spell_mandokir_bloodletting_AuraScript : public AuraScript
{
- mob_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
+ PrepareAuraScript(spell_mandokir_bloodletting_AuraScript);
- void Reset()
+ bool Validate(SpellInfo const* /*spell*/)
{
- demoralizing_Shout_Timer = urand (2000, 4000);
- cleave_Timer = urand (5000, 8000);
+ if (!sSpellMgr->GetSpellInfo(SPELL_BLOODLETTING_DAMAGE))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_BLOODLETTING_HEAL))
+ return false;
+ return true;
}
- void EnterCombat(Unit* /*who*/) {}
+ void HandleEffectPeriodic(AuraEffect const* aurEff)
+ {
+ Unit* target = GetTarget();
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
- void JustDied(Unit* /*killer*/)
+ int32 damage = std::max<int32>(7500, target->CountPctFromCurHealth(aurEff->GetAmount()));
+
+ caster->CastCustomSpell(target, SPELL_BLOODLETTING_DAMAGE, &damage, 0, 0, true);
+ target->CastCustomSpell(caster, SPELL_BLOODLETTING_HEAL, &damage, 0, 0, true);
+ }
+
+ void Register()
{
- instance->SetBossState(DATA_MANDOKIR, SPECIAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_mandokir_bloodletting_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
+ };
- void UpdateAI(uint32 diff)
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mandokir_bloodletting_AuraScript();
+ }
+};
+
+class spell_mandokir_spirit_vengeance_cancel : public SpellScriptLoader
+{
+ public:
+ spell_mandokir_spirit_vengeance_cancel() : SpellScriptLoader("spell_mandokir_spirit_vengeance_cancel") { }
+
+ class spell_mandokir_spirit_vengeance_cancel_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mandokir_spirit_vengeance_cancel_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
{
- // Return since we have no target
- if (!UpdateVictim())
+ if (Player* target = GetHitPlayer())
+ target->RemoveAura(uint32(GetEffectValue()));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mandokir_spirit_vengeance_cancel_SpellScript();
+ }
+};
+
+class DevastatingSlamTargetSelector : public std::unary_function<Unit *, bool>
+{
+ public:
+ DevastatingSlamTargetSelector(Creature* me, const Unit* victim) : _me(me), _victim(victim) {}
+
+ bool operator() (WorldObject* target)
+ {
+ if (target == _victim && _me->getThreatManager().getThreatList().size() > 1)
+ return true;
+
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return true;
+
+ return false;
+ }
+
+ Creature* _me;
+ Unit const* _victim;
+};
+
+class spell_mandokir_devastating_slam : public SpellScriptLoader
+{
+ public:
+ spell_mandokir_devastating_slam() : SpellScriptLoader("spell_mandokir_devastating_slam") { }
+
+ class spell_mandokir_devastating_slam_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mandokir_devastating_slam_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(DevastatingSlamTargetSelector(GetCaster()->ToCreature(), GetCaster()->getVictim()));
+ if (targets.empty())
return;
- if (demoralizing_Shout_Timer <= diff)
- {
- DoCast(me, SPELL_DEMORALIZING_SHOUT);
- demoralizing_Shout_Timer = urand(22000, 30000);
- } else demoralizing_Shout_Timer -= diff;
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ float angle = 0.0f;
+ float x, y, z;
- if (cleave_Timer <= diff)
+ if (Player* target = GetHitPlayer())
{
- DoCastVictim(SPELL_CLEAVE, true);
- cleave_Timer = urand(6000, 9000);
- } else cleave_Timer -= diff;
+ caster->AttackStop();
+ caster->SetOrientation(caster->GetAngle(target));
+ caster->SetFacingTo(caster->GetAngle(target));
- DoMeleeAttackIfReady();
+ caster->CastSpell(caster, SPELL_DEVASTATING_SLAM, false);
+
+ // HACK: Need better way for pos calculation
+ for (uint8 i = 0; i <= 50; ++i)
+ {
+ angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
+ caster->GetClosePoint(x, y, z, 4.0f, frand(-2.5f, 50.0f), angle);
+
+ caster->CastSpell(x, y, z, SPELL_DEVASTATING_SLAM_DAMAGE, true);
+ }
+ }
}
- private:
- uint32 demoralizing_Shout_Timer;
- uint32 cleave_Timer;
- InstanceScript* instance;
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_devastating_slam_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_devastating_slam_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
+ }
};
- CreatureAI* GetAI(Creature* creature) const
+ SpellScript* GetSpellScript() const
{
- return new mob_vilebranch_speakerAI(creature);
+ return new spell_mandokir_devastating_slam_SpellScript();
}
};
-class spell_threatening_gaze : public SpellScriptLoader
+class spell_mandokir_ohgan_orders : public SpellScriptLoader
{
public:
- spell_threatening_gaze() : SpellScriptLoader("spell_threatening_gaze") { }
+ spell_mandokir_ohgan_orders() : SpellScriptLoader("spell_mandokir_ohgan_orders") { }
- class spell_threatening_gaze_AuraScript : public AuraScript
+ class spell_mandokir_ohgan_orders_SpellScript : public SpellScript
{
- PrepareAuraScript(spell_threatening_gaze_AuraScript);
+ PrepareSpellScript(spell_mandokir_ohgan_orders_SpellScript);
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void FilterTargets(std::list<WorldObject*>& targets)
{
+ if (targets.empty())
+ return;
+
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
+ caster->CastSpell(target, uint32(GetEffectValue()), true);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_ohgan_orders_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_ohgan_orders_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mandokir_ohgan_orders_SpellScript();
+ }
+};
+
+class spell_mandokir_ohgan_orders_trigger : public SpellScriptLoader
+{
+ public:
+ spell_mandokir_ohgan_orders_trigger() : SpellScriptLoader("spell_mandokir_ohgan_orders_trigger") { }
+
+ class spell_mandokir_ohgan_orders_trigger_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mandokir_ohgan_orders_trigger_AuraScript);
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
if (Unit* caster = GetCaster())
- if (Unit* target = GetTarget())
- if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
- caster->CastSpell(target, SPELL_WATCH_CHARGE);
+ {
+ // HACK: research better way
+ caster->ClearUnitState(UNIT_STATE_CASTING);
+ caster->GetMotionMaster()->Clear();
+ caster->DeleteThreatList();
+ caster->AddThreat(target, 50000000.0f);
+ caster->TauntApply(target);
+ }
}
void Register()
{
- OnEffectRemove += AuraEffectRemoveFn(spell_threatening_gaze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectApply += AuraEffectApplyFn(spell_mandokir_ohgan_orders_trigger_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
- return new spell_threatening_gaze_AuraScript();
+ return new spell_mandokir_ohgan_orders_trigger_AuraScript();
+ }
+};
+
+class spell_mandokir_reanimate_ohgan : public SpellScriptLoader
+{
+ public:
+ spell_mandokir_reanimate_ohgan() : SpellScriptLoader("spell_mandokir_reanimate_ohgan") { }
+
+ class spell_mandokir_reanimate_ohgan_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mandokir_reanimate_ohgan_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->RemoveAura(SPELL_PERMANENT_FEIGN_DEATH);
+ target->CastSpell(target, SPELL_OHGAN_HEART_VISUAL, true);
+ target->CastSpell((Unit*)NULL, SPELL_OHGAN_ORDERS, true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mandokir_reanimate_ohgan_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mandokir_reanimate_ohgan_SpellScript();
+ }
+};
+
+class spell_clear_all : public SpellScriptLoader
+{
+ public:
+ spell_clear_all() : SpellScriptLoader("spell_clear_all") { }
+
+ class spell_clear_all_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_clear_all_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ caster->RemoveAllAurasOnDeath();
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_clear_all_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_clear_all_SpellScript();
}
};
+class achievement_ohganot_so_fast : public AchievementCriteriaScript
+{
+ public:
+ achievement_ohganot_so_fast() : AchievementCriteriaScript("achievement_ohganot_so_fast") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_OHGANOT_SO_FAST);
+ }
+};
+
void AddSC_boss_mandokir()
{
new boss_mandokir();
- new mob_ohgan();
- new mob_vilebranch_speaker();
- new spell_threatening_gaze();
+ new npc_ohgan();
+ new npc_chained_spirit();
+ new spell_mandokir_decapitate();
+ new spell_mandokir_bloodletting();
+ new spell_mandokir_spirit_vengeance_cancel();
+ new spell_mandokir_devastating_slam();
+ new spell_mandokir_ohgan_orders();
+ new spell_mandokir_ohgan_orders_trigger();
+ new spell_mandokir_reanimate_ohgan();
+ new spell_clear_all();
+ new achievement_ohganot_so_fast();
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
deleted file mode 100644
index a35e18bee96..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Boss_Marli
-SD%Complete: 80
-SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers.
-SDCategory: Zul'Gurub
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "zulgurub.h"
-
-enum Says
-{
- SAY_AGGRO = 0,
- SAY_TRANSFORM = 1,
- SAY_SPIDER_SPAWN = 2,
- SAY_DEATH = 3
-};
-
-enum Spells
-{
- SPELL_CHARGE = 22911,
- SPELL_ASPECT_OF_MARLI = 24686, // A stun spell
- SPELL_ENVOLWINGWEB = 24110,
- SPELL_POISON_VOLLEY = 24099,
- SPELL_SPIDER_FORM = 24084,
- // The Spider Spell
- SPELL_LEVELUP = 24312 // Not right Spell.
-};
-
-enum Events
-{
- EVENT_SPAWN_START_SPIDERS = 1, // Phase 1
- EVENT_POISON_VOLLEY = 2, // Phase All
- EVENT_SPAWN_SPIDER = 3, // Phase All
- EVENT_CHARGE_PLAYER = 4, // Phase 3
- EVENT_ASPECT_OF_MARLI = 5, // Phase 2
- EVENT_TRANSFORM = 6, // Phase 2
- EVENT_TRANSFORM_BACK = 7 // Phase 3
-};
-
-enum Phases
-{
- PHASE_ONE = 1,
- PHASE_TWO = 2,
- PHASE_THREE = 3
-};
-
-enum ModelId
-{
- MODEL_MARLI = 15220
-};
-
-class boss_marli : public CreatureScript
-{
- public: boss_marli() : CreatureScript("boss_marli") {}
-
- struct boss_marliAI : public BossAI
- {
- boss_marliAI(Creature* creature) : BossAI(creature, DATA_MARLI) {}
-
- void Reset()
- {
- _Reset();
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_SPAWN_START_SPIDERS, 1000, 0, PHASE_ONE);
- Talk(SAY_AGGRO);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SPAWN_START_SPIDERS:
-
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- Talk(SAY_SPIDER_SPAWN);
- Creature* Spider = NULL;
- Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Spider)
- Spider->AI()->AttackStart(target);
- Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Spider)
- Spider->AI()->AttackStart(target);
- Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Spider)
- Spider->AI()->AttackStart(target);
- Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Spider)
- Spider->AI()->AttackStart(target);
- }
- events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_POISON_VOLLEY, 15000);
- events.ScheduleEvent(EVENT_SPAWN_SPIDER, 30000);
- events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO);
- events.SetPhase(PHASE_TWO);
- break;
- case EVENT_POISON_VOLLEY:
- DoCastVictim(SPELL_POISON_VOLLEY, true);
- events.ScheduleEvent(EVENT_POISON_VOLLEY, urand(10000, 20000));
- break;
- case EVENT_ASPECT_OF_MARLI:
- DoCastVictim(SPELL_ASPECT_OF_MARLI, true);
- events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, urand(13000, 18000), 0, PHASE_TWO);
- break;
- case EVENT_SPAWN_SPIDER:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- Creature* Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
- if (Spider)
- Spider->AI()->AttackStart(target);
- }
- events.ScheduleEvent(EVENT_SPAWN_SPIDER, urand(12000, 17000));
- break;
- case EVENT_TRANSFORM:
- {
- Talk(SAY_TRANSFORM);
- DoCast(me, SPELL_SPIDER_FORM);
- CreatureTemplate const* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- DoCast(me->getVictim(), SPELL_ENVOLWINGWEB);
- if (DoGetThreat(me->getVictim()))
- DoModifyThreatPercent(me->getVictim(), -100);
- events.ScheduleEvent(EVENT_CHARGE_PLAYER, 1500, 0, PHASE_THREE);
- events.ScheduleEvent(EVENT_TRANSFORM_BACK, 25000, 0, PHASE_THREE);
- events.SetPhase(PHASE_THREE);
- break;
- }
- case EVENT_CHARGE_PLAYER:
- {
- Unit* target = NULL;
- int i = 0;
- while (i++ < 3) // max 3 tries to get a random target with power_mana
- {
- target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); // not aggro leader
- if (target && target->getPowerType() == POWER_MANA)
- break;
- }
- if (target)
- {
- DoCast(target, SPELL_CHARGE);
- AttackStart(target);
- }
- events.ScheduleEvent(EVENT_CHARGE_PLAYER, 8000, 0, PHASE_THREE);
- break;
- }
- case EVENT_TRANSFORM_BACK:
- {
- me->SetDisplayId(MODEL_MARLI);
- CreatureTemplate const* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_POISON_VOLLEY, 15000);
- events.ScheduleEvent(EVENT_SPAWN_SPIDER, 30000);
- events.ScheduleEvent(EVENT_TRANSFORM, urand(35000, 60000), 0, PHASE_TWO);
- events.SetPhase(PHASE_TWO);
- break;
- }
- default:
- break;
- }
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_marliAI(creature);
- }
-};
-
-// Spawn of Marli
-class mob_spawn_of_marli : public CreatureScript
-{
- public: mob_spawn_of_marli() : CreatureScript("mob_spawn_of_marli") {}
-
- struct mob_spawn_of_marliAI : public ScriptedAI
- {
- mob_spawn_of_marliAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 LevelUp_Timer;
-
- void Reset()
- {
- LevelUp_Timer = 3000;
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- }
-
- void UpdateAI(uint32 diff)
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- //LevelUp_Timer
- if (LevelUp_Timer <= diff)
- {
- DoCast(me, SPELL_LEVELUP);
- LevelUp_Timer = 3000;
- } else LevelUp_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_spawn_of_marliAI(creature);
- }
-};
-
-void AddSC_boss_marli()
-{
- new boss_marli();
- new mob_spawn_of_marli();
-}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp
index 7e8c7dca7b4..e444f2f1c39 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp
@@ -16,66 +16,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Renataki
-SD%Complete: 100
-SDComment:
-SDCategory: Zul'Gurub
-EndScriptData */
-
+#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"
+enum Yells
+{
+};
+
enum Spells
{
- SPELL_AMBUSH = 34794,
- SPELL_THOUSANDBLADES = 34799
};
-enum Misc
+enum Events
{
- EQUIP_ID_MAIN_HAND = 0 //was item display id 31818, but this id does not exist
};
class boss_renataki : public CreatureScript
{
- public: boss_renataki() : CreatureScript("boss_renataki") {}
+ public:
+ boss_renataki() : CreatureScript("boss_renataki") { }
struct boss_renatakiAI : public BossAI
{
- boss_renatakiAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) {}
-
- uint32 Invisible_Timer;
- uint32 Ambush_Timer;
- uint32 Visible_Timer;
- uint32 Aggro_Timer;
- uint32 ThousandBlades_Timer;
-
- bool Invisible;
- bool Ambushed;
+ boss_renatakiAI(Creature* creature) : BossAI(creature, DATA_RENATAKI)
+ {
+ }
void Reset()
{
- _Reset();
- Invisible_Timer = urand(8000, 18000);
- Ambush_Timer = 3000;
- Visible_Timer = 4000;
- Aggro_Timer = urand(15000, 25000);
- ThousandBlades_Timer = urand(4000, 8000);
-
- Invisible = false;
- Ambushed = false;
}
- void JustDied(Unit* /*killer*/)
+ void EnterCombat(Unit* /*who*/)
{
- _JustDied();
}
- void EnterCombat(Unit* /*who*/)
+ void JustDied(Unit* /*killer*/)
{
- _EnterCombat();
}
void UpdateAI(uint32 diff)
@@ -83,76 +61,20 @@ class boss_renataki : public CreatureScript
if (!UpdateVictim())
return;
- //Invisible_Timer
- if (Invisible_Timer <= diff)
- {
- me->InterruptSpell(CURRENT_GENERIC_SPELL);
-
- SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
- me->SetDisplayId(11686);
-
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Invisible = true;
-
- Invisible_Timer = urand(15000, 30000);
- } else Invisible_Timer -= diff;
-
- if (Invisible)
- {
- if (Ambush_Timer <= diff)
- {
- Unit* target = NULL;
- target = SelectTarget(SELECT_TARGET_RANDOM, 0);
- if (target)
- {
- DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
- DoCast(target, SPELL_AMBUSH);
- }
-
- Ambushed = true;
- Ambush_Timer = 3000;
- } else Ambush_Timer -= diff;
- }
-
- if (Ambushed)
- {
- if (Visible_Timer <= diff)
- {
- me->InterruptSpell(CURRENT_GENERIC_SPELL);
-
- me->SetDisplayId(15268);
- SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
-
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Invisible = false;
+ events.Update(diff);
- Visible_Timer = 4000;
- } else Visible_Timer -= diff;
- }
-
- //Resetting some aggro so he attacks other gamers
- if (!Invisible)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ /*
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (Aggro_Timer <= diff)
+ switch (eventId)
{
- Unit* target = NULL;
- target = SelectTarget(SELECT_TARGET_RANDOM, 1);
-
- if (DoGetThreat(me->getVictim()))
- DoModifyThreatPercent(me->getVictim(), -50);
-
- if (target)
- AttackStart(target);
-
- Aggro_Timer = urand(7000, 20000);
- } else Aggro_Timer -= diff;
-
- if (ThousandBlades_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_THOUSANDBLADES);
- ThousandBlades_Timer = urand(7000, 12000);
- } else ThousandBlades_Timer -= diff;
+ default:
+ break;
+ }
}
+ */
DoMeleeAttackIfReady();
}
@@ -168,4 +90,3 @@ void AddSC_boss_renataki()
{
new boss_renataki();
}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
deleted file mode 100644
index 0b859b18777..00000000000
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Boss_Thekal
-SD%Complete: 95
-SDComment: Almost finished.
-SDCategory: Zul'Gurub
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "zulgurub.h"
-
-enum Says
-{
- SAY_AGGRO = 0,
- SAY_DEATH = 1
-};
-
-enum Spells
-{
- SPELL_MORTALCLEAVE = 22859, // Phase 1
- SPELL_SILENCE = 22666, // Phase 1
- SPELL_TIGER_FORM = 24169, // Phase 1
- SPELL_RESURRECT = 24173, // Phase 1 // Not used in script.
- SPELL_FRENZY = 8269, // Phase 2
- SPELL_FORCEPUNCH = 24189, // Phase 2
- SPELL_CHARGE = 24193, // Phase 2
- SPELL_ENRAGE = 8269, // Phase 2
- SPELL_SUMMONTIGERS = 24183, // Phase 2
- // Zealot Lor'Khan Spells
- SPELL_SHIELD = 20545,
- SPELL_BLOODLUST = 24185,
- SPELL_GREATERHEAL = 24208,
- SPELL_DISARM = 6713,
- // Zealot Zath Spells
- SPELL_SWEEPINGSTRIKES = 18765,
- SPELL_SINISTERSTRIKE = 15581,
- SPELL_GOUGE = 12540,
- SPELL_KICK = 15614,
- SPELL_BLIND = 21060
-};
-
-enum Events
-{
- EVENT_MORTALCLEAVE = 1, // Phase 1
- EVENT_SILENCE = 2, // Phase 1
- EVENT_CHECK_TIMER = 3, // Phase 1
- EVENT_RESURRECT_TIMER = 4, // Phase 1
- EVENT_FRENZY = 5, // Phase 2
- EVENT_FORCEPUNCH = 6, // Phase 2
- EVENT_SPELL_CHARGE = 7, // Phase 2
- EVENT_ENRAGE = 8, // Phase 2
- EVENT_SUMMONTIGERS = 9 // Phase 2
-};
-
-enum Phases
-{
- PHASE_ONE = 1,
- PHASE_TWO = 2
-};
-
-class boss_thekal : public CreatureScript
-{
- public: boss_thekal() : CreatureScript("boss_thekal") {}
-
- struct boss_thekalAI : public BossAI
- {
- boss_thekalAI(Creature* creature) : BossAI(creature, DATA_THEKAL) {}
-
- bool Enraged;
- bool WasDead;
-
- void Reset()
- {
- _Reset();
- Enraged = false;
- WasDead = false;
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- _EnterCombat();
- events.ScheduleEvent(EVENT_MORTALCLEAVE, 4000, 0, PHASE_ONE); // Phase 1
- events.ScheduleEvent(EVENT_SILENCE, 9000, 0, PHASE_ONE); // Phase 1
- events.ScheduleEvent(EVENT_CHECK_TIMER, 10000, 0, PHASE_ONE); // Phase 1
- events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10000, 0, PHASE_ONE); // Phase 1
- Talk(SAY_AGGRO);
- }
-
- void JustReachedHome()
- {
- if (instance)
- instance->SetBossState(DATA_THEKAL, NOT_STARTED);
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_MORTALCLEAVE:
- DoCastVictim(SPELL_MORTALCLEAVE, true);
- events.ScheduleEvent(EVENT_MORTALCLEAVE, urand(15000, 20000), 0, PHASE_ONE);
- break;
- case EVENT_SILENCE:
- DoCastVictim(SPELL_SILENCE, true);
- events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000), 0, PHASE_ONE);
- break;
- case EVENT_RESURRECT_TIMER:
- //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds.
- if (WasDead)
- {
- DoCast(me, SPELL_TIGER_FORM);
- me->SetObjectScale(2.00f);
- me->SetStandState(UNIT_STAND_STATE_STAND);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFullHealth();
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- DoResetThreat();
- events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO); // Phase 2
- events.ScheduleEvent(EVENT_FORCEPUNCH, 4000, 0, PHASE_TWO); // Phase 2
- events.ScheduleEvent(EVENT_SPELL_CHARGE, 12000, 0, PHASE_TWO); // Phase 2
- events.ScheduleEvent(EVENT_ENRAGE, 32000, 0, PHASE_TWO); // Phase 2
- events.ScheduleEvent(EVENT_SUMMONTIGERS, 25000, 0, PHASE_TWO); // Phase 2
- events.SetPhase(PHASE_TWO);
- }
- events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10000, 0, PHASE_ONE);
- break;
- case EVENT_CHECK_TIMER:
- //Check_Timer for the death of LorKhan and Zath.
- if (!WasDead)
- {
- if (instance)
- {
- if (instance->GetBossState(DATA_LORKHAN) == SPECIAL)
- {
- //Resurrect LorKhan
- if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN)))
- {
- pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pLorKhan->setFaction(14);
- pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pLorKhan->SetFullHealth();
- instance->SetData(DATA_LORKHAN, DONE);
- }
- }
-
- if (instance->GetBossState(DATA_ZATH) == SPECIAL)
- {
- //Resurrect Zath
- if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH)))
- {
- pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pZath->setFaction(14);
- pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pZath->SetFullHealth();
- instance->SetBossState(DATA_ZATH, DONE);
- }
- }
- }
- }
- events.ScheduleEvent(EVENT_CHECK_TIMER, 5000, 0, PHASE_ONE);
- break;
- case EVENT_FRENZY:
- DoCast(me, SPELL_FRENZY);
- events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO);
- break;
- case EVENT_FORCEPUNCH:
- DoCastVictim(SPELL_FORCEPUNCH, true);
- events.ScheduleEvent(EVENT_FORCEPUNCH, urand(16000, 21000), 0, PHASE_TWO);
- break;
- case EVENT_CHARGE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- DoCast(target, SPELL_CHARGE);
- DoResetThreat();
- AttackStart(target);
- }
- events.ScheduleEvent(EVENT_CHARGE, urand(15000, 22000), 0, PHASE_TWO);
- break;
- case EVENT_ENRAGE:
- if (HealthBelowPct(11) && !Enraged)
- {
- DoCast(me, SPELL_ENRAGE);
- Enraged = true;
- }
- events.ScheduleEvent(EVENT_ENRAGE, 30000);
- break;
- case EVENT_SUMMONTIGERS:
- DoCastVictim(SPELL_SUMMONTIGERS, true);
- events.ScheduleEvent(EVENT_SUMMONTIGERS, urand(10000, 14000), 0, PHASE_TWO);
- break;
- default:
- break;
- }
-
- if (me->IsFullHealth() && WasDead)
- WasDead = false;
-
- if ((events.IsInPhase(PHASE_ONE)) && !WasDead && !HealthAbovePct(5))
- {
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- me->AttackStop();
- if (instance)
- instance->SetBossState(DATA_THEKAL, SPECIAL);
- WasDead=true;
- }
- }
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_thekalAI(creature);
- }
-};
-
-//Zealot Lor'Khan
-class mob_zealot_lorkhan : public CreatureScript
-{
- public: mob_zealot_lorkhan() : CreatureScript("mob_zealot_lorkhan") {}
-
- struct mob_zealot_lorkhanAI : public ScriptedAI
- {
- mob_zealot_lorkhanAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- uint32 Shield_Timer;
- uint32 BloodLust_Timer;
- uint32 GreaterHeal_Timer;
- uint32 Disarm_Timer;
- uint32 Check_Timer;
-
- bool FakeDeath;
-
- InstanceScript* instance;
-
- void Reset()
- {
- Shield_Timer = 1000;
- BloodLust_Timer = 16000;
- GreaterHeal_Timer = 32000;
- Disarm_Timer = 6000;
- Check_Timer = 10000;
-
- FakeDeath = false;
-
- if (instance)
- instance->SetBossState(DATA_LORKHAN, NOT_STARTED);
-
- me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- //Shield_Timer
- if (Shield_Timer <= diff)
- {
- DoCast(me, SPELL_SHIELD);
- Shield_Timer = 61000;
- } else Shield_Timer -= diff;
-
- //BloodLust_Timer
- if (BloodLust_Timer <= diff)
- {
- DoCast(me, SPELL_BLOODLUST);
- BloodLust_Timer = 20000+rand()%8000;
- } else BloodLust_Timer -= diff;
-
- //Casting Greaterheal to Thekal or Zath if they are in meele range.
- if (GreaterHeal_Timer <= diff)
- {
- if (instance)
- {
- Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL));
- Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH));
-
- if (!pThekal || !pZath)
- return;
-
- switch (urand(0, 1))
- {
- case 0:
- if (me->IsWithinMeleeRange(pThekal))
- DoCast(pThekal, SPELL_GREATERHEAL);
- break;
- case 1:
- if (me->IsWithinMeleeRange(pZath))
- DoCast(pZath, SPELL_GREATERHEAL);
- break;
- }
- }
-
- GreaterHeal_Timer = 15000+rand()%5000;
- } else GreaterHeal_Timer -= diff;
-
- //Disarm_Timer
- if (Disarm_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_DISARM);
- Disarm_Timer = 15000+rand()%10000;
- } else Disarm_Timer -= diff;
-
- //Check_Timer for the death of LorKhan and Zath.
- if (!FakeDeath && Check_Timer <= diff)
- {
- if (instance)
- {
- if (instance->GetBossState(DATA_THEKAL) == SPECIAL)
- {
- //Resurrect Thekal
- if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL)))
- {
- pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pThekal->setFaction(14);
- pThekal->SetFullHealth();
- }
- }
-
- if (instance->GetBossState(DATA_ZATH) == SPECIAL)
- {
- //Resurrect Zath
- if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH)))
- {
- pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pZath->setFaction(14);
- pZath->SetFullHealth();
- }
- }
- }
-
- Check_Timer = 5000;
- } else Check_Timer -= diff;
-
- if (!HealthAbovePct(5))
- {
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- me->setFaction(35);
- me->AttackStop();
-
- if (instance)
- instance->SetBossState(DATA_LORKHAN, SPECIAL);
-
- FakeDeath = true;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_zealot_lorkhanAI(creature);
- }
-};
-
-//Zealot Zath
-class mob_zealot_zath : public CreatureScript
-{
- public:
-
- mob_zealot_zath()
- : CreatureScript("mob_zealot_zath")
- {
- }
-
- struct mob_zealot_zathAI : public ScriptedAI
- {
- mob_zealot_zathAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- uint32 SweepingStrikes_Timer;
- uint32 SinisterStrike_Timer;
- uint32 Gouge_Timer;
- uint32 Kick_Timer;
- uint32 Blind_Timer;
- uint32 Check_Timer;
-
- bool FakeDeath;
-
- InstanceScript* instance;
-
- void Reset()
- {
- SweepingStrikes_Timer = 13000;
- SinisterStrike_Timer = 8000;
- Gouge_Timer = 25000;
- Kick_Timer = 18000;
- Blind_Timer = 5000;
- Check_Timer = 10000;
-
- FakeDeath = false;
-
- if (instance)
- instance->SetBossState(DATA_ZATH, NOT_STARTED);
-
- me->SetStandState(UNIT_STAND_STATE_STAND);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- //SweepingStrikes_Timer
- if (SweepingStrikes_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SWEEPINGSTRIKES);
- SweepingStrikes_Timer = 22000+rand()%4000;
- } else SweepingStrikes_Timer -= diff;
-
- //SinisterStrike_Timer
- if (SinisterStrike_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SINISTERSTRIKE);
- SinisterStrike_Timer = 8000+rand()%8000;
- } else SinisterStrike_Timer -= diff;
-
- //Gouge_Timer
- if (Gouge_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_GOUGE);
-
- if (DoGetThreat(me->getVictim()))
- DoModifyThreatPercent(me->getVictim(), -100);
-
- Gouge_Timer = 17000+rand()%10000;
- } else Gouge_Timer -= diff;
-
- //Kick_Timer
- if (Kick_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_KICK);
- Kick_Timer = 15000+rand()%10000;
- } else Kick_Timer -= diff;
-
- //Blind_Timer
- if (Blind_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_BLIND);
- Blind_Timer = 10000+rand()%10000;
- } else Blind_Timer -= diff;
-
- //Check_Timer for the death of LorKhan and Zath.
- if (!FakeDeath && Check_Timer <= diff)
- {
- if (instance)
- {
- if (instance->GetBossState(DATA_LORKHAN) == SPECIAL)
- {
- //Resurrect LorKhan
- if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN)))
- {
- pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pLorKhan->setFaction(14);
- pLorKhan->SetFullHealth();
- }
- }
-
- if (instance->GetBossState(DATA_THEKAL) == SPECIAL)
- {
- //Resurrect Thekal
- if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL)))
- {
- pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- pThekal->setFaction(14);
- pThekal->SetFullHealth();
- }
- }
- }
-
- Check_Timer = 5000;
- } else Check_Timer -= diff;
-
- if (!HealthAbovePct(5))
- {
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- me->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- me->setFaction(35);
- me->AttackStop();
-
- if (instance)
- instance->SetBossState(DATA_ZATH, SPECIAL);
-
- FakeDeath = true;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_zealot_zathAI(creature);
- }
-};
-
-void AddSC_boss_thekal()
-{
- new boss_thekal();
- new mob_zealot_lorkhan();
- new mob_zealot_zath();
-}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp
index 884e5bfad10..0e8a37c43c3 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp
@@ -22,129 +22,56 @@
#include "Spell.h"
#include "zulgurub.h"
-/*
- * @todo
- * - Fix timers (research some more)
- */
-
-enum Says
+enum Yells
{
- SAY_VENOXIS_TRANSFORM = 1, // Let the coils of hate unfurl!
- SAY_VENOXIS_DEATH = 2 // Ssserenity.. at lassst!
+ SAY_AGGRO = 0,
+ SAY_BLOODVENOM = 1, // ID - 96842 Venomous Effusion
+ SAY_TRANSFROM = 2, // ID - 97354 Blessing of the Snake God
+ SAY_WORD_OF_HETHISS = 3, // ID - 96560 Word of Hethiss
+ EMOTE_BLOODVENOM = 4, // ID - 96842 Bloodvenom
+ EMOTE_VENOM_WITHDRAWAL = 5, // ID - 96653 Venom Withdrawal
+ SAY_PLAYER_KILL = 6,
+ SAY_DEATH = 7
};
enum Spells
{
- // troll form
- SPELL_THRASH = 3391,
- SPELL_DISPEL_MAGIC = 23859,
- SPELL_RENEW = 23895,
- SPELL_HOLY_NOVA = 23858,
- SPELL_HOLY_FIRE = 23860,
- SPELL_HOLY_WRATH = 23979,
- // snake form
- SPELL_POISON_CLOUD = 23861,
- SPELL_VENOM_SPIT = 23862,
-
- SPELL_PARASITIC_SERPENT = 23865,
- SPELL_SUMMON_PARASITIC_SERPENT = 23866,
- SPELL_PARASITIC_SERPENT_TRIGGER = 23867,
- // used when swapping event-stages
- SPELL_VENOXIS_TRANSFORM = 23849, // 50% health - shapechange to cobra
- SPELL_FRENZY = 8269 // 20% health - frenzy
};
enum Events
{
- // troll form
- EVENT_THRASH = 1,
- EVENT_DISPEL_MAGIC = 2,
- EVENT_RENEW = 3,
- EVENT_HOLY_NOVA = 4,
- EVENT_HOLY_FIRE = 5,
- EVENT_HOLY_WRATH = 6,
- // phase-changing
- EVENT_TRANSFORM = 7,
- // snake form events
- EVENT_POISON_CLOUD = 8,
- EVENT_VENOM_SPIT = 9,
- EVENT_PARASITIC_SERPENT = 10,
- EVENT_FRENZY = 11,
-};
-
-enum Phases
-{
- PHASE_ONE = 1, // troll form
- PHASE_TWO = 2 // snake form
-};
-
-enum NPCs
-{
- NPC_PARASITIC_SERPENT = 14884
};
class boss_venoxis : public CreatureScript
{
- public: boss_venoxis() : CreatureScript("boss_venoxis") {}
+ public:
+ boss_venoxis() : CreatureScript("boss_venoxis") { }
struct boss_venoxisAI : public BossAI
{
- boss_venoxisAI(Creature* creature) : BossAI(creature, DATA_VENOXIS) {}
+ boss_venoxisAI(Creature* creature) : BossAI(creature, DATA_VENOXIS) { }
void Reset()
{
_Reset();
- // remove all spells and auras from previous attempts
- me->RemoveAllAuras();
- me->SetReactState(REACT_PASSIVE);
- // set some internally used variables to their defaults
- _inMeleeRange = 0;
- _transformed = false;
- _frenzied = false;
- events.SetPhase(PHASE_ONE);
- }
-
- void JustDied(Unit* /*killer*/)
- {
- _JustDied();
- Talk(SAY_VENOXIS_DEATH);
- me->RemoveAllAuras();
}
void EnterCombat(Unit* /*who*/)
{
_EnterCombat();
- me->SetReactState(REACT_AGGRESSIVE);
- // Always running events
- events.ScheduleEvent(EVENT_THRASH, 5000);
- // Phase one events (regular form)
- events.ScheduleEvent(EVENT_HOLY_NOVA, 5000, 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_DISPEL_MAGIC, 35000, 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_HOLY_FIRE, 10000, 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_RENEW, 30000, 0, PHASE_ONE);
- events.ScheduleEvent(EVENT_HOLY_WRATH, 60000, 0, PHASE_ONE);
-
- events.SetPhase(PHASE_ONE);
+ Talk(SAY_AGGRO);
+ }
- // Set zone in combat
- DoZoneInCombat();
+ void JustDied(Unit* /*killer*/)
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
}
- void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/)
+ void KilledUnit(Unit* victim)
{
- // check if venoxis is ready to transform
- if (!_transformed && !HealthAbovePct(50))
- {
- _transformed = true;
- // schedule the event that changes our phase
- events.ScheduleEvent(EVENT_TRANSFORM, 100);
- }
- // we're losing health, bad, go frenzy
- else if (!_frenzied && !HealthAbovePct(20))
- {
- _frenzied = true;
- events.ScheduleEvent(EVENT_FRENZY, 100);
- }
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_PLAYER_KILL);
}
void UpdateAI(uint32 diff)
@@ -154,117 +81,26 @@ class boss_venoxis : public CreatureScript
events.Update(diff);
- // return back to main code if we're still casting
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
+ /*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
- // thrash is available in all phases
- case EVENT_THRASH:
- DoCast(me, SPELL_THRASH, true);
- events.ScheduleEvent(EVENT_THRASH, urand(10000, 20000));
- break;
-
- // troll form spells and Actions (first part)
- case EVENT_DISPEL_MAGIC:
- DoCast(me, SPELL_DISPEL_MAGIC);
- events.ScheduleEvent(EVENT_DISPEL_MAGIC, urand(15000, 20000), 0, PHASE_ONE);
- break;
- case EVENT_RENEW:
- DoCast(me, SPELL_RENEW);
- events.ScheduleEvent(EVENT_RENEW, urand(25000, 30000), 0, PHASE_ONE);
- break;
- case EVENT_HOLY_NOVA:
- _inMeleeRange = 0;
-
- for (uint8 i = 0; i < 10; ++i)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, i))
- // check if target is within melee-distance
- if (me->IsWithinMeleeRange(target))
- ++_inMeleeRange;
- }
-
- // trigger spellcast only if we have 3 or more targets to affect
- if (_inMeleeRange >= 3)
- DoCast(me->getVictim(), SPELL_HOLY_NOVA);
-
- events.ScheduleEvent(EVENT_HOLY_NOVA, urand(45000, 75000), 0, PHASE_ONE);
- break;
- case EVENT_HOLY_FIRE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_HOLY_FIRE);
- events.ScheduleEvent(EVENT_HOLY_FIRE, urand(45000, 60000), 0, PHASE_ONE);
- break;
- case EVENT_HOLY_WRATH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_HOLY_WRATH);
- events.ScheduleEvent(EVENT_HOLY_WRATH, urand(45000, 60000), 0, PHASE_ONE);
- break;
-
- //
- // snake form spells and Actions
- //
-
- case EVENT_VENOM_SPIT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_VENOM_SPIT);
- events.ScheduleEvent(EVENT_VENOM_SPIT, urand(5000, 15000), 0, PHASE_TWO);
- break;
- case EVENT_POISON_CLOUD:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_POISON_CLOUD);
- events.ScheduleEvent(EVENT_POISON_CLOUD, urand(15000, 20000), 0, PHASE_TWO);
- break;
- case EVENT_PARASITIC_SERPENT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SUMMON_PARASITIC_SERPENT);
- events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 15000, 0, PHASE_TWO);
- break;
- case EVENT_FRENZY:
- // frenzy at 20% health
- DoCast(me, SPELL_FRENZY, true);
- break;
-
- //
- // shape and phase-changing
- //
-
- case EVENT_TRANSFORM:
- // shapeshift at 50% health
- DoCast(me, SPELL_VENOXIS_TRANSFORM);
- Talk(SAY_VENOXIS_TRANSFORM);
- DoResetThreat();
-
- // phase two events (snakeform)
- events.ScheduleEvent(EVENT_VENOM_SPIT, 5000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_POISON_CLOUD, 10000, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 30000, 0, PHASE_TWO);
-
- // transformed, start phase two
- events.SetPhase(PHASE_TWO);
-
- break;
default:
break;
}
}
+ */
DoMeleeAttackIfReady();
}
-
- private:
- uint8 _inMeleeRange;
- bool _transformed;
- bool _frenzied;
};
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_venoxisAI(creature);
+ return GetZulGurubAI<boss_venoxisAI>(creature);
}
};
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp
index 6fb1c682a38..0dbfad612a8 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp
@@ -16,52 +16,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Wushoolay
-SD%Complete: 100
-SDComment:
-SDCategory: Zul'Gurub
-EndScriptData */
-
+#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"
+enum Yells
+{
+};
+
enum Spells
{
- SPELL_LIGHTNINGCLOUD = 25033,
- SPELL_LIGHTNINGWAVE = 24819
};
enum Events
{
- EVENT_LIGHTNINGCLOUD = 1,
- EVENT_LIGHTNINGWAVE = 2
};
class boss_wushoolay : public CreatureScript
{
- public: boss_wushoolay() : CreatureScript("boss_wushoolay") {}
+ public:
+ boss_wushoolay() : CreatureScript("boss_wushoolay") { }
struct boss_wushoolayAI : public BossAI
{
- boss_wushoolayAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) {}
+ boss_wushoolayAI(Creature* creature) : BossAI(creature, DATA_HAZZARAH)
+ {
+ }
void Reset()
{
- _Reset();
}
- void JustDied(Unit* /*killer*/)
+ void EnterCombat(Unit* /*who*/)
{
- _JustDied();
}
- void EnterCombat(Unit* /*who*/)
+ void JustDied(Unit* /*killer*/)
{
- _EnterCombat();
- events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, urand(5000, 10000));
- events.ScheduleEvent(EVENT_LIGHTNINGWAVE, urand(8000, 16000));
}
void UpdateAI(uint32 diff)
@@ -73,23 +65,16 @@ class boss_wushoolay : public CreatureScript
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
+ /*
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
- case EVENT_LIGHTNINGCLOUD:
- DoCastVictim(SPELL_LIGHTNINGCLOUD, true);
- events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, urand(15000, 20000));
- break;
- case EVENT_LIGHTNINGWAVE:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_LIGHTNINGWAVE);
- events.ScheduleEvent(EVENT_LIGHTNINGWAVE, urand(12000, 16000));
- break;
default:
break;
}
}
+ */
DoMeleeAttackIfReady();
}
@@ -105,4 +90,3 @@ void AddSC_boss_wushoolay()
{
new boss_wushoolay();
}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_zanzil.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_zanzil.cpp
new file mode 100644
index 00000000000..f4b8cc980d4
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_zanzil.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "zulgurub.h"
+
+enum Yells
+{
+ SAY_AGGRO = 0,
+ EMOTE_ZANZIL_ZOMBIES = 1, // ID - 96319 Zanzil's Resurrection Elixir
+ SAY_ZANZIL_ZOMBIES = 2, // ID - 96319 Zanzil's Resurrection Elixir
+ EMOTE_ZANZIL_GRAVEYARD_GAS = 3, // ID - 96338 Zanzil's Graveyard Gas
+ SAY_ZANZIL_GRAVEYARD_GAS = 4, // ID - 96338 Zanzil's Graveyard Gas
+ EMOTE_ZANZIL_BERSEKER = 5, // ID - 96316 Zanzil's Resurrection Elixir
+ SAY_ZANZIL_BERSEKER = 6, // ID - 96316 Zanzil's Resurrection Elixir
+ SAY_PLAYER_KILL = 7,
+ SAY_DEATH = 8
+};
+
+enum Spells
+{
+};
+
+enum Events
+{
+};
+
+class boss_zanzil : public CreatureScript
+{
+ public:
+ boss_zanzil() : CreatureScript("boss_zanzil") { }
+
+ struct boss_zanzilAI : public BossAI
+ {
+ boss_zanzilAI(Creature* creature) : BossAI(creature, DATA_ZANZIL) { }
+
+ void Reset()
+ {
+ _Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_PLAYER_KILL);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ /*
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ default:
+ break;
+ }
+ }
+ */
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetZulGurubAI<boss_zanzilAI>(creature);
+ }
+};
+
+void AddSC_boss_zanzil()
+{
+ new boss_zanzil();
+}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
index 01c5ef998f5..07655ea110c 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
@@ -16,67 +16,78 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Instance_ZulGurub
-SD%Complete: 80
-SDComment: Missing reset function after killing a boss for Ohgan, Thekal.
-SDCategory: Zul'Gurub
-EndScriptData */
-
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "zulgurub.h"
+DoorData const doorData[] =
+{
+ { GO_VENOXIS_COIL, DATA_VENOXIS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { GO_ARENA_DOOR_1, DATA_MANDOKIR, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { GO_FORCEFIELD, DATA_KILNARA, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { GO_ZANZIL_DOOR, DATA_ZANZIL, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ //{ GO_THE_CACHE_OF_MADNESS_DOOR, DATA_xxxxxxx, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
+};
+
class instance_zulgurub : public InstanceMapScript
{
- public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) {}
+ public:
+ instance_zulgurub() : InstanceMapScript(ZGScriptName, 859) { }
struct instance_zulgurub_InstanceMapScript : public InstanceScript
{
instance_zulgurub_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetBossNumber(EncounterCount);
- }
-
- void Initialize()
- {
- _zealotLorkhanGUID = 0;
- _zealotZathGUID = 0;
- _highPriestTekalGUID = 0;
- _jindoTheHexxerGUID = 0;
- _vilebranchSpeakerGUID = 0;
- _arlokkGUID = 0;
- _goForcefieldGUID = 0;
- _goGongOfBethekkGUID = 0;
- }
-
- bool IsEncounterInProgress() const
- {
- // not active in Zul'Gurub
- return false;
+ LoadDoorData(doorData);
+ venoxisGUID = 0;
+ mandokirGUID = 0;
+ kilnaraGUID = 0;
+ zanzilGUID = 0;
+ jindoGUID = 0;
+ hazzarahGUID = 0;
+ renatakiGUID = 0;
+ wushoolayGUID = 0;
+ grilekGUID = 0;
+ jindoTiggerGUID = 0;
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
- case NPC_ZEALOT_LORKHAN:
- _zealotLorkhanGUID = creature->GetGUID();
+ case NPC_VENOXIS:
+ venoxisGUID = creature->GetGUID();
+ break;
+ case NPC_MANDOKIR:
+ mandokirGUID = creature->GetGUID();
+ break;
+ case NPC_KILNARA:
+ kilnaraGUID = creature->GetGUID();
+ break;
+ case NPC_ZANZIL:
+ zanzilGUID = creature->GetGUID();
+ break;
+ case NPC_JINDO:
+ jindoGUID = creature->GetGUID();
break;
- case NPC_ZEALOT_ZATH:
- _zealotZathGUID = creature->GetGUID();
+ case NPC_HAZZARAH:
+ hazzarahGUID = creature->GetGUID();
break;
- case NPC_HIGH_PRIEST_THEKAL:
- _highPriestTekalGUID = creature->GetGUID();
+ case NPC_RENATAKI:
+ renatakiGUID = creature->GetGUID();
break;
- case NPC_JINDO_THE_HEXXER:
- _jindoTheHexxerGUID = creature->GetGUID();
+ case NPC_WUSHOOLAY:
+ wushoolayGUID = creature->GetGUID();
break;
- case NPC_VILEBRANCH_SPEAKER:
- _vilebranchSpeakerGUID = creature->GetGUID();
+ case NPC_GRILEK:
+ grilekGUID = creature->GetGUID();
break;
- case NPC_ARLOKK:
- _arlokkGUID = creature->GetGUID();
+ case NPC_JINDO_TRIGGER:
+ jindoTiggerGUID = creature->GetGUID();
+ break;
+ default:
break;
}
}
@@ -85,47 +96,104 @@ class instance_zulgurub : public InstanceMapScript
{
switch (go->GetEntry())
{
+ case GO_VENOXIS_COIL:
+ case GO_ARENA_DOOR_1:
case GO_FORCEFIELD:
- _goForcefieldGUID = go->GetGUID();
- break;
- case GO_GONG_OF_BETHEKK:
- _goGongOfBethekkGUID = go->GetGUID();
- if (GetBossState(DATA_ARLOKK) == DONE)
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- else
- go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ case GO_ZANZIL_DOOR:
+ case GO_THE_CACHE_OF_MADNESS_DOOR:
+ AddDoor(go, true);
break;
default:
break;
}
}
- uint64 GetData64(uint32 uiData) const
+ void OnGameObjectRemove(GameObject* go)
{
- switch (uiData)
+ switch (go->GetEntry())
{
- case DATA_LORKHAN:
- return _zealotLorkhanGUID;
- break;
- case DATA_ZATH:
- return _zealotZathGUID;
+ case GO_VENOXIS_COIL:
+ case GO_ARENA_DOOR_1:
+ case GO_FORCEFIELD:
+ case GO_ZANZIL_DOOR:
+ case GO_THE_CACHE_OF_MADNESS_DOOR:
+ AddDoor(go, false);
break;
- case DATA_THEKAL:
- return _highPriestTekalGUID;
+ default:
break;
+ }
+ }
+
+ bool SetBossState(uint32 type, EncounterState state)
+ {
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ switch (type)
+ {
+ case DATA_VENOXIS:
+ case DATA_MANDOKIR:
+ case DATA_KILNARA:
+ case DATA_ZANZIL:
case DATA_JINDO:
- return _jindoTheHexxerGUID;
+ case DATA_HAZZARAH:
+ case DATA_RENATAKI:
+ case DATA_WUSHOOLAY:
+ case DATA_GRILEK:
break;
- case NPC_ARLOKK:
- return _arlokkGUID;
- break;
- case GO_FORCEFIELD:
- return _goForcefieldGUID;
+ default:
break;
- case GO_GONG_OF_BETHEKK:
- return _goGongOfBethekkGUID;
+ }
+
+ return true;
+ }
+
+ /*
+ void SetData(uint32 type, uint32 data)
+ {
+ switch (type)
+ {
+ }
+ }
+
+ uint32 GetData(uint32 type) const
+ {
+ switch (type)
+ {
+ }
+
+ return 0;
+ }
+ */
+
+ uint64 GetData64(uint32 type) const
+ {
+ switch (type)
+ {
+ case DATA_VENOXIS:
+ return venoxisGUID;
+ case DATA_MANDOKIR:
+ return mandokirGUID;
+ case DATA_KILNARA:
+ return kilnaraGUID;
+ case DATA_ZANZIL:
+ return zanzilGUID;
+ case DATA_JINDO:
+ return jindoGUID;
+ case DATA_HAZZARAH:
+ return hazzarahGUID;
+ case DATA_RENATAKI:
+ return renatakiGUID;
+ case DATA_WUSHOOLAY:
+ return wushoolayGUID;
+ case DATA_GRILEK:
+ return grilekGUID;
+ case DATA_JINDOR_TRIGGER:
+ return jindoTiggerGUID;
+ default:
break;
}
+
return 0;
}
@@ -140,7 +208,7 @@ class instance_zulgurub : public InstanceMapScript
return saveStream.str();
}
- void Load(const char* str)
+ void Load(char const* str)
{
if (!str)
{
@@ -157,12 +225,13 @@ class instance_zulgurub : public InstanceMapScript
if (dataHead1 == 'Z' && dataHead2 == 'G')
{
- for (uint32 i = 0; i < EncounterCount; ++i)
+ for (uint8 i = 0; i < EncounterCount; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
+
SetBossState(i, EncounterState(tmpState));
}
}
@@ -171,18 +240,18 @@ class instance_zulgurub : public InstanceMapScript
OUT_LOAD_INST_DATA_COMPLETE;
}
- private:
- //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
- //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too.
-
- uint64 _zealotLorkhanGUID;
- uint64 _zealotZathGUID;
- uint64 _highPriestTekalGUID;
- uint64 _jindoTheHexxerGUID;
- uint64 _vilebranchSpeakerGUID;
- uint64 _arlokkGUID;
- uint64 _goForcefieldGUID;
- uint64 _goGongOfBethekkGUID;
+
+ protected:
+ uint64 venoxisGUID;
+ uint64 mandokirGUID;
+ uint64 kilnaraGUID;
+ uint64 zanzilGUID;
+ uint64 jindoGUID;
+ uint64 hazzarahGUID;
+ uint64 renatakiGUID;
+ uint64 wushoolayGUID;
+ uint64 grilekGUID;
+ uint64 jindoTiggerGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
index 77767153a96..90f9c98497c 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,51 +19,72 @@
#ifndef DEF_ZULGURUB_H
#define DEF_ZULGURUB_H
-uint32 const EncounterCount = 13;
-
#define ZGScriptName "instance_zulgurub"
+uint32 const EncounterCount = 5;
+
enum DataTypes
{
- DATA_JEKLIK = 0, // Main boss
- DATA_VENOXIS = 1, // Main boss
- DATA_MARLI = 2, // Main boss
- DATA_ARLOKK = 3, // Main boss
- DATA_THEKAL = 4, // Main boss
- DATA_HAKKAR = 5, // End boss
- DATA_MANDOKIR = 6, // Optional boss
- DATA_JINDO = 7, // Optional boss
- DATA_GAHZRANKA = 8, // Optional boss
- DATA_EDGE_OF_MADNESS = 9, // Optional Event Edge of Madness - one of: Gri'lek, Renataki, Hazza'rah, or Wushoolay
- DATA_LORKHAN = 10, // Zealot Lor'Khan add to High priest Thekal!
- DATA_ZATH = 11, // Zealot Zath add to High priest Thekal!
- DATA_OHGAN = 12, // Bloodlord Mandokir's raptor mount
- TYPE_EDGE_OF_MADNESS = 13 // Boss storage
+ DATA_VENOXIS = 0,
+ DATA_MANDOKIR = 1,
+ DATA_KILNARA = 2,
+ DATA_ZANZIL = 3,
+ DATA_JINDO = 4,
+
+ // Cache of Madness
+ DATA_HAZZARAH = 5,
+ DATA_RENATAKI = 6,
+ DATA_WUSHOOLAY = 7,
+ DATA_GRILEK = 8,
+
+ // Jin'do the Godbreaker
+ DATA_JINDOR_TRIGGER,
};
enum CreatureIds
{
- NPC_ARLOKK = 14515, // Arlokk Event
- NPC_PANTHER_TRIGGER = 15091, // Arlokk Event
- NPC_ZULIAN_PROWLER = 15101, // Arlokk Event
- NPC_ZEALOT_LORKHAN = 11347,
- NPC_ZEALOT_ZATH = 11348,
- NPC_HIGH_PRIEST_THEKAL = 14509,
- NPC_JINDO_THE_HEXXER = 11380,
- NPC_NIGHTMARE_ILLUSION = 15163,
- NPC_SHADE_OF_JINDO = 14986,
- NPC_SACRIFICED_TROLL = 14826,
- NPC_MANDOKIR = 11382, // Mandokir Event
- NPC_OHGAN = 14988, // Mandokir Event
- NPC_VILEBRANCH_SPEAKER = 11391, // Mandokir Event
- NPC_CHAINED_SPIRT = 15117 // Mandokir Event
+ NPC_VENOXIS = 52155,
+ NPC_MANDOKIR = 52151,
+ NPC_KILNARA = 52059,
+ NPC_ZANZIL = 52053,
+ NPC_JINDO = 52148,
+
+ // Cache of Madness
+ NPC_HAZZARAH = 52271,
+ NPC_RENATAKI = 52269,
+ NPC_WUSHOOLAY = 52286,
+ NPC_GRILEK = 52258,
+ // Bloodlord Mandokir
+ NPC_CHAINED_SPIRIT = 52156,
+ NPC_OHGAN = 52157,
+
+ // Jin'do the Godbreaker
+ NPC_JINDO_TRIGGER = 52150,
+ NPC_SPIRIT_OF_HAKKAR = 52222,
+ NPC_SHADOW_OF_HAKKAR = 52650
};
-enum GameobjectIds
+enum GameObjectIds
{
- GO_FORCEFIELD = 180497, // Arlokk Event
- GO_GONG_OF_BETHEKK = 180526 // Arlokk Event
+ // High Priest Venoxis
+ GO_VENOXIS_COIL = 208844,
+
+ // Bloodlord Mandokir
+ GO_ARENA_DOOR_1 = 208845,
+ GO_ARENA_DOOR_2 = 208847,
+ GO_ARENA_DOOR_3 = 208848,
+ GO_ARENA_DOOR_4 = 208846,
+ GO_ARENA_DOOR_5 = 208849,
+
+ // High Priestess Kilnara
+ GO_FORCEFIELD = 180497,
+
+ // Zanzil
+ GO_ZANZIL_DOOR = 208850,
+
+ // Cache of Madness
+ GO_THE_CACHE_OF_MADNESS_DOOR = 208843
};
template<class AI>
diff --git a/src/server/scripts/EasternKingdoms/boss_kruul.cpp b/src/server/scripts/EasternKingdoms/boss_kruul.cpp
deleted file mode 100644
index 997417714e8..00000000000
--- a/src/server/scripts/EasternKingdoms/boss_kruul.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Boss_Kruul
-SD%Complete: 100
-SDComment: Highlord Kruul are presumably no longer in-game on regular bases, however future events could bring him back.
-SDCategory: Bosses
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-
-enum Spells
-{
- SPELL_SHADOWVOLLEY = 21341,
- SPELL_CLEAVE = 20677,
- SPELL_THUNDERCLAP = 23931,
- SPELL_TWISTEDREFLECTION = 21063,
- SPELL_VOIDBOLT = 21066,
- SPELL_RAGE = 21340,
- SPELL_CAPTURESOUL = 21054
-};
-
-class boss_kruul : public CreatureScript
-{
-public:
- boss_kruul() : CreatureScript("boss_kruul") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new boss_kruulAI (creature);
- }
-
- struct boss_kruulAI : public ScriptedAI
- {
- boss_kruulAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 ShadowVolley_Timer;
- uint32 Cleave_Timer;
- uint32 ThunderClap_Timer;
- uint32 TwistedReflection_Timer;
- uint32 VoidBolt_Timer;
- uint32 Rage_Timer;
- uint32 Hound_Timer;
-
- void Reset()
- {
- ShadowVolley_Timer = 10000;
- Cleave_Timer = 14000;
- ThunderClap_Timer = 20000;
- TwistedReflection_Timer = 25000;
- VoidBolt_Timer = 30000;
- Rage_Timer = 60000; //Cast rage after 1 minute
- Hound_Timer = 8000;
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- }
-
- void KilledUnit(Unit* /*victim*/)
- {
- // When a player, pet or totem gets killed, Lord Kazzak casts this spell to instantly regenerate 70, 000 health.
- DoCast(me, SPELL_CAPTURESOUL);
- }
-
- void SummonHounds(Unit* victim)
- {
- if (Creature* Hound = DoSpawnCreature(19207, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
- Hound->AI()->AttackStart(victim);
- }
-
- void UpdateAI(uint32 diff)
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- //ShadowVolley_Timer
- if (ShadowVolley_Timer <= diff)
- {
- if (urand(0, 99) < 45)
- DoCast(me->getVictim(), SPELL_SHADOWVOLLEY);
-
- ShadowVolley_Timer = 5000;
- } else ShadowVolley_Timer -= diff;
-
- //Cleave_Timer
- if (Cleave_Timer <= diff)
- {
- if (urand(0, 1))
- DoCast(me->getVictim(), SPELL_CLEAVE);
-
- Cleave_Timer = 10000;
- } else Cleave_Timer -= diff;
-
- //ThunderClap_Timer
- if (ThunderClap_Timer <= diff)
- {
- if (urand(0, 9) < 2)
- DoCast(me->getVictim(), SPELL_THUNDERCLAP);
-
- ThunderClap_Timer = 12000;
- } else ThunderClap_Timer -= diff;
-
- //TwistedReflection_Timer
- if (TwistedReflection_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_TWISTEDREFLECTION);
- TwistedReflection_Timer = 30000;
- } else TwistedReflection_Timer -= diff;
-
- //VoidBolt_Timer
- if (VoidBolt_Timer <= diff)
- {
- if (urand(0, 9) < 4)
- DoCast(me->getVictim(), SPELL_VOIDBOLT);
-
- VoidBolt_Timer = 18000;
- } else VoidBolt_Timer -= diff;
-
- //Rage_Timer
- if (Rage_Timer <= diff)
- {
- DoCast(me, SPELL_RAGE);
- Rage_Timer = 70000;
- } else Rage_Timer -= diff;
-
- //Hound_Timer
- if (Hound_Timer <= diff)
- {
- SummonHounds(me->getVictim());
- SummonHounds(me->getVictim());
- SummonHounds(me->getVictim());
-
- Hound_Timer = 45000;
- } else Hound_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-void AddSC_boss_kruul()
-{
- new boss_kruul();
-}
diff --git a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
index 74344f28a9b..7465bbc3f17 100644
--- a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
@@ -49,7 +49,11 @@ enum eEnums
EMOTE_PROGRESS_8 = 8,
SAY_PROGRESS_9 = 9,
- QUEST_SUNKEN_TREASURE = 665,
+ EVENT_SAY_3 = 1,
+ EVENT_SAY_6 = 2,
+ EVENT_SAY_8 = 3,
+
+ QUEST_GOGGLE_BOGGLE = 26050,
MOB_VENGEFUL_SURGE = 2776
};
@@ -74,33 +78,22 @@ class npc_professor_phizzlethorpe : public CreatureScript
switch (waypointId)
{
- case 4:
+ case 6:
Talk(SAY_PROGRESS_2, player->GetGUID());
- break;
- case 5:
- Talk(SAY_PROGRESS_3, player->GetGUID());
+ events.ScheduleEvent(EVENT_SAY_3, 3000);
break;
case 8:
Talk(EMOTE_PROGRESS_4);
- break;
- case 9:
- me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96f, -2142.49f, 20.15f, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
- me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96f, -2142.49f, 20.15f, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
- break;
- case 10:
- Talk(SAY_PROGRESS_5, player->GetGUID());
+ me->SummonCreature(MOB_VENGEFUL_SURGE, -2065.505f, -2136.88f, 22.20362f, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ me->SummonCreature(MOB_VENGEFUL_SURGE, -2059.249f, -2134.88f, 21.51582f, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
break;
case 11:
- Talk(SAY_PROGRESS_6, player->GetGUID());
- SetRun();
+ Talk(SAY_PROGRESS_5, player->GetGUID());
+ events.ScheduleEvent(EVENT_SAY_6, 11000);
break;
- case 19:
+ case 17:
Talk(SAY_PROGRESS_7, player->GetGUID());
- break;
- case 20:
- Talk(EMOTE_PROGRESS_8);
- Talk(SAY_PROGRESS_9, player->GetGUID());
- player->GroupEventHappens(QUEST_SUNKEN_TREASURE, me);
+ events.ScheduleEvent(EVENT_SAY_8, 6000);
break;
}
}
@@ -117,8 +110,34 @@ class npc_professor_phizzlethorpe : public CreatureScript
void UpdateAI(uint32 diff)
{
+ Player* player = GetPlayerForEscort();
+ if (!player)
+ return;
+
+ events.Update(diff);
+
+ while (uint32 event = events.ExecuteEvent())
+ {
+ switch (event)
+ {
+ case EVENT_SAY_3:
+ Talk(SAY_PROGRESS_3, player->GetGUID());
+ break;
+ case EVENT_SAY_6:
+ Talk(SAY_PROGRESS_6, player->GetGUID());
+ SetRun();
+ break;
+ case EVENT_SAY_8:
+ Talk(EMOTE_PROGRESS_8);
+ Talk(SAY_PROGRESS_9, player->GetGUID());
+ player->GroupEventHappens(QUEST_GOGGLE_BOGGLE, me);
+ break;
+ }
+ }
npc_escortAI::UpdateAI(diff);
}
+
+ EventMap events;
};
CreatureAI* GetAI(Creature* creature) const
@@ -128,13 +147,13 @@ class npc_professor_phizzlethorpe : public CreatureScript
bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
{
- if (quest->GetQuestId() == QUEST_SUNKEN_TREASURE)
+ if (quest->GetQuestId() == QUEST_GOGGLE_BOGGLE)
{
creature->AI()->Talk(SAY_PROGRESS_1, player->GetGUID());
if (npc_escortAI* pEscortAI = CAST_AI(npc_professor_phizzlethorpeAI, (creature->AI())))
pEscortAI->Start(false, false, player->GetGUID(), quest);
- creature->setFaction(113);
+ creature->setFaction(42);
}
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp b/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
index 6bc316d1437..808515269ad 100644
--- a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
@@ -18,142 +18,19 @@
/* ScriptData
SDName: Burning_Steppes
-SD%Complete: 100
-SDComment: Quest support: 4224, 4866
+SD%Complete: 0
+SDComment:
SDCategory: Burning Steppes
EndScriptData */
-/* ContentData
-npc_ragged_john
-EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "Player.h"
-/*######
-## npc_ragged_john
-######*/
-
-#define GOSSIP_HELLO "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him."
-#define GOSSIP_SELECT1 "So what did you do?"
-#define GOSSIP_SELECT2 "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'."
-#define GOSSIP_SELECT3 "Ironfoe?"
-#define GOSSIP_SELECT4 "Interesting... continue John."
-#define GOSSIP_SELECT5 "So that's how Windsor died..."
-#define GOSSIP_SELECT6 "So how did he die?"
-#define GOSSIP_SELECT7 "Ok so where the hell is he? Wait a minute! Are you drunk?"
-#define GOSSIP_SELECT8 "WHY is he in Blackrock Depths?"
-#define GOSSIP_SELECT9 "300? So the Dark Irons killed him and dragged him into the Depths?"
-#define GOSSIP_SELECT10 "Ahh... Ironfoe"
-#define GOSSIP_SELECT11 "Thanks, Ragged John. Your story was very uplifting and informative"
-
-class npc_ragged_john : public CreatureScript
-{
-public:
- npc_ragged_john() : CreatureScript("npc_ragged_john") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(2714, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(2715, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->SEND_GOSSIP_MENU(2716, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->SEND_GOSSIP_MENU(2717, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- player->SEND_GOSSIP_MENU(2718, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
- player->SEND_GOSSIP_MENU(2719, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+6:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
- player->SEND_GOSSIP_MENU(2720, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+7:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
- player->SEND_GOSSIP_MENU(2721, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+8:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
- player->SEND_GOSSIP_MENU(2722, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+9:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
- player->SEND_GOSSIP_MENU(2723, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+10:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
- player->SEND_GOSSIP_MENU(2725, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+11:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(4224);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(4224) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(2713, creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_ragged_johnAI (creature);
- }
-
- struct npc_ragged_johnAI : public ScriptedAI
- {
- npc_ragged_johnAI(Creature* creature) : ScriptedAI(creature) {}
-
- void Reset() {}
-
- void MoveInLineOfSight(Unit* who)
- {
- if (who->HasAura(16468))
- {
- if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 15) && who->isInAccessiblePlaceFor(me))
- {
- DoCast(who, 16472);
- if (Player* player = who->ToPlayer())
- player->AreaExploredOrEventHappens(4866);
- }
- }
-
- ScriptedAI::MoveInLineOfSight(who);
- }
-
- void EnterCombat(Unit* /*who*/) {}
- };
-};
void AddSC_burning_steppes()
{
- new npc_ragged_john();
+
}
diff --git a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
index 858aa287c61..1a9aabcda57 100644
--- a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
@@ -19,13 +19,11 @@
/* ScriptData
SDName: Ghostlands
SD%Complete: 100
-SDComment: Quest support: 9692, 9212. Obtain Budd's Guise of Zul'aman. Vendor Rathis Tomber
+SDComment:
SDCategory: Ghostlands
EndScriptData */
/* ContentData
-npc_blood_knight_dawnstar
-npc_budd_nedreck
npc_rathis_tomber
npc_ranger_lilatha
EndContentData */
@@ -38,41 +36,6 @@ EndContentData */
#include "WorldSession.h"
/*######
-## npc_budd_nedreck
-######*/
-
-#define GOSSIP_HBN "You gave the crew disguises?"
-
-class npc_budd_nedreck : public CreatureScript
-{
-public:
- npc_budd_nedreck() : CreatureScript("npc_budd_nedreck") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->CastSpell(player, 42540, false);
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(11166) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
- return true;
- }
-};
-
-/*######
## npc_rathis_tomber
######*/
@@ -219,7 +182,6 @@ public:
void AddSC_ghostlands()
{
- new npc_budd_nedreck();
new npc_rathis_tomber();
new npc_ranger_lilatha();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
index ffd31937677..8373b20bc66 100644
--- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
@@ -19,13 +19,12 @@
/* ScriptData
SDName: Hinterlands
SD%Complete: 100
-SDComment: Quest support: 863, 2742
+SDComment: Quest support: 836
SDCategory: The Hinterlands
EndScriptData */
/* ContentData
npc_00x09hl
-npc_rinji
EndContentData */
#include "ScriptMgr.h"
@@ -147,206 +146,7 @@ public:
};
};
-/*######
-## npc_rinji
-######*/
-
-enum eRinji
-{
- SAY_RIN_BY_OUTRUNNER = 0,
-
- SAY_RIN_FREE = 0, //from here
- SAY_RIN_HELP = 1,
- SAY_RIN_COMPLETE = 2,
- SAY_RIN_PROGRESS_1 = 3,
- SAY_RIN_PROGRESS_2 = 4,
-
- QUEST_RINJI_TRAPPED = 2742,
- NPC_RANGER = 2694,
- NPC_OUTRUNNER = 2691,
- GO_RINJI_CAGE = 142036
-};
-
-struct Location
-{
- float m_fX, m_fY, m_fZ;
-};
-
-Location m_afAmbushSpawn[] =
-{
- {191.296204f, -2839.329346f, 107.388f},
- {70.972466f, -2848.674805f, 109.459f}
-};
-
-Location m_afAmbushMoveTo[] =
-{
- {166.630386f, -2824.780273f, 108.153f},
- {70.886589f, -2874.335449f, 116.675f}
-};
-
-class npc_rinji : public CreatureScript
-{
-public:
- npc_rinji() : CreatureScript("npc_rinji") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_RINJI_TRAPPED)
- {
- if (GameObject* go = creature->FindNearestGameObject(GO_RINJI_CAGE, INTERACTION_DISTANCE))
- go->UseDoorOrButton();
-
- if (npc_rinjiAI* pEscortAI = CAST_AI(npc_rinji::npc_rinjiAI, creature->AI()))
- pEscortAI->Start(false, false, player->GetGUID(), quest);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_rinjiAI(creature);
- }
-
- struct npc_rinjiAI : public npc_escortAI
- {
- npc_rinjiAI(Creature* creature) : npc_escortAI(creature)
- {
- m_bIsByOutrunner = false;
- m_iSpawnId = 0;
- }
-
- bool m_bIsByOutrunner;
- uint32 m_uiPostEventCount;
- uint32 m_uiPostEventTimer;
- int m_iSpawnId;
-
- void Reset()
- {
- m_uiPostEventCount = 0;
- m_uiPostEventTimer = 3000;
- }
-
- void JustRespawned()
- {
- m_bIsByOutrunner = false;
- m_iSpawnId = 0;
-
- npc_escortAI::JustRespawned();
- }
-
- void EnterCombat(Unit* who)
- {
- if (HasEscortState(STATE_ESCORT_ESCORTING))
- {
- if (who->GetEntry() == NPC_OUTRUNNER && !m_bIsByOutrunner)
- {
- if (Creature* talker = who->ToCreature())
- talker->AI()->Talk(SAY_RIN_BY_OUTRUNNER);
- m_bIsByOutrunner = true;
- }
-
- if (rand()%4)
- return;
-
- //only if attacked and escorter is not in combat?
- Talk(SAY_RIN_HELP);
- }
- }
-
- void DoSpawnAmbush(bool bFirst)
- {
- if (!bFirst)
- m_iSpawnId = 1;
-
- me->SummonCreature(NPC_RANGER,
- m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f,
- TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
-
- for (int i = 0; i < 2; ++i)
- {
- me->SummonCreature(NPC_OUTRUNNER,
- m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f,
- TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
- }
- }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->SetWalk(false);
- summoned->GetMotionMaster()->MovePoint(0, m_afAmbushMoveTo[m_iSpawnId].m_fX, m_afAmbushMoveTo[m_iSpawnId].m_fY, m_afAmbushMoveTo[m_iSpawnId].m_fZ);
- }
-
- void WaypointReached(uint32 waypointId)
- {
- Player* player = GetPlayerForEscort();
- if (!player)
- return;
-
- switch (waypointId)
- {
- case 1:
- Talk(SAY_RIN_FREE, player->GetGUID());
- break;
- case 7:
- DoSpawnAmbush(true);
- break;
- case 13:
- DoSpawnAmbush(false);
- break;
- case 17:
- Talk(SAY_RIN_COMPLETE, player->GetGUID());
- player->GroupEventHappens(QUEST_RINJI_TRAPPED, me);
- SetRun();
- m_uiPostEventCount = 1;
- break;
- }
- }
-
- void UpdateEscortAI(const uint32 uiDiff)
- {
- //Check if we have a current target
- if (!UpdateVictim())
- {
- if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPostEventCount)
- {
- if (m_uiPostEventTimer <= uiDiff)
- {
- m_uiPostEventTimer = 3000;
-
- if (Player* player = GetPlayerForEscort())
- {
- switch (m_uiPostEventCount)
- {
- case 1:
- Talk(SAY_RIN_PROGRESS_1, player->GetGUID());
- ++m_uiPostEventCount;
- break;
- case 2:
- Talk(SAY_RIN_PROGRESS_2, player->GetGUID());
- m_uiPostEventCount = 0;
- break;
- }
- }
- else
- {
- me->DespawnOrUnsummon();
- return;
- }
- }
- else
- m_uiPostEventTimer -= uiDiff;
- }
-
- return;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
void AddSC_hinterlands()
{
new npc_00x09hl();
- new npc_rinji();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_ironforge.cpp b/src/server/scripts/EasternKingdoms/zone_ironforge.cpp
index f9e8d4d16c6..fb5758fa5cf 100644
--- a/src/server/scripts/EasternKingdoms/zone_ironforge.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_ironforge.cpp
@@ -18,13 +18,12 @@
/* ScriptData
SDName: Ironforge
-SD%Complete: 100
-SDComment: Quest support: 3702
+SD%Complete: 0
+SDComment:
SDCategory: Ironforge
EndScriptData */
/* ContentData
-npc_royal_historian_archesonus
EndContentData */
#include "ScriptMgr.h"
@@ -32,68 +31,6 @@ EndContentData */
#include "ScriptedGossip.h"
#include "Player.h"
-/*######
-## npc_royal_historian_archesonus
-######*/
-
-#define GOSSIP_ITEM_ROYAL "I am ready to listen"
-#define GOSSIP_ITEM_ROYAL_1 "That is tragic. How did this happen?"
-#define GOSSIP_ITEM_ROYAL_2 "Interesting, continue please."
-#define GOSSIP_ITEM_ROYAL_3 "Unbelievable! How dare they??"
-#define GOSSIP_ITEM_ROYAL_4 "Of course I will help!"
-
-class npc_royal_historian_archesonus : public CreatureScript
-{
-public:
- npc_royal_historian_archesonus() : CreatureScript("npc_royal_historian_archesonus") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(2236, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(2237, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->SEND_GOSSIP_MENU(2238, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->SEND_GOSSIP_MENU(2239, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(3702);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(3702) == QUEST_STATUS_INCOMPLETE)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
- player->SEND_GOSSIP_MENU(2235, creature->GetGUID());
- }
- else
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
void AddSC_ironforge()
{
- new npc_royal_historian_archesonus();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp b/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp
index 30f12718d64..c9ad06b919c 100644
--- a/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp
@@ -18,13 +18,12 @@
/* ScriptData
SDName: Loch_Modan
-SD%Complete: 100
-SDComment: Quest support: 3181
+SD%Complete: 0
+SDComment:
SDCategory: Loch Modan
EndScriptData */
/* ContentData
-npc_mountaineer_pebblebitty
EndContentData */
#include "ScriptMgr.h"
@@ -32,75 +31,6 @@ EndContentData */
#include "ScriptedGossip.h"
#include "Player.h"
-/*######
-## npc_mountaineer_pebblebitty
-######*/
-
-#define GOSSIP_MP "Open the gate please, i need to get to Searing Gorge"
-
-#define GOSSIP_MP1 "But i need to get there, now open the gate!"
-#define GOSSIP_MP2 "Ok, so what is this other way?"
-#define GOSSIP_MP3 "Doesn't matter, i'm invulnerable."
-#define GOSSIP_MP4 "Yes..."
-#define GOSSIP_MP5 "Ok, i'll try to remember that."
-#define GOSSIP_MP6 "A key? Ok!"
-
-class npc_mountaineer_pebblebitty : public CreatureScript
-{
-public:
- npc_mountaineer_pebblebitty() : CreatureScript("npc_mountaineer_pebblebitty") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(1833, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->SEND_GOSSIP_MENU(1834, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->SEND_GOSSIP_MENU(1835, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- player->SEND_GOSSIP_MENU(1836, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
- player->SEND_GOSSIP_MENU(1837, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+6:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
- player->SEND_GOSSIP_MENU(1838, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+7:
- player->CLOSE_GOSSIP_MENU();
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (!player->GetQuestRewardStatus(3181) == 1)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
void AddSC_loch_modan()
{
- new npc_mountaineer_pebblebitty();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
index fc5ee94a55f..9f1c33e0b1e 100644
--- a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
@@ -17,8 +17,8 @@
/* Script Data Start
SDName: Redridge Mountains
-SD%Complete: 100%
-SDComment: Support for quest 219.
+SD%Complete: 0
+SDComment:
Script Data End */
#include "ScriptMgr.h"
@@ -26,148 +26,6 @@ Script Data End */
#include "ScriptedEscortAI.h"
#include "Player.h"
-enum eCorporalKeeshan
-{
- QUEST_MISSING_IN_ACTION = 219,
-
- SAY_CORPORAL_1 = 0,
- SAY_CORPORAL_2 = 1,
- SAY_CORPORAL_3 = 2,
- SAY_CORPORAL_4 = 3,
- SAY_CORPORAL_5 = 4,
-
- SPELL_MOCKING_BLOW = 21008,
- SPELL_SHIELD_BASH = 11972,
-};
-
-class npc_corporal_keeshan : public CreatureScript
-{
-public:
- npc_corporal_keeshan() : CreatureScript("npc_corporal_keeshan") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_MISSING_IN_ACTION)
- {
- CAST_AI(npc_corporal_keeshan::npc_corporal_keeshanAI, creature->AI())->Start(true, false, player->GetGUID(), quest);
- creature->AI()->Talk(SAY_CORPORAL_1);
- }
-
- return false;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_corporal_keeshanAI(creature);
- }
-
- struct npc_corporal_keeshanAI : public npc_escortAI
- {
- npc_corporal_keeshanAI(Creature* creature) : npc_escortAI(creature) {}
-
- uint32 uiPhase;
- uint32 uiTimer;
- uint32 uiMockingBlowTimer;
- uint32 uiShieldBashTimer;
-
- void Reset()
- {
- uiTimer = 0;
- uiPhase = 0;
- uiMockingBlowTimer = 5000;
- uiShieldBashTimer = 8000;
- }
-
- void WaypointReached(uint32 waypointId)
- {
- Player* player = GetPlayerForEscort();
- if (!player)
- return;
-
- if (waypointId >= 65 && me->GetUnitMovementFlags() == MOVEMENTFLAG_WALKING)
- me->SetWalk(false);
-
- switch (waypointId)
- {
- case 39:
- SetEscortPaused(true);
- uiTimer = 2000;
- uiPhase = 1;
- break;
- case 65:
- me->SetWalk(false);
- break;
- case 115:
- player->AreaExploredOrEventHappens(QUEST_MISSING_IN_ACTION);
- uiTimer = 2000;
- uiPhase = 4;
- break;
- }
- }
-
- void UpdateAI(uint32 uiDiff)
- {
- if (HasEscortState(STATE_ESCORT_NONE))
- return;
-
- npc_escortAI::UpdateAI(uiDiff);
-
- if (uiPhase)
- {
- if (uiTimer <= uiDiff)
- {
- switch (uiPhase)
- {
- case 1:
- me->SetStandState(UNIT_STAND_STATE_SIT);
- uiTimer = 1000;
- uiPhase = 2;
- break;
- case 2:
- Talk(SAY_CORPORAL_2);
- uiTimer = 15000;
- uiPhase = 3;
- break;
- case 3:
- Talk(SAY_CORPORAL_3);
- me->SetStandState(UNIT_STAND_STATE_STAND);
- SetEscortPaused(false);
- uiTimer = 0;
- uiPhase = 0;
- break;
- case 4:
- Talk(SAY_CORPORAL_4);
- uiTimer = 2500;
- uiPhase = 5;
- case 5:
- Talk(SAY_CORPORAL_5);
- uiTimer = 0;
- uiPhase = 0;
- }
- } else uiTimer -= uiDiff;
- }
-
- if (!UpdateVictim())
- return;
-
- if (uiMockingBlowTimer <= uiDiff)
- {
- DoCast(me->getVictim(), SPELL_MOCKING_BLOW);
- uiMockingBlowTimer = 5000;
- } else uiMockingBlowTimer -= uiDiff;
-
- if (uiShieldBashTimer <= uiDiff)
- {
- DoCast(me->getVictim(), SPELL_MOCKING_BLOW);
- uiShieldBashTimer = 8000;
- } else uiShieldBashTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
void AddSC_redridge_mountains()
{
- new npc_corporal_keeshan();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
index a0daf31ced9..5c7ff632c3e 100644
--- a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp
@@ -19,13 +19,12 @@
/* ScriptData
SDName: Silverpine_Forest
SD%Complete: 100
-SDComment: Quest support: 435, 452
+SDComment: Quest support: 435
SDCategory: Silverpine Forest
EndScriptData */
/* ContentData
npc_deathstalker_erland
-pyrewood_ambush
EndContentData */
#include "ScriptMgr.h"
@@ -136,192 +135,10 @@ public:
};
/*######
-## pyrewood_ambush
-#######*/
-
-#define QUEST_PYREWOOD_AMBUSH 452
-
-#define NPCSAY_INIT "Get ready, they'll be arriving any minute..." //not blizzlike
-#define NPCSAY_END "Thanks for your help!" //not blizzlike
-
-static float PyrewoodSpawnPoints[3][4] =
-{
- //pos_x pos_y pos_z orien
- //outside
- /*
- {-400.85f, 1513.64f, 18.67f, 0},
- {-397.32f, 1514.12f, 18.67f, 0},
- {-397.44f, 1511.09f, 18.67f, 0},
- */
- //door
- {-396.17f, 1505.86f, 19.77f, 0},
- {-396.91f, 1505.77f, 19.77f, 0},
- {-397.94f, 1504.74f, 19.77f, 0},
-};
-
-#define WAIT_SECS 6000
-
-class pyrewood_ambush : public CreatureScript
-{
-public:
- pyrewood_ambush() : CreatureScript("pyrewood_ambush") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest *quest)
- {
- if (quest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress)
- {
- CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress = true;
- CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->Phase = 0;
- CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->KillCount = 0;
- CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->PlayerGUID = player->GetGUID();
- }
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new pyrewood_ambushAI (creature);
- }
-
- struct pyrewood_ambushAI : public ScriptedAI
- {
- pyrewood_ambushAI(Creature* creature) : ScriptedAI(creature), Summons(me)
- {
- QuestInProgress = false;
- }
-
- uint32 Phase;
- int8 KillCount;
- uint32 WaitTimer;
- uint64 PlayerGUID;
- SummonList Summons;
-
- bool QuestInProgress;
-
- void Reset()
- {
- WaitTimer = WAIT_SECS;
-
- if (!QuestInProgress) //fix reset values (see UpdateVictim)
- {
- Phase = 0;
- KillCount = 0;
- PlayerGUID = 0;
- Summons.DespawnAll();
- }
- }
-
- void EnterCombat(Unit* /*who*/){}
-
- void JustSummoned(Creature* summoned)
- {
- Summons.Summon(summoned);
- ++KillCount;
- }
-
- void SummonedCreatureDespawn(Creature* summoned)
- {
- Summons.Despawn(summoned);
- --KillCount;
- }
-
- void SummonCreatureWithRandomTarget(uint32 creatureId, int position)
- {
- if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
- {
- Unit* target = NULL;
- if (PlayerGUID)
- if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- if (player->isAlive() && RAND(0, 1))
- target = player;
-
- if (!target)
- target = me;
-
- summoned->setFaction(168);
- summoned->AddThreat(target, 32.0f);
- summoned->AI()->AttackStart(target);
- }
- }
-
- void JustDied(Unit* /*killer*/)
- {
- if (PlayerGUID)
- if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- if (player->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE)
- player->FailQuest(QUEST_PYREWOOD_AMBUSH);
- }
-
- void UpdateAI(uint32 diff)
- {
- //TC_LOG_INFO(LOG_FILTER_TSCR, "DEBUG: p(%i) k(%i) d(%u) W(%i)", Phase, KillCount, diff, WaitTimer);
-
- if (!QuestInProgress)
- return;
-
- if (KillCount && Phase < 6)
- {
- if (!UpdateVictim()) //reset() on target Despawn...
- return;
-
- DoMeleeAttackIfReady();
- return;
- }
-
- switch (Phase)
- {
- case 0:
- if (WaitTimer == WAIT_SECS)
- me->MonsterSay(NPCSAY_INIT, LANG_UNIVERSAL, 0); //no blizzlike
-
- if (WaitTimer <= diff)
- {
- WaitTimer -= diff;
- return;
- }
- break;
- case 1:
- SummonCreatureWithRandomTarget(2060, 1);
- break;
- case 2:
- SummonCreatureWithRandomTarget(2061, 2);
- SummonCreatureWithRandomTarget(2062, 0);
- break;
- case 3:
- SummonCreatureWithRandomTarget(2063, 1);
- SummonCreatureWithRandomTarget(2064, 2);
- SummonCreatureWithRandomTarget(2065, 0);
- break;
- case 4:
- SummonCreatureWithRandomTarget(2066, 1);
- SummonCreatureWithRandomTarget(2067, 0);
- SummonCreatureWithRandomTarget(2068, 2);
- break;
- case 5: //end
- if (PlayerGUID)
- {
- if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- {
- me->MonsterSay(NPCSAY_END, LANG_UNIVERSAL, 0); //not blizzlike
- player->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me);
- }
- }
- QuestInProgress = false;
- Reset();
- break;
- }
- ++Phase; //prepare next phase
- }
- };
-};
-
-/*######
## AddSC
######*/
void AddSC_silverpine_forest()
{
new npc_deathstalker_erland();
- new pyrewood_ambush();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
index d8a2d765983..72520cf8dea 100644
--- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
@@ -16,632 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Stormwind_City
-SD%Complete: 100
-SDComment: Quest support: 1640, 1447, 4185, 11223, 434.
-SDCategory: Stormwind City
-EndScriptData */
-
-/* ContentData
-npc_archmage_malin
-npc_bartleby
-npc_lady_katrana_prestor
-npc_tyrion
-npc_tyrion_spybot
-npc_marzon_silent_blade
-npc_lord_gregor_lescovar
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "ScriptedEscortAI.h"
-#include "Player.h"
-
-/*######
-## npc_archmage_malin
-######*/
-
-#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar."
-
-class npc_archmage_malin : public CreatureScript
-{
-public:
- npc_archmage_malin() : CreatureScript("npc_archmage_malin") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->CastSpell(player, 42711, true);
- }
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
-/*######
-## npc_bartleby
-######*/
-
-enum eBartleby
-{
- FACTION_ENEMY = 168,
- QUEST_BEAT = 1640
-};
-
-class npc_bartleby : public CreatureScript
-{
-public:
- npc_bartleby() : CreatureScript("npc_bartleby") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_BEAT)
- {
- creature->setFaction(FACTION_ENEMY);
- creature->AI()->AttackStart(player);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_bartlebyAI(creature);
- }
-
- struct npc_bartlebyAI : public ScriptedAI
- {
- npc_bartlebyAI(Creature* creature) : ScriptedAI(creature)
- {
- m_uiNormalFaction = creature->getFaction();
- }
-
- uint32 m_uiNormalFaction;
-
- void Reset()
- {
- if (me->getFaction() != m_uiNormalFaction)
- me->setFaction(m_uiNormalFaction);
- }
-
- void AttackedBy(Unit* pAttacker)
- {
- if (me->getVictim())
- return;
-
- if (me->IsFriendlyTo(pAttacker))
- return;
-
- AttackStart(pAttacker);
- }
-
- void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
- {
- if (uiDamage > me->GetHealth() || me->HealthBelowPctDamaged(15, uiDamage))
- {
- //Take 0 damage
- uiDamage = 0;
-
- if (Player* player = pDoneBy->ToPlayer())
- player->AreaExploredOrEventHappens(QUEST_BEAT);
- EnterEvadeMode();
- }
- }
- };
-};
-
-/*######
-## npc_lady_katrana_prestor
-######*/
-
-#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice."
-#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor."
-#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent."
-#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor."
-
-class npc_lady_katrana_prestor : public CreatureScript
-{
-public:
- npc_lady_katrana_prestor() : CreatureScript("npc_lady_katrana_prestor") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(2694, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(2695, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->SEND_GOSSIP_MENU(2696, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(4185);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(2693, creature->GetGUID());
-
- return true;
- }
-};
-
-/*######
-## npc_lord_gregor_lescovar
-######*/
-
-enum eLordGregorLescovar
-{
- SAY_GUARD_2 = 0,
- SAY_LESCOVAR_2 = 0,
- SAY_LESCOVAR_3 = 1,
- SAY_LESCOVAR_4 = 2,
- SAY_MARZON_1 = 0,
- SAY_MARZON_2 = 1,
- SAY_TYRION_2 = 1,
-
- NPC_STORMWIND_ROYAL = 1756,
- NPC_MARZON_BLADE = 1755,
- NPC_TYRION = 7766,
-
- QUEST_THE_ATTACK = 434
-};
-
-class npc_lord_gregor_lescovar : public CreatureScript
-{
-public:
- npc_lord_gregor_lescovar() : CreatureScript("npc_lord_gregor_lescovar") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_lord_gregor_lescovarAI(creature);
- }
-
- struct npc_lord_gregor_lescovarAI : public npc_escortAI
- {
- npc_lord_gregor_lescovarAI(Creature* creature) : npc_escortAI(creature)
- {
- creature->RestoreFaction();
- }
-
- uint32 uiTimer;
- uint32 uiPhase;
-
- uint64 MarzonGUID;
-
- void Reset()
- {
- uiTimer = 0;
- uiPhase = 0;
-
- MarzonGUID = 0;
- }
-
- void EnterEvadeMode()
- {
- me->DisappearAndDie();
-
- if (Creature* pMarzon = Unit::GetCreature(*me, MarzonGUID))
- {
- if (pMarzon->isAlive())
- pMarzon->DisappearAndDie();
- }
- }
-
- void EnterCombat(Unit* who)
- {
- if (Creature* pMarzon = Unit::GetCreature(*me, MarzonGUID))
- {
- if (pMarzon->isAlive() && !pMarzon->isInCombat())
- pMarzon->AI()->AttackStart(who);
- }
- }
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 14:
- SetEscortPaused(true);
- Talk(SAY_LESCOVAR_2);
- uiTimer = 3000;
- uiPhase = 1;
- break;
- case 16:
- SetEscortPaused(true);
- if (Creature* pMarzon = me->SummonCreature(NPC_MARZON_BLADE, -8411.360352f, 480.069733f, 123.760895f, 4.941504f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000))
- {
- pMarzon->GetMotionMaster()->MovePoint(0, -8408.000977f, 468.611450f, 123.759903f);
- MarzonGUID = pMarzon->GetGUID();
- }
- uiTimer = 2000;
- uiPhase = 4;
- break;
- }
- }
- //TO-DO: We don't have movemaps, also we can't make 2 npcs walks to one point propperly (and we can not use escort ai, because they are 2 different spawns and with same entry), because of it we make them, disappear.
- void DoGuardsDisappearAndDie()
- {
- std::list<Creature*> GuardList;
- me->GetCreatureListWithEntryInGrid(GuardList, NPC_STORMWIND_ROYAL, 8.0f);
- if (!GuardList.empty())
- {
- for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
- {
- if (Creature* pGuard = *itr)
- pGuard->DisappearAndDie();
- }
- }
- }
-
- void UpdateAI(uint32 uiDiff)
- {
- if (uiPhase)
- {
- if (uiTimer <= uiDiff)
- {
- switch (uiPhase)
- {
- case 1:
- if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 8.0f, true))
- pGuard->AI()->Talk(SAY_GUARD_2);
- uiTimer = 3000;
- uiPhase = 2;
- break;
- case 2:
- DoGuardsDisappearAndDie();
- uiTimer = 2000;
- uiPhase = 3;
- break;
- case 3:
- SetEscortPaused(false);
- uiTimer = 0;
- uiPhase = 0;
- break;
- case 4:
- Talk(SAY_LESCOVAR_3);
- uiTimer = 0;
- uiPhase = 0;
- break;
- case 5:
- if (Creature* pMarzon = Unit::GetCreature(*me, MarzonGUID))
- pMarzon->AI()->Talk(SAY_MARZON_1);
- uiTimer = 3000;
- uiPhase = 6;
- break;
- case 6:
- Talk(SAY_LESCOVAR_4);
- if (Player* player = GetPlayerForEscort())
- player->AreaExploredOrEventHappens(QUEST_THE_ATTACK);
- uiTimer = 2000;
- uiPhase = 7;
- break;
- case 7:
- if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION, 20.0f, true))
- pTyrion->AI()->Talk(SAY_TYRION_2);
- if (Creature* pMarzon = Unit::GetCreature(*me, MarzonGUID))
- pMarzon->setFaction(14);
- me->setFaction(14);
- uiTimer = 0;
- uiPhase = 0;
- break;
- }
- } else uiTimer -= uiDiff;
- }
- npc_escortAI::UpdateAI(uiDiff);
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
-## npc_marzon_silent_blade
-######*/
-
-class npc_marzon_silent_blade : public CreatureScript
-{
-public:
- npc_marzon_silent_blade() : CreatureScript("npc_marzon_silent_blade") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_marzon_silent_bladeAI(creature);
- }
-
- struct npc_marzon_silent_bladeAI : public ScriptedAI
- {
- npc_marzon_silent_bladeAI(Creature* creature) : ScriptedAI(creature)
- {
- me->SetWalk(true);
- }
-
- void Reset()
- {
- me->RestoreFaction();
- }
-
- void EnterCombat(Unit* who)
- {
- Talk(SAY_MARZON_2);
-
- if (me->isSummon())
- {
- if (Unit* summoner = me->ToTempSummon()->GetSummoner())
- {
- if (summoner->GetTypeId() == TYPEID_UNIT && summoner->isAlive() && !summoner->isInCombat())
- summoner->ToCreature()->AI()->AttackStart(who);
- }
- }
- }
-
- void EnterEvadeMode()
- {
- me->DisappearAndDie();
-
- if (me->isSummon())
- {
- if (Unit* summoner = me->ToTempSummon()->GetSummoner())
- {
- if (summoner->GetTypeId() == TYPEID_UNIT && summoner->isAlive())
- summoner->ToCreature()->DisappearAndDie();
- }
- }
- }
-
- void MovementInform(uint32 uiType, uint32 /*uiId*/)
- {
- if (uiType != POINT_MOTION_TYPE)
- return;
-
- if (me->isSummon())
- {
- Unit* summoner = me->ToTempSummon()->GetSummoner();
- if (summoner && summoner->GetTypeId() == TYPEID_UNIT && summoner->IsAIEnabled)
- {
- npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI* ai =
- CAST_AI(npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI, summoner->GetAI());
- if (ai)
- {
- ai->uiTimer = 2000;
- ai->uiPhase = 5;
- }
- //me->ChangeOrient(0.0f, summoner);
- }
- }
- }
-
- void UpdateAI(uint32 /*diff*/)
- {
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
-## npc_tyrion_spybot
-######*/
-
-enum eTyrionSpybot
-{
- SAY_QUEST_ACCEPT_ATTACK = 0,
- SAY_SPYBOT_1 = 1,
- SAY_SPYBOT_2 = 2,
- SAY_SPYBOT_3 = 3,
- SAY_SPYBOT_4 = 4,
- SAY_TYRION_1 = 0,
- SAY_GUARD_1 = 1,
- SAY_LESCOVAR_1 = 3,
-
- NPC_PRIESTESS_TYRIONA = 7779,
- NPC_LORD_GREGOR_LESCOVAR = 1754,
-};
-
-class npc_tyrion_spybot : public CreatureScript
-{
-public:
- npc_tyrion_spybot() : CreatureScript("npc_tyrion_spybot") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_tyrion_spybotAI(creature);
- }
-
- struct npc_tyrion_spybotAI : public npc_escortAI
- {
- npc_tyrion_spybotAI(Creature* creature) : npc_escortAI(creature) {}
-
- uint32 uiTimer;
- uint32 uiPhase;
-
- void Reset()
- {
- uiTimer = 0;
- uiPhase = 0;
- }
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 1:
- SetEscortPaused(true);
- uiTimer = 2000;
- uiPhase = 1;
- break;
- case 5:
- SetEscortPaused(true);
- Talk(SAY_SPYBOT_1);
- uiTimer = 2000;
- uiPhase = 5;
- break;
- case 17:
- SetEscortPaused(true);
- Talk(SAY_SPYBOT_3);
- uiTimer = 3000;
- uiPhase = 8;
- break;
- }
- }
-
- void UpdateAI(uint32 uiDiff)
- {
- if (uiPhase)
- {
- if (uiTimer <= uiDiff)
- {
- switch (uiPhase)
- {
- case 1:
- Talk(SAY_QUEST_ACCEPT_ATTACK);
- uiTimer = 3000;
- uiPhase = 2;
- break;
- case 2:
- if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION, 10.0f))
- pTyrion->AI()->Talk(SAY_TYRION_1);
- uiTimer = 3000;
- uiPhase = 3;
- break;
- case 3:
- me->UpdateEntry(NPC_PRIESTESS_TYRIONA, ALLIANCE);
- uiTimer = 2000;
- uiPhase = 4;
- break;
- case 4:
- SetEscortPaused(false);
- uiPhase = 0;
- uiTimer = 0;
- break;
- case 5:
- if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 10.0f, true))
- pGuard->AI()->Talk(SAY_GUARD_1);
- uiTimer = 3000;
- uiPhase = 6;
- break;
- case 6:
- Talk(SAY_SPYBOT_2);
- uiTimer = 3000;
- uiPhase = 7;
- break;
- case 7:
- SetEscortPaused(false);
- uiTimer = 0;
- uiPhase = 0;
- break;
- case 8:
- if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR, 10.0f))
- pLescovar->AI()->Talk(SAY_LESCOVAR_1);
- uiTimer = 3000;
- uiPhase = 9;
- break;
- case 9:
- Talk(SAY_SPYBOT_4);
- uiTimer = 3000;
- uiPhase = 10;
- break;
- case 10:
- if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR, 10.0f))
- {
- if (Player* player = GetPlayerForEscort())
- {
- CAST_AI(npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI, pLescovar->AI())->Start(false, false, player->GetGUID());
- CAST_AI(npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI, pLescovar->AI())->SetMaxPlayerDistance(200.0f);
- }
- }
- me->DisappearAndDie();
- uiTimer = 0;
- uiPhase = 0;
- break;
- }
- } else uiTimer -= uiDiff;
- }
- npc_escortAI::UpdateAI(uiDiff);
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
-## npc_tyrion
-######*/
-
-enum eTyrion
-{
- NPC_TYRION_SPYBOT = 8856
-};
-
-class npc_tyrion : public CreatureScript
-{
-public:
- npc_tyrion() : CreatureScript("npc_tyrion") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_THE_ATTACK)
- {
- if (Creature* pSpybot = creature->FindNearestCreature(NPC_TYRION_SPYBOT, 5.0f, true))
- {
- CAST_AI(npc_tyrion_spybot::npc_tyrion_spybotAI, pSpybot->AI())->Start(false, false, player->GetGUID());
- CAST_AI(npc_tyrion_spybot::npc_tyrion_spybotAI, pSpybot->AI())->SetMaxPlayerDistance(200.0f);
- }
- return true;
- }
- return false;
- }
-};
-
void AddSC_stormwind_city()
{
- new npc_archmage_malin();
- new npc_bartleby();
- new npc_lady_katrana_prestor();
- new npc_tyrion();
- new npc_tyrion_spybot();
- new npc_lord_gregor_lescovar();
- new npc_marzon_silent_blade();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
index c7780bb0065..110cead529e 100644
--- a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
@@ -16,140 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedEscortAI.h"
-#include "Player.h"
-
-/*######
-## npc_galen_goodward
-######*/
-
-enum Galen
-{
- QUEST_GALENS_ESCAPE = 1393,
-
- GO_GALENS_CAGE = 37118,
-
- SAY_PERIODIC = 0,
- SAY_QUEST_ACCEPTED = 1,
- SAY_ATTACKED = 2,
- SAY_QUEST_COMPLETE = 3,
- EMOTE_WHISPER = 4,
- EMOTE_DISAPPEAR = 5,
-};
-
-class npc_galen_goodward : public CreatureScript
-{
-public:
-
- npc_galen_goodward() : CreatureScript("npc_galen_goodward") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_GALENS_ESCAPE)
- {
- CAST_AI(npc_galen_goodward::npc_galen_goodwardAI, creature->AI())->Start(false, false, player->GetGUID());
- creature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
- creature->AI()->Talk(SAY_QUEST_ACCEPTED);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_galen_goodwardAI(creature);
- }
-
- struct npc_galen_goodwardAI : public npc_escortAI
- {
- npc_galen_goodwardAI(Creature* creature) : npc_escortAI(creature)
- {
- m_uiGalensCageGUID = 0;
- Reset();
- }
-
- uint64 m_uiGalensCageGUID;
- uint32 m_uiPeriodicSay;
-
- void Reset()
- {
- m_uiPeriodicSay = 6000;
- }
-
- void EnterCombat(Unit* who)
- {
- if (HasEscortState(STATE_ESCORT_ESCORTING))
- Talk(SAY_ATTACKED, who->GetGUID());
- }
-
- void WaypointStart(uint32 uiPointId)
- {
- switch (uiPointId)
- {
- case 0:
- {
- GameObject* pCage = NULL;
- if (m_uiGalensCageGUID)
- pCage = me->GetMap()->GetGameObject(m_uiGalensCageGUID);
- else
- pCage = GetClosestGameObjectWithEntry(me, GO_GALENS_CAGE, INTERACTION_DISTANCE);
- if (pCage)
- {
- pCage->UseDoorOrButton();
- m_uiGalensCageGUID = pCage->GetGUID();
- }
- break;
- }
- case 21:
- Talk(EMOTE_DISAPPEAR);
- break;
- }
- }
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 0:
- if (GameObject* pCage = me->GetMap()->GetGameObject(m_uiGalensCageGUID))
- pCage->ResetDoorOrButton();
- break;
- case 20:
- if (Player* player = GetPlayerForEscort())
- {
- me->SetFacingToObject(player);
- Talk(SAY_QUEST_COMPLETE, player->GetGUID());
- Talk(EMOTE_WHISPER, player->GetGUID());
- player->GroupEventHappens(QUEST_GALENS_ESCAPE, me);
- }
- SetRun(true);
- break;
- }
- }
-
- void UpdateAI(uint32 uiDiff)
- {
- npc_escortAI::UpdateAI(uiDiff);
-
- if (HasEscortState(STATE_ESCORT_NONE))
- return;
-
- if (m_uiPeriodicSay < uiDiff)
- {
- if (!HasEscortState(STATE_ESCORT_ESCORTING))
- Talk(SAY_PERIODIC);
- m_uiPeriodicSay = 15000;
- }
- else
- m_uiPeriodicSay -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
void AddSC_swamp_of_sorrows()
{
- new npc_galen_goodward();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
index 9a496fadb1e..903c88ad89a 100644
--- a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp
@@ -16,202 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Tirisfal_Glades
-SD%Complete: 100
-SDComment: Quest support: 590, 1819
-SDCategory: Tirisfal Glades
-EndScriptData */
-
-/* ContentData
-npc_calvin_montague
-go_mausoleum_door
-go_mausoleum_trigger
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "Player.h"
-
-/*######
-## npc_calvin_montague
-######*/
-
-enum Calvin
-{
- SAY_COMPLETE = 0,
- SPELL_DRINK = 2639, // possibly not correct spell (but iconId is correct)
- QUEST_590 = 590,
- FACTION_HOSTILE = 168
-};
-
-class npc_calvin_montague : public CreatureScript
-{
-public:
- npc_calvin_montague() : CreatureScript("npc_calvin_montague") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_590)
- {
- creature->setFaction(FACTION_HOSTILE);
- creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- CAST_AI(npc_calvin_montague::npc_calvin_montagueAI, creature->AI())->AttackStart(player);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_calvin_montagueAI (creature);
- }
-
- struct npc_calvin_montagueAI : public ScriptedAI
- {
- npc_calvin_montagueAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 m_uiPhase;
- uint32 m_uiPhaseTimer;
- uint64 m_uiPlayerGUID;
-
- void Reset()
- {
- m_uiPhase = 0;
- m_uiPhaseTimer = 5000;
- m_uiPlayerGUID = 0;
-
- me->RestoreFaction();
-
- if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- }
-
- void EnterCombat(Unit* /*who*/) {}
-
- void AttackedBy(Unit* pAttacker)
- {
- if (me->getVictim() || me->IsFriendlyTo(pAttacker))
- return;
-
- AttackStart(pAttacker);
- }
-
- void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
- {
- if (uiDamage > me->GetHealth() || me->HealthBelowPctDamaged(15, uiDamage))
- {
- uiDamage = 0;
-
- me->RestoreFaction();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- me->CombatStop(true);
-
- m_uiPhase = 1;
-
- if (pDoneBy->GetTypeId() == TYPEID_PLAYER)
- m_uiPlayerGUID = pDoneBy->GetGUID();
- }
- }
-
- void UpdateAI(uint32 diff)
- {
- if (m_uiPhase)
- {
- if (m_uiPhaseTimer <= diff)
- m_uiPhaseTimer = 7500;
- else
- {
- m_uiPhaseTimer -= diff;
- return;
- }
-
- switch (m_uiPhase)
- {
- case 1:
- Talk(SAY_COMPLETE);
- ++m_uiPhase;
- break;
- case 2:
- if (Player* player = Unit::GetPlayer(*me, m_uiPlayerGUID))
- player->AreaExploredOrEventHappens(QUEST_590);
-
- DoCast(me, SPELL_DRINK, true);
- ++m_uiPhase;
- break;
- case 3:
- EnterEvadeMode();
- break;
- }
-
- return;
- }
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
-## go_mausoleum_door
-## go_mausoleum_trigger
-######*/
-
-enum eMausoleum
-{
- QUEST_ULAG = 1819,
- NPC_ULAG = 6390,
- GO_TRIGGER = 104593,
- GO_DOOR = 176594
-};
-
-class go_mausoleum_door : public GameObjectScript
-{
-public:
- go_mausoleum_door() : GameObjectScript("go_mausoleum_door") { }
-
- bool OnGossipHello(Player* player, GameObject* /*go*/)
- {
- if (player->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE)
- return false;
-
- if (GameObject* pTrigger = player->FindNearestGameObject(GO_TRIGGER, 30.0f))
- {
- pTrigger->SetGoState(GO_STATE_READY);
- player->SummonCreature(NPC_ULAG, 2390.26f, 336.47f, 40.01f, 2.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
- return false;
- }
-
- return false;
- }
-};
-
-class go_mausoleum_trigger : public GameObjectScript
-{
-public:
- go_mausoleum_trigger() : GameObjectScript("go_mausoleum_trigger") { }
-
- bool OnGossipHello(Player* player, GameObject* go)
- {
- if (player->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE)
- return false;
-
- if (GameObject* pDoor = player->FindNearestGameObject(GO_DOOR, 30.0f))
- {
- go->SetGoState(GO_STATE_ACTIVE);
- pDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- return true;
- }
-
- return false;
- }
-};
-
void AddSC_tirisfal_glades()
{
- new npc_calvin_montague();
- new go_mausoleum_door();
- new go_mausoleum_trigger();
}
diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
index 0f52daba991..f4f7dc6a23e 100644
--- a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
+++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp
@@ -242,8 +242,7 @@ public:
{
case 4:
SetEscortPaused(true);
- me->SetOrientation(1.775791f);
- me->SendMovementFlagUpdate();
+ me->SetFacingTo(1.775791f);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Talk(SAY_MORRIDUNE_2);
break;
diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt
index 536824e7a63..6f145d3e9a4 100644
--- a/src/server/scripts/Kalimdor/CMakeLists.txt
+++ b/src/server/scripts/Kalimdor/CMakeLists.txt
@@ -111,6 +111,14 @@ set(scripts_STAT_SRCS
Kalimdor/OnyxiasLair/boss_onyxia.cpp
Kalimdor/OnyxiasLair/onyxias_lair.h
Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp
+ Kalimdor/HallsOfOrigination/halls_of_origination.h
+ Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp
+ Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp
+ Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp
+ Kalimdor/HallsOfOrigination/boss_anraphet.cpp
+ Kalimdor/Firelands/instance_firelands.cpp
+ Kalimdor/Firelands/firelands.h
+ Kalimdor/Firelands/boss_alysrazor.cpp
)
message(" -> Prepared: Kalimdor")
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp
index fb2c1b3e47d..002ddda549d 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp
@@ -30,6 +30,7 @@ EndScriptData */
#include "Player.h"
#include "WorldPacket.h"
#include "Opcodes.h"
+#include "WorldSession.h"
enum Misc
{
@@ -221,7 +222,8 @@ public:
i->getSource()->GetSession()->SendPacket(&packet);
WorldPacket data2(SMSG_PLAY_SOUND, 4);
- data2 << 10986;
+ data2 << uint32(10986);
+ data2 << uint64(unit->GetGUID());
i->getSource()->GetSession()->SendPacket(&data2);
}
}
diff --git a/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp
new file mode 100644
index 00000000000..f9e736afd6f
--- /dev/null
+++ b/src/server/scripts/Kalimdor/Firelands/boss_alysrazor.cpp
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "PassiveAI.h"
+#include "SpellScript.h"
+#include "MoveSplineInit.h"
+#include "Cell.h"
+#include "CellImpl.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "firelands.h"
+
+enum Texts
+{
+ // Egg Pile
+ EMOTE_CRACKING_EGGS = 0, // The Molten Eggs begin to crack and splinter!
+};
+
+enum Spells
+{
+ // Harbinger of Flame
+ SPELL_FIRE_IT_UP = 100093,
+ SPELL_FIEROBLAST_TRASH = 100094,
+ SPELL_FIEROCLAST_BARRAGE = 100095,
+ SPELL_FIRE_CHANNELING = 100109,
+
+ // Blazing Monstrosity
+ SPELL_RIDE_MONSTROSITY = 93970,
+ SPELL_SHARE_HEALTH_LEFT = 101502,
+ SPELL_SHARE_HEALTH_RIGHT = 101503,
+ SPELL_SLEEP_ULTRA_HIGH_PRIORITY = 99480,
+ SPELL_GENERIC_DUMMY_CAST = 100088,
+ SPELL_LEFT_SIDE_SMACK_L = 100076,
+ SPELL_RIGHT_SIDE_SMACK_L = 100078,
+ SPELL_HEAD_BONK_L = 100080,
+ SPELL_TICKLE_L = 100082,
+ SPELL_KNOCKBACK_RIGHT = 100084,
+ SPELL_KNOCKBACK_LEFT = 100085,
+ SPELL_KNOCKBACK_FORWARD = 100086,
+ SPELL_KNOCKBACK_BACK = 100087,
+ SPELL_HEAD_BONK_R = 100089,
+ SPELL_LEFT_SIDE_SMACK_R = 100090,
+ SPELL_RIGHT_SIDE_SMACK_R = 100091,
+ SPELL_TICKLE_R = 100092,
+ SPELL_MOLTEN_BARRAGE_EFFECT_L = 100071,
+ SPELL_MOLTEN_BARRAGE_LEFT = 100072,
+ SPELL_MOLTEN_BARRAGE_RIGHT = 100073,
+ SPELL_MOLTEN_BARRAGE_EFFECT_R = 100074,
+ SPELL_MOLTEN_BARRAGE_VISUAL = 100075,
+ SPELL_AGGRO_CLOSEST = 100462,
+ SPELL_INVISIBILITY_AND_STEALTH_DETECTION = 18950,
+
+ // Egg Pile
+ SPELL_SUMMON_SMOULDERING_HATCHLING = 100096,
+ SPELL_MOLTEN_EGG_TRASH_CALL_L = 100097,
+ SPELL_MOLTEN_EGG_TRASH_CALL_R = 100098,
+ SPELL_ALYSRAZOR_COSMETIC_EGG_XPLOSION = 100099,
+};
+
+#define SPELL_SHARE_HEALTH (me->GetEntry() == NPC_BLAZING_MONSTROSITY_LEFT ? SPELL_SHARE_HEALTH_LEFT : SPELL_SHARE_HEALTH_RIGHT)
+#define SPELL_MOLTEN_BARRAGE (me->GetEntry() == NPC_BLAZING_MONSTROSITY_LEFT ? SPELL_MOLTEN_BARRAGE_LEFT : SPELL_MOLTEN_BARRAGE_RIGHT)
+#define SPELL_MOLTEN_BARRAGE_EFFECT (me->GetEntry() == NPC_BLAZING_MONSTROSITY_LEFT ? SPELL_MOLTEN_BARRAGE_EFFECT_L : SPELL_MOLTEN_BARRAGE_EFFECT_R)
+
+enum Events
+{
+ // Blazing Monstrosity
+ EVENT_START_SPITTING = 1,
+ EVENT_CONTINUE_SPITTING = 2,
+
+ // Harbinger of Flame
+ EVENT_FIEROBLAST = 1,
+ EVENT_FIEROCLAST_BARRAGE = 2,
+
+ // Egg Pile
+ EVENT_SUMMON_SMOULDERING_HATCHLING = 1,
+};
+
+enum MiscData
+{
+ MODEL_INVISIBLE_STALKER = 11686,
+ ANIM_KIT_BIRD_WAKE = 1469,
+ ANIM_KIT_BIRD_TURN = 1473,
+};
+
+class RespawnEggEvent : public BasicEvent
+{
+ public:
+ explicit RespawnEggEvent(Creature* egg) : _egg(egg) { }
+
+ bool Execute(uint64 /*time*/, uint32 /*diff*/)
+ {
+ _egg->RestoreDisplayId();
+ return true;
+ }
+
+ private:
+ Creature* _egg;
+};
+
+class MoltenEggCheck
+{
+ public:
+ explicit MoltenEggCheck(Creature* pile) : _eggPile(pile) { }
+
+ bool operator()(Unit* object) const
+ {
+ if (object->GetEntry() != NPC_MOLTEN_EGG_TRASH)
+ return false;
+
+ if (object->GetDisplayId() != object->GetNativeDisplayId())
+ return false;
+
+ if (_eggPile->GetDistance2d(object) > 20.0f)
+ return false;
+
+ return true;
+ }
+
+ private:
+ Creature* _eggPile;
+};
+
+class TrashRespawnWorker
+{
+ public:
+ void operator()(Creature* creature) const
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_BLAZING_MONSTROSITY_LEFT:
+ case NPC_BLAZING_MONSTROSITY_RIGHT:
+ case NPC_EGG_PILE:
+ case NPC_HARBINGER_OF_FLAME:
+ case NPC_MOLTEN_EGG_TRASH:
+ if (!creature->isAlive())
+ creature->Respawn(true);
+ break;
+ case NPC_SMOULDERING_HATCHLING:
+ creature->DespawnOrUnsummon();
+ break;
+ }
+ }
+};
+
+static void AlysrazorTrashEvaded(Creature* creature)
+{
+ TrashRespawnWorker check;
+ Trinity::CreatureWorker<TrashRespawnWorker> worker(creature, check);
+ creature->VisitNearbyGridObject(SIZE_OF_GRIDS, worker);
+}
+
+class npc_harbinger_of_flame : public CreatureScript
+{
+ public:
+ npc_harbinger_of_flame() : CreatureScript("npc_harbinger_of_flame") { }
+
+ struct npc_harbinger_of_flameAI : public ScriptedAI
+ {
+ npc_harbinger_of_flameAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void EnterCombat(Unit* /*target*/)
+ {
+ if (Creature* bird = ObjectAccessor::GetCreature(*me, me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT)))
+ DoZoneInCombat(bird, 200.0f);
+
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_FIEROBLAST, 1);
+ _events.ScheduleEvent(EVENT_FIEROCLAST_BARRAGE, 6000);
+ }
+
+ void JustReachedHome()
+ {
+ AlysrazorTrashEvaded(me);
+ }
+
+ void MoveInLineOfSight(Unit* unit)
+ {
+ if (me->isInCombat())
+ return;
+
+ if (!unit->isCharmedOwnedByPlayerOrPlayer())
+ return;
+
+ ScriptedAI::MoveInLineOfSight(unit);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!me->isInCombat())
+ if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
+ if (Creature* fireBird = me->FindNearestCreature((me->GetHomePosition().GetPositionY() > -275.0f ? NPC_BLAZING_MONSTROSITY_LEFT : NPC_BLAZING_MONSTROSITY_RIGHT), 100.0f))
+ DoCast(fireBird, SPELL_FIRE_CHANNELING);
+
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FIEROBLAST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_RIDE_MONSTROSITY))
+ DoCast(target, SPELL_FIEROBLAST_TRASH);
+ _events.RescheduleEvent(EVENT_FIEROBLAST, 500); // cast time is longer, but thanks to UNIT_STATE_CASTING check it won't trigger more often (need this because this creature gets a stacking haste aura)
+ break;
+ case EVENT_FIEROCLAST_BARRAGE:
+ DoCastAOE(SPELL_FIEROCLAST_BARRAGE);
+ _events.ScheduleEvent(EVENT_FIEROCLAST_BARRAGE, urand(9000, 12000));
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_harbinger_of_flameAI(creature);
+ }
+};
+
+class npc_blazing_monstrosity : public CreatureScript
+{
+ public:
+ npc_blazing_monstrosity() : CreatureScript("npc_blazing_monstrosity") { }
+
+ struct npc_blazing_monstrosityAI : public PassiveAI
+ {
+ npc_blazing_monstrosityAI(Creature* creature) : PassiveAI(creature), _summons(creature)
+ {
+ }
+
+ void EnterEvadeMode()
+ {
+ _summons.DespawnAll();
+ _events.Reset();
+ PassiveAI::EnterEvadeMode();
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ _summons.DespawnAll();
+ _events.Reset();
+ }
+
+ void JustReachedHome()
+ {
+ AlysrazorTrashEvaded(me);
+ }
+
+ void EnterCombat(Unit* /*target*/)
+ {
+ DoZoneInCombat();
+ me->RemoveAurasDueToSpell(SPELL_SLEEP_ULTRA_HIGH_PRIORITY);
+ me->PlayOneShotAnimKit(ANIM_KIT_BIRD_WAKE);
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_START_SPITTING, 6000);
+ _events.ScheduleEvent(EVENT_CONTINUE_SPITTING, 9000);
+ }
+
+ void PassengerBoarded(Unit* passenger, int8 /*seat*/, bool apply)
+ {
+ if (!apply)
+ return;
+
+ // Our passenger is another vehicle (boardable by players)
+ DoCast(passenger, SPELL_SHARE_HEALTH, true);
+ passenger->setFaction(35);
+ passenger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ // Hack to relocate vehicle on vehicle so exiting players are not moved under map
+ Movement::MoveSplineInit init(passenger);
+ init.DisableTransportPathTransformations();
+ init.MoveTo(0.6654003f, 0.0f, 1.9815f);
+ init.SetFacing(0.0f);
+ init.Launch();
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ _summons.Summon(summon);
+ }
+
+ void SummonedCreatureDespawn(Creature* summon)
+ {
+ _summons.Despawn(summon);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_START_SPITTING:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_RIDE_MONSTROSITY))
+ DoCast(target, SPELL_MOLTEN_BARRAGE);
+ break;
+ case EVENT_CONTINUE_SPITTING:
+ DoCastAOE(SPELL_MOLTEN_BARRAGE_EFFECT);
+ if (Creature* egg = me->FindNearestCreature(NPC_EGG_PILE, 100.0f))
+ egg->AI()->DoAction(me->GetEntry());
+ break;
+ }
+ }
+ }
+
+ private:
+ SummonList _summons;
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_blazing_monstrosityAI(creature);
+ }
+};
+
+class npc_molten_barrage : public CreatureScript
+{
+ public:
+ npc_molten_barrage() : CreatureScript("npc_molten_barrage") { }
+
+ struct npc_molten_barrageAI : public NullCreatureAI
+ {
+ npc_molten_barrageAI(Creature* creature) : NullCreatureAI(creature)
+ {
+ }
+
+ void AttackStart(Unit* target)
+ {
+ if (target)
+ me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_IDLE);
+ }
+
+ void IsSummonedBy(Unit* /*summoner*/)
+ {
+ DoCastAOE(SPELL_AGGRO_CLOSEST, true);
+ DoCast(me, SPELL_MOLTEN_BARRAGE_VISUAL);
+ DoCast(me, SPELL_INVISIBILITY_AND_STEALTH_DETECTION, true);
+ }
+
+ void MovementInform(uint32 movementType, uint32 /*pointId*/)
+ {
+ if (movementType != EFFECT_MOTION_TYPE)
+ return;
+
+ DoCastAOE(SPELL_AGGRO_CLOSEST);
+ me->ClearUnitState(UNIT_STATE_CANNOT_TURN);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_molten_barrageAI(creature);
+ }
+};
+
+class npc_egg_pile : public CreatureScript
+{
+ public:
+ npc_egg_pile() : CreatureScript("npc_egg_pile") { }
+
+ struct npc_egg_pileAI : public CreatureAI
+ {
+ npc_egg_pileAI(Creature* creature) : CreatureAI(creature)
+ {
+ }
+
+ void AttackStart(Unit* /*target*/) { }
+
+ void Reset()
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _events.Reset();
+ _callHatchlingSpell = 0;
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ _events.Reset();
+ std::list<Creature*> eggs;
+ GetCreatureListWithEntryInGrid(eggs, me, NPC_MOLTEN_EGG_TRASH, 20.0f);
+ for (std::list<Creature*>::const_iterator itr = eggs.begin(); itr != eggs.end(); ++itr)
+ (*itr)->CastSpell(*itr, SPELL_ALYSRAZOR_COSMETIC_EGG_XPLOSION, TRIGGERED_FULL_MASK);
+
+ DoCast(me, SPELL_ALYSRAZOR_COSMETIC_EGG_XPLOSION, true);
+ }
+
+ void JustReachedHome()
+ {
+ AlysrazorTrashEvaded(me);
+ }
+
+ void DoAction(int32 action)
+ {
+ if (action != NPC_BLAZING_MONSTROSITY_LEFT &&
+ action != NPC_BLAZING_MONSTROSITY_RIGHT)
+ return;
+
+ if (action == NPC_BLAZING_MONSTROSITY_LEFT)
+ Talk(EMOTE_CRACKING_EGGS);
+
+ _callHatchlingSpell = (action == NPC_BLAZING_MONSTROSITY_LEFT) ? SPELL_MOLTEN_EGG_TRASH_CALL_L : SPELL_MOLTEN_EGG_TRASH_CALL_R;
+ DoZoneInCombat();
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_SUMMON_SMOULDERING_HATCHLING, 1);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON_SMOULDERING_HATCHLING:
+ {
+ std::list<Creature*> eggs;
+ MoltenEggCheck check(me);
+ Trinity::CreatureListSearcher<MoltenEggCheck> searcher(me, eggs, check);
+ me->VisitNearbyGridObject(20.0f, searcher);
+ if (!eggs.empty())
+ {
+ Creature* egg = Trinity::Containers::SelectRandomContainerElement(eggs);
+ egg->CastSpell(egg, SPELL_SUMMON_SMOULDERING_HATCHLING, TRIGGERED_FULL_MASK);
+ egg->SetDisplayId(MODEL_INVISIBLE_STALKER);
+ egg->m_Events.AddEvent(new RespawnEggEvent(egg), egg->m_Events.CalculateTime(5000));
+ }
+
+ if (_callHatchlingSpell)
+ DoCastAOE(_callHatchlingSpell, true);
+ _events.ScheduleEvent(EVENT_SUMMON_SMOULDERING_HATCHLING, urand(6000, 10000));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ uint32 _callHatchlingSpell;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_egg_pileAI(creature);
+ }
+};
+
+class spell_alysrazor_cosmetic_egg_xplosion : public SpellScriptLoader
+{
+ public:
+ spell_alysrazor_cosmetic_egg_xplosion() : SpellScriptLoader("spell_alysrazor_cosmetic_egg_xplosion") { }
+
+ class spell_alysrazor_cosmetic_egg_xplosion_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_alysrazor_cosmetic_egg_xplosion_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sCreatureDisplayInfoStore.LookupEntry(MODEL_INVISIBLE_STALKER))
+ return false;
+ return true;
+ }
+
+ void HandleExplosion(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->SetDisplayId(MODEL_INVISIBLE_STALKER);
+ if (Creature* creature = GetHitCreature())
+ creature->DespawnOrUnsummon(4000);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_alysrazor_cosmetic_egg_xplosion_SpellScript::HandleExplosion, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_alysrazor_cosmetic_egg_xplosion_SpellScript();
+ }
+};
+
+class spell_alysrazor_turn_monstrosity : public SpellScriptLoader
+{
+ public:
+ spell_alysrazor_turn_monstrosity() : SpellScriptLoader("spell_alysrazor_turn_monstrosity") { }
+
+ class spell_alysrazor_turn_monstrosity_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_alysrazor_turn_monstrosity_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_GENERIC_DUMMY_CAST))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_KNOCKBACK_RIGHT))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_KNOCKBACK_LEFT))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_KNOCKBACK_FORWARD))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_KNOCKBACK_BACK))
+ return false;
+ return true;
+ }
+
+ void KnockBarrage(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->GetMotionMaster()->MoveIdle();
+ if (TempSummon* summ = GetHitUnit()->ToTempSummon())
+ if (Unit* summoner = summ->GetSummoner())
+ GetHitUnit()->CastSpell(summoner, SPELL_GENERIC_DUMMY_CAST, TRIGGERED_FULL_MASK);
+
+ float angle = 0.0f;
+ if (Unit* bird = GetCaster()->GetVehicleBase())
+ {
+ bird->SetInFront(GetHitUnit());
+ angle = bird->GetOrientation();
+ }
+
+ uint32 spellId = 0;
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_RIGHT_SIDE_SMACK_R:
+ case SPELL_RIGHT_SIDE_SMACK_L:
+ spellId = SPELL_KNOCKBACK_RIGHT;
+ angle -= M_PI * 0.5f;
+ break;
+ case SPELL_LEFT_SIDE_SMACK_R:
+ case SPELL_LEFT_SIDE_SMACK_L:
+ spellId = SPELL_KNOCKBACK_LEFT;
+ angle += M_PI * 0.5f;
+ break;
+ case SPELL_HEAD_BONK_R:
+ case SPELL_HEAD_BONK_L:
+ spellId = SPELL_KNOCKBACK_FORWARD;
+ break;
+ case SPELL_TICKLE_R:
+ case SPELL_TICKLE_L:
+ spellId = SPELL_KNOCKBACK_BACK;
+ angle -= M_PI;
+ break;
+ }
+
+ // Cannot wait for object update to process facing spline, it's needed in next spell cast
+ GetHitUnit()->SetOrientation(angle);
+ GetHitUnit()->SetFacingTo(angle);
+ GetHitUnit()->AddUnitState(UNIT_STATE_CANNOT_TURN);
+ GetHitUnit()->CastSpell(GetHitUnit(), spellId, TRIGGERED_FULL_MASK);
+ }
+
+ void TurnBird(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->PlayOneShotAnimKit(ANIM_KIT_BIRD_TURN);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_alysrazor_turn_monstrosity_SpellScript::KnockBarrage, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_alysrazor_turn_monstrosity_SpellScript::TurnBird, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_alysrazor_turn_monstrosity_SpellScript();
+ }
+};
+
+class spell_alysrazor_aggro_closest : public SpellScriptLoader
+{
+ public:
+ spell_alysrazor_aggro_closest() : SpellScriptLoader("spell_alysrazor_aggro_closest") { }
+
+ class spell_alysrazor_aggro_closest_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_alysrazor_aggro_closest_SpellScript);
+
+ bool Load()
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void HandleEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ float curThreat = GetCaster()->getThreatManager().getThreat(GetHitUnit(), true);
+ GetCaster()->getThreatManager().addThreat(GetHitUnit(), -curThreat + 50000.0f / std::min(1.0f, GetCaster()->GetDistance(GetHitUnit())));
+ }
+
+ void UpdateThreat()
+ {
+ GetCaster()->ClearUnitState(UNIT_STATE_CASTING);
+ GetCaster()->GetAI()->AttackStart(GetCaster()->ToCreature()->SelectVictim());
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_alysrazor_aggro_closest_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ AfterCast += SpellCastFn(spell_alysrazor_aggro_closest_SpellScript::UpdateThreat);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_alysrazor_aggro_closest_SpellScript();
+ }
+};
+
+class spell_alysrazor_fieroblast : public SpellScriptLoader
+{
+ public:
+ spell_alysrazor_fieroblast() : SpellScriptLoader("spell_alysrazor_fieroblast") { }
+
+ class spell_alysrazor_fieroblast_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_alysrazor_fieroblast_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_FIRE_IT_UP))
+ return false;
+ return true;
+ }
+
+ void FireItUp()
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_FIRE_IT_UP, TRIGGERED_FULL_MASK);
+ }
+
+ void Register()
+ {
+ AfterCast += SpellCastFn(spell_alysrazor_fieroblast_SpellScript::FireItUp);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_alysrazor_fieroblast_SpellScript();
+ }
+};
+
+void AddSC_boss_alysrazor()
+{
+ new npc_harbinger_of_flame();
+ new npc_blazing_monstrosity();
+ new npc_molten_barrage();
+ new npc_egg_pile();
+ new spell_alysrazor_cosmetic_egg_xplosion();
+ new spell_alysrazor_turn_monstrosity();
+ new spell_alysrazor_aggro_closest();
+ new spell_alysrazor_fieroblast();
+}
diff --git a/src/server/scripts/Kalimdor/Firelands/firelands.h b/src/server/scripts/Kalimdor/Firelands/firelands.h
new file mode 100644
index 00000000000..cf12892b2c9
--- /dev/null
+++ b/src/server/scripts/Kalimdor/Firelands/firelands.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FIRELANDS_H_
+#define FIRELANDS_H_
+
+#include "Map.h"
+#include "CreatureAI.h"
+
+#define FirelandsScriptName "instance_firelands"
+
+uint32 const EncounterCount = 7;
+
+enum DataTypes
+{
+ DATA_BETH_TILAC = 0,
+ DATA_LORD_RHYOLITH = 1,
+ DATA_SHANNOX = 2,
+ DATA_ALYSRAZOR = 3,
+ DATA_BALEROC = 4,
+ DATA_MAJORDOMO_STAGHELM = 5,
+ DATA_RAGNAROS = 6,
+};
+
+enum CreatureIds
+{
+ NPC_BLAZING_MONSTROSITY_LEFT = 53786,
+ NPC_BLAZING_MONSTROSITY_RIGHT = 53791,
+ NPC_EGG_PILE = 53795,
+ NPC_HARBINGER_OF_FLAME = 53793,
+ NPC_MOLTEN_EGG_TRASH = 53914,
+ NPC_SMOULDERING_HATCHLING = 53794,
+};
+
+class DelayedAttackStartEvent : public BasicEvent
+{
+ public:
+ DelayedAttackStartEvent(Creature* owner) : _owner(owner) { }
+
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/)
+ {
+ _owner->AI()->DoZoneInCombat(_owner, 200.0f);
+ return true;
+ }
+
+ private:
+ Creature* _owner;
+};
+
+template<class AI>
+CreatureAI* GetFirelandsAI(Creature* creature)
+{
+ if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(FirelandsScriptName))
+ return new AI(creature);
+ return NULL;
+}
+
+#endif // FIRELANDS_H_
diff --git a/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp b/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
new file mode 100644
index 00000000000..dd8b2a76093
--- /dev/null
+++ b/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "InstanceScript.h"
+#include "firelands.h"
+
+class instance_firelands : public InstanceMapScript
+{
+ public:
+ instance_firelands() : InstanceMapScript(FirelandsScriptName, 720) { }
+
+ struct instance_firelands_InstanceScript : public InstanceScript
+ {
+ instance_firelands_InstanceScript(InstanceMap* map) : InstanceScript(map)
+ {
+ }
+
+ void Initialize()
+ {
+ SetBossNumber(EncounterCount);
+ }
+
+ void OnCreatureCreate(Creature* creature)
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_SMOULDERING_HATCHLING:
+ // Cannot directly start attacking here as the creature is not yet on map
+ creature->m_Events.AddEvent(new DelayedAttackStartEvent(creature), creature->m_Events.CalculateTime(500));
+ break;
+ }
+ }
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const
+ {
+ return new instance_firelands_InstanceScript(map);
+ }
+};
+
+void AddSC_instance_firelands()
+{
+ new instance_firelands();
+}
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
new file mode 100644
index 00000000000..953ea2b4dc2
--- /dev/null
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "GridNotifiers.h"
+#include "Player.h"
+#include "ObjectAccessor.h"
+#include "halls_of_origination.h"
+
+enum Texts
+{
+ ANRAPHET_SAY_INTRO = 0,
+ ANRAPHET_SAY_AGGRO = 1,
+ ANRAPHET_SAY_OMEGA_STANCE = 2,
+ ANRAPHET_SAY_KILL = 3,
+ ANRAPHET_SAY_DEATH = 4,
+
+ BRANN_SAY_DOOR_INTRO = 0, // Right, let's go! Just need to input the final entry sequence into the door mechanism... and...
+ BRANN_SAY_UNLOCK_DOOR = 1, // That did the trick! The control room should be right behind this... oh... wow...
+ BRANN_SAY_TROGGS = 2, // What? This isn't the control room! There's another entire defense mechanism in place, and the blasted Rock Troggs broke into here somehow. Troggs. Why did it have to be Troggs!
+ BRANN_SAY_THINK = 3, // Ok, let me think a moment.
+ BRANN_SAY_MIRRORS = 4, // Mirrors pointing all over the place.
+ BRANN_SAY_ELEMENTALS = 5, // Four platforms with huge elementals.
+ BRANN_SAY_GET_IT = 6, // I got it! I saw a tablet that mentioned this chamber. This is the Vault of Lights! Ok, simple enough. I need you adventurers to take out each of the four elementals to trigger the opening sequence for the far door!
+ BRANN_1_ELEMENTAL_DEAD = 7, // One down!
+ BRANN_2_ELEMENTAL_DEAD = 8, // Another one down! Just look at those light beams! They seem to be connecting to the far door!
+ BRANN_3_ELEMENTAL_DEAD = 9, // One more elemental to go! The door is almost open!
+ BRANN_4_ELEMENTAL_DEAD = 10, // That''s it, you''ve done it! The vault door is opening! Now we can... oh, no!
+ BRANN_SAY_ANRAPHET_DIED = 11, // We''ve done it! The control room is breached!
+ BRANN_SAY_MOMENT = 12 // Here we go! Now this should only take a moment...
+};
+
+enum Events
+{
+ EVENT_BRANN_MOVE_INTRO = 1,
+ EVENT_BRANN_UNLOCK_DOOR = 2,
+ EVENT_BRANN_THINK = 3,
+ EVENT_BRANN_SET_ORIENTATION_1 = 4,
+ EVENT_BRANN_SET_ORIENTATION_2 = 5,
+ EVENT_BRANN_SET_ORIENTATION_3 = 6,
+ EVENT_BRANN_SAY_ELEMENTALS = 7,
+ EVENT_BRANN_SAY_GET_IT = 8,
+ EVENT_BRANN_SET_ORIENTATION_4 = 9,
+
+ EVENT_ANRAPHET_APPEAR = 10,
+ EVENT_ANRAPHET_ACTIVATE = 11,
+ EVENT_ANRAPHET_DESTROY = 12,
+ EVENT_ANRAPHET_READY = 13,
+ EVENT_ANRAPHET_NEMESIS_STRIKE = 14,
+ EVENT_ANRAPHET_ALPHA_BEAMS = 15,
+ EVENT_ANRAPHET_OMEGA_STANCE = 16,
+ EVENT_ANRAPHET_CRUMBLING_RUIN = 17,
+ EVENT_ANRAPHET_ACTIVATE_OMEGA = 18
+};
+
+enum Spells
+{
+ SPELL_DESTRUCTION_PROTOCOL = 77437,
+
+ SPELL_ALPHA_BEAMS = 76184,
+ SPELL_ALPHA_BEAMS_BACK_CAST = 76912,
+
+ SPELL_CRUMBLING_RUIN = 75609,
+
+
+ SPELL_NEMESIS_STRIKE = 75604,
+
+ SPELL_OMEGA_STANCE_SUMMON = 77106,
+ SPELL_OMEGA_STANCE = 75622,
+ SPELL_OMEGA_STANCE_SPIDER_TRIGGER = 77121,
+};
+
+enum Phases
+{
+ PHASE_INTRO = 1,
+ PHASE_COMBAT = 2,
+
+ PHASE_MASK_COMBAT = (1 << PHASE_COMBAT),
+};
+
+enum Points
+{
+ POINT_ANRAPHET_ACTIVATE = 0,
+ MAX_BRANN_WAYPOINTS_INTRO = 17
+};
+
+Position const AnraphetActivatePos = {-193.656f, 366.689f, 75.91001f, 3.138207f};
+
+Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] =
+{
+ {-429.583f, 367.019f, 89.79282f, 0.0f},
+ {-409.9531f, 367.0469f, 89.81111f, 0.0f},
+ {-397.8246f, 366.967f, 86.37722f, 0.0f},
+ {-383.7813f, 366.8229f, 82.07919f, 0.0f},
+ {-368.2604f, 366.7448f, 77.0984f, 0.0f},
+ {-353.6458f, 366.4896f, 75.92504f, 0.0f},
+ {-309.0608f, 366.7205f, 75.91345f, 0.0f},
+ {-276.3303f, 367.0f, 75.92413f, 0.0f},
+ {-246.5104f, 366.6389f, 75.87791f, 0.0f},
+ {-202.0417f, 366.7517f, 75.92508f, 0.0f},
+ {-187.6024f, 366.7656f, 76.23077f, 0.0f},
+ {-155.0938f, 366.783f, 86.45834f, 0.0f},
+ {-143.5694f, 366.8177f, 89.73354f, 0.0f},
+ {-128.5608f, 366.8629f, 89.74199f, 0.0f},
+ {-103.559f, 366.5938f, 89.79725f, 0.0f},
+ {-71.58507f, 367.0278f, 89.77069f, 0.0f},
+ {-35.04861f, 366.6563f, 89.77447f, 0.0f},
+};
+
+class boss_anraphet : public CreatureScript
+{
+public:
+ boss_anraphet() : CreatureScript("boss_anraphet") { }
+
+ struct boss_anraphetAI : public BossAI
+ {
+ boss_anraphetAI(Creature* creature) : BossAI(creature, DATA_ANRAPHET) { }
+
+ void ScheduleCombatEvents()
+ {
+ events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 8000, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, 10000, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, 35000, 0, PHASE_COMBAT);
+ }
+
+ void Reset()
+ {
+ _Reset();
+ me->SetWalk(false);
+ events.SetPhase(PHASE_INTRO);
+ if (instance->GetData(DATA_DEAD_ELEMENTALS) == 4)
+ {
+ // Set to combat automatically, Brann's event won't repeat
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ events.SetPhase(PHASE_COMBAT);
+ ScheduleCombatEvents();
+ me->SetHomePosition(AnraphetActivatePos);
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
+ Talk(ANRAPHET_SAY_AGGRO);
+ _EnterCombat();
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ Talk(ANRAPHET_SAY_DEATH);
+
+ if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRANN_0_GUID)))
+ brann->AI()->DoAction(ACTION_ANRAPHET_DIED);
+
+ _JustDied();
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(ANRAPHET_SAY_KILL);
+ }
+
+ void JustReachedHome()
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ _JustReachedHome();
+ instance->SetBossState(DATA_ANRAPHET, FAIL);
+ }
+
+ void DoAction(int32 action)
+ {
+ if (action == ACTION_ANRAPHET_INTRO)
+ events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, 6000, 0, PHASE_INTRO);
+ }
+
+ void MovementInform(uint32 type, uint32 point)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (point == POINT_ANRAPHET_ACTIVATE)
+ {
+ events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, 1500, 0, PHASE_INTRO);
+ me->SetHomePosition(AnraphetActivatePos);
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if ((events.GetPhaseMask() & PHASE_MASK_COMBAT) && (!UpdateVictim() || !CheckInRoom()))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ANRAPHET_APPEAR:
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(POINT_ANRAPHET_ACTIVATE, AnraphetActivatePos);
+ break;
+ case EVENT_ANRAPHET_ACTIVATE:
+ me->SetWalk(false);
+ Talk(ANRAPHET_SAY_INTRO);
+ events.ScheduleEvent(EVENT_ANRAPHET_DESTROY, 17500, 0, PHASE_INTRO);
+ return;
+ case EVENT_ANRAPHET_DESTROY:
+ DoCastAOE(SPELL_DESTRUCTION_PROTOCOL);
+ events.ScheduleEvent(EVENT_ANRAPHET_READY, 6000, 0, PHASE_INTRO);
+ break;
+ case EVENT_ANRAPHET_READY:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ events.SetPhase(PHASE_COMBAT);
+ ScheduleCombatEvents();
+ break;
+ case EVENT_ANRAPHET_NEMESIS_STRIKE:
+ DoCastVictim(SPELL_NEMESIS_STRIKE);
+ events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, 21500, 0, PHASE_COMBAT);
+ break;
+ case EVENT_ANRAPHET_ALPHA_BEAMS:
+ DoCast(me, SPELL_ALPHA_BEAMS);
+ events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 12500, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, urand(40000, 45000), 0, PHASE_COMBAT);
+ break;
+ case EVENT_ANRAPHET_OMEGA_STANCE:
+ DoCast(me, SPELL_OMEGA_STANCE_SUMMON);
+ DoCast(me, SPELL_OMEGA_STANCE);
+ Talk(ANRAPHET_SAY_OMEGA_STANCE);
+ events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, urand(45000, 50000), 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, 13000, 0, PHASE_COMBAT);
+ break;
+ case EVENT_ANRAPHET_CRUMBLING_RUIN:
+ DoCast(me, SPELL_CRUMBLING_RUIN);
+ break;
+ }
+ }
+
+ if (events.GetPhaseMask() & PHASE_MASK_COMBAT)
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetHallsOfOriginationAI<boss_anraphetAI>(creature);
+ }
+};
+
+class npc_omega_stance : public CreatureScript
+{
+ public:
+ npc_omega_stance() : CreatureScript("npc_omega_stance") { }
+
+ struct npc_omega_stanceAI : public ScriptedAI
+ {
+ npc_omega_stanceAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(Unit* /*who*/)
+ {
+ DoCast(me, SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true);
+ }
+
+ void EnterEvadeMode() { }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_omega_stanceAI(creature);
+ }
+};
+
+class npc_alpha_beam : public CreatureScript
+{
+ public:
+ npc_alpha_beam() : CreatureScript("npc_alpha_beam") { }
+
+ struct npc_alpha_beamAI : public ScriptedAI
+ {
+ npc_alpha_beamAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void IsSummonedBy(Unit* /*summoner*/)
+ {
+ if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ANRAPHET_GUID)))
+ anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST);
+ }
+
+ void EnterEvadeMode() { } // Never evade
+
+ private:
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetHallsOfOriginationAI<npc_alpha_beamAI>(creature);
+ }
+};
+
+class npc_brann_bronzebeard_anraphet : public CreatureScript
+{
+ public:
+ npc_brann_bronzebeard_anraphet() : CreatureScript("npc_brann_bronzebeard_anraphet") { }
+
+ struct npc_brann_bronzebeard_anraphetAI : public CreatureAI
+ {
+ npc_brann_bronzebeard_anraphetAI(Creature* creature) : CreatureAI(creature), _currentPoint(0), _instance(creature->GetInstanceScript()) { }
+
+ void sGossipSelect(Player* /*player*/, uint32 sender, uint32 action)
+ {
+ if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == DONE)
+ return;
+
+ if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
+ {
+ _instance->SetBossState(DATA_VAULT_OF_LIGHTS, IN_PROGRESS);
+ _currentPoint = 0;
+ events.Reset();
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->SetWalk(true);
+ Talk(BRANN_SAY_DOOR_INTRO);
+ events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, 7500);
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_ELEMENTAL_DIED:
+ {
+ uint32 dead = _instance->GetData(DATA_DEAD_ELEMENTALS);
+ Talk(BRANN_1_ELEMENTAL_DEAD + dead - 1);
+ if (dead == 4)
+ {
+ _instance->DoCastSpellOnPlayers(SPELL_VAULT_OF_LIGHTS_CREDIT);
+ if (Creature* anraphet = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ANRAPHET_GUID)))
+ anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO);
+ }
+ break;
+ }
+ case ACTION_ANRAPHET_DIED:
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1000);
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BRANN_MOVE_INTRO:
+ if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO)
+ me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]);
+ break;
+ case EVENT_BRANN_UNLOCK_DOOR:
+ Talk(BRANN_SAY_UNLOCK_DOOR);
+ _instance->SetBossState(DATA_VAULT_OF_LIGHTS, DONE);
+ _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_EVENT);
+ events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 3500);
+ break;
+ case EVENT_BRANN_THINK:
+ Talk(BRANN_SAY_THINK);
+ events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_1, 6000);
+ break;
+ case EVENT_BRANN_SET_ORIENTATION_1:
+ me->SetFacingTo(5.445427f);
+ Talk(BRANN_SAY_MIRRORS);
+ events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_2, 1000);
+ break;
+ case EVENT_BRANN_SET_ORIENTATION_2:
+ me->SetFacingTo(0.6283185f);
+ events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_3, 2500);
+ break;
+ case EVENT_BRANN_SET_ORIENTATION_3:
+ me->SetFacingTo(0.01745329f);
+ events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, 200);
+ break;
+ case EVENT_BRANN_SAY_ELEMENTALS:
+ Talk(BRANN_SAY_ELEMENTALS);
+ events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, 3500);
+ break;
+ case EVENT_BRANN_SAY_GET_IT:
+ Talk(BRANN_SAY_GET_IT);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ break;
+ case EVENT_BRANN_SET_ORIENTATION_4:
+ me->SetFacingTo(3.141593f);
+ break;
+ }
+ }
+ }
+
+ void MovementInform(uint32 movementType, uint32 pointId)
+ {
+ if (movementType != POINT_MOTION_TYPE)
+ return;
+
+ _currentPoint = pointId + 1;
+ uint32 delay = 1;
+
+ switch (pointId)
+ {
+ case 0:
+ Talk(BRANN_SAY_TROGGS);
+ events.ScheduleEvent(EVENT_BRANN_THINK, 15000);
+ return;
+ case 1:
+ Talk(BRANN_SAY_ANRAPHET_DIED);
+ delay = 1000;
+ break;
+ case 14:
+ Talk(BRANN_SAY_MOMENT);
+ delay = 2200;
+ break;
+ case 16:
+ events.ScheduleEvent(EVENT_BRANN_SET_ORIENTATION_4, 6000);
+ return;
+ default:
+ break;
+ }
+
+ events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay);
+ }
+
+ protected:
+ EventMap events;
+ uint32 _currentPoint;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetHallsOfOriginationAI<npc_brann_bronzebeard_anraphetAI>(creature);
+ }
+};
+
+class spell_anraphet_alpha_beams : public SpellScriptLoader
+{
+public:
+ spell_anraphet_alpha_beams() : SpellScriptLoader("spell_anraphet_alpha_beams") { }
+
+ class spell_anraphet_alpha_beams_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_anraphet_alpha_beams_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.empty())
+ return;
+
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_anraphet_alpha_beams_SpellScript();
+ }
+};
+
+class spell_anraphet_omega_stance_summon : public SpellScriptLoader
+{
+public:
+ spell_anraphet_omega_stance_summon() : SpellScriptLoader("spell_anraphet_omega_stance_summon") { }
+
+ class spell_anraphet_omega_stance_summon_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_anraphet_omega_stance_summon_SpellScript);
+
+ void ModDestHeight(SpellEffIndex /*effIndex*/)
+ {
+ Position offset = {0.0f, 0.0f, 30.0f, 0.0f};
+ const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset);
+ GetHitDest()->RelocateOffset(offset);
+ }
+
+ void Register()
+ {
+ OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_summon_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_anraphet_omega_stance_summon_SpellScript();
+ }
+};
+
+class spell_omega_stance_spider_effect : public SpellScriptLoader
+{
+public:
+ spell_omega_stance_spider_effect() : SpellScriptLoader("spell_omega_stance_spider_effect") { }
+
+ class spell_omega_stance_spider_effect_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_omega_stance_spider_effect_SpellScript);
+
+ void SetDestPosition(SpellEffIndex effIndex)
+ {
+ // Do our own calculations for the destination position.
+ /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration)
+ Unit* caster = GetCaster();
+ float angle = float(rand_norm()) * static_cast<float>(2 * M_PI);
+ uint32 dist = caster->GetObjectSize() + GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster()) * (float)rand_norm();
+
+ float x = caster->GetPositionX() + dist * std::cos(angle);
+ float y = caster->GetPositionY() + dist * std::sin(angle);
+ float z = caster->GetMap()->GetHeight(x, y, caster->GetPositionZ());
+
+ const_cast<WorldLocation*>(GetExplTargetDest())->Relocate(x, y, z);
+ GetHitDest()->Relocate(x, y, z);
+ }
+
+ void Register()
+ {
+ OnEffectLaunch += SpellEffectFn(spell_omega_stance_spider_effect_SpellScript::SetDestPosition, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_omega_stance_spider_effect_SpellScript();
+ }
+};
+
+void AddSC_boss_anraphet()
+{
+ new boss_anraphet();
+ new spell_anraphet_alpha_beams();
+ new npc_brann_bronzebeard_anraphet();
+ new npc_alpha_beam();
+ new spell_anraphet_omega_stance_summon();
+ new spell_omega_stance_spider_effect();
+ new npc_omega_stance();
+}
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp
new file mode 100644
index 00000000000..e8c65cf14e4
--- /dev/null
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "Player.h"
+#include "Weather.h"
+#include "WorldSession.h"
+#include "halls_of_origination.h"
+
+enum Texts
+{
+ SAY_AGGRO = 0,
+ SAY_DEATH = 1,
+};
+
+enum Events
+{
+ EVENT_RAGING_SMASH = 1,
+ EVENT_FLAME_BOLT = 2,
+ EVENT_EARTH_SPIKE = 3,
+ EVENT_PTAH_EXPLODE = 4,
+ EVENT_QUICKSAND = 5,
+};
+
+enum Spells
+{
+ SPELL_RAGING_SMASH = 83650,
+ SPELL_FLAME_BOLT = 77370,
+ SPELL_EARTH_SPIKE_WARN = 94974,
+
+ SPELL_PTAH_EXPLOSION = 75519,
+ SPELL_SANDSTORM = 75491,
+
+ SPELL_SUMMON_QUICKSAND = 75550, // Spell not in DBC, no SMSG_SPELL_START/GO for it
+
+ SPELL_BEETLE_BURROW = 75463,
+
+ SPELL_SUMMON_JEWELED_SCARAB = 75462,
+ SPELL_SUMMON_DUSTBONE_HORROR = 75521,
+};
+
+enum Phases
+{
+ PHASE_NORMAL = 1,
+ PHASE_DISPERSE = 2,
+
+ PHASE_MASK_DISPERSE = (1 << PHASE_DISPERSE),
+ PHASE_MASK_NORMAL = (1 << PHASE_NORMAL),
+};
+
+enum PtahData
+{
+ DATA_SUMMON_DEATHS = 0
+};
+
+class SummonScarab : public BasicEvent
+{
+public:
+ SummonScarab(Unit* owner, InstanceScript* instance) : _owner(owner), _instance(instance) { }
+
+ bool Execute(uint64 /*execTime*/, uint32 /*diff*/)
+ {
+ if (!_instance || _instance->GetBossState(DATA_EARTHRAGER_PTAH) != IN_PROGRESS)
+ return true; // delete event
+
+ _owner->CastSpell(_owner, SPELL_SUMMON_JEWELED_SCARAB);
+ _owner->RemoveAurasDueToSpell(SPELL_BEETLE_BURROW);
+ return true;
+ }
+protected:
+ Unit* _owner;
+ InstanceScript* _instance;
+};
+
+class boss_earthrager_ptah : public CreatureScript
+{
+public:
+ boss_earthrager_ptah() : CreatureScript("boss_earthrager_ptah") { }
+
+ struct boss_earthrager_ptahAI : public BossAI
+ {
+ boss_earthrager_ptahAI(Creature* creature) : BossAI(creature, DATA_EARTHRAGER_PTAH), _summonDeaths(0), _hasDispersed(false) { }
+
+ void Cleanup()
+ {
+ std::list<Creature*> units;
+
+ GetCreatureListWithEntryInGrid(units, me, NPC_DUSTBONE_HORROR, 100.0f);
+ for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
+ (*itr)->DespawnOrUnsummon();
+
+ GetCreatureListWithEntryInGrid(units, me, NPC_JEWELED_SCARAB, 100.0f);
+ for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
+ (*itr)->DespawnOrUnsummon();
+ }
+
+ void SendWeather(WeatherState weather, float grade) const
+ {
+ WorldPacket data(SMSG_WEATHER, 9);
+ data << uint32(weather);
+ data << float(grade);
+ data << uint8(0);
+ SendPacketToPlayers(&data);
+ }
+
+ // Send packet to all players in Tomb of the Earthrager
+ void SendPacketToPlayers(WorldPacket const* data) const
+ {
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ if (!players.isEmpty())
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->getSource())
+ if (player->GetAreaId() == AREA_TOMB_OF_THE_EARTHRAGER)
+ player->GetSession()->SendPacket(data);
+ }
+
+ void Reset()
+ {
+ _summonDeaths = 0;
+ _hasDispersed = false;
+ Cleanup();
+ _Reset();
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (me->HealthBelowPctDamaged(50, damage) && (events.GetPhaseMask() & PHASE_MASK_NORMAL) && !_hasDispersed)
+ {
+ events.SetPhase(PHASE_DISPERSE);
+ _hasDispersed = true;
+
+ me->AttackStop();
+ DoCast(me, SPELL_SANDSTORM);
+ SendWeather(WEATHER_STATE_LIGHT_SANDSTORM, 1.0f);
+ events.ScheduleEvent(EVENT_PTAH_EXPLODE, 6000, 0, PHASE_DISPERSE);
+ events.ScheduleEvent(EVENT_QUICKSAND, 10000, 0, PHASE_DISPERSE);
+
+ std::list<Creature*> stalkers;
+ GetCreatureListWithEntryInGrid(stalkers, me, NPC_BEETLE_STALKER, 100.0f);
+ std::list<Creature*> beetlers = stalkers;
+
+ Trinity::Containers::RandomResizeList(beetlers, 9); // Holds the summoners of Jeweled Scarab
+
+ for (std::list<Creature*>::iterator itr = beetlers.begin(); itr != beetlers.end(); ++itr)
+ {
+ stalkers.remove((*itr)); // Remove it to prevent a single trigger from spawning multiple npcs.
+ (*itr)->CastSpell((*itr), SPELL_BEETLE_BURROW); // Cast visual
+ // Summon after 5 seconds.
+ (*itr)->m_Events.AddEvent(new SummonScarab((*itr), instance), (*itr)->m_Events.CalculateTime(5000));
+ }
+
+ Trinity::Containers::RandomResizeList(stalkers, 2); // Holds the summoners of Dustbone Horror
+
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ (*itr)->CastSpell((*itr), SPELL_SUMMON_DUSTBONE_HORROR);
+ }
+ }
+
+ void SetData(uint32 index, uint32 /*value*/)
+ {
+ if (index == DATA_SUMMON_DEATHS)
+ {
+ ++_summonDeaths;
+ if (_summonDeaths == 11) // All summons died
+ {
+ SendWeather(WEATHER_STATE_FOG, 0.0f);
+ me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION);
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
+ }
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
+ Talk(SAY_AGGRO);
+ _EnterCombat();
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ Talk(SAY_DEATH);
+ _JustDied();
+ Cleanup();
+ }
+
+ void JustReachedHome()
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ _JustReachedHome();
+ instance->SetBossState(DATA_EARTHRAGER_PTAH, FAIL);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RAGING_SMASH:
+ DoCastVictim(SPELL_RAGING_SMASH);
+ events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
+ break;
+ case EVENT_FLAME_BOLT:
+ DoCast(me, SPELL_FLAME_BOLT);
+ events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
+ break;
+ case EVENT_EARTH_SPIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_EARTH_SPIKE_WARN);
+ events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
+ break;
+ case EVENT_PTAH_EXPLODE:
+ DoCast(me, SPELL_PTAH_EXPLOSION);
+ break;
+ case EVENT_QUICKSAND:
+ // Spell not in DBC, it is not cast either, according to sniffs
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ if (Creature* quicksand = me->SummonCreature(NPC_QUICKSAND, *target))
+ quicksand->SetUInt32Value(UNIT_CREATED_BY_SPELL, SPELL_SUMMON_QUICKSAND);
+ events.ScheduleEvent(EVENT_QUICKSAND, 10000, 0, PHASE_DISPERSE);
+ break;
+ }
+ }
+
+ if (events.GetPhaseMask() & PHASE_MASK_NORMAL) // Do not melee in the disperse phase
+ DoMeleeAttackIfReady();
+ }
+
+ protected:
+ uint8 _summonDeaths;
+ bool _hasDispersed;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetHallsOfOriginationAI<boss_earthrager_ptahAI>(creature);
+ }
+};
+
+class spell_earthrager_ptah_flame_bolt : public SpellScriptLoader
+{
+ public:
+ spell_earthrager_ptah_flame_bolt() : SpellScriptLoader("spell_earthrager_ptah_flame_bolt") { }
+
+ class spell_earthrager_ptah_flame_bolt_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_earthrager_ptah_flame_bolt_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ Trinity::Containers::RandomResizeList(targets, GetCaster()->GetMap()->IsHeroic() ? 3 : 2);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_earthrager_ptah_flame_bolt_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_earthrager_ptah_flame_bolt_SpellScript();
+ }
+};
+
+class spell_earthrager_ptah_explosion : public SpellScriptLoader
+{
+public:
+ spell_earthrager_ptah_explosion() : SpellScriptLoader("spell_earthrager_ptah_explosion") { }
+
+ class spell_earthrager_ptah_explosion_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_earthrager_ptah_explosion_AuraScript);
+
+ void SetFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* ptah = GetCaster())
+ {
+ ptah->SetFlag(UNIT_FIELD_FLAGS, uint32(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_29 | UNIT_FLAG_UNK_31));
+ ptah->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ }
+ }
+
+ void RemoveFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* ptah = GetCaster())
+ {
+ ptah->RemoveFlag(UNIT_FIELD_FLAGS, uint32(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_29 | UNIT_FLAG_UNK_31));
+ ptah->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_earthrager_ptah_explosion_AuraScript::SetFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_earthrager_ptah_explosion_AuraScript::RemoveFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_earthrager_ptah_explosion_AuraScript();
+ }
+};
+
+void AddSC_boss_earthrager_ptah()
+{
+ new boss_earthrager_ptah();
+ new spell_earthrager_ptah_flame_bolt();
+ new spell_earthrager_ptah_explosion();
+}
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp
new file mode 100644
index 00000000000..61110a3454e
--- /dev/null
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "GridNotifiers.h"
+#include "Player.h"
+#include "halls_of_origination.h"
+
+enum Texts
+{
+ SAY_AGGRO = 0,
+ SAY_SHIELD = 1,
+ EMOTE_SHIELD = 2,
+ EMOTE_UNSHIELD = 3,
+ SAY_KILL = 4,
+ SAY_DEATH = 5
+};
+
+enum Events
+{
+ EVENT_DIVINE_RECKONING = 1,
+ EVENT_BURNING_LIGHT = 2,
+ EVENT_SEAR = 3,
+};
+
+enum Spells
+{
+ SPELL_DIVINE_RECKONING = 75592,
+ SPELL_BURNING_LIGHT = 75115,
+ SPELL_REVERBERATING_HYMN = 75322,
+ SPELL_SHIELD_OF_LIGHT = 74938,
+
+ SPELL_ACTIVATE_BEACONS = 76599,
+ SPELL_TELEPORT = 74969,
+
+ SPELL_SHIELD_VISUAL_RIGHT = 83698,
+ SPELL_BEAM_OF_LIGHT_RIGHT = 76573,
+
+ SPELL_SHIELD_VISUAL_LEFT = 83697,
+ SPELL_BEAM_OF_LIGHT_LEFT = 74930,
+
+ SPELL_SEARING_LIGHT = 75194,
+};
+
+enum Phases
+{
+ PHASE_SHIELDED = 0,
+ PHASE_FIRST_SHIELD = 1, // Ready to be shielded for the first time
+ PHASE_SECOND_SHIELD = 2, // First shield already happened, ready to be shielded a second time
+ PHASE_FINAL = 3 // Already shielded twice, ready to finish the encounter normally.
+};
+
+enum Actions
+{
+ ACTION_DISABLE_BEACON,
+};
+
+class boss_temple_guardian_anhuur : public CreatureScript
+{
+public:
+ boss_temple_guardian_anhuur() : CreatureScript("boss_temple_guardian_anhuur") { }
+
+ struct boss_temple_guardian_anhuurAI : public BossAI
+ {
+ boss_temple_guardian_anhuurAI(Creature* creature) : BossAI(creature, DATA_TEMPLE_GUARDIAN_ANHUUR) { }
+
+ void CleanStalkers()
+ {
+ std::list<Creature*> stalkers;
+ GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ {
+ (*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_RIGHT);
+ (*itr)->RemoveAurasDueToSpell(SPELL_BEAM_OF_LIGHT_LEFT);
+ }
+ }
+
+ void Reset()
+ {
+ _phase = PHASE_FIRST_SHIELD;
+ _oldPhase = PHASE_FIRST_SHIELD;
+ _beacons = 0;
+ _Reset();
+ CleanStalkers();
+ me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
+ events.ScheduleEvent(EVENT_DIVINE_RECKONING, urand(10000, 12000));
+ events.ScheduleEvent(EVENT_BURNING_LIGHT, 12000);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if ((me->HealthBelowPctDamaged(66, damage) && _phase == PHASE_FIRST_SHIELD) ||
+ (me->HealthBelowPctDamaged(33, damage) && _phase == PHASE_SECOND_SHIELD))
+ {
+ _beacons = 2;
+ _phase++; // Increase the phase
+ _oldPhase = _phase;
+
+ _phase = PHASE_SHIELDED;
+
+ me->InterruptNonMeleeSpells(true);
+ me->AttackStop();
+ DoCast(me, SPELL_TELEPORT);
+
+ DoCast(me, SPELL_SHIELD_OF_LIGHT);
+ me->SetFlag(UNIT_FIELD_FLAGS, uint32(UNIT_FLAG_UNK_31));
+
+ DoCastAOE(SPELL_ACTIVATE_BEACONS);
+
+ std::list<Creature*> stalkers;
+ GameObject* door = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ANHUUR_DOOR));
+ GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
+
+ stalkers.remove_if(Trinity::HeightDifferenceCheck(door, 0.0f, false)); // Target only the bottom ones
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ {
+ if ((*itr)->GetPositionX() > door->GetPositionX())
+ {
+ (*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_LEFT, true);
+ (*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_LEFT, true);
+ }
+ else
+ {
+ (*itr)->CastSpell((*itr), SPELL_SHIELD_VISUAL_RIGHT, true);
+ (*itr)->CastSpell((*itr), SPELL_BEAM_OF_LIGHT_RIGHT, true);
+ }
+ }
+
+ DoCast(me, SPELL_REVERBERATING_HYMN);
+
+ Talk(EMOTE_SHIELD);
+ Talk(SAY_SHIELD);
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ if (action == ACTION_DISABLE_BEACON)
+ {
+ --_beacons;
+ if (!_beacons)
+ {
+ me->RemoveAurasDueToSpell(SPELL_SHIELD_OF_LIGHT);
+ Talk(EMOTE_UNSHIELD);
+ _phase = _oldPhase;
+ }
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
+ Talk(SAY_AGGRO);
+ _EnterCombat();
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ Talk(SAY_DEATH);
+ _JustDied();
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void JustReachedHome()
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ _JustReachedHome();
+ instance->SetBossState(DATA_TEMPLE_GUARDIAN_ANHUUR, FAIL);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim() || !CheckInRoom() || me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) || _phase == PHASE_SHIELDED)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DIVINE_RECKONING:
+ DoCastVictim(SPELL_DIVINE_RECKONING);
+ events.ScheduleEvent(EVENT_DIVINE_RECKONING, urand(10000, 12000));
+ break;
+ case EVENT_BURNING_LIGHT:
+ {
+ Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me));
+ if (!unit)
+ unit = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true);
+ DoCast(unit, SPELL_BURNING_LIGHT);
+ events.ScheduleEvent(EVENT_SEAR, 2000);
+ events.ScheduleEvent(EVENT_BURNING_LIGHT, 12000);
+ break;
+ }
+ case EVENT_SEAR:
+ {
+ Unit* target = me->FindNearestCreature(NPC_SEARING_LIGHT, 100.0f);
+ if (!target)
+ break;
+
+ std::list<Creature*> stalkers;
+ GetCreatureListWithEntryInGrid(stalkers, me, NPC_CAVE_IN_STALKER, 100.0f);
+ stalkers.remove_if(Trinity::HeightDifferenceCheck(ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ANHUUR_DOOR)), 5.0f, true));
+
+ if (stalkers.empty())
+ break;
+
+ stalkers.sort(Trinity::ObjectDistanceOrderPred(target));
+
+ // Get the closest statue face (any of its eyes)
+ Creature* eye1 = stalkers.front();
+ stalkers.remove(eye1); // Remove the eye.
+ stalkers.sort(Trinity::ObjectDistanceOrderPred(eye1)); // Find the second eye.
+ Creature* eye2 = stalkers.front();
+
+ eye1->CastSpell(eye1, SPELL_SEARING_LIGHT, true);
+ eye2->CastSpell(eye2, SPELL_SEARING_LIGHT, true);
+ break;
+ }
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ uint8 _phase;
+ uint8 _oldPhase;
+ uint8 _beacons;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetHallsOfOriginationAI<boss_temple_guardian_anhuurAI>(creature);
+ }
+};
+
+class spell_anhuur_shield_of_light : public SpellScriptLoader
+{
+ public:
+ spell_anhuur_shield_of_light() : SpellScriptLoader("spell_anhuur_shield_of_light") { }
+
+ class spell_anhuur_shield_of_light_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_anhuur_shield_of_light_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (InstanceMap* instance = GetCaster()->GetMap()->ToInstanceMap())
+ {
+ if (InstanceScript* const script = instance->GetInstanceScript())
+ {
+ if (GameObject* go = ObjectAccessor::GetGameObject(*GetCaster(), script->GetData64(DATA_ANHUUR_DOOR)))
+ {
+ targets.remove_if(Trinity::HeightDifferenceCheck(go, 5.0f, false));
+ targets.remove(GetCaster());
+ targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
+ targets.resize(2);
+ }
+ }
+ }
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anhuur_shield_of_light_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_anhuur_shield_of_light_SpellScript();
+ }
+};
+
+class spell_anhuur_disable_beacon_beams : public SpellScriptLoader
+{
+ public:
+ spell_anhuur_disable_beacon_beams() : SpellScriptLoader("spell_anhuur_disable_beacon_beams") { }
+
+ class spell_anhuur_disable_beacon_beams_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_anhuur_disable_beacon_beams_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->RemoveAurasDueToSpell(GetEffectValue());
+ }
+
+ void Notify(SpellEffIndex /*index*/)
+ {
+ if (InstanceMap* instance = GetCaster()->GetMap()->ToInstanceMap())
+ if (InstanceScript* const script = instance->GetInstanceScript())
+ if (Creature* anhuur = instance->GetCreature(script->GetData64(DATA_ANHUUR_GUID)))
+ anhuur->AI()->DoAction(ACTION_DISABLE_BEACON);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_anhuur_disable_beacon_beams_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHit += SpellEffectFn(spell_anhuur_disable_beacon_beams_SpellScript::Notify, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_anhuur_disable_beacon_beams_SpellScript();
+ }
+};
+
+class spell_anhuur_activate_beacons : public SpellScriptLoader
+{
+ public:
+ spell_anhuur_activate_beacons() : SpellScriptLoader("spell_anhuur_activate_beacons") { }
+
+ class spell_anhuur_activate_beacons_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_anhuur_activate_beacons_SpellScript);
+
+ void Activate(SpellEffIndex index)
+ {
+ PreventHitDefaultEffect(index);
+ GetHitGObj()->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_anhuur_activate_beacons_SpellScript::Activate, EFFECT_0, SPELL_EFFECT_ACTIVATE_OBJECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_anhuur_activate_beacons_SpellScript();
+ }
+};
+
+class spell_anhuur_divine_reckoning : public SpellScriptLoader
+{
+public:
+ spell_anhuur_divine_reckoning() : SpellScriptLoader("spell_anhuur_divine_reckoning") { }
+
+ class spell_anhuur_divine_reckoning_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_anhuur_divine_reckoning_AuraScript);
+
+ void OnPeriodic(AuraEffect const* aurEff)
+ {
+ if (Unit* caster = GetCaster())
+ {
+ CustomSpellValues values;
+ values.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
+ caster->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, values, GetTarget());
+ }
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_anhuur_divine_reckoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_anhuur_divine_reckoning_AuraScript();
+ }
+};
+
+void AddSC_boss_temple_guardian_anhuur()
+{
+ new boss_temple_guardian_anhuur();
+ new spell_anhuur_shield_of_light();
+ new spell_anhuur_disable_beacon_beams();
+ new spell_anhuur_activate_beacons();
+ new spell_anhuur_divine_reckoning();
+}
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h
new file mode 100644
index 00000000000..5cc83e4af9c
--- /dev/null
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HALLS_OF_ORIGINATION_H
+#define HALLS_OF_ORIGINATION_H
+
+#define HoOScriptName "instance_halls_of_origination"
+
+uint32 const EncounterCount = 12;
+
+enum Data
+{
+ // Bosses
+ DATA_TEMPLE_GUARDIAN_ANHUUR,
+ DATA_EARTHRAGER_PTAH,
+ DATA_VAULT_OF_LIGHTS,
+ DATA_FIRE_WARDEN,
+ DATA_EARTH_WARDEN,
+ DATA_WATER_WARDEN,
+ DATA_AIR_WARDEN,
+ DATA_ANRAPHET,
+ DATA_ISISET,
+ DATA_AMMUNAE,
+ DATA_SETESH,
+ DATA_RAJH,
+
+ // Temple Guardian Anhuur
+ DATA_ANHUUR_GUID,
+ DATA_ANHUUR_LEFT_BEACON,
+ DATA_ANHUUR_RIGHT_BEACON,
+ DATA_ANHUUR_BRIDGE,
+ DATA_ANHUUR_DOOR,
+
+ // Anraphet
+ DATA_BRANN_0_GUID,
+ DATA_DEAD_ELEMENTALS,
+ DATA_ANRAPHET_GUID,
+};
+
+enum Creatures
+{
+ BOSS_TEMPLE_GUARDIAN_ANHUUR = 39425,
+ NPC_CAVE_IN_STALKER = 40183,
+ NPC_SEARING_LIGHT = 40283,
+
+ BOSS_EARTHRAGER_PTAH = 39428,
+ NPC_BEETLE_STALKER = 40459, // Summons both Jeweled Scarab and Dustbone Horror
+ NPC_JEWELED_SCARAB = 40458,
+ NPC_DUSTBONE_HORROR = 40450,
+ NPC_QUICKSAND = 40503, // Summoned by a spell not in dbc (75550)
+
+ BOSS_ANRAPHET = 39788,
+ NPC_FIRE_WARDEN = 39800,
+ NPC_EARTH_WARDEN = 39801,
+ NPC_WATER_WARDEN = 39802,
+ NPC_AIR_WARDEN = 39803,
+
+ WARDEN_ENTRY_DATA_DELTA = NPC_FIRE_WARDEN - DATA_FIRE_WARDEN,
+
+ NPC_BRANN_BRONZEBEARD_0 = 39908,
+ NPC_OMEGA_STANCE = 41194,
+};
+
+enum GameObjects
+{
+ GO_ANHUURS_BRIDGE = 206506,
+ GO_DOODAD_ULDUM_ELEVATOR_COL01 = 207725,
+ GO_ANHUURS_DOOR = 202307,
+ GO_ANHUURS_RIGHT_BEACON = 203136,
+ GO_ANHUURS_LEFT_BEACON = 203133,
+
+ GO_VAULT_OF_LIGHTS_DOOR = 202313,
+ GO_SUN_MIRROR = 207726,
+ GO_ANRAPHET_DOOR = 202314,
+
+ GO_DOODAD_ULDUM_LIGHTMACHINE_01 = 207375,
+ GO_DOODAD_ULDUM_LIGHTMACHINE_02 = 207374,
+ GO_DOODAD_ULDUM_LIGHTMACHINE_03 = 207377,
+ GO_DOODAD_ULDUM_LIGHTMACHINE_04 = 207376,
+
+ GO_DOODAD_ULDUM_LASERBEAMS01 = 207662, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_02
+ GO_DOODAD_ULDUM_LASERBEAMS_01 = 207663, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_01
+ GO_DOODAD_ULDUM_LASERBEAMS_02 = 207664, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_04
+ GO_DOODAD_ULDUM_LASERBEAMS_03 = 207665, // Matches GO_DOODAD_ULDUM_LIGHTMACHINE_03
+};
+
+enum Misc
+{
+ AREA_TOMB_OF_THE_EARTHRAGER = 5610,
+ ACHIEV_VAULT_OF_LIGHTS_EVENT = 24212, // Faster Than The Speed Of Light
+ SPELL_VAULT_OF_LIGHTS_CREDIT = 94067, // Not in DBC
+};
+
+enum GlobalActions
+{
+ ACTION_ANRAPHET_INTRO,
+ ACTION_ELEMENTAL_DIED,
+ ACTION_ANRAPHET_DIED,
+ ACTION_OMEGA_TRIGGER,
+};
+
+template<class AI>
+CreatureAI* GetHallsOfOriginationAI(Creature* creature)
+{
+ if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(HoOScriptName))
+ return new AI(creature);
+ return NULL;
+}
+
+#endif // HALLS_OF_ORIGINATION_H
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp
new file mode 100644
index 00000000000..8c160bdc6f7
--- /dev/null
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "InstanceScript.h"
+#include "ScriptedCreature.h"
+#include "Map.h"
+#include "PoolMgr.h"
+#include "AccountMgr.h"
+#include "halls_of_origination.h"
+#include "Player.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+
+DoorData const doorData[] =
+{
+ {GO_ANHUURS_DOOR, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_ANHUURS_BRIDGE, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_ELEVATOR_COL01, DATA_TEMPLE_GUARDIAN_ANHUUR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_VAULT_OF_LIGHTS_DOOR, DATA_VAULT_OF_LIGHTS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LIGHTMACHINE_02, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LASERBEAMS01, DATA_EARTH_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LIGHTMACHINE_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LASERBEAMS_01, DATA_FIRE_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LIGHTMACHINE_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LASERBEAMS_03, DATA_WATER_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LIGHTMACHINE_04, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {GO_DOODAD_ULDUM_LASERBEAMS_02, DATA_AIR_WARDEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
+};
+
+class instance_halls_of_origination : public InstanceMapScript
+{
+ public:
+ instance_halls_of_origination() : InstanceMapScript(HoOScriptName, 644) { }
+
+ struct instance_halls_of_origination_InstanceMapScript : public InstanceScript
+ {
+ instance_halls_of_origination_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ {
+ SetBossNumber(EncounterCount);
+ LoadDoorData(doorData);
+ TempleGuardianAnhuurGUID = 0;
+ AnhuursBridgeGUID = 0;
+ AnhuursDoorGUID = 0;
+ AnhuurRightBeaconGUID = 0;
+ AnhuurLeftBeaconGUID = 0;
+ BrannBronzebeardGUID = 0;
+ AnraphetGUID = 0;
+ AnraphetDoorGUID = 0;
+ SunMirrorGUID = 0;
+ _deadElementals = 0;
+ }
+
+ void OnGameObjectCreate(GameObject* go)
+ {
+ switch (go->GetEntry())
+ {
+ case GO_ANHUURS_BRIDGE:
+ AnhuursBridgeGUID = go->GetGUID();
+ case GO_DOODAD_ULDUM_ELEVATOR_COL01:
+ case GO_VAULT_OF_LIGHTS_DOOR:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_01:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_02:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_03:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_04:
+ case GO_DOODAD_ULDUM_LASERBEAMS01:
+ case GO_DOODAD_ULDUM_LASERBEAMS_01:
+ case GO_DOODAD_ULDUM_LASERBEAMS_02:
+ case GO_DOODAD_ULDUM_LASERBEAMS_03:
+ AddDoor(go, true);
+ break;
+ case GO_ANHUURS_DOOR:
+ AnhuursDoorGUID = go->GetGUID();
+ AddDoor(go, true);
+ break;
+ case GO_ANHUURS_RIGHT_BEACON:
+ AnhuurRightBeaconGUID = go->GetGUID();
+ break;
+ case GO_ANHUURS_LEFT_BEACON:
+ AnhuurLeftBeaconGUID = go->GetGUID();
+ break;
+ case GO_SUN_MIRROR:
+ SunMirrorGUID = go->GetGUID();
+ break;
+ case GO_ANRAPHET_DOOR:
+ AnraphetDoorGUID = go->GetGUID();
+ break;
+ }
+ }
+
+ void OnGameObjectRemove(GameObject* go)
+ {
+ switch (go->GetEntry())
+ {
+ case GO_ANHUURS_BRIDGE:
+ case GO_DOODAD_ULDUM_ELEVATOR_COL01:
+ case GO_ANHUURS_DOOR:
+ case GO_VAULT_OF_LIGHTS_DOOR:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_01:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_02:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_03:
+ case GO_DOODAD_ULDUM_LIGHTMACHINE_04:
+ case GO_DOODAD_ULDUM_LASERBEAMS01:
+ case GO_DOODAD_ULDUM_LASERBEAMS_01:
+ case GO_DOODAD_ULDUM_LASERBEAMS_02:
+ case GO_DOODAD_ULDUM_LASERBEAMS_03:
+ AddDoor(go, false);
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* creature)
+ {
+ switch (creature->GetEntry())
+ {
+ case BOSS_TEMPLE_GUARDIAN_ANHUUR:
+ TempleGuardianAnhuurGUID = creature->GetGUID();
+ break;
+ case NPC_BRANN_BRONZEBEARD_0:
+ BrannBronzebeardGUID = creature->GetGUID();
+ break;
+ case BOSS_ANRAPHET:
+ AnraphetGUID = creature->GetGUID();
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 data) const
+ {
+ switch (data)
+ {
+ case DATA_DEAD_ELEMENTALS:
+ return _deadElementals;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 index) const
+ {
+ switch (index)
+ {
+ case DATA_ANHUUR_BRIDGE:
+ return AnhuursBridgeGUID;
+ case DATA_ANHUUR_DOOR:
+ return AnhuursDoorGUID;
+ case DATA_ANHUUR_LEFT_BEACON:
+ return AnhuurLeftBeaconGUID;
+ case DATA_ANHUUR_RIGHT_BEACON:
+ return AnhuurRightBeaconGUID;
+ case DATA_ANHUUR_GUID:
+ return TempleGuardianAnhuurGUID;
+ case DATA_BRANN_0_GUID:
+ return BrannBronzebeardGUID;
+ case DATA_ANRAPHET_GUID:
+ return AnraphetGUID;
+ }
+
+ return 0;
+ }
+
+ void IncreaseDeadElementals(uint32 inc)
+ {
+ _deadElementals += inc;
+ if (_deadElementals == 4)
+ {
+ if (GameObject* mirror = instance->GetGameObject(SunMirrorGUID))
+ mirror->SetGoState(GO_STATE_ACTIVE);
+ if (GameObject* door = instance->GetGameObject(AnraphetDoorGUID))
+ door->SetGoState(GO_STATE_ACTIVE);
+ }
+ }
+
+ void OnUnitDeath(Unit* unit)
+ {
+ Creature* creature = unit->ToCreature();
+ if (!creature)
+ return;
+
+ switch (creature->GetEntry())
+ {
+ case NPC_FIRE_WARDEN:
+ case NPC_EARTH_WARDEN:
+ case NPC_WATER_WARDEN:
+ case NPC_AIR_WARDEN:
+ uint32 data = creature->GetEntry() - WARDEN_ENTRY_DATA_DELTA;
+ SetBossState(data, IN_PROGRESS); // Needs to be set to IN_PROGRESS or else the gameobjects state won't be updated
+ SetBossState(data, DONE);
+ IncreaseDeadElementals(1);
+ if (Creature* brann = instance->GetCreature(BrannBronzebeardGUID))
+ brann->AI()->DoAction(ACTION_ELEMENTAL_DIED);
+ break;
+ }
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "H O " << GetBossSaveData() << _deadElementals;
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
+ }
+
+ void Load(const char* str)
+ {
+ if (!str)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(str);
+
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(str);
+ loadStream >> dataHead1 >> dataHead2;
+
+ if (dataHead1 == 'H' && dataHead2 == 'O')
+ {
+ for (uint32 i = 0; i < EncounterCount; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+ SetBossState(i, EncounterState(tmpState));
+ }
+ uint32 tmp;
+ loadStream >> tmp;
+ IncreaseDeadElementals(tmp);
+ }
+ else
+ OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ protected:
+ uint64 TempleGuardianAnhuurGUID;
+ uint64 AnhuursBridgeGUID;
+ uint64 AnhuursDoorGUID;
+ uint64 AnhuurRightBeaconGUID;
+ uint64 AnhuurLeftBeaconGUID;
+ uint64 BrannBronzebeardGUID;
+ uint64 AnraphetGUID;
+ uint64 AnraphetDoorGUID;
+ uint64 SunMirrorGUID;
+ uint32 _deadElementals;
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const
+ {
+ return new instance_halls_of_origination_InstanceMapScript(map);
+ }
+};
+
+void AddSC_instance_halls_of_origination()
+{
+ new instance_halls_of_origination();
+}
diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp
index 66834a68253..a44568e0472 100644
--- a/src/server/scripts/Kalimdor/zone_azshara.cpp
+++ b/src/server/scripts/Kalimdor/zone_azshara.cpp
@@ -16,523 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Azshara
-SD%Complete: 90
-SDComment: Quest support: 2744, 3141, 9364, 10994
-SDCategory: Azshara
-EndScriptData */
-
-/* ContentData
-mobs_spitelashes
-npc_loramus_thalipedes
-mob_rizzle_sprysprocket
-mob_depth_charge
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "Player.h"
-#include "SpellInfo.h"
-#include "WorldSession.h"
-
-/*######
-## mobs_spitelashes
-######*/
-
-class mobs_spitelashes : public CreatureScript
-{
-public:
- mobs_spitelashes() : CreatureScript("mobs_spitelashes") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mobs_spitelashesAI (creature);
- }
-
- struct mobs_spitelashesAI : public ScriptedAI
- {
- mobs_spitelashesAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 morphtimer;
- bool spellhit;
-
- void Reset()
- {
- morphtimer = 0;
- spellhit = false;
- }
-
- void EnterCombat(Unit* /*who*/) { }
-
- void SpellHit(Unit* unit, const SpellInfo* spell)
- {
- if (spellhit)
- return;
-
- switch (spell->Id)
- {
- case 118:
- case 12824:
- case 12825:
- case 12826:
- if (Player* player = unit->ToPlayer())
- if (player->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE)
- {
- spellhit = true;
- DoCast(me, 29124);
- }
- break;
- default:
- break;
- }
- }
-
- void UpdateAI(uint32 diff)
- {
- // we mustn't remove the Creature in the same round in which we cast the summon spell, otherwise there will be no summons
- if (spellhit && morphtimer >= 5000)
- {
- me->DespawnOrUnsummon();
- return;
- }
- // walk 5 seconds before summoning
- if (spellhit && morphtimer<5000)
- {
- morphtimer+=diff;
- if (morphtimer >= 5000)
- {
- DoCast(me, 28406); //summon copies
- DoCast(me, 6924); //visual explosion
- }
- }
- if (!UpdateVictim())
- return;
-
- /// @todo add abilities for the different creatures
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## npc_loramus_thalipedes
-######*/
-
-#define GOSSIP_HELLO_LT1 "Can you help me?"
-#define GOSSIP_HELLO_LT2 "Tell me your story"
-#define GOSSIP_SELECT_LT1 "Please continue"
-#define GOSSIP_SELECT_LT2 "I do not understand"
-#define GOSSIP_SELECT_LT3 "Indeed"
-#define GOSSIP_SELECT_LT4 "I will do this with or your help, Loramus"
-#define GOSSIP_SELECT_LT5 "Yes"
-
-class npc_loramus_thalipedes : public CreatureScript
-{
-public:
- npc_loramus_thalipedes() : CreatureScript("npc_loramus_thalipedes") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(2744);
- break;
-
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
- player->SEND_GOSSIP_MENU(1813, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+21:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
- player->SEND_GOSSIP_MENU(1814, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+22:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23);
- player->SEND_GOSSIP_MENU(1815, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+23:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24);
- player->SEND_GOSSIP_MENU(1816, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+24:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
- player->SEND_GOSSIP_MENU(1817, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+25:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(3141);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(2744) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- if (player->GetQuestStatus(3141) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
-/*####
-# mob_rizzle_sprysprocket
-####*/
-
-enum RizzleSprysprocketData
-{
- QUEST_CHASING_THE_MOONSTONE = 10994,
-
- MOB_DEPTH_CHARGE = 23025,
-
- SPELL_RIZZLE_BLACKJACK = 39865,
- SPELL_RIZZLE_ESCAPE = 39871,
- SPELL_RIZZLE_FROST_GRENADE = 40525,
- SPELL_DEPTH_CHARGE_TRAP = 38576,
- SPELL_PERIODIC_DEPTH_CHARGE = 39912,
- SPELL_GIVE_SOUTHFURY_MOONSTONE = 39886,
-
- SAY_RIZZLE_START = 0,
- SAY_RIZZLE_GRENADE = 1,
- SAY_RIZZLE_FINAL = 2,
- MSG_ESCAPE_NOTICE = 3
-};
-
-#define GOSSIP_GET_MOONSTONE "Hand over the Southfury moonstone and I'll let you go."
-
-Position const WPs[58] =
-{
- {3691.97f, -3962.41f, 35.9118f, 3.67f},
- {3675.02f, -3960.49f, 35.9118f, 3.67f},
- {3653.19f, -3958.33f, 33.9118f, 3.59f},
- {3621.12f, -3958.51f, 29.9118f, 3.48f},
- {3604.86f, -3963, 29.9118f, 3.48f},
- {3569.94f, -3970.25f, 29.9118f, 3.44f},
- {3541.03f, -3975.64f, 29.9118f, 3.41f},
- {3510.84f, -3978.71f, 29.9118f, 3.41f},
- {3472.7f, -3997.07f, 29.9118f, 3.35f},
- {3439.15f, -4014.55f, 29.9118f, 3.29f},
- {3412.8f, -4025.87f, 29.9118f, 3.25f},
- {3384.95f, -4038.04f, 29.9118f, 3.24f},
- {3346.77f, -4052.93f, 29.9118f, 3.22f},
- {3299.56f, -4071.59f, 29.9118f, 3.20f},
- {3261.22f, -4080.38f, 30.9118f, 3.19f},
- {3220.68f, -4083.09f, 31.9118f, 3.18f},
- {3187.11f, -4070.45f, 33.9118f, 3.16f},
- {3162.78f, -4062.75f, 33.9118f, 3.15f},
- {3136.09f, -4050.32f, 33.9118f, 3.07f},
- {3119.47f, -4044.51f, 36.0363f, 3.07f},
- {3098.95f, -4019.8f, 33.9118f, 3.07f},
- {3073.07f, -4011.42f, 33.9118f, 3.07f},
- {3051.71f, -3993.37f, 33.9118f, 3.02f},
- {3027.52f, -3978.6f, 33.9118f, 3.00f},
- {3003.78f, -3960.14f, 33.9118f, 2.98f},
- {2977.99f, -3941.98f, 31.9118f, 2.96f},
- {2964.57f, -3932.07f, 30.9118f, 2.96f},
- {2947.9f, -3921.31f, 29.9118f, 2.96f},
- {2924.91f, -3910.8f, 29.9118f, 2.94f},
- {2903.04f, -3896.42f, 29.9118f, 2.93f},
- {2884.75f, -3874.03f, 29.9118f, 2.90f},
- {2868.19f, -3851.48f, 29.9118f, 2.82f},
- {2854.62f, -3819.72f, 29.9118f, 2.80f},
- {2825.53f, -3790.4f, 29.9118f, 2.744f},
- {2804.31f, -3773.05f, 29.9118f, 2.71f},
- {2769.78f, -3763.57f, 29.9118f, 2.70f},
- {2727.23f, -3745.92f, 30.9118f, 2.69f},
- {2680.12f, -3737.49f, 30.9118f, 2.67f},
- {2647.62f, -3739.94f, 30.9118f, 2.66f},
- {2616.6f, -3745.75f, 30.9118f, 2.64f},
- {2589.38f, -3731.97f, 30.9118f, 2.61f},
- {2562.94f, -3722.35f, 31.9118f, 2.56f},
- {2521.05f, -3716.6f, 31.9118f, 2.55f},
- {2485.26f, -3706.67f, 31.9118f, 2.51f},
- {2458.93f, -3696.67f, 31.9118f, 2.51f},
- {2432, -3692.03f, 31.9118f, 2.46f},
- {2399.59f, -3681.97f, 31.9118f, 2.45f},
- {2357.75f, -3666.6f, 31.9118f, 2.44f},
- {2311.99f, -3656.88f, 31.9118f, 2.94f},
- {2263.41f, -3649.55f, 31.9118f, 3.02f},
- {2209.05f, -3641.76f, 31.9118f, 2.99f},
- {2164.83f, -3637.64f, 31.9118f, 3.15f},
- {2122.42f, -3639, 31.9118f, 3.21f},
- {2075.73f, -3643.59f, 31.9118f, 3.22f},
- {2033.59f, -3649.52f, 31.9118f, 3.42f},
- {1985.22f, -3662.99f, 31.9118f, 3.42f},
- {1927.09f, -3679.56f, 33.9118f, 3.42f},
- {1873.57f, -3695.32f, 33.9118f, 3.44f}
-};
-
-class mob_rizzle_sprysprocket : public CreatureScript
-{
-public:
- mob_rizzle_sprysprocket() : CreatureScript("mob_rizzle_sprysprocket") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF + 1 && player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) == QUEST_STATUS_INCOMPLETE)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->CastSpell(player, SPELL_GIVE_SOUTHFURY_MOONSTONE, true);
- CAST_AI(mob_rizzle_sprysprocket::mob_rizzle_sprysprocketAI, creature->AI())->MustDieTimer = 3000;
- CAST_AI(mob_rizzle_sprysprocket::mob_rizzle_sprysprocketAI, creature->AI())->MustDie = true;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) != QUEST_STATUS_INCOMPLETE)
- return true;
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GET_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(10811, creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_rizzle_sprysprocketAI (creature);
- }
-
- struct mob_rizzle_sprysprocketAI : public ScriptedAI
- {
- mob_rizzle_sprysprocketAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 SpellEscapeTimer;
- uint32 TeleportTimer;
- uint32 CheckTimer;
- uint32 GrenadeTimer;
- uint32 MustDieTimer;
- uint32 CurrWP;
-
- uint64 PlayerGUID;
-
- bool MustDie;
- bool Escape;
- bool ContinueWP;
- bool Reached;
-
- void Reset()
- {
- SpellEscapeTimer = 1300;
- TeleportTimer = 3500;
- CheckTimer = 10000;
- GrenadeTimer = 30000;
- MustDieTimer = 3000;
- CurrWP = 0;
-
- PlayerGUID = 0;
-
- MustDie = false;
- Escape = false;
- ContinueWP = false;
- Reached = false;
- }
-
- void UpdateAI(uint32 diff)
- {
- if (MustDie)
- {
- if (MustDieTimer <= diff)
- {
- me->DespawnOrUnsummon();
- return;
- } else MustDieTimer -= diff;
- }
-
- if (!Escape)
- {
- if (!PlayerGUID)
- return;
-
- if (SpellEscapeTimer <= diff)
- {
- DoCast(me, SPELL_RIZZLE_ESCAPE, false);
- SpellEscapeTimer = 10000;
- } else SpellEscapeTimer -= diff;
-
- if (TeleportTimer <= diff)
- {
- // temp solution - unit can't be teleported by core using spelleffect 5, only players
- DoTeleportTo(3706.39f, -3969.15f, 35.9118f);
-
- //begin swimming and summon depth charges
- Player* player = Unit::GetPlayer(*me, PlayerGUID);
- if (!player)
- return;
-
- Talk(MSG_ESCAPE_NOTICE, player->GetGUID());
- DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE);
- me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING);
- me->SetSpeed(MOVE_RUN, 0.85f, true);
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]);
- Escape = true;
- } else TeleportTimer -= diff;
-
- return;
- }
-
- if (ContinueWP)
- {
- me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]);
- ContinueWP = false;
- }
-
- if (GrenadeTimer <= diff)
- {
- Player* player = Unit::GetPlayer(*me, PlayerGUID);
- if (player)
- {
- Talk(SAY_RIZZLE_GRENADE, player->GetGUID());
- DoCast(player, SPELL_RIZZLE_FROST_GRENADE, true);
- }
- GrenadeTimer = 30000;
- } else GrenadeTimer -= diff;
-
- if (CheckTimer <= diff)
- {
- Player* player = Unit::GetPlayer(*me, PlayerGUID);
- if (!player)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- if (me->IsWithinDist(player, 10) && me->GetPositionX() > player->GetPositionX() && !Reached)
- {
- Talk(SAY_RIZZLE_FINAL);
- me->SetUInt32Value(UNIT_NPC_FLAGS, 1);
- me->setFaction(35);
- me->GetMotionMaster()->MoveIdle();
- me->RemoveAurasDueToSpell(SPELL_PERIODIC_DEPTH_CHARGE);
- Reached = true;
- }
-
- CheckTimer = 1000;
- } else CheckTimer -= diff;
-
- }
-
- void SendText(int32 iTextEntry, Player* player)
- {
- LocaleConstant loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
- const char* text = sObjectMgr->GetTrinityString(iTextEntry, loc_idx);
- sWorld->SendServerMessage(SERVER_MSG_STRING, text, player);
- }
-
- void AttackStart(Unit* who)
- {
- if (!who || PlayerGUID)
- return;
-
- Player* player = who->ToPlayer();
-
- if (player && player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) == QUEST_STATUS_INCOMPLETE)
- {
- PlayerGUID = who->GetGUID();
- Talk(SAY_RIZZLE_START);
- DoCast(who, SPELL_RIZZLE_BLACKJACK, false);
- return;
- }
- }
-
- void EnterCombat(Unit* /*who*/) {}
-
- void MovementInform(uint32 type, uint32 id)
- {
- if (type != POINT_MOTION_TYPE)
- return;
-
- if (id == 57)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- ++CurrWP;
- ContinueWP = true;
- }
- };
-};
-
-/*####
-# mob_depth_charge
-####*/
-class mob_depth_charge : public CreatureScript
-{
-public:
- mob_depth_charge() : CreatureScript("mob_depth_charge") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_depth_chargeAI (creature);
- }
-
- struct mob_depth_chargeAI : public ScriptedAI
- {
- mob_depth_chargeAI(Creature* creature) : ScriptedAI(creature) {}
-
- bool WeMustDie;
- uint32 WeMustDieTimer;
-
- void Reset()
- {
- me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- WeMustDie = false;
- WeMustDieTimer = 1000;
- }
-
- void UpdateAI(uint32 diff)
- {
- if (WeMustDie)
- {
- if (WeMustDieTimer <= diff)
- me->DespawnOrUnsummon();
- else
- WeMustDieTimer -= diff;
- }
- return;
- }
-
- void MoveInLineOfSight(Unit* who)
- {
- if (!who)
- return;
-
- if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 5))
- {
- DoCast(who, SPELL_DEPTH_CHARGE_TRAP);
- WeMustDie = true;
- return;
- }
- }
-
- void AttackStart(Unit* /*who*/) {}
-
- void EnterCombat(Unit* /*who*/) {}
- };
-};
-
void AddSC_azshara()
{
- new mobs_spitelashes();
- new npc_loramus_thalipedes();
- new mob_rizzle_sprysprocket();
- new mob_depth_charge();
}
diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
index cb5c36e4412..f34c658cb64 100644
--- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
+++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp
@@ -19,7 +19,7 @@
/* ScriptData
SDName: Azuremyst_Isle
SD%Complete: 75
-SDComment: Quest support: 9283, 9537, 9582, 9554, 9531, ? (special flight path, proper model for mount missing). Injured Draenei cosmetic only, 9582.
+SDComment: Quest support: 9283, 9537, 9582, 9554, ? (special flight path, proper model for mount missing). Injured Draenei cosmetic only, 9582.
SDCategory: Azuremyst Isle
EndScriptData */
@@ -28,7 +28,6 @@ npc_draenei_survivor
npc_engineer_spark_overgrind
npc_injured_draenei
npc_magwin
-npc_geezle
go_ravager_cage
npc_death_ravager
EndContentData */
@@ -763,7 +762,6 @@ void AddSC_azuremyst_isle()
new npc_engineer_spark_overgrind();
new npc_injured_draenei();
new npc_magwin();
- new npc_geezle();
new npc_death_ravager();
new go_ravager_cage();
new npc_stillpine_capitive();
diff --git a/src/server/scripts/Kalimdor/zone_darkshore.cpp b/src/server/scripts/Kalimdor/zone_darkshore.cpp
index c7115a9098b..b98c51b552e 100644
--- a/src/server/scripts/Kalimdor/zone_darkshore.cpp
+++ b/src/server/scripts/Kalimdor/zone_darkshore.cpp
@@ -16,379 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Darkshore
-SD%Complete: 100
-SDComment: Quest support: 731, 2078, 5321
-SDCategory: Darkshore
-EndScriptData */
-
-/* ContentData
-npc_kerlonian
-npc_prospector_remtravel
-npc_threshwackonator
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "ScriptedEscortAI.h"
-#include "ScriptedFollowerAI.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-/*####
-# npc_kerlonian
-####*/
-
-enum Kerlonian
-{
- SAY_KER_START = 0,
- EMOTE_KER_SLEEP = 1,
- SAY_KER_SLEEP = 2,
- SAY_KER_ALERT_1 = 3,
- SAY_KER_END = 4,
- EMOTE_KER_AWAKEN = 5,
-
- SPELL_SLEEP_VISUAL = 25148,
- SPELL_AWAKEN = 17536,
- QUEST_SLEEPER_AWAKENED = 5321,
- NPC_LILADRIS = 11219, //attackers entries unknown
- FACTION_KER_ESCORTEE = 113
-};
-
-/// @todo make concept similar as "ringo" -escort. Find a way to run the scripted attacks, _if_ player are choosing road.
-class npc_kerlonian : public CreatureScript
-{
-public:
- npc_kerlonian() : CreatureScript("npc_kerlonian") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_SLEEPER_AWAKENED)
- {
- if (npc_kerlonianAI* pKerlonianAI = CAST_AI(npc_kerlonian::npc_kerlonianAI, creature->AI()))
- {
- creature->SetStandState(UNIT_STAND_STATE_STAND);
- creature->AI()->Talk(SAY_KER_START, player->GetGUID());
- pKerlonianAI->StartFollow(player, FACTION_KER_ESCORTEE, quest);
- }
- }
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_kerlonianAI(creature);
- }
-
- struct npc_kerlonianAI : public FollowerAI
- {
- npc_kerlonianAI(Creature* creature) : FollowerAI(creature) { }
-
- uint32 FallAsleepTimer;
-
- void Reset()
- {
- FallAsleepTimer = urand(10000, 45000);
- }
-
- void MoveInLineOfSight(Unit* who)
- {
- FollowerAI::MoveInLineOfSight(who);
-
- if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && who->GetEntry() == NPC_LILADRIS)
- {
- if (me->IsWithinDistInMap(who, INTERACTION_DISTANCE*5))
- {
- if (Player* player = GetLeaderForFollower())
- {
- if (player->GetQuestStatus(QUEST_SLEEPER_AWAKENED) == QUEST_STATUS_INCOMPLETE)
- player->GroupEventHappens(QUEST_SLEEPER_AWAKENED, me);
-
- Talk(SAY_KER_END);
- }
-
- SetFollowComplete();
- }
- }
- }
-
- void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell)
- {
- if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_AWAKEN)
- ClearSleeping();
- }
-
- void SetSleeping()
- {
- SetFollowPaused(true);
-
- Talk(EMOTE_KER_SLEEP);
-
- Talk(SAY_KER_SLEEP);
-
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- DoCast(me, SPELL_SLEEP_VISUAL, false);
- }
-
- void ClearSleeping()
- {
- me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL);
- me->SetStandState(UNIT_STAND_STATE_STAND);
-
- Talk(EMOTE_KER_AWAKEN);
-
- SetFollowPaused(false);
- }
-
- void UpdateFollowerAI(uint32 Diff)
- {
- if (!UpdateVictim())
- {
- if (!HasFollowState(STATE_FOLLOW_INPROGRESS))
- return;
-
- if (!HasFollowState(STATE_FOLLOW_PAUSED))
- {
- if (FallAsleepTimer <= Diff)
- {
- SetSleeping();
- FallAsleepTimer = urand(25000, 90000);
- }
- else
- FallAsleepTimer -= Diff;
- }
-
- return;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*####
-# npc_prospector_remtravel
-####*/
-
-enum Remtravel
-{
- SAY_REM_START = 0,
- SAY_REM_AGGRO = 1,
- SAY_REM_RAMP1_1 = 2,
- SAY_REM_RAMP1_2 = 3,
- SAY_REM_BOOK = 4,
- SAY_REM_TENT1_1 = 5,
- SAY_REM_TENT1_2 = 6,
- SAY_REM_MOSS = 7,
- EMOTE_REM_MOSS = 8,
- SAY_REM_MOSS_PROGRESS = 9,
- SAY_REM_PROGRESS = 10,
- SAY_REM_REMEMBER = 11,
- EMOTE_REM_END = 12,
-
- FACTION_ESCORTEE = 10,
- QUEST_ABSENT_MINDED_PT2 = 731,
- NPC_GRAVEL_SCOUT = 2158,
- NPC_GRAVEL_BONE = 2159,
- NPC_GRAVEL_GEO = 2160
-};
-
-class npc_prospector_remtravel : public CreatureScript
-{
-public:
- npc_prospector_remtravel() : CreatureScript("npc_prospector_remtravel") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_ABSENT_MINDED_PT2)
- {
- if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_remtravel::npc_prospector_remtravelAI, creature->AI()))
- pEscortAI->Start(false, false, player->GetGUID());
-
- creature->setFaction(FACTION_ESCORTEE);
- }
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_prospector_remtravelAI(creature);
- }
-
- struct npc_prospector_remtravelAI : public npc_escortAI
- {
- npc_prospector_remtravelAI(Creature* creature) : npc_escortAI(creature) {}
-
- void WaypointReached(uint32 waypointId)
- {
- if (Player* player = GetPlayerForEscort())
- {
- switch (waypointId)
- {
- case 0:
- Talk(SAY_REM_START, player->GetGUID());
- break;
- case 5:
- Talk(SAY_REM_RAMP1_1, player->GetGUID());
- break;
- case 6:
- DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- break;
- case 9:
- Talk(SAY_REM_RAMP1_2, player->GetGUID());
- break;
- case 14:
- //depend quest rewarded?
- Talk(SAY_REM_BOOK, player->GetGUID());
- break;
- case 15:
- Talk(SAY_REM_TENT1_1, player->GetGUID());
- break;
- case 16:
- DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- break;
- case 17:
- Talk(SAY_REM_TENT1_2, player->GetGUID());
- break;
- case 26:
- Talk(SAY_REM_MOSS, player->GetGUID());
- break;
- case 27:
- Talk(EMOTE_REM_MOSS, player->GetGUID());
- break;
- case 28:
- Talk(SAY_REM_MOSS_PROGRESS, player->GetGUID());
- break;
- case 29:
- DoSpawnCreature(NPC_GRAVEL_SCOUT, -15.0f, 3.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- DoSpawnCreature(NPC_GRAVEL_BONE, -15.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- DoSpawnCreature(NPC_GRAVEL_GEO, -15.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- break;
- case 31:
- Talk(SAY_REM_PROGRESS, player->GetGUID());
- break;
- case 41:
- Talk(SAY_REM_REMEMBER, player->GetGUID());
- break;
- case 42:
- Talk(EMOTE_REM_END, player->GetGUID());
- player->GroupEventHappens(QUEST_ABSENT_MINDED_PT2, me);
- break;
- }
- }
- }
-
- void Reset() {}
-
- void EnterCombat(Unit* who)
- {
- if (urand(0, 1))
- Talk(SAY_REM_AGGRO, who->GetGUID());
- }
-
- void JustSummoned(Creature* /*pSummoned*/)
- {
- //unsure if it should be any
- //pSummoned->AI()->AttackStart(me);
- }
- };
-
-};
-
-/*####
-# npc_threshwackonator
-####*/
-
-enum Threshwackonator
-{
- EMOTE_START = 0,
- SAY_AT_CLOSE = 1,
- QUEST_GYROMAST_REV = 2078,
- NPC_GELKAK = 6667,
- FACTION_HOSTILE = 14
-};
-
-#define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key"
-
-class npc_threshwackonator : public CreatureScript
-{
-public:
- npc_threshwackonator() : CreatureScript("npc_threshwackonator") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->CLOSE_GOSSIP_MENU();
-
- if (npc_threshwackonatorAI* pThreshAI = CAST_AI(npc_threshwackonator::npc_threshwackonatorAI, creature->AI()))
- {
- creature->AI()->Talk(EMOTE_START);
- pThreshAI->StartFollow(player);
- }
- }
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (player->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INSERT_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_threshwackonatorAI(creature);
- }
-
- struct npc_threshwackonatorAI : public FollowerAI
- {
- npc_threshwackonatorAI(Creature* creature) : FollowerAI(creature) { }
-
- void Reset() { }
-
- void MoveInLineOfSight(Unit* who)
- {
- FollowerAI::MoveInLineOfSight(who);
-
- if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && who->GetEntry() == NPC_GELKAK)
- {
- if (me->IsWithinDistInMap(who, 10.0f))
- {
- Talk(SAY_AT_CLOSE, who->GetGUID());
- DoAtEnd();
- }
- }
- }
-
- void DoAtEnd()
- {
- me->setFaction(FACTION_HOSTILE);
-
- if (Player* pHolder = GetLeaderForFollower())
- me->AI()->AttackStart(pHolder);
-
- SetFollowComplete();
- }
- };
-
-};
-
void AddSC_darkshore()
{
- new npc_kerlonian();
- new npc_prospector_remtravel();
- new npc_threshwackonator();
}
diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp
index b21cb28e0d5..ab37f94ce40 100644
--- a/src/server/scripts/Kalimdor/zone_desolace.cpp
+++ b/src/server/scripts/Kalimdor/zone_desolace.cpp
@@ -19,14 +19,12 @@
/* ScriptData
SDName: Desolace
SD%Complete: 100
-SDComment: Quest support: 5561
+SDComment: Quest support: 5561, 5581
SDCategory: Desolace
EndScriptData */
/* ContentData
npc_aged_dying_ancient_kodo
-go_iruxos
-npc_dalinda_malem
go_demon_portal
EndContentData */
@@ -118,104 +116,6 @@ public:
};
/*######
-## go_iruxos
-## Hand of Iruxos
-######*/
-
-enum Iruxos
-{
- QUEST_HAND_IRUXOS = 5381,
- NPC_DEMON_SPIRIT = 11876,
-};
-
-class go_iruxos : public GameObjectScript
-{
- public:
- go_iruxos() : GameObjectScript("go_iruxos") { }
-
- bool OnGossipHello(Player* player, GameObject* go)
- {
- if (player->GetQuestStatus(QUEST_HAND_IRUXOS) == QUEST_STATUS_INCOMPLETE && !go->FindNearestCreature(NPC_DEMON_SPIRIT, 25.0f, true))
- player->SummonCreature(NPC_DEMON_SPIRIT, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
-
- return true;
- }
-};
-
-/*######
-## npc_dalinda_malem. Quest 1440
-######*/
-
-enum Dalinda
-{
- QUEST_RETURN_TO_VAHLARRIEL = 1440
-};
-
-class npc_dalinda : public CreatureScript
-{
-public:
- npc_dalinda() : CreatureScript("npc_dalinda") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_RETURN_TO_VAHLARRIEL)
- {
- if (npc_escortAI* pEscortAI = CAST_AI(npc_dalinda::npc_dalindaAI, creature->AI()))
- {
- pEscortAI->Start(true, false, player->GetGUID());
- creature->setFaction(113);
- }
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_dalindaAI(creature);
- }
-
- struct npc_dalindaAI : public npc_escortAI
- {
- npc_dalindaAI(Creature* creature) : npc_escortAI(creature) { }
-
- void WaypointReached(uint32 waypointId)
- {
- Player* player = GetPlayerForEscort();
-
- switch (waypointId)
- {
- case 1:
- me->IsStandState();
- break;
- case 15:
- if (player)
- player->GroupEventHappens(QUEST_RETURN_TO_VAHLARRIEL, me);
- break;
- }
- }
-
- void EnterCombat(Unit* /*who*/) { }
-
- void Reset() {}
-
- void JustDied(Unit* /*killer*/)
- {
- if (Player* player = GetPlayerForEscort())
- player->FailQuest(QUEST_RETURN_TO_VAHLARRIEL);
- return;
- }
-
- void UpdateAI(uint32 Diff)
- {
- npc_escortAI::UpdateAI(Diff);
- if (!UpdateVictim())
- return;
- DoMeleeAttackIfReady();
- }
- };
-};
-
-/*######
## go_demon_portal
######*/
@@ -246,7 +146,5 @@ class go_demon_portal : public GameObjectScript
void AddSC_desolace()
{
new npc_aged_dying_ancient_kodo();
- new go_iruxos();
- new npc_dalinda();
new go_demon_portal();
}
diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp
index 801ffbc038e..6b82ee99f0a 100644
--- a/src/server/scripts/Kalimdor/zone_durotar.cpp
+++ b/src/server/scripts/Kalimdor/zone_durotar.cpp
@@ -17,13 +17,12 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
-#include "Vehicle.h"
#include "SpellScript.h"
#include "Player.h"
/*######
-##Quest 5441: Lazy Peons
-##npc_lazy_peon
+## Quest 25134: Lazy Peons
+## npc_lazy_peon
######*/
enum LazyPeonYells
@@ -33,10 +32,10 @@ enum LazyPeonYells
enum LazyPeon
{
- QUEST_LAZY_PEONS = 5441,
- GO_LUMBERPILE = 175784,
- SPELL_BUFF_SLEEP = 17743,
- SPELL_AWAKEN_PEON = 19938
+ QUEST_LAZY_PEONS = 25134,
+ GO_LUMBERPILE = 175784,
+ SPELL_BUFF_SLEEP = 17743,
+ SPELL_AWAKEN_PEON = 19938
};
class npc_lazy_peon : public CreatureScript
@@ -94,7 +93,7 @@ public:
if (RebuffTimer <= Diff)
{
DoCast(me, SPELL_BUFF_SLEEP);
- RebuffTimer = 300000; //Rebuff agian in 5 minutes
+ RebuffTimer = 300000; //Rebuff agian in 5 minutes
}
else
RebuffTimer -= Diff;
@@ -105,432 +104,6 @@ public:
};
};
-enum Texts
-{
- // Tiger Matriarch Credit
- SAY_MATRIARCH_AGGRO = 0,
-
- // Troll Volunteer
- SAY_VOLUNTEER_START = 0,
- SAY_VOLUNTEER_END = 1,
-};
-
-enum Spells
-{
- // Tiger Matriarch Credit
- SPELL_SUMMON_MATRIARCH = 75187,
- SPELL_NO_SUMMON_AURA = 75213,
- SPELL_DETECT_INVIS = 75180,
- SPELL_SUMMON_ZENTABRA_TRIGGER = 75212,
-
- // Tiger Matriarch
- SPELL_POUNCE = 61184,
- SPELL_FURIOUS_BITE = 75164,
- SPELL_SUMMON_ZENTABRA = 75181,
- SPELL_SPIRIT_OF_THE_TIGER_RIDER = 75166,
- SPELL_EJECT_PASSENGERS = 50630,
-
- // Troll Volunteer
- SPELL_VOLUNTEER_AURA = 75076,
- SPELL_PETACT_AURA = 74071,
- SPELL_QUEST_CREDIT = 75106,
- SPELL_MOUNTING_CHECK = 75420,
- SPELL_TURNIN = 73953,
- SPELL_AOE_TURNIN = 75107,
-
- // Vol'jin War Drums
- SPELL_MOTIVATE_1 = 75088,
- SPELL_MOTIVATE_2 = 75086,
-};
-
-enum Creatures
-{
- // Tiger Matriarch Credit
- NPC_TIGER_VEHICLE = 40305,
-
- // Troll Volunteer
- NPC_URUZIN = 40253,
- NPC_VOLUNTEER_1 = 40264,
- NPC_VOLUNTEER_2 = 40260,
-
- // Vol'jin War Drums
- NPC_CITIZEN_1 = 40256,
- NPC_CITIZEN_2 = 40257,
-};
-
-enum Events
-{
- // Tiger Matriarch Credit
- EVENT_CHECK_SUMMON_AURA = 1,
-
- // Tiger Matriarch
- EVENT_POUNCE = 2,
- EVENT_NOSUMMON = 3,
-};
-
-enum Points
-{
- POINT_URUZIN = 4026400,
-};
-
-class npc_tiger_matriarch_credit : public CreatureScript
-{
- public:
- npc_tiger_matriarch_credit() : CreatureScript("npc_tiger_matriarch_credit") { }
-
- struct npc_tiger_matriarch_creditAI : public ScriptedAI
- {
- npc_tiger_matriarch_creditAI(Creature* creature) : ScriptedAI(creature)
- {
- SetCombatMovement(false);
- events.ScheduleEvent(EVENT_CHECK_SUMMON_AURA, 2000);
- }
-
- void UpdateAI(uint32 diff)
- {
- events.Update(diff);
-
- if (events.ExecuteEvent() == EVENT_CHECK_SUMMON_AURA)
- {
- std::list<Creature*> tigers;
- GetCreatureListWithEntryInGrid(tigers, me, NPC_TIGER_VEHICLE, 15.0f);
- if (!tigers.empty())
- {
- for (std::list<Creature*>::iterator itr = tigers.begin(); itr != tigers.end(); ++itr)
- {
- if (!(*itr)->isSummon())
- continue;
-
- if (Unit* summoner = (*itr)->ToTempSummon()->GetSummoner())
- if (!summoner->HasAura(SPELL_NO_SUMMON_AURA) && !summoner->HasAura(SPELL_SUMMON_ZENTABRA_TRIGGER)
- && !summoner->isInCombat())
- {
- me->AddAura(SPELL_NO_SUMMON_AURA, summoner);
- me->AddAura(SPELL_DETECT_INVIS, summoner);
- summoner->CastSpell(summoner, SPELL_SUMMON_MATRIARCH, true);
- Talk(SAY_MATRIARCH_AGGRO, summoner->GetGUID());
- }
- }
- }
-
- events.ScheduleEvent(EVENT_CHECK_SUMMON_AURA, 5000);
- }
- }
-
- private:
- EventMap events;
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_tiger_matriarch_creditAI(creature);
- }
-};
-
-class npc_tiger_matriarch : public CreatureScript
-{
- public:
- npc_tiger_matriarch() : CreatureScript("npc_tiger_matriarch") {}
-
- struct npc_tiger_matriarchAI : public ScriptedAI
- {
- npc_tiger_matriarchAI(Creature* creature) : ScriptedAI(creature),
- _tigerGuid(0)
- {
- }
-
- void EnterCombat(Unit* /*target*/)
- {
- _events.Reset();
- _events.ScheduleEvent(EVENT_POUNCE, 100);
- _events.ScheduleEvent(EVENT_NOSUMMON, 50000);
- }
-
- void IsSummonedBy(Unit* summoner)
- {
- if (summoner->GetTypeId() != TYPEID_PLAYER || !summoner->GetVehicle())
- return;
-
- _tigerGuid = summoner->GetVehicle()->GetBase()->GetGUID();
- if (Unit* tiger = ObjectAccessor::GetUnit(*me, _tigerGuid))
- {
- me->AddThreat(tiger, 500000.0f);
- DoCast(me, SPELL_FURIOUS_BITE);
- }
- }
-
- void KilledUnit(Unit* victim)
- {
- if (victim->GetTypeId() != TYPEID_UNIT || !victim->isSummon())
- return;
-
- if (Unit* vehSummoner = victim->ToTempSummon()->GetSummoner())
- {
- vehSummoner->RemoveAurasDueToSpell(SPELL_NO_SUMMON_AURA);
- vehSummoner->RemoveAurasDueToSpell(SPELL_DETECT_INVIS);
- vehSummoner->RemoveAurasDueToSpell(SPELL_SPIRIT_OF_THE_TIGER_RIDER);
- vehSummoner->RemoveAurasDueToSpell(SPELL_SUMMON_ZENTABRA_TRIGGER);
- }
- me->DespawnOrUnsummon();
- }
-
- void DamageTaken(Unit* attacker, uint32& damage)
- {
- if (!attacker->isSummon())
- return;
-
- if (HealthBelowPct(20))
- {
- damage = 0;
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- if (Unit* vehSummoner = attacker->ToTempSummon()->GetSummoner())
- {
- vehSummoner->AddAura(SPELL_SUMMON_ZENTABRA_TRIGGER, vehSummoner);
- vehSummoner->CastSpell(vehSummoner, SPELL_SUMMON_ZENTABRA, true);
- attacker->CastSpell(attacker, SPELL_EJECT_PASSENGERS, true);
- vehSummoner->RemoveAurasDueToSpell(SPELL_NO_SUMMON_AURA);
- vehSummoner->RemoveAurasDueToSpell(SPELL_DETECT_INVIS);
- vehSummoner->RemoveAurasDueToSpell(SPELL_SPIRIT_OF_THE_TIGER_RIDER);
- vehSummoner->RemoveAurasDueToSpell(SPELL_SUMMON_ZENTABRA_TRIGGER);
- }
-
- me->DespawnOrUnsummon();
- }
- }
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- if (!_tigerGuid)
- return;
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_POUNCE:
- DoCastVictim(SPELL_POUNCE);
- _events.ScheduleEvent(EVENT_POUNCE, 30000);
- break;
- case EVENT_NOSUMMON: // Reapply SPELL_NO_SUMMON_AURA
- if (Unit* tiger = ObjectAccessor::GetUnit(*me, _tigerGuid))
- {
- if (tiger->isSummon())
- if (Unit* vehSummoner = tiger->ToTempSummon()->GetSummoner())
- me->AddAura(SPELL_NO_SUMMON_AURA, vehSummoner);
- }
- _events.ScheduleEvent(EVENT_NOSUMMON, 50000);
- break;
- default:
- break;
- }
- }
-
- DoMeleeAttackIfReady();
- }
-
- private:
- EventMap _events;
- uint64 _tigerGuid;
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_tiger_matriarchAI(creature);
- }
-};
-
-// These models was found in sniff.
-/// @todo generalize these models with race from dbc
-uint32 const trollmodel[] =
-{11665, 11734, 11750, 12037, 12038, 12042, 12049, 12849, 13529, 14759, 15570, 15701,
-15702, 1882, 1897, 1976, 2025, 27286, 2734, 2735, 4084, 4085, 4087, 4089, 4231, 4357,
-4358, 4360, 4361, 4362, 4363, 4370, 4532, 4537, 4540, 4610, 6839, 7037, 9767, 9768};
-
-class npc_troll_volunteer : public CreatureScript
-{
- public:
- npc_troll_volunteer() : CreatureScript("npc_troll_volunteer") { }
-
- struct npc_troll_volunteerAI : public ScriptedAI
- {
- npc_troll_volunteerAI(Creature* creature) : ScriptedAI(creature)
- {
- }
-
- void InitializeAI()
- {
- if (me->isDead() || !me->GetOwner())
- return;
-
- Reset();
-
- switch (urand(0, 3))
- {
- case 0:
- _mountModel = 6471;
- break;
- case 1:
- _mountModel = 6473;
- break;
- case 2:
- _mountModel = 6469;
- break;
- default:
- _mountModel = 6472;
- break;
- }
- me->SetDisplayId(trollmodel[urand(0, 39)]);
- if (Player* player = me->GetOwner()->ToPlayer())
- me->GetMotionMaster()->MoveFollow(player, 5.0f, float(rand_norm() + 1.0f) * M_PI / 3.0f * 4.0f);
- }
-
- void Reset()
- {
- _complete = false;
- me->AddAura(SPELL_VOLUNTEER_AURA, me);
- me->AddAura(SPELL_MOUNTING_CHECK, me);
- DoCast(me, SPELL_PETACT_AURA);
- me->SetReactState(REACT_PASSIVE);
- Talk(SAY_VOLUNTEER_START);
- }
-
- // This is needed for mount check aura to know what mountmodel the npc got stored
- uint32 GetMountId()
- {
- return _mountModel;
- }
-
- void MovementInform(uint32 type, uint32 id)
- {
- if (type != POINT_MOTION_TYPE)
- return;
- if (id == POINT_URUZIN)
- me->DespawnOrUnsummon();
- }
-
- void SpellHit(Unit* caster, SpellInfo const* spell)
- {
- if (spell->Id == SPELL_AOE_TURNIN && caster->GetEntry() == NPC_URUZIN && !_complete)
- {
- _complete = true; // Preventing from giving credit twice
- DoCast(me, SPELL_TURNIN);
- DoCast(me, SPELL_QUEST_CREDIT);
- me->RemoveAurasDueToSpell(SPELL_MOUNTING_CHECK);
- me->Dismount();
- Talk(SAY_VOLUNTEER_END);
- me->GetMotionMaster()->MovePoint(POINT_URUZIN, caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
- }
- }
-
- private:
- uint32 _mountModel;
- bool _complete;
- };
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_troll_volunteerAI(creature);
- }
-};
-
-typedef npc_troll_volunteer::npc_troll_volunteerAI VolunteerAI;
-
-class spell_mount_check : public SpellScriptLoader
-{
- public:
- spell_mount_check() : SpellScriptLoader("spell_mount_check") {}
-
- class spell_mount_check_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_mount_check_AuraScript)
- bool Validate(SpellInfo const* /*spellEntry*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_MOUNTING_CHECK))
- return false;
- return true;
- }
-
- void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
- {
- Unit* target = GetTarget();
- Unit* owner = target->GetOwner();
-
- if (!owner)
- return;
-
- if (owner->IsMounted() && !target->IsMounted())
- {
- if (VolunteerAI* volunteerAI = CAST_AI(VolunteerAI, target->GetAI()))
- target->Mount(volunteerAI->GetMountId());
- }
- else if (!owner->IsMounted() && target->IsMounted())
- target->Dismount();
-
- target->SetSpeed(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
- target->SetSpeed(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK));
- }
-
- void Register()
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_mount_check_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_mount_check_AuraScript();
- }
-};
-
-class spell_voljin_war_drums : public SpellScriptLoader
-{
- public:
- spell_voljin_war_drums() : SpellScriptLoader("spell_voljin_war_drums") {}
-
- class spell_voljin_war_drums_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_voljin_war_drums_SpellScript)
- bool Validate(SpellInfo const* /*spellEntry*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_MOTIVATE_1))
- return false;
- if (!sSpellMgr->GetSpellInfo(SPELL_MOTIVATE_2))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
- {
- uint32 motivate = 0;
- if (target->GetEntry() == NPC_CITIZEN_1)
- motivate = SPELL_MOTIVATE_1;
- else if (target->GetEntry() == NPC_CITIZEN_2)
- motivate = SPELL_MOTIVATE_2;
- if (motivate)
- caster->CastSpell(target, motivate, false);
- }
- }
-
- void Register()
- {
- OnEffectHitTarget += SpellEffectFn(spell_voljin_war_drums_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_voljin_war_drums_SpellScript();
- }
-};
-
enum VoodooSpells
{
SPELL_BREW = 16712, // Special Brew
@@ -550,9 +123,9 @@ class spell_voodoo : public SpellScriptLoader
class spell_voodoo_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_voodoo_SpellScript)
+ PrepareSpellScript(spell_voodoo_SpellScript);
- bool Validate(SpellInfo const* /*spellEntry*/)
+ bool Validate(SpellInfo const* /*spell*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_BREW) || !sSpellMgr->GetSpellInfo(SPELL_GHOSTLY) ||
!sSpellMgr->GetSpellInfo(SPELL_HEX1) || !sSpellMgr->GetSpellInfo(SPELL_HEX2) ||
@@ -584,10 +157,5 @@ class spell_voodoo : public SpellScriptLoader
void AddSC_durotar()
{
new npc_lazy_peon();
- new npc_tiger_matriarch_credit();
- new npc_tiger_matriarch();
- new npc_troll_volunteer();
- new spell_mount_check();
- new spell_voljin_war_drums();
new spell_voodoo();
}
diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
index 3a82a1f9a55..ed50f1a79f1 100644
--- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
+++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
@@ -19,16 +19,13 @@
/* ScriptData
SDName: Dustwallow_Marsh
SD%Complete: 95
-SDComment: Quest support: 11180, 558, 11126, 11142, 11174, Vendor Nat Pagle
+SDComment: Quest support: 1270, 1222, 27245
SDCategory: Dustwallow Marsh
EndScriptData */
/* ContentData
-mobs_risen_husk_spirit
-npc_lady_jaina_proudmoore
-npc_nat_pagle
-npc_private_hendel
-npc_cassa_crimsonwing - handled by npc_taxi
+npc_stinky
+go_blackhoof_cage
EndContentData */
#include "ScriptMgr.h"
@@ -766,13 +763,7 @@ public:
void AddSC_dustwallow_marsh()
{
- new mobs_risen_husk_spirit();
- new npc_lady_jaina_proudmoore();
- new npc_nat_pagle();
- new npc_private_hendel();
- new npc_zelfrax();
new npc_stinky();
- new npc_theramore_guard();
new spell_ooze_zap();
new spell_ooze_zap_channel_end();
new spell_energize_aoe();
diff --git a/src/server/scripts/Kalimdor/zone_felwood.cpp b/src/server/scripts/Kalimdor/zone_felwood.cpp
index e23eaa961bb..47a6d10f67b 100644
--- a/src/server/scripts/Kalimdor/zone_felwood.cpp
+++ b/src/server/scripts/Kalimdor/zone_felwood.cpp
@@ -19,12 +19,11 @@
/* ScriptData
SDName: Felwood
SD%Complete: 95
-SDComment: Quest support: 4101, 4102
+SDComment: Quest support:
SDCategory: Felwood
EndScriptData */
/* ContentData
-npcs_riverbreeze_and_silversky
EndContentData */
#include "ScriptMgr.h"
@@ -32,75 +31,6 @@ EndContentData */
#include "ScriptedGossip.h"
#include "Player.h"
-/*######
-## npcs_riverbreeze_and_silversky
-######*/
-
-#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon"
-
-enum RiverbreezeAndSilversky
-{
- SPELL_CENARION_BEACON = 15120,
-
- NPC_ARATHANDRIS_SILVERSKY = 9528,
- NPC_MAYBESS_RIVERBREEZE = 9529,
-
- QUEST_CLEASING_FELWOOD_A = 4101,
- QUEST_CLEASING_FELWOOD_H = 4102
-};
-
-class npcs_riverbreeze_and_silversky : public CreatureScript
-{
-public:
- npcs_riverbreeze_and_silversky() : CreatureScript("npcs_riverbreeze_and_silversky") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->CastSpell(player, SPELL_CENARION_BEACON, false);
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- uint32 creatureId = creature->GetEntry();
-
- if (creatureId == NPC_ARATHANDRIS_SILVERSKY)
- {
- if (player->GetQuestRewardStatus(QUEST_CLEASING_FELWOOD_A))
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(2848, creature->GetGUID());
- } else if (player->GetTeam() == HORDE)
- player->SEND_GOSSIP_MENU(2845, creature->GetGUID());
- else
- player->SEND_GOSSIP_MENU(2844, creature->GetGUID());
- }
-
- if (creatureId == NPC_MAYBESS_RIVERBREEZE)
- {
- if (player->GetQuestRewardStatus(QUEST_CLEASING_FELWOOD_H))
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(2849, creature->GetGUID());
- } else if (player->GetTeam() == ALLIANCE)
- player->SEND_GOSSIP_MENU(2843, creature->GetGUID());
- else
- player->SEND_GOSSIP_MENU(2842, creature->GetGUID());
- }
-
- return true;
- }
-};
-
void AddSC_felwood()
{
- new npcs_riverbreeze_and_silversky();
}
diff --git a/src/server/scripts/Kalimdor/zone_feralas.cpp b/src/server/scripts/Kalimdor/zone_feralas.cpp
index 2d5b383cefc..bde5e6ac25e 100644
--- a/src/server/scripts/Kalimdor/zone_feralas.cpp
+++ b/src/server/scripts/Kalimdor/zone_feralas.cpp
@@ -16,237 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Feralas
-SD%Complete: 100
-SDComment: Quest support: 3520, 2767, Special vendor Gregan Brewspewer
-SDCategory: Feralas
-EndScriptData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedEscortAI.h"
-#include "ScriptedGossip.h"
-#include "SpellScript.h"
-#include "Player.h"
-#include "WorldSession.h"
-
-/*######
-## npc_gregan_brewspewer
-######*/
-
-#define GOSSIP_HELLO "Buy somethin', will ya?"
-
-class npc_gregan_brewspewer : public CreatureScript
-{
-public:
- npc_gregan_brewspewer() : CreatureScript("npc_gregan_brewspewer") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- player->SEND_GOSSIP_MENU(2434, creature->GetGUID());
- }
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(creature->GetGUID());
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (creature->isVendor() && player->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(2433, creature->GetGUID());
- return true;
- }
-
-};
-
-/*######
-## npc_oox22fe
-######*/
-
-enum OOX
-{
- SAY_OOX_START = 0,
- SAY_OOX_AGGRO = 1,
- SAY_OOX_AMBUSH = 2,
- SAY_OOX_END = 3,
-
- NPC_YETI = 7848,
- NPC_GORILLA = 5260,
- NPC_WOODPAW_REAVER = 5255,
- NPC_WOODPAW_BRUTE = 5253,
- NPC_WOODPAW_ALPHA = 5258,
- NPC_WOODPAW_MYSTIC = 5254,
-
- QUEST_RESCUE_OOX22FE = 2767,
- FACTION_ESCORTEE_A = 774,
- FACTION_ESCORTEE_H = 775
-};
-
-class npc_oox22fe : public CreatureScript
-{
-public:
- npc_oox22fe() : CreatureScript("npc_oox22fe") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_RESCUE_OOX22FE)
- {
- creature->AI()->Talk(SAY_OOX_START);
- //change that the npc is not lying dead on the ground
- creature->SetStandState(UNIT_STAND_STATE_STAND);
-
- if (player->GetTeam() == ALLIANCE)
- creature->setFaction(FACTION_ESCORTEE_A);
-
- if (player->GetTeam() == HORDE)
- creature->setFaction(FACTION_ESCORTEE_H);
-
- if (npc_escortAI* pEscortAI = CAST_AI(npc_oox22fe::npc_oox22feAI, creature->AI()))
- pEscortAI->Start(true, false, player->GetGUID());
-
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_oox22feAI(creature);
- }
-
- struct npc_oox22feAI : public npc_escortAI
- {
- npc_oox22feAI(Creature* creature) : npc_escortAI(creature) { }
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- // First Ambush(3 Yetis)
- case 11:
- Talk(SAY_OOX_AMBUSH);
- me->SummonCreature(NPC_YETI, -4841.01f, 1593.91f, 73.42f, 3.98f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_YETI, -4837.61f, 1568.58f, 78.21f, 3.13f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_YETI, -4841.89f, 1569.95f, 76.53f, 0.68f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- break;
- //Second Ambush(3 Gorillas)
- case 21:
- Talk(SAY_OOX_AMBUSH);
- me->SummonCreature(NPC_GORILLA, -4595.81f, 2005.99f, 53.08f, 3.74f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_GORILLA, -4597.53f, 2008.31f, 52.70f, 3.78f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_GORILLA, -4599.37f, 2010.59f, 52.77f, 3.84f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- break;
- //Third Ambush(4 Gnolls)
- case 30:
- Talk(SAY_OOX_AMBUSH);
- me->SummonCreature(NPC_WOODPAW_REAVER, -4425.14f, 2075.87f, 47.77f, 3.77f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_WOODPAW_BRUTE, -4426.68f, 2077.98f, 47.57f, 3.77f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_WOODPAW_MYSTIC, -4428.33f, 2080.24f, 47.43f, 3.87f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- me->SummonCreature(NPC_WOODPAW_ALPHA, -4430.04f, 2075.54f, 46.83f, 3.81f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- break;
- case 37:
- Talk(SAY_OOX_END);
- // Award quest credit
- if (Player* player = GetPlayerForEscort())
- player->GroupEventHappens(QUEST_RESCUE_OOX22FE, me);
- break;
- }
- }
-
- void Reset()
- {
- if (!HasEscortState(STATE_ESCORT_ESCORTING))
- me->SetStandState(UNIT_STAND_STATE_DEAD);
- }
-
- void EnterCombat(Unit* /*who*/)
- {
- //For an small probability the npc says something when he get aggro
- if (urand(0, 9) > 7)
- Talk(SAY_OOX_AGGRO);
- }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->AI()->AttackStart(me);
- }
- };
-
-};
-
-/*######
-## npc_screecher_spirit
-######*/
-
-class npc_screecher_spirit : public CreatureScript
-{
-public:
- npc_screecher_spirit() : CreatureScript("npc_screecher_spirit") { }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- player->SEND_GOSSIP_MENU(2039, creature->GetGUID());
- player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
-
- return true;
- }
-
-};
-
-enum GordunniTrap
-{
- GO_GORDUNNI_DIRT_MOUND = 144064,
-};
-
-class spell_gordunni_trap : public SpellScriptLoader
-{
- public:
- spell_gordunni_trap() : SpellScriptLoader("spell_gordunni_trap") { }
-
- class spell_gordunni_trap_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gordunni_trap_SpellScript);
-
- void HandleDummy()
- {
- if (Unit* caster = GetCaster())
- if (GameObject* chest = caster->SummonGameObject(GO_GORDUNNI_DIRT_MOUND, caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
- {
- chest->SetSpellId(GetSpellInfo()->Id);
- caster->RemoveGameObject(chest, false);
- }
- }
-
- void Register()
- {
- OnCast += SpellCastFn(spell_gordunni_trap_SpellScript::HandleDummy);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_gordunni_trap_SpellScript();
- }
-};
-
-/*######
-## AddSC
-######*/
-
void AddSC_feralas()
{
- new npc_gregan_brewspewer();
- new npc_oox22fe();
- new npc_screecher_spirit();
- new spell_gordunni_trap();
+
}
diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp
index b6a0c1e9d1e..e5dc84c607e 100644
--- a/src/server/scripts/Kalimdor/zone_moonglade.cpp
+++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp
@@ -18,17 +18,13 @@
/* ScriptData
SDName: Moonglade
-SD%Complete: 100
-SDComment: Quest support: 30, 272, 5929, 5930, 10965. Special Flight Paths for Druid class.
+SD%Complete: 0
+SDComment: Quest support:
SDCategory: Moonglade
EndScriptData */
/* ContentData
-npc_bunthen_plainswind
-npc_great_bear_spirit
-npc_silva_filnaveth
-npc_clintar_spirit
-npc_clintar_dreamwalker
+npc_omen
EndContentData */
#include "ScriptMgr.h"
diff --git a/src/server/scripts/Kalimdor/zone_mulgore.cpp b/src/server/scripts/Kalimdor/zone_mulgore.cpp
index b81b8eb9eb7..626cfa8bc19 100644
--- a/src/server/scripts/Kalimdor/zone_mulgore.cpp
+++ b/src/server/scripts/Kalimdor/zone_mulgore.cpp
@@ -19,14 +19,13 @@
/* ScriptData
SDName: Mulgore
SD%Complete: 100
-SDComment: Support for quest: 11129, 772
+SDComment: Support for quest: 11129, 861
SDCategory: Mulgore
EndScriptData */
/* ContentData
npc_skorn_whitecloud
npc_kyle_frenzied
-npc_plains_vision
EndContentData */
#include "ScriptMgr.h"
@@ -201,127 +200,8 @@ public:
};
-/*#####
-# npc_plains_vision
-######*/
-
-Position const wpPlainVision[50] =
-{
- {-2226.32f, -408.095f, -9.36235f, 0.0f},
- {-2203.04f, -437.212f, -5.72498f, 0.0f},
- {-2163.91f, -457.851f, -7.09049f, 0.0f},
- {-2123.87f, -448.137f, -9.29591f, 0.0f},
- {-2104.66f, -427.166f, -6.49513f, 0.0f},
- {-2101.48f, -422.826f, -5.3567f, 0.0f},
- {-2097.56f, -417.083f, -7.16716f, 0.0f},
- {-2084.87f, -398.626f, -9.88973f, 0.0f},
- {-2072.71f, -382.324f, -10.2488f, 0.0f},
- {-2054.05f, -356.728f, -6.22468f, 0.0f},
- {-2051.8f, -353.645f, -5.35791f, 0.0f},
- {-2049.08f, -349.912f, -6.15723f, 0.0f},
- {-2030.6f, -310.724f, -9.59302f, 0.0f},
- {-2002.15f, -249.308f, -10.8124f, 0.0f},
- {-1972.85f, -195.811f, -10.6316f, 0.0f},
- {-1940.93f, -147.652f, -11.7055f, 0.0f},
- {-1888.06f, -81.943f, -11.4404f, 0.0f},
- {-1837.05f, -34.0109f, -12.258f, 0.0f},
- {-1796.12f, -14.6462f, -10.3581f, 0.0f},
- {-1732.61f, -4.27746f, -10.0213f, 0.0f},
- {-1688.94f, -0.829945f, -11.7103f, 0.0f},
- {-1681.32f, 13.0313f, -9.48056f, 0.0f},
- {-1677.04f, 36.8349f, -7.10318f, 0.0f},
- {-1675.2f, 68.559f, -8.95384f, 0.0f},
- {-1676.57f, 89.023f, -9.65104f, 0.0f},
- {-1678.16f, 110.939f, -10.1782f, 0.0f},
- {-1677.86f, 128.681f, -5.73869f, 0.0f},
- {-1675.27f, 144.324f, -3.47916f, 0.0f},
- {-1671.7f, 163.169f, -1.23098f, 0.0f},
- {-1666.61f, 181.584f, 5.26145f, 0.0f},
- {-1661.51f, 196.154f, 8.95252f, 0.0f},
- {-1655.47f, 210.811f, 8.38727f, 0.0f},
- {-1647.07f, 226.947f, 5.27755f, 0.0f},
- {-1621.65f, 232.91f, 2.69579f, 0.0f},
- {-1600.23f, 237.641f, 2.98539f, 0.0f},
- {-1576.07f, 242.546f, 4.66541f, 0.0f},
- {-1554.57f, 248.494f, 6.60377f, 0.0f},
- {-1547.53f, 259.302f, 10.6741f, 0.0f},
- {-1541.7f, 269.847f, 16.4418f, 0.0f},
- {-1539.83f, 278.989f, 21.0597f, 0.0f},
- {-1540.16f, 290.219f, 27.8247f, 0.0f},
- {-1538.99f, 298.983f, 34.0032f, 0.0f},
- {-1540.38f, 307.337f, 41.3557f, 0.0f},
- {-1536.61f, 314.884f, 48.0179f, 0.0f},
- {-1532.42f, 323.277f, 55.6667f, 0.0f},
- {-1528.77f, 329.774f, 61.1525f, 0.0f},
- {-1525.65f, 333.18f, 63.2161f, 0.0f},
- {-1517.01f, 350.713f, 62.4286f, 0.0f},
- {-1511.39f, 362.537f, 62.4539f, 0.0f},
- {-1508.68f, 366.822f, 62.733f, 0.0f}
-};
-
-class npc_plains_vision : public CreatureScript
-{
-public:
- npc_plains_vision() : CreatureScript("npc_plains_vision") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_plains_visionAI (creature);
- }
-
- struct npc_plains_visionAI : public ScriptedAI
- {
- npc_plains_visionAI(Creature* creature) : ScriptedAI(creature) {}
-
- bool newWaypoint;
- uint8 WayPointId;
- uint8 amountWP;
-
- void Reset()
- {
- WayPointId = 0;
- newWaypoint = true;
- amountWP = 49;
- }
-
- void EnterCombat(Unit* /*who*/){}
-
- void MovementInform(uint32 type, uint32 id)
- {
- if (type != POINT_MOTION_TYPE)
- return;
-
- if (id < amountWP)
- {
- ++WayPointId;
- newWaypoint = true;
- }
- else
- {
- me->setDeathState(JUST_DIED);
- me->RemoveCorpse();
- }
- }
-
- void UpdateAI(uint32 /*diff*/)
- {
- if (newWaypoint)
- {
- me->GetMotionMaster()->MovePoint(WayPointId, wpPlainVision[WayPointId]);
- newWaypoint = false;
- }
- }
- };
-
-};
-
-/*#####
-#
-######*/
-
void AddSC_mulgore()
{
new npc_skorn_whitecloud();
new npc_kyle_frenzied();
- new npc_plains_vision();
}
diff --git a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
index bae229b1161..ccc8bdc257a 100644
--- a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
+++ b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp
@@ -18,14 +18,12 @@
/* ScriptData
SDName: Orgrimmar
-SD%Complete: 100
-SDComment: Quest support: 2460, 6566
+SD%Complete: 0
+SDComment: Quest support:
SDCategory: Orgrimmar
EndScriptData */
/* ContentData
-npc_shenthul
-npc_thrall_warchief
EndContentData */
#include "ScriptMgr.h"
@@ -33,222 +31,6 @@ EndContentData */
#include "ScriptedGossip.h"
#include "Player.h"
-/*######
-## npc_shenthul
-######*/
-
-enum Shenthul
-{
- QUEST_SHATTERED_SALUTE = 2460
-};
-
-class npc_shenthul : public CreatureScript
-{
-public:
- npc_shenthul() : CreatureScript("npc_shenthul") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_SHATTERED_SALUTE)
- {
- CAST_AI(npc_shenthul::npc_shenthulAI, creature->AI())->CanTalk = true;
- CAST_AI(npc_shenthul::npc_shenthulAI, creature->AI())->PlayerGUID = player->GetGUID();
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_shenthulAI (creature);
- }
-
- struct npc_shenthulAI : public ScriptedAI
- {
- npc_shenthulAI(Creature* creature) : ScriptedAI(creature) {}
-
- bool CanTalk;
- bool CanEmote;
- uint32 SaluteTimer;
- uint32 ResetTimer;
- uint64 PlayerGUID;
-
- void Reset()
- {
- CanTalk = false;
- CanEmote = false;
- SaluteTimer = 6000;
- ResetTimer = 0;
- PlayerGUID = 0;
- }
-
- void EnterCombat(Unit* /*who*/) {}
-
- void UpdateAI(uint32 diff)
- {
- if (CanEmote)
- {
- if (ResetTimer <= diff)
- {
- if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- {
- if (player->GetTypeId() == TYPEID_PLAYER && player->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE)
- player->FailQuest(QUEST_SHATTERED_SALUTE);
- }
- Reset();
- } else ResetTimer -= diff;
- }
-
- if (CanTalk && !CanEmote)
- {
- if (SaluteTimer <= diff)
- {
- me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
- CanEmote = true;
- ResetTimer = 60000;
- } else SaluteTimer -= diff;
- }
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
-
- void ReceiveEmote(Player* player, uint32 emote)
- {
- if (emote == TEXT_EMOTE_SALUTE && player->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE)
- {
- if (CanEmote)
- {
- player->AreaExploredOrEventHappens(QUEST_SHATTERED_SALUTE);
- Reset();
- }
- }
- }
- };
-
-};
-
-/*######
-## npc_thrall_warchief
-######*/
-
-enum ThrallWarchief
-{
- QUEST_6566 = 6566,
-
- SPELL_CHAIN_LIGHTNING = 16033,
- SPELL_SHOCK = 16034
-};
-
-#define GOSSIP_HTW "Please share your wisdom with me, Warchief."
-#define GOSSIP_STW1 "What discoveries?"
-#define GOSSIP_STW2 "Usurper?"
-#define GOSSIP_STW3 "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?"
-#define GOSSIP_STW4 "I... I did not think of it that way, Warchief."
-#define GOSSIP_STW5 "I live only to serve, Warchief! My life is empty and meaningless without your guidance."
-#define GOSSIP_STW6 "Of course, Warchief!"
-
-/// @todo verify abilities/timers
-class npc_thrall_warchief : public CreatureScript
-{
-public:
- npc_thrall_warchief() : CreatureScript("npc_thrall_warchief") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- player->SEND_GOSSIP_MENU(5733, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
- player->SEND_GOSSIP_MENU(5734, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
- player->SEND_GOSSIP_MENU(5735, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
- player->SEND_GOSSIP_MENU(5736, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
- player->SEND_GOSSIP_MENU(5737, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+6:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7);
- player->SEND_GOSSIP_MENU(5738, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+7:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(QUEST_6566);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HTW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_thrall_warchiefAI (creature);
- }
-
- struct npc_thrall_warchiefAI : public ScriptedAI
- {
- npc_thrall_warchiefAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 ChainLightningTimer;
- uint32 ShockTimer;
-
- void Reset()
- {
- ChainLightningTimer = 2000;
- ShockTimer = 8000;
- }
-
- void EnterCombat(Unit* /*who*/) {}
-
- void UpdateAI(uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- if (ChainLightningTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING);
- ChainLightningTimer = 9000;
- } else ChainLightningTimer -= diff;
-
- if (ShockTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_SHOCK);
- ShockTimer = 15000;
- } else ShockTimer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
void AddSC_orgrimmar()
{
- new npc_shenthul();
- new npc_thrall_warchief();
}
diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp
index 70e7f731fc4..95c030e6dfe 100644
--- a/src/server/scripts/Kalimdor/zone_silithus.cpp
+++ b/src/server/scripts/Kalimdor/zone_silithus.cpp
@@ -19,14 +19,14 @@
/* ScriptData
SDName: Silithus
SD%Complete: 100
-SDComment: Quest support: 7785, 8304, 8507.
+SDComment: Quest support: 7785, 8304.
SDCategory: Silithus
EndScriptData */
/* ContentData
npc_highlord_demitrian
npcs_rutgar_and_frankal
-quest_a_pawn_on_the_eternal_pawn
+go_wind_stone
EndContentData */
#include "ScriptMgr.h"
@@ -1505,10 +1505,6 @@ class go_wind_stone : public GameObjectScript
void AddSC_silithus()
{
- new go_crystalline_tear();
- new npc_anachronos_quest_trigger();
- new npc_anachronos_the_ancient();
- new mob_qiraj_war_spawn();
new npc_highlord_demitrian();
new npcs_rutgar_and_frankal();
new go_wind_stone();
diff --git a/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp b/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
index 26c92c7404c..4c22b4fc81d 100644
--- a/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
+++ b/src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp
@@ -16,164 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Stonetalon_Mountains
-SD%Complete: 95
-SDComment: Quest support: 6627, 6523
-SDCategory: Stonetalon Mountains
-EndScriptData */
-
-/* ContentData
-npc_braug_dimspirit
-npc_kaya_flathoof
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "ScriptedEscortAI.h"
-#include "Player.h"
-
-/*######
-## npc_braug_dimspirit
-######*/
-
-#define GOSSIP_HBD1 "Ysera"
-#define GOSSIP_HBD2 "Neltharion"
-#define GOSSIP_HBD3 "Nozdormu"
-#define GOSSIP_HBD4 "Alexstrasza"
-#define GOSSIP_HBD5 "Malygos"
-
-class npc_braug_dimspirit : public CreatureScript
-{
-public:
- npc_braug_dimspirit() : CreatureScript("npc_braug_dimspirit") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->CastSpell(player, 6766, false);
-
- }
- if (action == GOSSIP_ACTION_INFO_DEF+2)
- {
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(6627);
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(6627) == QUEST_STATUS_INCOMPLETE)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(5820, creature->GetGUID());
- }
- else
- player->SEND_GOSSIP_MENU(5819, creature->GetGUID());
-
- return true;
- }
-
-};
-
-/*######
-## npc_kaya_flathoof
-######*/
-
-enum Kaya
-{
- FACTION_ESCORTEE_H = 775,
-
- NPC_GRIMTOTEM_RUFFIAN = 11910,
- NPC_GRIMTOTEM_BRUTE = 11912,
- NPC_GRIMTOTEM_SORCERER = 11913,
-
- SAY_START = 0,
- SAY_AMBUSH = 1,
- SAY_END = 2,
-
- QUEST_PROTECT_KAYA = 6523
-};
-
-class npc_kaya_flathoof : public CreatureScript
-{
-public:
- npc_kaya_flathoof() : CreatureScript("npc_kaya_flathoof") { }
-
- struct npc_kaya_flathoofAI : public npc_escortAI
- {
- npc_kaya_flathoofAI(Creature* creature) : npc_escortAI(creature) {}
-
- void WaypointReached(uint32 waypointId)
- {
- Player* player = GetPlayerForEscort();
- if (!player)
- return;
-
- switch (waypointId)
- {
- case 16:
- Talk(SAY_AMBUSH);
- me->SummonCreature(NPC_GRIMTOTEM_BRUTE, -48.53f, -503.34f, -46.31f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- me->SummonCreature(NPC_GRIMTOTEM_RUFFIAN, -38.85f, -503.77f, -45.90f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- me->SummonCreature(NPC_GRIMTOTEM_SORCERER, -36.37f, -496.23f, -45.71f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
- break;
- case 18:
- me->SetInFront(player);
- Talk(SAY_END);
- player->GroupEventHappens(QUEST_PROTECT_KAYA, me);
- break;
- }
- }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->AI()->AttackStart(me);
- }
-
- void Reset(){}
- };
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_PROTECT_KAYA)
- {
- if (npc_escortAI* pEscortAI = CAST_AI(npc_kaya_flathoof::npc_kaya_flathoofAI, creature->AI()))
- pEscortAI->Start(true, false, player->GetGUID());
-
- creature->AI()->Talk(SAY_START);
- creature->setFaction(113);
- creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_kaya_flathoofAI(creature);
- }
-
-};
-
-/*######
-## AddSC
-######*/
-
void AddSC_stonetalon_mountains()
{
- new npc_braug_dimspirit();
- new npc_kaya_flathoof();
}
diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp
index a0e57a1092f..7e4a1d980db 100644
--- a/src/server/scripts/Kalimdor/zone_tanaris.cpp
+++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp
@@ -19,18 +19,14 @@
/* ScriptData
SDName: Tanaris
SD%Complete: 80
-SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor
+SDComment: Quest support: 648, 10277, 10279(Special flight path).
SDCategory: Tanaris
EndScriptData */
/* ContentData
-mob_aquementas
npc_custodian_of_time
-npc_marin_noggenfogger
npc_steward_of_time
-npc_stone_watcher_of_norgannon
npc_OOX17
-npc_tooga
EndContentData */
#include "ScriptMgr.h"
@@ -281,39 +277,6 @@ public:
};
/*######
-## npc_marin_noggenfogger
-######*/
-
-class npc_marin_noggenfogger : public CreatureScript
-{
-public:
- npc_marin_noggenfogger() : CreatureScript("npc_marin_noggenfogger") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (creature->isVendor() && player->GetQuestRewardStatus(2662))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-
-};
-
-/*######
## npc_steward_of_time
######*/
@@ -360,70 +323,6 @@ public:
};
/*######
-## npc_stone_watcher_of_norgannon
-######*/
-
-#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?"
-#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?"
-#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?"
-#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!"
-#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?"
-#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum."
-
-class npc_stone_watcher_of_norgannon : public CreatureScript
-{
-public:
- npc_stone_watcher_of_norgannon() : CreatureScript("npc_stone_watcher_of_norgannon") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(1675, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- player->SEND_GOSSIP_MENU(1676, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
- player->SEND_GOSSIP_MENU(1677, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
- player->SEND_GOSSIP_MENU(1678, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
- player->SEND_GOSSIP_MENU(1679, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(2954);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(1674, creature->GetGUID());
-
- return true;
- }
-
-};
-
-/*######
## npc_OOX17
######*/
@@ -677,11 +576,7 @@ public:
void AddSC_tanaris()
{
- new mob_aquementas();
new npc_custodian_of_time();
- new npc_marin_noggenfogger();
new npc_steward_of_time();
- new npc_stone_watcher_of_norgannon();
new npc_OOX17();
- new npc_tooga();
}
diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
index 4ab64846f1c..d21ca8c9427 100644
--- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp
+++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
@@ -19,16 +19,11 @@
/* ScriptData
SDName: The_Barrens
SD%Complete: 90
-SDComment: Quest support: 863, 898, 1719, 2458, 4921, 6981,
+SDComment: Quest support: 863
SDCategory: Barrens
EndScriptData */
/* ContentData
-npc_beaten_corpse
-npc_gilthares
-npc_sputtervalve
-npc_taskmaster_fizzule
-npc_twiggy_flathead
npc_wizzlecrank_shredder
EndContentData */
@@ -688,10 +683,5 @@ public:
void AddSC_the_barrens()
{
- new npc_beaten_corpse();
- new npc_gilthares();
- new npc_sputtervalve();
- new npc_taskmaster_fizzule();
- new npc_twiggy_flathead();
new npc_wizzlecrank_shredder();
}
diff --git a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
index 02e64421ecb..df75b045309 100644
--- a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
+++ b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp
@@ -16,448 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Thousand Needles
-SD%Complete: 100
-SDComment: Support for Quest: 1950, 4770, 4904, 4966, 5151.
-SDCategory: Thousand Needles
-EndScriptData */
-
-/* ContentData
-npc_kanati
-npc_lakota_windsong
-npc_swiftmountain
-npc_plucky
-npc_enraged_panther
-go_panther_cage
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "ScriptedEscortAI.h"
-#include "Player.h"
-
-/*#####
-# npc_kanati
-######*/
-
-enum Kanati
-{
- SAY_KAN_START = 0,
-
- QUEST_PROTECT_KANATI = 4966,
- NPC_GALAK_ASS = 10720
-};
-
-Position const GalakLoc = {-4867.387695f, -1357.353760f, -48.226f, 0.0f};
-
-class npc_kanati : public CreatureScript
-{
-public:
- npc_kanati() : CreatureScript("npc_kanati") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_PROTECT_KANATI)
- if (npc_kanatiAI* pEscortAI = CAST_AI(npc_kanati::npc_kanatiAI, creature->AI()))
- pEscortAI->Start(false, false, player->GetGUID(), quest, true);
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_kanatiAI(creature);
- }
-
- struct npc_kanatiAI : public npc_escortAI
- {
- npc_kanatiAI(Creature* creature) : npc_escortAI(creature) { }
-
- void Reset() {}
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 0:
- Talk(SAY_KAN_START);
- DoSpawnGalak();
- break;
- case 1:
- if (Player* player = GetPlayerForEscort())
- player->GroupEventHappens(QUEST_PROTECT_KANATI, me);
- break;
- }
- }
-
- void DoSpawnGalak()
- {
- for (int i = 0; i < 3; ++i)
- me->SummonCreature(NPC_GALAK_ASS, GalakLoc, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
- }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->AI()->AttackStart(me);
- }
- };
-
-};
-
-/*######
-# npc_lakota_windsong
-######*/
-
-enum Lakota
-{
- SAY_LAKO_START = 0,
- SAY_LAKO_LOOK_OUT = 1,
- SAY_LAKO_HERE_COME = 2,
- SAY_LAKO_MORE = 3,
- SAY_LAKO_END = 4,
-
- QUEST_FREE_AT_LAST = 4904,
- NPC_GRIM_BANDIT = 10758,
- FACTION_ESCORTEE_LAKO = 232, //guessed
-
- ID_AMBUSH_1 = 0,
- ID_AMBUSH_2 = 2,
- ID_AMBUSH_3 = 4
-};
-
-Position const BanditLoc[6] =
-{
- {-4905.479492f, -2062.732666f, 84.352f, 0.0f},
- {-4915.201172f, -2073.528320f, 84.733f, 0.0f},
- {-4878.883301f, -1986.947876f, 91.966f, 0.0f},
- {-4877.503906f, -1966.113403f, 91.859f, 0.0f},
- {-4767.985352f, -1873.169189f, 90.192f, 0.0f},
- {-4788.861328f, -1888.007813f, 89.888f, 0.0f}
-};
-
-class npc_lakota_windsong : public CreatureScript
-{
-public:
- npc_lakota_windsong() : CreatureScript("npc_lakota_windsong") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_FREE_AT_LAST)
- {
- creature->AI()->Talk(SAY_LAKO_START, player->GetGUID());
- creature->setFaction(FACTION_ESCORTEE_LAKO);
-
- if (npc_lakota_windsongAI* pEscortAI = CAST_AI(npc_lakota_windsong::npc_lakota_windsongAI, creature->AI()))
- pEscortAI->Start(false, false, player->GetGUID(), quest);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_lakota_windsongAI(creature);
- }
-
- struct npc_lakota_windsongAI : public npc_escortAI
- {
- npc_lakota_windsongAI(Creature* creature) : npc_escortAI(creature) { }
-
- void Reset() {}
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 8:
- Talk(SAY_LAKO_LOOK_OUT);
- DoSpawnBandits(ID_AMBUSH_1);
- break;
- case 14:
- Talk(SAY_LAKO_HERE_COME);
- DoSpawnBandits(ID_AMBUSH_2);
- break;
- case 21:
- Talk(SAY_LAKO_MORE);
- DoSpawnBandits(ID_AMBUSH_3);
- break;
- case 45:
- if (Player* player = GetPlayerForEscort())
- player->GroupEventHappens(QUEST_FREE_AT_LAST, me);
- break;
- }
- }
-
- void DoSpawnBandits(int AmbushId)
- {
- for (int i = 0; i < 2; ++i)
- me->SummonCreature(NPC_GRIM_BANDIT, BanditLoc[i+AmbushId], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
- }
- };
-
-};
-
-/*######
-# npc_paoka_swiftmountain
-######*/
-
-enum Packa
-{
- SAY_START = 0,
- SAY_WYVERN = 1,
- SAY_COMPLETE = 2,
-
- QUEST_HOMEWARD = 4770,
- NPC_WYVERN = 4107,
- FACTION_ESCORTEE = 232 //guessed
-};
-
-Position const WyvernLoc[3] =
-{
- {-4990.606f, -906.057f, -5.343f, 0.0f},
- {-4970.241f, -927.378f, -4.951f, 0.0f},
- {-4985.364f, -952.528f, -5.199f, 0.0f}
-};
-
-class npc_paoka_swiftmountain : public CreatureScript
-{
-public:
- npc_paoka_swiftmountain() : CreatureScript("npc_paoka_swiftmountain") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_HOMEWARD)
- {
- creature->AI()->Talk(SAY_START, player->GetGUID());
- creature->setFaction(FACTION_ESCORTEE);
-
- if (npc_paoka_swiftmountainAI* pEscortAI = CAST_AI(npc_paoka_swiftmountain::npc_paoka_swiftmountainAI, creature->AI()))
- pEscortAI->Start(false, false, player->GetGUID(), quest);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_paoka_swiftmountainAI(creature);
- }
-
- struct npc_paoka_swiftmountainAI : public npc_escortAI
- {
- npc_paoka_swiftmountainAI(Creature* creature) : npc_escortAI(creature) { }
-
- void Reset() {}
-
- void WaypointReached(uint32 waypointId)
- {
- switch (waypointId)
- {
- case 15:
- Talk(SAY_WYVERN);
- DoSpawnWyvern();
- break;
- case 26:
- Talk(SAY_COMPLETE);
- break;
- case 27:
- if (Player* player = GetPlayerForEscort())
- player->GroupEventHappens(QUEST_HOMEWARD, me);
- break;
- }
- }
-
- void DoSpawnWyvern()
- {
- for (int i = 0; i < 3; ++i)
- me->SummonCreature(NPC_WYVERN, WyvernLoc[i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
- }
- };
-};
-
-/*#####
-# npc_plucky
-######*/
-
-#define GOSSIP_P "Please tell me the Phrase.."
-
-enum Plucky
-{
- FACTION_FRIENDLY = 35,
- QUEST_SCOOP = 1950,
- SPELL_PLUCKY_HUMAN = 9192,
- SPELL_PLUCKY_CHICKEN = 9220
-};
-
-class npc_plucky : public CreatureScript
-{
-public:
- npc_plucky() : CreatureScript("npc_plucky") { }
-
- bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->CLOSE_GOSSIP_MENU();
- player->CompleteQuest(QUEST_SCOOP);
- break;
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (player->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_P, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(738, creature->GetGUID());
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_pluckyAI(creature);
- }
-
- struct npc_pluckyAI : public ScriptedAI
- {
- npc_pluckyAI(Creature* creature) : ScriptedAI(creature) { NormFaction = creature->getFaction(); }
-
- uint32 NormFaction;
- uint32 ResetTimer;
-
- void Reset()
- {
- ResetTimer = 120000;
-
- if (me->getFaction() != NormFaction)
- me->setFaction(NormFaction);
-
- if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
-
- DoCast(me, SPELL_PLUCKY_CHICKEN, false);
- }
-
- void ReceiveEmote(Player* player, uint32 TextEmote)
- {
- if (player->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE)
- {
- if (TextEmote == TEXT_EMOTE_BECKON)
- {
- me->setFaction(FACTION_FRIENDLY);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- DoCast(me, SPELL_PLUCKY_HUMAN, false);
- }
- }
-
- if (TextEmote == TEXT_EMOTE_CHICKEN)
- {
- if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
- return;
- else
- {
- me->setFaction(FACTION_FRIENDLY);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- DoCast(me, SPELL_PLUCKY_HUMAN, false);
- me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
- }
- }
- }
-
- void UpdateAI(uint32 Diff)
- {
- if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
- {
- if (ResetTimer <= Diff)
- {
- if (!me->getVictim())
- EnterEvadeMode();
- else
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
-
- return;
- }
- else
- ResetTimer -= Diff;
- }
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-enum PantherCage
-{
- ENRAGED_PANTHER = 10992
-};
-
-class go_panther_cage : public GameObjectScript
-{
-public:
- go_panther_cage() : GameObjectScript("go_panther_cage") { }
-
- bool OnGossipHello(Player* player, GameObject* go)
- {
- go->UseDoorOrButton();
- if (player->GetQuestStatus(5151) == QUEST_STATUS_INCOMPLETE)
- {
- if (Creature* panther = go->FindNearestCreature(ENRAGED_PANTHER, 5, true))
- {
- panther->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- panther->SetReactState(REACT_AGGRESSIVE);
- panther->AI()->AttackStart(player);
- }
- }
-
- return true;
- }
-};
-
-class npc_enraged_panther : public CreatureScript
-{
-public:
- npc_enraged_panther() : CreatureScript("npc_enraged_panther") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_enraged_pantherAI(creature);
- }
-
- struct npc_enraged_pantherAI : public ScriptedAI
- {
- npc_enraged_pantherAI(Creature* creature) : ScriptedAI(creature) {}
-
- void Reset()
- {
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetReactState(REACT_PASSIVE);
- }
-
- void UpdateAI(uint32 /*diff*/)
- {
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
void AddSC_thousand_needles()
{
- new npc_kanati();
- new npc_lakota_windsong();
- new npc_paoka_swiftmountain();
- new npc_plucky();
- new npc_enraged_panther();
- new go_panther_cage();
}
diff --git a/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp b/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
index c949a551118..e2cf1fdd855 100644
--- a/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
+++ b/src/server/scripts/Kalimdor/zone_thunder_bluff.cpp
@@ -48,30 +48,6 @@ class npc_cairne_bloodhoof : public CreatureScript
public:
npc_cairne_bloodhoof() : CreatureScript("npc_cairne_bloodhoof") { }
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_SENDER_INFO)
- {
- player->CastSpell(player, 23123, false);
- player->SEND_GOSSIP_MENU(7014, creature->GetGUID());
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(925) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HCB, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO);
-
- player->SEND_GOSSIP_MENU(7013, creature->GetGUID());
-
- return true;
- }
-
CreatureAI* GetAI(Creature* creature) const
{
return new npc_cairne_bloodhoofAI (creature);
diff --git a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
index 9c89ad6d53a..823fe56d364 100644
--- a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
+++ b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp
@@ -16,333 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Ungoro Crater
-SD%Complete: 100
-SDComment: Support for Quest: 4245, 4491
-SDCategory: Ungoro Crater
-EndScriptData */
-
-/* ContentData
-npc_a-me
-npc_ringo
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedEscortAI.h"
-#include "ScriptedFollowerAI.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-enum AmeData
-{
- SAY_READY = 0,
- SAY_AGGRO1 = 1,
- SAY_SEARCH = 2,
- SAY_AGGRO2 = 3,
- SAY_AGGRO3 = 4,
- SAY_FINISH = 5,
-
- SPELL_DEMORALIZINGSHOUT = 13730,
-
- QUEST_CHASING_AME = 4245,
- ENTRY_TARLORD = 6519,
- ENTRY_TARLORD1 = 6519,
- ENTRY_STOMPER = 6513,
-};
-
-class npc_ame : public CreatureScript
-{
-public:
- npc_ame() : CreatureScript("npc_ame") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
- {
- if (quest->GetQuestId() == QUEST_CHASING_AME)
- {
- CAST_AI(npc_escortAI, (creature->AI()))->Start(false, false, player->GetGUID());
- creature->AI()->Talk(SAY_READY, player->GetGUID());
- creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- // Change faction so mobs attack
- creature->setFaction(113);
- }
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_ameAI(creature);
- }
-
- struct npc_ameAI : public npc_escortAI
- {
- npc_ameAI(Creature* creature) : npc_escortAI(creature) {}
-
- uint32 DemoralizingShoutTimer;
-
- void WaypointReached(uint32 waypointId)
- {
- if (Player* player = GetPlayerForEscort())
- {
- switch (waypointId)
- {
- case 19:
- me->SummonCreature(ENTRY_STOMPER, -6391.69f, -1730.49f, -272.83f, 4.96f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
- Talk(SAY_AGGRO1, player->GetGUID());
- break;
- case 28:
- Talk(SAY_SEARCH, player->GetGUID());
- break;
- case 38:
- me->SummonCreature(ENTRY_TARLORD, -6370.75f, -1382.84f, -270.51f, 6.06f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
- Talk(SAY_AGGRO2, player->GetGUID());
- break;
- case 49:
- me->SummonCreature(ENTRY_TARLORD1, -6324.44f, -1181.05f, -270.17f, 4.34f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
- Talk(SAY_AGGRO3, player->GetGUID());
- break;
- case 55:
- Talk(SAY_FINISH, player->GetGUID());
- player->GroupEventHappens(QUEST_CHASING_AME, me);
- break;
- }
- }
- }
-
- void Reset()
- {
- DemoralizingShoutTimer = 5000;
- }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->AI()->AttackStart(me);
- }
-
- void JustDied(Unit* /*killer*/)
- {
- if (Player* player = GetPlayerForEscort())
- player->FailQuest(QUEST_CHASING_AME);
- }
-
- void UpdateAI(uint32 diff)
- {
- npc_escortAI::UpdateAI(diff);
- if (!UpdateVictim())
- return;
-
- if (DemoralizingShoutTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT);
- DemoralizingShoutTimer = 70000;
- } else DemoralizingShoutTimer -= diff;
- }
- };
-};
-
-/*####
-# npc_ringo
-####*/
-
-enum Ringo
-{
- SAY_RIN_START = 0,
-
- SAY_FAINT = 1,
-
- SAY_WAKE = 2,
-
- SAY_RIN_END_1 = 3,
- SAY_SPR_END_2 = 0,
- SAY_RIN_END_3 = 4,
- EMOTE_RIN_END_4 = 5,
- EMOTE_RIN_END_5 = 6,
- SAY_RIN_END_6 = 7,
- SAY_SPR_END_7 = 1,
- EMOTE_RIN_END_8 = 8,
-
- SPELL_REVIVE_RINGO = 15591,
- QUEST_A_LITTLE_HELP = 4491,
- NPC_SPRAGGLE = 9997,
- FACTION_ESCORTEE = 113
-};
-
-class npc_ringo : public CreatureScript
-{
-public:
- npc_ringo() : CreatureScript("npc_ringo") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
- {
- if (quest->GetQuestId() == QUEST_A_LITTLE_HELP)
- {
- if (npc_ringoAI* ringoAI = CAST_AI(npc_ringo::npc_ringoAI, creature->AI()))
- {
- creature->SetStandState(UNIT_STAND_STATE_STAND);
- ringoAI->StartFollow(player, FACTION_ESCORTEE, quest);
- }
- }
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_ringoAI(creature);
- }
-
- struct npc_ringoAI : public FollowerAI
- {
- npc_ringoAI(Creature* creature) : FollowerAI(creature) { }
-
- uint32 FaintTimer;
- uint32 EndEventProgress;
- uint32 EndEventTimer;
-
- uint64 SpraggleGUID;
-
- void Reset()
- {
- FaintTimer = urand(30000, 60000);
- EndEventProgress = 0;
- EndEventTimer = 1000;
- SpraggleGUID = 0;
- }
-
- void MoveInLineOfSight(Unit* who)
- {
- FollowerAI::MoveInLineOfSight(who);
-
- if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && who->GetEntry() == NPC_SPRAGGLE)
- {
- if (me->IsWithinDistInMap(who, INTERACTION_DISTANCE))
- {
- if (Player* player = GetLeaderForFollower())
- {
- if (player->GetQuestStatus(QUEST_A_LITTLE_HELP) == QUEST_STATUS_INCOMPLETE)
- player->GroupEventHappens(QUEST_A_LITTLE_HELP, me);
- }
-
- SpraggleGUID = who->GetGUID();
- SetFollowComplete(true);
- }
- }
- }
-
- void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell)
- {
- if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_REVIVE_RINGO)
- ClearFaint();
- }
-
- void SetFaint()
- {
- if (!HasFollowState(STATE_FOLLOW_POSTEVENT))
- {
- SetFollowPaused(true);
-
- Talk(SAY_FAINT);
- }
-
- //what does actually happen here? Emote? Aura?
- me->SetStandState(UNIT_STAND_STATE_SLEEP);
- }
-
- void ClearFaint()
- {
- me->SetStandState(UNIT_STAND_STATE_STAND);
-
- if (HasFollowState(STATE_FOLLOW_POSTEVENT))
- return;
-
- Talk(SAY_WAKE);
-
- SetFollowPaused(false);
- }
-
- void UpdateFollowerAI(uint32 Diff)
- {
- if (!UpdateVictim())
- {
- if (HasFollowState(STATE_FOLLOW_POSTEVENT))
- {
- if (EndEventTimer <= Diff)
- {
- Creature* spraggle = Creature::GetCreature(*me, SpraggleGUID);
- if (!spraggle || !spraggle->isAlive())
- {
- SetFollowComplete();
- return;
- }
-
- switch (EndEventProgress)
- {
- case 1:
- Talk(SAY_RIN_END_1);
- EndEventTimer = 3000;
- break;
- case 2:
- spraggle->AI()->Talk(SAY_SPR_END_2);
- EndEventTimer = 5000;
- break;
- case 3:
- Talk(SAY_RIN_END_3);
- EndEventTimer = 1000;
- break;
- case 4:
- Talk(EMOTE_RIN_END_4);
- SetFaint();
- EndEventTimer = 9000;
- break;
- case 5:
- Talk(EMOTE_RIN_END_5);
- ClearFaint();
- EndEventTimer = 1000;
- break;
- case 6:
- Talk(SAY_RIN_END_6);
- EndEventTimer = 3000;
- break;
- case 7:
- spraggle->AI()->Talk(SAY_SPR_END_7);
- EndEventTimer = 10000;
- break;
- case 8:
- Talk(EMOTE_RIN_END_8);
- EndEventTimer = 5000;
- break;
- case 9:
- SetFollowComplete();
- break;
- }
-
- ++EndEventProgress;
- }
- else
- EndEventTimer -= Diff;
- }
- else if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !HasFollowState(STATE_FOLLOW_PAUSED))
- {
- if (FaintTimer <= Diff)
- {
- SetFaint();
- FaintTimer = urand(60000, 120000);
- }
- else
- FaintTimer -= Diff;
- }
-
- return;
- }
-
- DoMeleeAttackIfReady();
- }
- };
-};
-
void AddSC_ungoro_crater()
{
- new npc_ame();
- new npc_ringo();
}
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
index a9fad9c5451..6bc6279da79 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
@@ -176,7 +176,7 @@ class boss_elder_nadox : public CreatureScript
}
}
- if (me->HealthBelowPct(100 - AmountHealthModifier * 25))
+ if (me->HealthBelowPct(100 - AmountHealthModifier* 25))
{
Talk(EMOTE_HATCHES, me->GetGUID());
DoCast(me, SPELL_SUMMON_SWARM_GUARD);
@@ -298,7 +298,7 @@ public:
void FilterTargets(std::list<WorldObject*>& targets)
{
- targets.remove_if(GuardianCheck());
+ targets.remove_if (GuardianCheck());
}
void Register()
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index c36815b49f3..9a61b83dbce 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -20,7 +20,6 @@
#include "SpellAuraEffects.h"
#include "Spell.h"
#include "Vehicle.h"
-#include "MapManager.h"
#include "GameObjectAI.h"
#include "ScriptedCreature.h"
#include "ruby_sanctum.h"
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
index 553b836da8f..cd5efa56840 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
@@ -479,17 +479,15 @@ public:
switch (uiWaypoint)
{
case 0:
- me->SetOrientation(5.81f);
+ me->SetFacingTo(5.81f);
break;
case 1:
- me->SetOrientation(4.60f);
+ me->SetFacingTo(4.60f);
break;
case 2:
- me->SetOrientation(2.79f);
+ me->SetFacingTo(2.79f);
break;
}
-
- me->SendMovementFlagUpdate();
}
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
index e637de75b4d..5cc8f517533 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
@@ -132,9 +132,9 @@ bool GrandChampionsOutVehicle(Creature* me)
if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
{
- if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
- !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
- !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!pGrandChampion1->m_movementInfo.t_guid &&
+ !pGrandChampion2->m_movementInfo.t_guid &&
+ !pGrandChampion3->m_movementInfo.t_guid)
return true;
}
@@ -386,7 +386,7 @@ public:
}
}else uiPhaseTimer -= uiDiff;
- if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!UpdateVictim() || me->m_movementInfo.t_guid)
return;
if (uiInterceptTimer <= uiDiff)
@@ -530,7 +530,7 @@ public:
uiFireBallTimer = 5000;
} else uiFireBallTimer -= uiDiff;
- if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!UpdateVictim() || me->m_movementInfo.t_guid)
return;
if (uiFireBallTimer <= uiDiff)
@@ -668,7 +668,7 @@ public:
}
}else uiPhaseTimer -= uiDiff;
- if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!UpdateVictim() || me->m_movementInfo.t_guid)
return;
if (uiChainLightningTimer <= uiDiff)
@@ -814,7 +814,7 @@ public:
}
}else uiPhaseTimer -= uiDiff;
- if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!UpdateVictim() || me->m_movementInfo.t_guid)
return;
if (uiLightningArrowsTimer <= uiDiff)
@@ -962,7 +962,7 @@ public:
}
} else uiPhaseTimer -= uiDiff;
- if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (!UpdateVictim() || me->m_movementInfo.t_guid)
return;
if (uiEviscerateTimer <= uiDiff)
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
index 472048501a5..9d0bb450a73 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp
@@ -191,10 +191,7 @@ public:
return;
if (uiPointId == 1)
- {
- me->SetOrientation(ORIENTATION);
- me->SendMovementFlagUpdate();
- }
+ me->SetFacingTo(ORIENTATION);
}
void DoSummonGrandChampion(uint32 uiBoss)
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
index 61a654ec2bb..c3158acf67d 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
@@ -300,8 +300,7 @@ class boss_devourer_of_souls : public CreatureScript
DoCast(me, SPELL_WAILING_SOULS_STARTING);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
- me->SetOrientation(me->GetAngle(target));
- me->SendMovementFlagUpdate();
+ me->SetFacingTo(me->GetAngle(target));
DoCast(me, SPELL_WAILING_SOULS_BEAM);
}
@@ -327,8 +326,7 @@ class boss_devourer_of_souls : public CreatureScript
case EVENT_WAILING_SOULS_TICK:
beamAngle += beamAngleDiff;
- me->SetOrientation(beamAngle);
- me->SendMovementFlagUpdate();
+ me->SetFacingTo(beamAngle);
me->StopMoving();
DoCast(me, SPELL_WAILING_SOULS);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
index 938b2e94d02..4fbfe4219d4 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
@@ -204,7 +204,6 @@ class boss_blood_queen_lana_thel : public CreatureScript
minchar->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
minchar->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
minchar->SetCanFly(false);
- minchar->SendMovementFlagUpdate();
minchar->RemoveAllAuras();
minchar->GetMotionMaster()->MoveCharge(4629.3711f, 2782.6089f, 401.5301f, SPEED_CHARGE/3.0f);
}
@@ -237,7 +236,6 @@ class boss_blood_queen_lana_thel : public CreatureScript
me->SetDisableGravity(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
me->SetCanFly(true);
- me->SendMovementFlagUpdate();
me->GetMotionMaster()->MovePoint(POINT_MINCHAR, mincharPos);
}
}
@@ -317,7 +315,6 @@ class boss_blood_queen_lana_thel : public CreatureScript
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
me->SetCanFly(false);
- me->SendMovementFlagUpdate();
me->SetReactState(REACT_AGGRESSIVE);
if (Unit* victim = me->SelectVictim())
AttackStart(victim);
@@ -444,7 +441,6 @@ class boss_blood_queen_lana_thel : public CreatureScript
me->SetDisableGravity(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
me->SetCanFly(true);
- me->SendMovementFlagUpdate();
me->GetMotionMaster()->MovePoint(POINT_AIR, airPos);
break;
case EVENT_AIR_FLY_DOWN:
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index 59c9393c934..a78f25bd394 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -355,7 +355,7 @@ class boss_lady_deathwhisper : public CreatureScript
void DamageTaken(Unit* /*damageDealer*/, uint32& damage)
{
// phase transition
- if (events.IsInPhase(PHASE_ONE) && damage > me->GetPower(POWER_MANA))
+ if (events.IsInPhase(PHASE_ONE) && damage > uint32(me->GetPower(POWER_MANA)))
{
Talk(SAY_PHASE_2);
Talk(EMOTE_PHASE_2);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index 033674767e6..65da2226a74 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -374,25 +374,6 @@ class NecroticPlagueTargetCheck : public std::unary_function<Unit*, bool>
uint32 _notAura2;
};
-class HeightDifferenceCheck
-{
- public:
- HeightDifferenceCheck(GameObject* go, float diff, bool reverse)
- : _baseObject(go), _difference(diff), _reverse(reverse)
- {
- }
-
- bool operator()(WorldObject* unit) const
- {
- return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse;
- }
-
- private:
- GameObject* _baseObject;
- float _difference;
- bool _reverse;
-};
-
class FrozenThroneResetWorker
{
public:
@@ -1115,6 +1096,7 @@ class boss_the_lich_king : public CreatureScript
{
WorldPacket data(SMSG_PLAY_MUSIC, 4);
data << uint32(musicId);
+ data << uint64(me->GetGUID());
SendPacketToPlayers(&data);
}
@@ -1526,7 +1508,7 @@ class npc_valkyr_shadowguard : public CreatureScript
{
std::list<Creature*> triggers;
GetCreatureListWithEntryInGrid(triggers, me, NPC_WORLD_TRIGGER, 150.0f);
- triggers.remove_if(HeightDifferenceCheck(platform, 5.0f, true));
+ triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true));
if (triggers.empty())
return;
@@ -2317,7 +2299,7 @@ class spell_the_lich_king_quake : public SpellScriptLoader
void FilterTargets(std::list<WorldObject*>& targets)
{
if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetData64(DATA_ARTHAS_PLATFORM)))
- targets.remove_if(HeightDifferenceCheck(platform, 5.0f, false));
+ targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false));
}
void HandleSendEvent(SpellEffIndex /*effIndex*/)
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
index 0e5941138a6..ebd1aa85078 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp
@@ -294,7 +294,6 @@ class boss_sapphiron : public CreatureScript
case EVENT_LIFTOFF:
Talk(EMOTE_AIR_PHASE);
me->SetDisableGravity(true);
- me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_ICEBOLT, 1500);
_iceboltCount = RAID_MODE(2, 3);
return;
@@ -339,7 +338,6 @@ class boss_sapphiron : public CreatureScript
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
Talk(EMOTE_GROUND_PHASE);
me->SetDisableGravity(false);
- me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_GROUND, 1500);
return;
case EVENT_GROUND:
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
index f2090f6a2e6..8ff0c798f00 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
@@ -325,8 +325,7 @@ public:
break;
case 7:
Talk(SAY_SVALA_INTRO_2);
- me->SetOrientation(1.58f);
- me->SendMovementFlagUpdate();
+ me->SetFacingTo(1.58f);
arthas->SetVisible(false);
++introPhase;
introTimer = 13800;
diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp
index 16965b83d25..b1091013270 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -2363,10 +2363,7 @@ public:
me->StopMoving();
me->SetUInt32Value(UNIT_NPC_FLAGS, 0);
if (Player* player = me->GetPlayer(*me, uiPlayerGUID))
- {
- me->SetInFront(player);
- me->SendMovementFlagUpdate();
- }
+ me->SetFacingToObject(player);
uiEventTimer = 3000;
uiEventPhase = 1;
}
@@ -2416,10 +2413,7 @@ public:
case NPC_SALTY_JOHN_THORPE:
Talk(SAY_HIDDEN_CULTIST_4);
if (Player* player = me->GetPlayer(*me, uiPlayerGUID))
- {
- me->SetInFront(player);
- me->SendMovementFlagUpdate();
- }
+ me->SetFacingToObject(player);
uiEventTimer = 3000;
uiEventPhase = 3;
break;
diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp
index 33440cad48b..d3d77cdd9da 100644
--- a/src/server/scripts/Northrend/zone_dalaran.cpp
+++ b/src/server/scripts/Northrend/zone_dalaran.cpp
@@ -126,52 +126,7 @@ public:
}
};
-/*######
-## npc_hira_snowdawn
-######*/
-
-enum eHiraSnowdawn
-{
- SPELL_COLD_WEATHER_FLYING = 54197
-};
-
-#define GOSSIP_TEXT_TRAIN_HIRA "I seek training to ride a steed."
-
-class npc_hira_snowdawn : public CreatureScript
-{
-public:
- npc_hira_snowdawn() : CreatureScript("npc_hira_snowdawn") { }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (!creature->isVendor() || !creature->isTrainer())
- return false;
-
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_TRAIN_HIRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
-
- if (player->getLevel() >= 80 && player->HasSpell(SPELL_COLD_WEATHER_FLYING))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_TRAIN)
- player->GetSession()->SendTrainerList(creature->GetGUID());
-
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(creature->GetGUID());
-
- return true;
- }
-};
-
void AddSC_dalaran()
{
new npc_mageguard_dalaran;
- new npc_hira_snowdawn;
}
diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp
index 33a573b9b35..1d04a9b163c 100644
--- a/src/server/scripts/Northrend/zone_zuldrak.cpp
+++ b/src/server/scripts/Northrend/zone_zuldrak.cpp
@@ -1372,8 +1372,7 @@ public:
player->CLOSE_GOSSIP_MENU();
creature->CastSpell(player, SPELL_QUEST_CREDIT, true);
CAST_AI(npc_crusade_recruit::npc_crusade_recruitAI, (creature->AI()))->m_uiPhase = 1;
- creature->SetInFront(player);
- creature->SendMovementFlagUpdate();
+ creature->SetFacingToObject(player);
}
return true;
diff --git a/src/server/scripts/OutdoorPvP/CMakeLists.txt b/src/server/scripts/OutdoorPvP/CMakeLists.txt
index 1789cbc1ffe..ef10db772c9 100644
--- a/src/server/scripts/OutdoorPvP/CMakeLists.txt
+++ b/src/server/scripts/OutdoorPvP/CMakeLists.txt
@@ -17,8 +17,6 @@ set(scripts_STAT_SRCS
OutdoorPvP/OutdoorPvPNA.cpp
OutdoorPvP/OutdoorPvPHP.cpp
OutdoorPvP/OutdoorPvPTF.h
- OutdoorPvP/OutdoorPvPEP.h
- OutdoorPvP/OutdoorPvPEP.cpp
OutdoorPvP/OutdoorPvPHP.h
OutdoorPvP/OutdoorPvPZM.h
OutdoorPvP/OutdoorPvPNA.h
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp
deleted file mode 100644
index 79755c0f57d..00000000000
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ScriptMgr.h"
-#include "OutdoorPvPEP.h"
-#include "WorldPacket.h"
-#include "Player.h"
-#include "GameObject.h"
-#include "ObjectMgr.h"
-#include "ObjectAccessor.h"
-#include "OutdoorPvPMgr.h"
-#include "Creature.h"
-#include "Language.h"
-#include "World.h"
-#include "GossipDef.h"
-
-OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP* pvp)
-: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSide(0)
-{
- SetCapturePointData(EPCapturePoints[EP_EWT].entry, EPCapturePoints[EP_EWT].map, EPCapturePoints[EP_EWT].x, EPCapturePoints[EP_EWT].y, EPCapturePoints[EP_EWT].z, EPCapturePoints[EP_EWT].o, EPCapturePoints[EP_EWT].rot0, EPCapturePoints[EP_EWT].rot1, EPCapturePoints[EP_EWT].rot2, EPCapturePoints[EP_EWT].rot3);
- AddObject(EP_EWT_FLAGS, EPTowerFlags[EP_EWT].entry, EPTowerFlags[EP_EWT].map, EPTowerFlags[EP_EWT].x, EPTowerFlags[EP_EWT].y, EPTowerFlags[EP_EWT].z, EPTowerFlags[EP_EWT].o, EPTowerFlags[EP_EWT].rot0, EPTowerFlags[EP_EWT].rot1, EPTowerFlags[EP_EWT].rot2, EPTowerFlags[EP_EWT].rot3);
-}
-
-void OPvPCapturePointEP_EWT::ChangeState()
-{
- // if changing from controlling alliance to horde or vice versa
- if ( m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_EWT, 0);
- }
- else if ( m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_EWT, 0);
- }
-
- uint32 artkit = 21;
-
- switch (m_State)
- {
- case OBJECTIVESTATE_ALLIANCE:
- m_TowerState = EP_TS_A;
- artkit = 2;
- SummonSupportUnitAtNorthpassTower(ALLIANCE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_EWT, ALLIANCE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A));
- break;
- case OBJECTIVESTATE_HORDE:
- m_TowerState = EP_TS_H;
- artkit = 1;
- SummonSupportUnitAtNorthpassTower(HORDE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_EWT, HORDE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H));
- break;
- case OBJECTIVESTATE_NEUTRAL:
- m_TowerState = EP_TS_N;
- break;
- case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
- case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- break;
- case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
- case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- break;
- }
-
- GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID);
- GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_EWT_FLAGS]);
- if (flag)
- {
- flag->SetGoArtKit(artkit);
- }
- if (flag2)
- {
- flag2->SetGoArtKit(artkit);
- }
-
- UpdateTowerState();
-
- // complete quest objective
- if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H)
- SendObjectiveComplete(EP_EWT_CM, 0);
-}
-
-void OPvPCapturePointEP_EWT::SendChangePhase()
-{
- // send this too, sometimes the slider disappears, dunno why :(
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- // send these updates to only the ones in this objective
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- // send this too, sometimes it resets :S
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
-}
-
-void OPvPCapturePointEP_EWT::FillInitialWorldStates(WorldPacket &data)
-{
- data << EP_EWT_A << uint32(bool(m_TowerState & EP_TS_A));
- data << EP_EWT_H << uint32(bool(m_TowerState & EP_TS_H));
- data << EP_EWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A));
- data << EP_EWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H));
- data << EP_EWT_N << uint32(bool(m_TowerState & EP_TS_N));
-}
-
-void OPvPCapturePointEP_EWT::UpdateTowerState()
-{
- m_PvP->SendUpdateWorldState(EP_EWT_A, bool(m_TowerState & EP_TS_A));
- m_PvP->SendUpdateWorldState(EP_EWT_H, bool(m_TowerState & EP_TS_H));
- m_PvP->SendUpdateWorldState(EP_EWT_N_A, bool(m_TowerState & EP_TS_N_A));
- m_PvP->SendUpdateWorldState(EP_EWT_N_H, bool(m_TowerState & EP_TS_N_H));
- m_PvP->SendUpdateWorldState(EP_EWT_N, bool(m_TowerState & EP_TS_N));
-}
-
-bool OPvPCapturePointEP_EWT::HandlePlayerEnter(Player* player)
-{
- if (OPvPCapturePoint::HandlePlayerEnter(player))
- {
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
- return true;
- }
- return false;
-}
-
-void OPvPCapturePointEP_EWT::HandlePlayerLeave(Player* player)
-{
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0);
- OPvPCapturePoint::HandlePlayerLeave(player);
-}
-
-void OPvPCapturePointEP_EWT::SummonSupportUnitAtNorthpassTower(uint32 team)
-{
- if (m_UnitsSummonedSide != team)
- {
- m_UnitsSummonedSide = team;
- const creature_type * ct = NULL;
- if (team == ALLIANCE)
- ct=EP_EWT_Summons_A;
- else
- ct=EP_EWT_Summons_H;
-
- for (uint8 i = 0; i < EP_EWT_NUM_CREATURES; ++i)
- {
- DelCreature(i);
- AddCreature(i, ct[i].entry, ct[i].teamval, ct[i].map, ct[i].x, ct[i].y, ct[i].z, ct[i].o, 1000000);
- }
- }
-}
-
-// NPT
-OPvPCapturePointEP_NPT::OPvPCapturePointEP_NPT(OutdoorPvP* pvp)
-: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_SummonedGOSide(0)
-{
- SetCapturePointData(EPCapturePoints[EP_NPT].entry, EPCapturePoints[EP_NPT].map, EPCapturePoints[EP_NPT].x, EPCapturePoints[EP_NPT].y, EPCapturePoints[EP_NPT].z, EPCapturePoints[EP_NPT].o, EPCapturePoints[EP_NPT].rot0, EPCapturePoints[EP_NPT].rot1, EPCapturePoints[EP_NPT].rot2, EPCapturePoints[EP_NPT].rot3);
- AddObject(EP_NPT_FLAGS, EPTowerFlags[EP_NPT].entry, EPTowerFlags[EP_NPT].map, EPTowerFlags[EP_NPT].x, EPTowerFlags[EP_NPT].y, EPTowerFlags[EP_NPT].z, EPTowerFlags[EP_NPT].o, EPTowerFlags[EP_NPT].rot0, EPTowerFlags[EP_NPT].rot1, EPTowerFlags[EP_NPT].rot2, EPTowerFlags[EP_NPT].rot3);
-}
-
-void OPvPCapturePointEP_NPT::ChangeState()
-{
- // if changing from controlling alliance to horde or vice versa
- if ( m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_NPT, 0);
- }
- else if ( m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_NPT, 0);
- }
-
- uint32 artkit = 21;
-
- switch (m_State)
- {
- case OBJECTIVESTATE_ALLIANCE:
- m_TowerState = EP_TS_A;
- artkit = 2;
- SummonGO(ALLIANCE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_NPT, ALLIANCE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A));
- break;
- case OBJECTIVESTATE_HORDE:
- m_TowerState = EP_TS_H;
- artkit = 1;
- SummonGO(HORDE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_NPT, HORDE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H));
- break;
- case OBJECTIVESTATE_NEUTRAL:
- m_TowerState = EP_TS_N;
- m_SummonedGOSide = 0;
- DelObject(EP_NPT_BUFF);
- break;
- case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- break;
- case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- m_SummonedGOSide = 0;
- DelObject(EP_NPT_BUFF);
- break;
- case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- break;
- case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- m_SummonedGOSide = 0;
- DelObject(EP_NPT_BUFF);
- break;
- }
-
- GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID);
- GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_NPT_FLAGS]);
- if (flag)
- {
- flag->SetGoArtKit(artkit);
- }
- if (flag2)
- {
- flag2->SetGoArtKit(artkit);
- }
-
- UpdateTowerState();
-
- // complete quest objective
- if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H)
- SendObjectiveComplete(EP_NPT_CM, 0);
-}
-
-void OPvPCapturePointEP_NPT::SendChangePhase()
-{
- // send this too, sometimes the slider disappears, dunno why :(
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- // send these updates to only the ones in this objective
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- // send this too, sometimes it resets :S
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
-}
-
-void OPvPCapturePointEP_NPT::FillInitialWorldStates(WorldPacket &data)
-{
- data << EP_NPT_A << uint32(bool(m_TowerState & EP_TS_A));
- data << EP_NPT_H << uint32(bool(m_TowerState & EP_TS_H));
- data << EP_NPT_N_A << uint32(bool(m_TowerState & EP_TS_N_A));
- data << EP_NPT_N_H << uint32(bool(m_TowerState & EP_TS_N_H));
- data << EP_NPT_N << uint32(bool(m_TowerState & EP_TS_N));
-}
-
-void OPvPCapturePointEP_NPT::UpdateTowerState()
-{
- m_PvP->SendUpdateWorldState(EP_NPT_A, bool(m_TowerState & EP_TS_A));
- m_PvP->SendUpdateWorldState(EP_NPT_H, bool(m_TowerState & EP_TS_H));
- m_PvP->SendUpdateWorldState(EP_NPT_N_A, bool(m_TowerState & EP_TS_N_A));
- m_PvP->SendUpdateWorldState(EP_NPT_N_H, bool(m_TowerState & EP_TS_N_H));
- m_PvP->SendUpdateWorldState(EP_NPT_N, bool(m_TowerState & EP_TS_N));
-}
-
-bool OPvPCapturePointEP_NPT::HandlePlayerEnter(Player* player)
-{
- if (OPvPCapturePoint::HandlePlayerEnter(player))
- {
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
- return true;
- }
- return false;
-}
-
-void OPvPCapturePointEP_NPT::HandlePlayerLeave(Player* player)
-{
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0);
- OPvPCapturePoint::HandlePlayerLeave(player);
-}
-
-void OPvPCapturePointEP_NPT::SummonGO(uint32 team)
-{
- if (m_SummonedGOSide != team)
- {
- m_SummonedGOSide = team;
- DelObject(EP_NPT_BUFF);
- AddObject(EP_NPT_BUFF, EP_NPT_LordaeronShrine.entry, EP_NPT_LordaeronShrine.map, EP_NPT_LordaeronShrine.x, EP_NPT_LordaeronShrine.y, EP_NPT_LordaeronShrine.z, EP_NPT_LordaeronShrine.o, EP_NPT_LordaeronShrine.rot0, EP_NPT_LordaeronShrine.rot1, EP_NPT_LordaeronShrine.rot2, EP_NPT_LordaeronShrine.rot3);
- GameObject* go = HashMapHolder<GameObject>::Find(m_Objects[EP_NPT_BUFF]);
- if (go)
- go->SetUInt32Value(GAMEOBJECT_FACTION, (team == ALLIANCE ? 84 : 83));
- }
-}
-
-// CGT
-OPvPCapturePointEP_CGT::OPvPCapturePointEP_CGT(OutdoorPvP* pvp)
-: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_GraveyardSide(0)
-{
- SetCapturePointData(EPCapturePoints[EP_CGT].entry, EPCapturePoints[EP_CGT].map, EPCapturePoints[EP_CGT].x, EPCapturePoints[EP_CGT].y, EPCapturePoints[EP_CGT].z, EPCapturePoints[EP_CGT].o, EPCapturePoints[EP_CGT].rot0, EPCapturePoints[EP_CGT].rot1, EPCapturePoints[EP_CGT].rot2, EPCapturePoints[EP_CGT].rot3);
- AddObject(EP_CGT_FLAGS, EPTowerFlags[EP_CGT].entry, EPTowerFlags[EP_CGT].map, EPTowerFlags[EP_CGT].x, EPTowerFlags[EP_CGT].y, EPTowerFlags[EP_CGT].z, EPTowerFlags[EP_CGT].o, EPTowerFlags[EP_CGT].rot0, EPTowerFlags[EP_CGT].rot1, EPTowerFlags[EP_CGT].rot2, EPTowerFlags[EP_CGT].rot3);
-}
-
-void OPvPCapturePointEP_CGT::ChangeState()
-{
- // if changing from controlling alliance to horde or vice versa
- if ( m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_CGT, 0);
- }
- else if ( m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_CGT, 0);
- }
-
- uint32 artkit = 21;
-
- switch (m_State)
- {
- case OBJECTIVESTATE_ALLIANCE:
- m_TowerState = EP_TS_A;
- artkit = 2;
- LinkGraveYard(ALLIANCE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_CGT, ALLIANCE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A));
- break;
- case OBJECTIVESTATE_HORDE:
- m_TowerState = EP_TS_H;
- artkit = 1;
- LinkGraveYard(HORDE);
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_CGT, HORDE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H));
- break;
- case OBJECTIVESTATE_NEUTRAL:
- m_TowerState = EP_TS_N;
- break;
- case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
- case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- break;
- case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
- case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- break;
- }
-
- GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID);
- GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_CGT_FLAGS]);
- if (flag)
- {
- flag->SetGoArtKit(artkit);
- }
- if (flag2)
- {
- flag2->SetGoArtKit(artkit);
- }
-
- UpdateTowerState();
-
- // complete quest objective
- if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H)
- SendObjectiveComplete(EP_CGT_CM, 0);
-}
-
-void OPvPCapturePointEP_CGT::SendChangePhase()
-{
- // send this too, sometimes the slider disappears, dunno why :(
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- // send these updates to only the ones in this objective
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- // send this too, sometimes it resets :S
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
-}
-
-void OPvPCapturePointEP_CGT::FillInitialWorldStates(WorldPacket &data)
-{
- data << EP_CGT_A << uint32(bool(m_TowerState & EP_TS_A));
- data << EP_CGT_H << uint32(bool(m_TowerState & EP_TS_H));
- data << EP_CGT_N_A << uint32(bool(m_TowerState & EP_TS_N_A));
- data << EP_CGT_N_H << uint32(bool(m_TowerState & EP_TS_N_H));
- data << EP_CGT_N << uint32(bool(m_TowerState & EP_TS_N));
-}
-
-void OPvPCapturePointEP_CGT::UpdateTowerState()
-{
- m_PvP->SendUpdateWorldState(EP_CGT_A, bool(m_TowerState & EP_TS_A));
- m_PvP->SendUpdateWorldState(EP_CGT_H, bool(m_TowerState & EP_TS_H));
- m_PvP->SendUpdateWorldState(EP_CGT_N_A, bool(m_TowerState & EP_TS_N_A));
- m_PvP->SendUpdateWorldState(EP_CGT_N_H, bool(m_TowerState & EP_TS_N_H));
- m_PvP->SendUpdateWorldState(EP_CGT_N, bool(m_TowerState & EP_TS_N));
-}
-
-bool OPvPCapturePointEP_CGT::HandlePlayerEnter(Player* player)
-{
- if (OPvPCapturePoint::HandlePlayerEnter(player))
- {
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
- return true;
- }
- return false;
-}
-
-void OPvPCapturePointEP_CGT::HandlePlayerLeave(Player* player)
-{
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0);
- OPvPCapturePoint::HandlePlayerLeave(player);
-}
-
-void OPvPCapturePointEP_CGT::LinkGraveYard(uint32 team)
-{
- if (m_GraveyardSide != team)
- {
- m_GraveyardSide = team;
- sObjectMgr->RemoveGraveYardLink(EP_GraveYardId, EP_GraveYardZone, team, false);
- sObjectMgr->AddGraveYardLink(EP_GraveYardId, EP_GraveYardZone, team, false);
- }
-}
-
-// PWT
-OPvPCapturePointEP_PWT::OPvPCapturePointEP_PWT(OutdoorPvP* pvp)
-: OPvPCapturePoint(pvp), m_FlightMasterSpawned(0), m_TowerState(EP_TS_N)
-{
- SetCapturePointData(EPCapturePoints[EP_PWT].entry, EPCapturePoints[EP_PWT].map, EPCapturePoints[EP_PWT].x, EPCapturePoints[EP_PWT].y, EPCapturePoints[EP_PWT].z, EPCapturePoints[EP_PWT].o, EPCapturePoints[EP_PWT].rot0, EPCapturePoints[EP_PWT].rot1, EPCapturePoints[EP_PWT].rot2, EPCapturePoints[EP_PWT].rot3);
- AddObject(EP_PWT_FLAGS, EPTowerFlags[EP_PWT].entry, EPTowerFlags[EP_PWT].map, EPTowerFlags[EP_PWT].x, EPTowerFlags[EP_PWT].y, EPTowerFlags[EP_PWT].z, EPTowerFlags[EP_PWT].o, EPTowerFlags[EP_PWT].rot0, EPTowerFlags[EP_PWT].rot1, EPTowerFlags[EP_PWT].rot2, EPTowerFlags[EP_PWT].rot3);
-}
-
-void OPvPCapturePointEP_PWT::ChangeState()
-{
- // if changing from controlling alliance to horde or vice versa
- if ( m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_PWT, 0);
- }
- else if ( m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State )
- {
- sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H));
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_PWT, 0);
- }
-
- uint32 artkit = 21;
-
- switch (m_State)
- {
- case OBJECTIVESTATE_ALLIANCE:
- m_TowerState = EP_TS_A;
- SummonFlightMaster(ALLIANCE);
- artkit = 2;
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_PWT, ALLIANCE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A));
- break;
- case OBJECTIVESTATE_HORDE:
- m_TowerState = EP_TS_H;
- SummonFlightMaster(HORDE);
- artkit = 1;
- ((OutdoorPvPEP*)m_PvP)->SetControlledState(EP_PWT, HORDE);
- if (m_OldState != m_State) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H));
- break;
- case OBJECTIVESTATE_NEUTRAL:
- m_TowerState = EP_TS_N;
- DelCreature(EP_PWT_FLIGHTMASTER);
- m_FlightMasterSpawned = 0;
- break;
- case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- break;
- case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
- m_TowerState = EP_TS_N_A;
- DelCreature(EP_PWT_FLIGHTMASTER);
- m_FlightMasterSpawned = 0;
- break;
- case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- break;
- case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
- m_TowerState = EP_TS_N_H;
- DelCreature(EP_PWT_FLIGHTMASTER);
- m_FlightMasterSpawned = 0;
- break;
- }
-
- GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID);
- GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_PWT_FLAGS]);
- if (flag)
- {
- flag->SetGoArtKit(artkit);
- }
- if (flag2)
- {
- flag2->SetGoArtKit(artkit);
- }
-
- UpdateTowerState();
-
- // complete quest objective
- if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H)
- SendObjectiveComplete(EP_PWT_CM, 0);
-}
-
-void OPvPCapturePointEP_PWT::SendChangePhase()
-{
- // send this too, sometimes the slider disappears, dunno why :(
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- // send these updates to only the ones in this objective
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- // send this too, sometimes it resets :S
- SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
-}
-
-void OPvPCapturePointEP_PWT::FillInitialWorldStates(WorldPacket &data)
-{
- data << EP_PWT_A << uint32(bool(m_TowerState & EP_TS_A));
- data << EP_PWT_H << uint32(bool(m_TowerState & EP_TS_H));
- data << EP_PWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A));
- data << EP_PWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H));
- data << EP_PWT_N << uint32(bool(m_TowerState & EP_TS_N));
-}
-
-void OPvPCapturePointEP_PWT::UpdateTowerState()
-{
- m_PvP->SendUpdateWorldState(EP_PWT_A, bool(m_TowerState & EP_TS_A));
- m_PvP->SendUpdateWorldState(EP_PWT_H, bool(m_TowerState & EP_TS_H));
- m_PvP->SendUpdateWorldState(EP_PWT_N_A, bool(m_TowerState & EP_TS_N_A));
- m_PvP->SendUpdateWorldState(EP_PWT_N_H, bool(m_TowerState & EP_TS_N_H));
- m_PvP->SendUpdateWorldState(EP_PWT_N, bool(m_TowerState & EP_TS_N));
-}
-
-bool OPvPCapturePointEP_PWT::HandlePlayerEnter(Player* player)
-{
- if (OPvPCapturePoint::HandlePlayerEnter(player))
- {
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1);
- uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct);
- return true;
- }
- return false;
-}
-
-void OPvPCapturePointEP_PWT::HandlePlayerLeave(Player* player)
-{
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0);
- OPvPCapturePoint::HandlePlayerLeave(player);
-}
-
-void OPvPCapturePointEP_PWT::SummonFlightMaster(uint32 team)
-{
- if (m_FlightMasterSpawned != team)
- {
- m_FlightMasterSpawned = team;
- DelCreature(EP_PWT_FLIGHTMASTER);
- AddCreature(EP_PWT_FLIGHTMASTER, EP_PWT_FlightMaster.entry, team, EP_PWT_FlightMaster.map, EP_PWT_FlightMaster.x, EP_PWT_FlightMaster.y, EP_PWT_FlightMaster.z, EP_PWT_FlightMaster.o);
- /*
- // sky - we need update gso code
-
- Creature* c = HashMapHolder<Creature>::Find(m_Creatures[EP_PWT_FLIGHTMASTER]);
- //Spawn flight master as friendly to capturing team
- c->SetUInt32Value(GAMEOBJECT_FACTION, (team == ALLIANCE ? 55 : 68));
- if (c)
- {
- GossipOption gso;
- gso.Action = GOSSIP_OPTION_OUTDOORPVP;
- gso.GossipId = 0;
- gso.OptionText.assign(sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_NPT));
- gso.Id = 50;
- gso.Icon = 0;
- gso.NpcFlag = 0;
- gso.BoxMoney = 0;
- gso.Coded = false;
- c->addGossipOption(gso);
-
- gso.Action = GOSSIP_OPTION_OUTDOORPVP;
- gso.GossipId = 0;
- gso.OptionText.assign(sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_EWT));
- gso.Id = 50;
- gso.Icon = 0;
- gso.NpcFlag = 0;
- gso.BoxMoney = 0;
- gso.Coded = false;
- c->addGossipOption(gso);
-
- gso.Action = GOSSIP_OPTION_OUTDOORPVP;
- gso.GossipId = 0;
- gso.OptionText.assign(sObjectMgr->GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_CGT));
- gso.Id = 50;
- gso.Icon = 0;
- gso.NpcFlag = 0;
- gso.BoxMoney = 0;
- gso.Coded = false;
- c->addGossipOption(gso);
- }
- */
- }
-}
-
-// ep
-OutdoorPvPEP::OutdoorPvPEP()
-{
- m_TypeId = OUTDOOR_PVP_EP;
- memset(EP_Controls, 0, sizeof(EP_Controls));
- m_AllianceTowersControlled = 0;
- m_HordeTowersControlled = 0;
-}
-
-bool OutdoorPvPEP::SetupOutdoorPvP()
-{
- for (uint8 i = 0; i < EPBuffZonesNum; ++i)
- RegisterZone(EPBuffZones[i]);
-
- AddCapturePoint(new OPvPCapturePointEP_EWT(this));
- AddCapturePoint(new OPvPCapturePointEP_PWT(this));
- AddCapturePoint(new OPvPCapturePointEP_CGT(this));
- AddCapturePoint(new OPvPCapturePointEP_NPT(this));
- return true;
-}
-
-bool OutdoorPvPEP::Update(uint32 diff)
-{
- if (OutdoorPvP::Update(diff))
- {
- m_AllianceTowersControlled = 0;
- m_HordeTowersControlled = 0;
- for (int i = 0; i < EP_TOWER_NUM; ++i)
- {
- if (EP_Controls[i] == ALLIANCE)
- ++m_AllianceTowersControlled;
- else if (EP_Controls[i] == HORDE)
- ++m_HordeTowersControlled;
- SendUpdateWorldState(EP_UI_TOWER_COUNT_A, m_AllianceTowersControlled);
- SendUpdateWorldState(EP_UI_TOWER_COUNT_H, m_HordeTowersControlled);
- BuffTeams();
- }
- return true;
- }
- return false;
-}
-
-void OutdoorPvPEP::HandlePlayerEnterZone(Player* player, uint32 zone)
-{
- // add buffs
- if (player->GetTeam() == ALLIANCE)
- {
- if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5)
- player->CastSpell(player, EP_AllianceBuffs[m_AllianceTowersControlled-1], true);
- }
- else
- {
- if (m_HordeTowersControlled && m_HordeTowersControlled < 5)
- player->CastSpell(player, EP_HordeBuffs[m_HordeTowersControlled-1], true);
- }
- OutdoorPvP::HandlePlayerEnterZone(player, zone);
-}
-
-void OutdoorPvPEP::HandlePlayerLeaveZone(Player* player, uint32 zone)
-{
- // remove buffs
- if (player->GetTeam() == ALLIANCE)
- {
- for (int i = 0; i < 4; ++i)
- player->RemoveAurasDueToSpell(EP_AllianceBuffs[i]);
- }
- else
- {
- for (int i = 0; i < 4; ++i)
- player->RemoveAurasDueToSpell(EP_HordeBuffs[i]);
- }
- OutdoorPvP::HandlePlayerLeaveZone(player, zone);
-}
-
-void OutdoorPvPEP::BuffTeams()
-{
- for (PlayerSet::iterator itr = m_players[0].begin(); itr != m_players[0].end(); ++itr)
- {
- if (Player* player = ObjectAccessor::FindPlayer(*itr))
- {
- for (int i = 0; i < 4; ++i)
- player->RemoveAurasDueToSpell(EP_AllianceBuffs[i]);
- if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5)
- player->CastSpell(player, EP_AllianceBuffs[m_AllianceTowersControlled-1], true);
- }
- }
- for (PlayerSet::iterator itr = m_players[1].begin(); itr != m_players[1].end(); ++itr)
- {
- if (Player* player = ObjectAccessor::FindPlayer(*itr))
- {
- for (int i = 0; i < 4; ++i)
- player->RemoveAurasDueToSpell(EP_HordeBuffs[i]);
- if (m_HordeTowersControlled && m_HordeTowersControlled < 5)
- player->CastSpell(player, EP_HordeBuffs[m_HordeTowersControlled-1], true);
- }
- }
-}
-
-void OutdoorPvPEP::SetControlledState(uint32 index, uint32 state)
-{
- EP_Controls[index] = state;
-}
-
-void OutdoorPvPEP::FillInitialWorldStates(WorldPacket & data)
-{
- data << EP_UI_TOWER_COUNT_A << m_AllianceTowersControlled;
- data << EP_UI_TOWER_COUNT_H << m_HordeTowersControlled;
- data << EP_UI_TOWER_SLIDER_DISPLAY << uint32(0);
- data << EP_UI_TOWER_SLIDER_POS << uint32(50);
- data << EP_UI_TOWER_SLIDER_N << uint32(100);
- for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
- {
- itr->second->FillInitialWorldStates(data);
- }
-}
-
-void OutdoorPvPEP::SendRemoveWorldStates(Player* player)
-{
- player->SendUpdateWorldState(EP_UI_TOWER_COUNT_A, 0);
- player->SendUpdateWorldState(EP_UI_TOWER_COUNT_H, 0);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, 0);
- player->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, 0);
-
- player->SendUpdateWorldState(EP_EWT_A, 0);
- player->SendUpdateWorldState(EP_EWT_H, 0);
- player->SendUpdateWorldState(EP_EWT_N, 0);
- player->SendUpdateWorldState(EP_EWT_N_A, 0);
- player->SendUpdateWorldState(EP_EWT_N_H, 0);
-
- player->SendUpdateWorldState(EP_PWT_A, 0);
- player->SendUpdateWorldState(EP_PWT_H, 0);
- player->SendUpdateWorldState(EP_PWT_N, 0);
- player->SendUpdateWorldState(EP_PWT_N_A, 0);
- player->SendUpdateWorldState(EP_PWT_N_H, 0);
-
- player->SendUpdateWorldState(EP_NPT_A, 0);
- player->SendUpdateWorldState(EP_NPT_H, 0);
- player->SendUpdateWorldState(EP_NPT_N, 0);
- player->SendUpdateWorldState(EP_NPT_N_A, 0);
- player->SendUpdateWorldState(EP_NPT_N_H, 0);
-
- player->SendUpdateWorldState(EP_CGT_A, 0);
- player->SendUpdateWorldState(EP_CGT_H, 0);
- player->SendUpdateWorldState(EP_CGT_N, 0);
- player->SendUpdateWorldState(EP_CGT_N_A, 0);
- player->SendUpdateWorldState(EP_CGT_N_H, 0);
-}
-
-class OutdoorPvP_eastern_plaguelands : public OutdoorPvPScript
-{
- public:
-
- OutdoorPvP_eastern_plaguelands()
- : OutdoorPvPScript("outdoorpvp_ep")
- {
- }
-
- OutdoorPvP* GetOutdoorPvP() const
- {
- return new OutdoorPvPEP();
- }
-};
-
-void AddSC_outdoorpvp_ep()
-{
- new OutdoorPvP_eastern_plaguelands();
-}
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h
deleted file mode 100644
index cdd944107bc..00000000000
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OUTDOOR_PVP_EP_
-#define OUTDOOR_PVP_EP_
-
-#include "DBCStructure.h"
-#include "OutdoorPvP.h"
-
-const uint32 EP_AllianceBuffs[4] = {11413, 11414, 11415, 1386};
-
-const uint32 EP_HordeBuffs[4] = {30880, 30683, 30682, 29520};
-
-const uint32 EP_GraveYardZone = 139;
-
-const uint32 EP_GraveYardId = 927;
-
-const uint8 EPBuffZonesNum = 3;
-
-const uint32 EP_EWT_CM = 17690;
-const uint32 EP_CGT_CM = 17689;
-const uint32 EP_NPT_CM = 17696;
-const uint32 EP_PWT_CM = 17698;
-
-const uint32 EPBuffZones[EPBuffZonesNum] = {139, 2017, 2057};
-
-enum EP_TaxiNodes
-{
- EP_CGT_Taxi = 87,
- EP_EWT_Taxi = 86,
- EP_NPT_Taxi = 85,
- EP_PWT_Taxi = 84
-};
-
-enum EP_EastwallTowerWorldStates
-{
- EP_EWT_A = 2354,
- EP_EWT_H = 2356,
- EP_EWT_N_A = 2359, // ally conquested
- EP_EWT_N_H = 2360,
- EP_EWT_N = 2361
-};
-
-enum EP_NorthpassTowerWorldStates
-{
- EP_NPT_N = 2352,
- EP_NPT_N_A = 2362,
- EP_NPT_N_H = 2363,
- EP_NPT_A = 2372,
- EP_NPT_H = 2373
-};
-
-enum EP_PlagewoodTowerWorldStates
-{
- EP_PWT_N_A = 2366,
- EP_PWT_N_H = 2353, //2367 not present! use neutral!
- EP_PWT_A = 2370,
- EP_PWT_H = 2371,
- EP_PWT_N = 2353
-};
-
-enum EP_CrownGuardTowerWorldStates
-{
- EP_CGT_N_A = 2374,
- EP_CGT_N_H = 2375,
- EP_CGT_A = 2378,
- EP_CGT_H = 2379,
- EP_CGT_N = 2355
-};
-
-enum EP_WorldStates
-{
- EP_UI_TOWER_SLIDER_DISPLAY = 2426,
- EP_UI_TOWER_SLIDER_POS = 2427,
- EP_UI_TOWER_SLIDER_N = 2428,
-
- EP_UI_TOWER_COUNT_A = 2327,
- EP_UI_TOWER_COUNT_H = 2328
-};
-
-enum EP_Summons
-{
- EP_EWT_COMMANDER = 0,
- EP_EWT_SOLDIER1,
- EP_EWT_SOLDIER2,
- EP_EWT_SOLDIER3,
- EP_EWT_SOLDIER4,
- EP_PWT_FLIGHTMASTER,
-};
-
-enum EP_GoSummons
-{
- EP_NPT_BUFF = 0,
- EP_NPT_FLAGS,
- EP_EWT_FLAGS,
- EP_CGT_FLAGS,
- EP_PWT_FLAGS
-};
-
-enum EP_Towers
-{
- EP_EWT = 0, // plaguelands 03
- EP_NPT, // plaguelands 01
- EP_PWT, // plaguelands 04
- EP_CGT, // plaguelands 02
- EP_TOWER_NUM
-};
-
-const go_type EPCapturePoints[EP_TOWER_NUM] =
-{
- {182097, 0, 2574.51f, -4794.89f, 144.704f, -1.45003f, -0.097056f, 0.095578f, -0.656229f, 0.742165f},
- {181899, 0, 3181.08f, -4379.36f, 174.123f, -2.03472f, -0.065392f, 0.119494f, -0.842275f, 0.521553f},
- {182098, 0, 2962.71f, -3042.31f, 154.789f, 2.08426f, -0.074807f, -0.113837f, 0.855928f, 0.49883f},
- {182096, 0, 1860.85f, -3731.23f, 196.716f, -2.53214f, 0.033967f, -0.131914f, 0.944741f, -0.298177f}
-};
-
-const go_type EPTowerFlags[EP_TOWER_NUM] =
-{
- {182106, 0, 2569.60f, -4772.93f, 115.399f, 2.72271f, 0.0f, 0.0f, 0.978148f, 0.207912f},
- {182106, 0, 3148.17f, -4365.51f, 145.029f, 1.53589f, 0.0f, 0.0f, 0.694658f, 0.71934f},
- {182106, 0, 2992.63f, -3022.95f, 125.593f, 3.03687f, 0.0f, 0.0f, 0.99863f, 0.052336f},
- {182106, 0, 1838.42f, -3703.56f, 167.713f, 0.890118f, 0.0f, 0.0f, 0.430511f, 0.902585f}
-};
-
-const uint32 EPTowerPlayerEnterEvents[EP_TOWER_NUM] = {10691, 10699, 10701, 10705};
-
-const uint32 EPTowerPlayerLeaveEvents[EP_TOWER_NUM] = {10692, 10698, 10700, 10704};
-
-const uint8 EP_NUM_CREATURES = 6;
-const uint8 EP_EWT_NUM_CREATURES = 5;
-
-// one lordaeron commander, 4 soldiers
-// should be spawned at EWT and follow a path, but trans-grid pathing isn't safe, so summon them directly at NPT
-const creature_type EP_EWT_Summons_A[EP_EWT_NUM_CREATURES] =
-{
- {17635, 469, 0, 3167.61f, -4352.09f, 138.20f, 4.5811f},
- {17647, 469, 0, 3172.74f, -4352.99f, 139.14f, 4.9873f},
- {17647, 469, 0, 3165.89f, -4354.46f, 138.67f, 3.7244f},
- {17647, 469, 0, 3164.65f, -4350.26f, 138.22f, 2.4794f},
- {17647, 469, 0, 3169.91f, -4349.68f, 138.37f, 0.7444f}
-};
-
-const creature_type EP_EWT_Summons_H[EP_EWT_NUM_CREATURES] =
-{
- {17995, 67, 0, 3167.61f, -4352.09f, 138.20f, 4.5811f},
- {17996, 67, 0, 3172.74f, -4352.99f, 139.14f, 4.9873f},
- {17996, 67, 0, 3165.89f, -4354.46f, 138.67f, 3.7244f},
- {17996, 67, 0, 3164.65f, -4350.26f, 138.22f, 2.4794f},
- {17996, 67, 0, 3169.91f, -4349.68f, 138.37f, 0.7444f}
-};
-
-enum EP_TowerStates
-{
- EP_TS_N = 1,
- EP_TS_N_A = 2,
- EP_TS_N_H = 4,
- EP_TS_A_P = 8,
- EP_TS_H_P = 16,
- EP_TS_A = 32,
- EP_TS_H = 64
-};
-
-// when spawning, pay attention at setting the faction manually!
-const creature_type EP_PWT_FlightMaster = {17209, 0, 0, 2987.5f, -3049.11f, 120.126f, 5.75959f};
-
-// after spawning, modify the faction so that only the controller will be able to use it with SetUInt32Value(GAMEOBJECT_FACTION, faction_id);
-const go_type EP_NPT_LordaeronShrine = {181682, 0, 3167.72f, -4355.91f, 138.785f, 1.69297f, 0.0f, 0.0f, 0.748956f, 0.66262f};
-
-class OutdoorPvPEP;
-
-class OPvPCapturePointEP_EWT : public OPvPCapturePoint
-{
- public:
-
- OPvPCapturePointEP_EWT(OutdoorPvP* pvp);
-
- void ChangeState();
-
- void SendChangePhase();
-
- void FillInitialWorldStates(WorldPacket & data);
-
- // used when player is activated/inactivated in the area
- bool HandlePlayerEnter(Player* player);
- void HandlePlayerLeave(Player* player);
-
- protected:
-
- void SummonSupportUnitAtNorthpassTower(uint32 team);
-
- void UpdateTowerState();
-
- protected:
-
- uint32 m_TowerState;
-
- uint32 m_UnitsSummonedSide;
-};
-
-class OPvPCapturePointEP_NPT : public OPvPCapturePoint
-{
- public:
-
- OPvPCapturePointEP_NPT(OutdoorPvP* pvp);
-
- void ChangeState();
-
- void SendChangePhase();
-
- void FillInitialWorldStates(WorldPacket & data);
-
- // used when player is activated/inactivated in the area
- bool HandlePlayerEnter(Player* player);
- void HandlePlayerLeave(Player* player);
-
- protected:
-
- void SummonGO(uint32 team);
-
- void UpdateTowerState();
-
- protected:
-
- uint32 m_TowerState;
-
- uint32 m_SummonedGOSide;
-};
-
-class OPvPCapturePointEP_CGT : public OPvPCapturePoint
-{
- public:
-
- OPvPCapturePointEP_CGT(OutdoorPvP* pvp);
-
- void ChangeState();
-
- void SendChangePhase();
-
- void FillInitialWorldStates(WorldPacket & data);
-
- // used when player is activated/inactivated in the area
- bool HandlePlayerEnter(Player* player);
- void HandlePlayerLeave(Player* player);
-
- protected:
-
- void LinkGraveYard(uint32 team);
-
- void UpdateTowerState();
-
- protected:
-
- uint32 m_TowerState;
-
- uint32 m_GraveyardSide;
-};
-
-class OPvPCapturePointEP_PWT : public OPvPCapturePoint
-{
- public:
-
- OPvPCapturePointEP_PWT(OutdoorPvP* pvp);
-
- void ChangeState();
-
- void SendChangePhase();
-
- void FillInitialWorldStates(WorldPacket & data);
-
- // used when player is activated/inactivated in the area
- bool HandlePlayerEnter(Player* player);
- void HandlePlayerLeave(Player* player);
-
- protected:
-
- void SummonFlightMaster(uint32 team);
-
- void UpdateTowerState();
-
- protected:
-
- uint32 m_FlightMasterSpawned;
-
- uint32 m_TowerState;
-};
-
-class OutdoorPvPEP : public OutdoorPvP
-{
- public:
-
- OutdoorPvPEP();
-
- bool SetupOutdoorPvP();
-
- void HandlePlayerEnterZone(Player* player, uint32 zone);
- void HandlePlayerLeaveZone(Player* player, uint32 zone);
-
- bool Update(uint32 diff);
-
- void FillInitialWorldStates(WorldPacket &data);
-
- void SendRemoveWorldStates(Player* player);
-
- void BuffTeams();
-
- void SetControlledState(uint32 index, uint32 state);
-
- private:
-
- // how many towers are controlled
- uint32 EP_Controls[EP_TOWER_NUM];
-
- uint32 m_AllianceTowersControlled;
- uint32 m_HordeTowersControlled;
-};
-
-#endif
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index ea8fb5795bd..96495232aeb 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -48,12 +48,12 @@ enum DeathKnightSpells
SPELL_DK_UNHOLY_PRESENCE = 48265,
SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622,
SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962,
- SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736,
+ SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736
};
enum DeathKnightSpellIcons
{
- DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751,
+ DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751
};
// 50462 - Anti-Magic Shell (on raid member)
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index 160f14ff670..8fd44544fb8 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -29,6 +29,15 @@
enum DruidSpells
{
+ SPELL_DRUID_WRATH = 5176,
+ SPELL_DRUID_STARFIRE = 2912,
+ SPELL_DRUID_STARSURGE = 78674,
+ SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE = 89265,
+ SPELL_DRUID_STARSURGE_ENERGIZE = 86605,
+ SPELL_DRUID_LUNAR_ECLIPSE_MARKER = 67484, // Will make the yellow arrow on eclipse bar point to the blue side (lunar)
+ SPELL_DRUID_SOLAR_ECLIPSE_MARKER = 67483, // Will make the yellow arrow on eclipse bar point to the yellow side (solar)
+ SPELL_DRUID_SOLAR_ECLIPSE = 48517,
+ SPELL_DRUID_LUNAR_ECLIPSE = 48518,
SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185,
SPELL_DRUID_GLYPH_OF_TYPHOON = 62135,
SPELL_DRUID_IDOL_OF_FERAL_SHADOWS = 34241,
@@ -43,7 +52,117 @@ enum DruidSpells
SPELL_DRUID_SURVIVAL_INSTINCTS = 50322,
SPELL_DRUID_SAVAGE_ROAR = 62071,
SPELL_DRUID_TIGER_S_FURY_ENERGIZE = 51178,
- SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950,
+ SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950
+};
+
+// 2912, 5176, 78674 - Starfire, Wrath, and Starsurge
+class spell_dru_eclipse_energize : public SpellScriptLoader
+{
+ public:
+ spell_dru_eclipse_energize() : SpellScriptLoader("spell_dru_eclipse_energize") { }
+
+ class spell_dru_eclipse_energize_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dru_eclipse_energize_SpellScript);
+
+ int32 energizeAmount;
+
+ bool Load()
+ {
+ if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
+ return false;
+
+ if (GetCaster()->ToPlayer()->getClass() != CLASS_DRUID)
+ return false;
+
+ energizeAmount = 0;
+
+ return true;
+ }
+
+ void HandleEnergize(SpellEffIndex effIndex)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+
+ // No boomy, no deal.
+ if (caster->GetPrimaryTalentTree(caster->GetActiveSpec()) != TALENT_TREE_DRUID_BALANCE)
+ return;
+
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_DRUID_WRATH:
+ {
+ energizeAmount = -GetSpellInfo()->Effects[effIndex].BasePoints; // -13
+ // If we are set to fill the lunar side or we've just logged in with 0 power..
+ if ((!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER))
+ || caster->GetPower(POWER_ECLIPSE) == 0)
+ {
+ caster->CastCustomSpell(caster, SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE, &energizeAmount, 0, 0, true);
+ // If the energize was due to 0 power, cast the eclipse marker aura
+ if (!caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER))
+ caster->CastSpell(caster, SPELL_DRUID_LUNAR_ECLIPSE_MARKER, true);
+ }
+ // The energizing effect brought us out of the solar eclipse, remove the aura
+ if (caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE) && caster->GetPower(POWER_ECLIPSE) <= 0)
+ caster->RemoveAurasDueToSpell(SPELL_DRUID_SOLAR_ECLIPSE);
+ break;
+ }
+ case SPELL_DRUID_STARFIRE:
+ {
+ energizeAmount = GetSpellInfo()->Effects[effIndex].BasePoints; // 20
+ // If we are set to fill the solar side or we've just logged in with 0 power..
+ if ((!caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER))
+ || caster->GetPower(POWER_ECLIPSE) == 0)
+ {
+ caster->CastCustomSpell(caster, SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE, &energizeAmount, 0, 0, true);
+ // If the energize was due to 0 power, cast the eclipse marker aura
+ if (!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER))
+ caster->CastSpell(caster, SPELL_DRUID_SOLAR_ECLIPSE_MARKER, true);
+ }
+ // The energizing effect brought us out of the lunar eclipse, remove the aura
+ if (caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE) && caster->GetPower(POWER_ECLIPSE) >= 0)
+ caster->RemoveAura(SPELL_DRUID_LUNAR_ECLIPSE);
+ break;
+ }
+ case SPELL_DRUID_STARSURGE:
+ {
+ // If we are set to fill the solar side or we've just logged in with 0 power (confirmed with sniffs)
+ if ((!caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER))
+ || caster->GetPower(POWER_ECLIPSE) == 0)
+ {
+ energizeAmount = GetSpellInfo()->Effects[effIndex].BasePoints; // 15
+ caster->CastCustomSpell(caster, SPELL_DRUID_STARSURGE_ENERGIZE, &energizeAmount, 0, 0, true);
+
+ // If the energize was due to 0 power, cast the eclipse marker aura
+ if (!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER))
+ caster->CastSpell(caster, SPELL_DRUID_SOLAR_ECLIPSE_MARKER, true);
+ }
+ else if (!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER))
+ {
+ energizeAmount = -GetSpellInfo()->Effects[effIndex].BasePoints; // -15
+ caster->CastCustomSpell(caster, SPELL_DRUID_STARSURGE_ENERGIZE, &energizeAmount, 0, 0, true);
+ }
+ // The energizing effect brought us out of the lunar eclipse, remove the aura
+ if (caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE) && caster->GetPower(POWER_ECLIPSE) >= 0)
+ caster->RemoveAura(SPELL_DRUID_LUNAR_ECLIPSE);
+ // The energizing effect brought us out of the solar eclipse, remove the aura
+ else if (caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE) && caster->GetPower(POWER_ECLIPSE) <= 0)
+ caster->RemoveAura(SPELL_DRUID_SOLAR_ECLIPSE);
+ break;
+ }
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_dru_eclipse_energize_SpellScript::HandleEnergize, EFFECT_1, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_dru_eclipse_energize_SpellScript;
+ }
};
// -1850 - Dash
@@ -664,7 +783,7 @@ class spell_dru_savage_roar : public SpellScriptLoader
{
PrepareAuraScript(spell_dru_savage_roar_AuraScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_SAVAGE_ROAR))
return false;
@@ -857,7 +976,7 @@ class spell_dru_swift_flight_passive : public SpellScriptLoader
void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
{
if (Player* caster = GetCaster()->ToPlayer())
- if (caster->Has310Flyer(false))
+ if (caster->GetSkillValue(SKILL_RIDING) >= 375)
amount = 310;
}
@@ -988,6 +1107,7 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader
void AddSC_druid_spell_scripts()
{
new spell_dru_dash();
+ new spell_dru_eclipse_energize();
new spell_dru_enrage();
new spell_dru_glyph_of_starfire();
new spell_dru_idol_lifebloom();
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index c591f3141ed..cb010f44f9a 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1652,61 +1652,6 @@ class spell_gen_oracle_wolvar_reputation : public SpellScriptLoader
}
};
-enum DamageReductionAura
-{
- SPELL_BLESSING_OF_SANCTUARY = 20911,
- SPELL_GREATER_BLESSING_OF_SANCTUARY = 25899,
- SPELL_RENEWED_HOPE = 63944,
- SPELL_VIGILANCE = 50720,
- SPELL_DAMAGE_REDUCTION_AURA = 68066,
-};
-
-class spell_gen_damage_reduction_aura : public SpellScriptLoader
-{
- public:
- spell_gen_damage_reduction_aura() : SpellScriptLoader("spell_gen_damage_reduction_aura") { }
-
- class spell_gen_damage_reduction_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_damage_reduction_AuraScript);
-
- bool Validate(SpellInfo const* /*SpellEntry*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_DAMAGE_REDUCTION_AURA))
- return false;
- return true;
- }
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- target->CastSpell(target, SPELL_DAMAGE_REDUCTION_AURA, true);
- }
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- if (target->HasAura(SPELL_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_BLESSING_OF_SANCTUARY) ||
- target->HasAura(SPELL_GREATER_BLESSING_OF_SANCTUARY) ||
- target->HasAura(SPELL_RENEWED_HOPE) ||
- target->HasAura(SPELL_VIGILANCE)))
- target->RemoveAurasDueToSpell(SPELL_DAMAGE_REDUCTION_AURA);
- }
-
- void Register()
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_damage_reduction_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_damage_reduction_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
- }
-
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_gen_damage_reduction_AuraScript();
- }
-};
-
enum DummyTrigger
{
SPELL_PERSISTANT_SHIELD_TRIGGERED = 26470,
@@ -3210,12 +3155,13 @@ class spell_gen_mount : public SpellScriptLoader
break;
case 300:
if (canFly)
- {
- if (_mount310 && target->Has310Flyer(false))
- mount = _mount310;
- else
- mount = _mount280;
- }
+ mount = _mount280;
+ else
+ mount = _mount100;
+ break;
+ case 375:
+ if (canFly)
+ mount = _mount310;
else
mount = _mount100;
break;
@@ -3401,6 +3347,35 @@ class spell_gen_gift_of_naaru : public SpellScriptLoader
}
};
+class spell_gen_increase_stats_buff : public SpellScriptLoader
+{
+ public:
+ spell_gen_increase_stats_buff(char const* scriptName) : SpellScriptLoader(scriptName) { }
+
+ class spell_gen_increase_stats_buff_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_increase_stats_buff_SpellScript);
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (GetHitUnit()->IsInRaidWith(GetCaster()))
+ GetCaster()->CastSpell(GetCaster(), GetEffectValue() + 1, true); // raid buff
+ else
+ GetCaster()->CastSpell(GetHitUnit(), GetEffectValue(), true); // single-target buff
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_increase_stats_buff_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gen_increase_stats_buff_SpellScript();
+ }
+};
+
enum Replenishment
{
SPELL_REPLENISHMENT = 57669,
@@ -3456,60 +3431,157 @@ class spell_gen_replenishment : public SpellScriptLoader
}
};
-enum ServiceUniform
+enum RunningWildMountIds
{
- SPELL_SERVICE_UNIFORM = 71450,
-
- MODEL_GOBLIN_MALE = 31002,
- MODEL_GOBLIN_FEMALE = 31003,
+ RUNNING_WILD_MODEL_MALE = 29422,
+ RUNNING_WILD_MODEL_FEMALE = 29423,
+ SPELL_ALTERED_FORM = 97709,
};
-class spell_gen_aura_service_uniform : public SpellScriptLoader
+class spell_gen_running_wild : public SpellScriptLoader
{
public:
- spell_gen_aura_service_uniform() : SpellScriptLoader("spell_gen_aura_service_uniform") { }
+ spell_gen_running_wild() : SpellScriptLoader("spell_gen_running_wild") { }
- class spell_gen_aura_service_uniform_AuraScript : public AuraScript
+ class spell_gen_running_wild_AuraScript : public AuraScript
{
- PrepareAuraScript(spell_gen_aura_service_uniform_AuraScript);
+ PrepareAuraScript(spell_gen_running_wild_AuraScript);
bool Validate(SpellInfo const* /*spell*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_SERVICE_UNIFORM))
+ if (!sCreatureDisplayInfoStore.LookupEntry(RUNNING_WILD_MODEL_MALE))
+ return false;
+ if (!sCreatureDisplayInfoStore.LookupEntry(RUNNING_WILD_MODEL_FEMALE))
return false;
return true;
}
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void HandleMount(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
- // Apply model goblin
Unit* target = GetTarget();
- if (target->GetTypeId() == TYPEID_PLAYER)
+ PreventDefaultAction();
+
+ target->Mount(target->getGender() == GENDER_FEMALE ? RUNNING_WILD_MODEL_FEMALE : RUNNING_WILD_MODEL_MALE, 0, 0);
+
+ // cast speed aura
+ if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(aurEff->GetAmount()))
+ target->CastSpell(target, mountCapability->SpeedModSpell, TRIGGERED_FULL_MASK);
+ }
+
+ void Register()
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_gen_running_wild_AuraScript::HandleMount, EFFECT_1, SPELL_AURA_MOUNTED, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ class spell_gen_running_wild_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_running_wild_SpellScript);
+
+ bool Validate(SpellInfo const* /*spell*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_ALTERED_FORM))
+ return false;
+ return true;
+ }
+
+ bool Load()
+ {
+ // Definitely not a good thing, but currently the only way to do something at cast start
+ // Should be replaced as soon as possible with a new hook: BeforeCastStart
+ GetCaster()->CastSpell(GetCaster(), SPELL_ALTERED_FORM, TRIGGERED_FULL_MASK);
+ return false;
+ }
+
+ void Register()
+ {
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_gen_running_wild_AuraScript();
+ }
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gen_running_wild_SpellScript();
+ }
+};
+
+class spell_gen_two_forms : public SpellScriptLoader
+{
+ public:
+ spell_gen_two_forms() : SpellScriptLoader("spell_gen_two_forms") { }
+
+ class spell_gen_two_forms_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_two_forms_SpellScript);
+
+ SpellCastResult CheckCast()
+ {
+ if (GetCaster()->isInCombat())
{
- if (target->getGender() == GENDER_MALE)
- target->SetDisplayId(MODEL_GOBLIN_MALE);
- else
- target->SetDisplayId(MODEL_GOBLIN_FEMALE);
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_CANT_TRANSFORM);
+ return SPELL_FAILED_CUSTOM_ERROR;
}
+
+ // Player cannot transform to human form if he is forced to be worgen for some reason (Darkflight)
+ if (GetCaster()->GetAuraEffectsByType(SPELL_AURA_WORGEN_ALTERED_FORM).size() > 1)
+ {
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_CANT_TRANSFORM);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
+
+ return SPELL_CAST_OK;
}
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void HandleTransform(SpellEffIndex effIndex)
{
- Unit* target = GetTarget();
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->RestoreDisplayId();
+ Unit* target = GetHitUnit();
+ PreventHitDefaultEffect(effIndex);
+ if (target->HasAuraType(SPELL_AURA_WORGEN_ALTERED_FORM))
+ target->RemoveAurasByType(SPELL_AURA_WORGEN_ALTERED_FORM);
+ else // Basepoints 1 for this aura control whether to trigger transform transition animation or not.
+ target->CastCustomSpell(SPELL_ALTERED_FORM, SPELLVALUE_BASE_POINT0, 1, target, TRIGGERED_FULL_MASK);
}
void Register()
{
- AfterEffectApply += AuraEffectRemoveFn(spell_gen_aura_service_uniform_AuraScript::OnApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_gen_aura_service_uniform_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
+ OnCheckCast += SpellCheckCastFn(spell_gen_two_forms_SpellScript::CheckCast);
+ OnEffectHitTarget += SpellEffectFn(spell_gen_two_forms_SpellScript::HandleTransform, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
- AuraScript* GetAuraScript() const
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gen_two_forms_SpellScript();
+ }
+};
+
+class spell_gen_darkflight : public SpellScriptLoader
+{
+ public:
+ spell_gen_darkflight() : SpellScriptLoader("spell_gen_darkflight") { }
+
+ class spell_gen_darkflight_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_darkflight_SpellScript);
+
+ void TriggerTransform()
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_ALTERED_FORM, TRIGGERED_FULL_MASK);
+ }
+
+ void Register()
+ {
+ AfterCast += SpellCastFn(spell_gen_darkflight_SpellScript::TriggerTransform);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
{
- return new spell_gen_aura_service_uniform_AuraScript();
+ return new spell_gen_darkflight_SpellScript();
}
};
@@ -3635,7 +3707,6 @@ void AddSC_generic_spell_scripts()
new spell_gen_launch();
new spell_gen_vehicle_scaling();
new spell_gen_oracle_wolvar_reputation();
- new spell_gen_damage_reduction_aura();
new spell_gen_dummy_trigger();
new spell_gen_spirit_healer_res();
new spell_gen_gadgetzan_transporter_backfire();
@@ -3678,8 +3749,17 @@ void AddSC_generic_spell_scripts()
new spell_gen_upper_deck_create_foam_sword();
new spell_gen_bonked();
new spell_gen_gift_of_naaru();
+ new spell_gen_increase_stats_buff("spell_pal_blessing_of_kings");
+ new spell_gen_increase_stats_buff("spell_pal_blessing_of_might");
+ new spell_gen_increase_stats_buff("spell_dru_mark_of_the_wild");
+ new spell_gen_increase_stats_buff("spell_pri_power_word_fortitude");
+ new spell_gen_increase_stats_buff("spell_pri_shadow_protection");
+ new spell_gen_increase_stats_buff("spell_mage_arcane_brilliance");
+ new spell_gen_increase_stats_buff("spell_mage_dalaran_brilliance");
new spell_gen_replenishment();
- new spell_gen_aura_service_uniform();
+ new spell_gen_running_wild();
+ new spell_gen_two_forms();
+ new spell_gen_darkflight();
new spell_gen_orc_disguise();
new spell_gen_whisper_gulch_yogg_saron_whisper();
}
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 0c9817ba167..a8407525a1b 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -2293,8 +2293,7 @@ class spell_item_unusual_compass : public SpellScriptLoader
void HandleDummy(SpellEffIndex /* effIndex */)
{
Unit* caster = GetCaster();
- caster->SetOrientation(frand(0.0f, 62832.0f) / 10000.0f);
- caster->SendMovementFlagUpdate(true);
+ caster->SetFacingTo(frand(0.0f, 62832.0f) / 10000.0f);
}
void Register()
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index e27248da6fc..c1edf4b05d4 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -25,6 +25,7 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
+#include "Pet.h"
enum MageSpells
{
@@ -47,6 +48,38 @@ enum MageSpells
SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT = 70908,
SPELL_MAGE_SUMMON_WATER_ELEMENTAL_TEMPORARY = 70907,
SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126,
+
+ SPELL_MAGE_FLAMESTRIKE = 2120,
+
+ SPELL_MAGE_CHILLED_R1 = 12484,
+ SPELL_MAGE_CHILLED_R2 = 12485,
+
+ SPELL_MAGE_CONE_OF_COLD_AURA_R1 = 11190,
+ SPELL_MAGE_CONE_OF_COLD_AURA_R2 = 12489,
+ SPELL_MAGE_CONE_OF_COLD_TRIGGER_R1 = 83301,
+ SPELL_MAGE_CONE_OF_COLD_TRIGGER_R2 = 83302,
+
+ SPELL_MAGE_SHATTERED_BARRIER_R1 = 44745,
+ SPELL_MAGE_SHATTERED_BARRIER_R2 = 54787,
+ SPELL_MAGE_SHATTERED_BARRIER_FREEZE_R1 = 55080,
+ SPELL_MAGE_SHATTERED_BARRIER_FREEZE_R2 = 83073,
+
+ SPELL_MAGE_IMPROVED_MANA_GEM_TRIGGERED = 83098,
+
+ SPELL_MAGE_RING_OF_FROST_SUMMON = 82676,
+ SPELL_MAGE_RING_OF_FROST_FREEZE = 82691,
+ SPELL_MAGE_RING_OF_FROST_DUMMY = 91264,
+
+ SPELL_MAGE_FINGERS_OF_FROST = 44544
+};
+
+enum MageIcons
+{
+ ICON_MAGE_SHATTER = 976,
+ ICON_MAGE_IMPROVED_FLAMESTRIKE = 37,
+ ICON_MAGE_IMPROVED_FREEZE = 94,
+ ICON_MAGE_INCANTER_S_ABSORPTION = 2941,
+ ICON_MAGE_IMPROVED_MANA_GEM = 1036
};
// Incanter's Absorbtion
@@ -74,7 +107,7 @@ class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript
}
};
-// -11113 - Blast Wave
+// 11113 - Blast Wave
class spell_mage_blast_wave : public SpellScriptLoader
{
public:
@@ -86,21 +119,40 @@ class spell_mage_blast_wave : public SpellScriptLoader
bool Validate(SpellInfo const* /*spellInfo*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FLAMESTRIKE))
return false;
return true;
}
- void HandleKnockBack(SpellEffIndex effIndex)
+ void CountTargets(std::list<WorldObject*>& targetList)
+ {
+ _targetCount = targetList.size();
+ }
+
+ void HandleImprovedFlamestrike()
{
- if (GetCaster()->HasAura(SPELL_MAGE_GLYPH_OF_BLAST_WAVE))
- PreventHitDefaultEffect(effIndex);
+ if (_targetCount >= 2)
+ if (AuraEffect* aurEff = GetCaster()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, ICON_MAGE_IMPROVED_FLAMESTRIKE, EFFECT_0))
+ if (roll_chance_i(aurEff->GetAmount()))
+ {
+ float x, y, z;
+ WorldLocation const* loc = GetExplTargetDest();
+ if (!loc)
+ return;
+
+ loc->GetPosition(x, y, z);
+ GetCaster()->CastSpell(x, y, z, SPELL_MAGE_FLAMESTRIKE, true);
+ }
}
void Register()
{
- OnEffectHitTarget += SpellEffectFn(spell_mage_blast_wave_SpellScript::HandleKnockBack, EFFECT_2, SPELL_EFFECT_KNOCK_BACK);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mage_blast_wave_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ AfterCast += SpellCastFn(spell_mage_blast_wave_SpellScript::HandleImprovedFlamestrike);
}
+
+ private:
+ uint32 _targetCount;
};
SpellScript* GetSpellScript() const
@@ -154,6 +206,50 @@ class spell_mage_burnout : public SpellScriptLoader
}
};
+// 42208 - Blizzard
+/// Updated 4.3.4
+class spell_mage_blizzard : public SpellScriptLoader
+{
+ public:
+ spell_mage_blizzard() : SpellScriptLoader("spell_mage_blizzard") { }
+
+ class spell_mage_blizzard_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_blizzard_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_CHILLED_R1))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_CHILLED_R2))
+ return false;
+ return true;
+ }
+
+ void AddChillEffect(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* unitTarget = GetHitUnit())
+ {
+ if (caster->IsScriptOverriden(GetSpellInfo(), 836))
+ caster->CastSpell(unitTarget, SPELL_MAGE_CHILLED_R1, true);
+ else if (caster->IsScriptOverriden(GetSpellInfo(), 988))
+ caster->CastSpell(unitTarget, SPELL_MAGE_CHILLED_R2, true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mage_blizzard_SpellScript::AddChillEffect, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_blizzard_SpellScript();
+ }
+};
+
// 11958 - Cold Snap
class spell_mage_cold_snap : public SpellScriptLoader
{
@@ -201,6 +297,112 @@ class spell_mage_cold_snap : public SpellScriptLoader
}
};
+// 120 - Cone of Cold
+/// Updated 4.3.4
+class spell_mage_cone_of_cold : public SpellScriptLoader
+{
+ public:
+ spell_mage_cone_of_cold() : SpellScriptLoader("spell_mage_cone_of_cold") { }
+
+ class spell_mage_cone_of_cold_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_cone_of_cold_SpellScript);
+
+ void HandleConeOfColdScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Unit* unitTarget = GetHitUnit())
+ {
+ if (caster->HasAura(SPELL_MAGE_CONE_OF_COLD_AURA_R1)) // Improved Cone of Cold Rank 1
+ unitTarget->CastSpell(unitTarget, SPELL_MAGE_CONE_OF_COLD_TRIGGER_R1, true);
+ else if (caster->HasAura(SPELL_MAGE_CONE_OF_COLD_AURA_R2)) // Improved Cone of Cold Rank 2
+ unitTarget->CastSpell(unitTarget, SPELL_MAGE_CONE_OF_COLD_TRIGGER_R2, true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mage_cone_of_cold_SpellScript::HandleConeOfColdScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_cone_of_cold_SpellScript();
+ }
+};
+
+// 42955 Conjure Refreshment
+/// Updated 4.3.4
+struct ConjureRefreshmentData
+{
+ uint32 minLevel;
+ uint32 maxLevel;
+ uint32 spellId;
+};
+
+uint8 const MAX_CONJURE_REFRESHMENT_SPELLS = 7;
+ConjureRefreshmentData const _conjureData[MAX_CONJURE_REFRESHMENT_SPELLS] =
+{
+ { 33, 43, 92739 },
+ { 44, 53, 92799 },
+ { 54, 63, 92802 },
+ { 64, 73, 92805 },
+ { 74, 79, 74625 },
+ { 80, 84, 92822 },
+ { 85, 85, 92727 }
+};
+
+// 42955 - Conjure Refreshment
+class spell_mage_conjure_refreshment : public SpellScriptLoader
+{
+ public:
+ spell_mage_conjure_refreshment() : SpellScriptLoader("spell_mage_conjure_refreshment") { }
+
+ class spell_mage_conjure_refreshment_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_conjure_refreshment_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ for (uint8 i = 0; i < MAX_CONJURE_REFRESHMENT_SPELLS; ++i)
+ if (!sSpellMgr->GetSpellInfo(_conjureData[i].spellId))
+ return false;
+ return true;
+ }
+
+ bool Load()
+ {
+ if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ return true;
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ uint8 level = GetHitUnit()->getLevel();
+ for (uint8 i = 0; i < MAX_CONJURE_REFRESHMENT_SPELLS; ++i)
+ {
+ ConjureRefreshmentData const& spellData = _conjureData[i];
+ if (level < spellData.minLevel || level > spellData.maxLevel)
+ continue;
+ GetHitUnit()->CastSpell(GetHitUnit(), spellData.spellId);
+ break;
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mage_conjure_refreshment_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_conjure_refreshment_SpellScript();
+ }
+};
+
// -543 - Fire Ward
// -6143 - Frost Ward
class spell_mage_fire_frost_ward : public SpellScriptLoader
@@ -319,49 +521,115 @@ class spell_mage_focus_magic : public SpellScriptLoader
}
};
-// -11426 - Ice Barrier
-class spell_mage_ice_barrier : public SpellScriptLoader
+// 116 - Frostbolt
+/// Updated 4.3.4
+class spell_mage_frostbolt : public SpellScriptLoader
+{
+ public:
+ spell_mage_frostbolt() : SpellScriptLoader("spell_mage_frostbolt") { }
+
+ class spell_mage_frostbolt_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_frostbolt_SpellScript);
+
+ void RecalculateDamage(SpellEffIndex /*effIndex*/)
+ {
+ if (GetHitUnit() && GetHitUnit()->HasAuraState(AURA_STATE_FROZEN, GetSpellInfo(), GetCaster()))
+ {
+ if (AuraEffect* aurEff = GetCaster()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, ICON_MAGE_SHATTER, EFFECT_1))
+ {
+ int32 damage = GetHitDamage();
+ AddPct(damage, aurEff->GetAmount());
+ SetHitDamage(damage);
+ }
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mage_frostbolt_SpellScript::RecalculateDamage, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_frostbolt_SpellScript();
+ }
+};
+
+// -44457 - Living Bomb
+class spell_mage_living_bomb : public SpellScriptLoader
{
public:
- spell_mage_ice_barrier() : SpellScriptLoader("spell_mage_ice_barrier") { }
+ spell_mage_living_bomb() : SpellScriptLoader("spell_mage_living_bomb") { }
- class spell_mage_ice_barrier_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript
+ class spell_mage_living_bomb_AuraScript : public AuraScript
{
- PrepareAuraScript(spell_mage_ice_barrier_AuraScript);
+ PrepareAuraScript(spell_mage_living_bomb_AuraScript);
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)
+ bool Validate(SpellInfo const* spellInfo)
{
- canBeRecalculated = false;
- if (Unit* caster = GetCaster())
- {
- // +80.68% from sp bonus
- float bonus = 0.8068f;
-
- bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask());
-
- // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :)
- // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage
- bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus);
+ if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->Effects[EFFECT_1].CalcValue())))
+ return false;
+ return true;
+ }
- bonus *= caster->CalculateLevelPenalty(GetSpellInfo());
+ void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
+ if (removeMode != AURA_REMOVE_BY_ENEMY_SPELL && removeMode != AURA_REMOVE_BY_EXPIRE)
+ return;
- amount += int32(bonus);
- }
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), uint32(aurEff->GetAmount()), true, NULL, aurEff);
}
void Register()
{
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_ice_barrier_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
- AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_ice_barrier_AuraScript::Trigger, EFFECT_0);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_mage_living_bomb_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
- return new spell_mage_ice_barrier_AuraScript();
+ return new spell_mage_living_bomb_AuraScript();
}
};
+// 11426 - Ice Barrier
+/// Updated 4.3.4
+class spell_mage_ice_barrier : public SpellScriptLoader
+{
+ public:
+ spell_mage_ice_barrier() : SpellScriptLoader("spell_mage_ice_barrier") { }
+
+ class spell_mage_ice_barrier_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_ice_barrier_AuraScript);
+
+ void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
+ return;
+
+ if (GetTarget()->HasAura(SPELL_MAGE_SHATTERED_BARRIER_R1))
+ GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_SHATTERED_BARRIER_FREEZE_R1, true);
+ else if (GetTarget()->HasAura(SPELL_MAGE_SHATTERED_BARRIER_R2))
+ GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_SHATTERED_BARRIER_FREEZE_R2, true);
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_mage_ice_barrier_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_ice_barrier_AuraScript();
+ }
+};
+
// -11119 - Ignite
class spell_mage_ignite : public SpellScriptLoader
{
@@ -409,81 +677,75 @@ class spell_mage_ignite : public SpellScriptLoader
}
};
-// -44457 - Living Bomb
-class spell_mage_living_bomb : public SpellScriptLoader
+// 543 - Mage Ward
+/// Updated 4.3.4
+class spell_mage_mage_ward : public SpellScriptLoader
{
- public:
- spell_mage_living_bomb() : SpellScriptLoader("spell_mage_living_bomb") { }
-
- class spell_mage_living_bomb_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_mage_living_bomb_AuraScript);
-
- bool Validate(SpellInfo const* spell)
- {
- if (!sSpellMgr->GetSpellInfo(uint32(spell->Effects[EFFECT_1].CalcValue())))
- return false;
- return true;
- }
-
- void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
- {
- AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode();
- if (removeMode != AURA_REMOVE_BY_ENEMY_SPELL && removeMode != AURA_REMOVE_BY_EXPIRE)
- return;
-
- if (Unit* caster = GetCaster())
- caster->CastSpell(GetTarget(), uint32(aurEff->GetAmount()), true, NULL, aurEff);
- }
-
- void Register()
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_mage_living_bomb_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_mage_living_bomb_AuraScript();
- }
+ public:
+ spell_mage_mage_ward() : SpellScriptLoader("spell_mage_mage_ward") { }
+
+ class spell_mage_mage_ward_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_mage_ward_AuraScript);
+
+ void HandleAbsorb(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount)
+ {
+ if (AuraEffect* aurEff = GetTarget()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_GENERIC, ICON_MAGE_INCANTER_S_ABSORPTION, EFFECT_0))
+ {
+ int32 bp = CalculatePct(absorbAmount, aurEff->GetAmount());
+ GetTarget()->CastCustomSpell(GetTarget(), SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true);
+ }
+ }
+
+ void Register()
+ {
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_mage_ward_AuraScript::HandleAbsorb, EFFECT_0);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_mage_ward_AuraScript();
+ }
};
-// -1463 - Mana Shield
+// 1463 - Mana Shield
+/// Updated 4.3.4
class spell_mage_mana_shield : public SpellScriptLoader
{
public:
- spell_mage_mana_shield() : SpellScriptLoader("spell_mage_mana_shield") { }
-
- class spell_mage_mana_shield_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript
- {
- PrepareAuraScript(spell_mage_mana_shield_AuraScript);
-
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
- {
- canBeRecalculated = false;
- if (Unit* caster = GetCaster())
- {
- // +80.53% from sp bonus
- float bonus = 0.8053f;
-
- bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask());
- bonus *= caster->CalculateLevelPenalty(GetSpellInfo());
-
- amount += int32(bonus);
- }
- }
-
- void Register()
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_mana_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MANA_SHIELD);
- AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_mana_shield_AuraScript::Trigger, EFFECT_0);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_mage_mana_shield_AuraScript();
- }
+ spell_mage_mana_shield() : SpellScriptLoader("spell_mage_mana_shield") { }
+
+ class spell_mage_mana_shield_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_mana_shield_AuraScript);
+
+ void HandleAbsorb(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount)
+ {
+ if (AuraEffect* aurEff = GetTarget()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_GENERIC, ICON_MAGE_INCANTER_S_ABSORPTION, EFFECT_0))
+ {
+ int32 bp = CalculatePct(absorbAmount, aurEff->GetAmount());
+ GetTarget()->CastCustomSpell(GetTarget(), SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true);
+ }
+ }
+
+ void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
+ GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_INCANTERS_ABSORBTION_R1, true);
+ }
+
+ void Register()
+ {
+ AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_mana_shield_AuraScript::HandleAbsorb, EFFECT_0);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_mage_mana_shield_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_MANA_SHIELD, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_mana_shield_AuraScript();
+ }
};
// -29074 - Master of Elements
@@ -534,7 +796,7 @@ class spell_mage_master_of_elements : public SpellScriptLoader
enum SilvermoonPolymorph
{
- NPC_AUROSALIA = 18744,
+ NPC_AUROSALIA = 18744
};
/// @todo move out of here and rename - not a mage spell
@@ -553,7 +815,7 @@ class spell_mage_polymorph_cast_visual : public SpellScriptLoader
bool Validate(SpellInfo const* /*spellInfo*/)
{
// check if spell ids exist in dbc
- for (uint32 i = 0; i < 6; ++i)
+ for (uint32 i = 0; i < 6; i++)
if (!sSpellMgr->GetSpellInfo(PolymorhForms[i]))
return false;
return true;
@@ -568,6 +830,7 @@ class spell_mage_polymorph_cast_visual : public SpellScriptLoader
void Register()
{
+ // add dummy effect spell handler to Polymorph visual
OnEffectHitTarget += SpellEffectFn(spell_mage_polymorph_cast_visual_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -578,7 +841,7 @@ class spell_mage_polymorph_cast_visual : public SpellScriptLoader
}
};
-const uint32 spell_mage_polymorph_cast_visual::spell_mage_polymorph_cast_visual_SpellScript::PolymorhForms[6] =
+uint32 const spell_mage_polymorph_cast_visual::spell_mage_polymorph_cast_visual_SpellScript::PolymorhForms[6] =
{
SPELL_MAGE_SQUIRREL_FORM,
SPELL_MAGE_GIRAFFE_FORM,
@@ -588,6 +851,192 @@ const uint32 spell_mage_polymorph_cast_visual::spell_mage_polymorph_cast_visual_
SPELL_MAGE_SHEEP_FORM
};
+// 5405 - Replenish Mana (Mana Gem)
+/// Updated 4.3.4
+class spell_mage_replenish_mana : public SpellScriptLoader
+{
+ public:
+ spell_mage_replenish_mana() : SpellScriptLoader("spell_mage_replenish_mana") { }
+
+ class spell_mage_replenish_mana_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_replenish_mana_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_IMPROVED_MANA_GEM_TRIGGERED))
+ return false;
+ return true;
+ }
+
+ void HandleImprovedManaGem()
+ {
+ if (AuraEffect* aurEff = GetCaster()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, ICON_MAGE_IMPROVED_MANA_GEM, EFFECT_0))
+ {
+ int32 bp = CalculatePct(GetCaster()->GetMaxPower(POWER_MANA), aurEff->GetAmount());
+ GetCaster()->CastCustomSpell(GetCaster(), SPELL_MAGE_IMPROVED_MANA_GEM_TRIGGERED, &bp, &bp, NULL, true);
+ }
+ }
+
+ void Register()
+ {
+ AfterCast += SpellCastFn(spell_mage_replenish_mana_SpellScript::HandleImprovedManaGem);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_replenish_mana_SpellScript();
+ }
+};
+
+// 82676 - Ring of Frost
+/// Updated 4.3.4
+class spell_mage_ring_of_frost : public SpellScriptLoader
+{
+ public:
+ spell_mage_ring_of_frost() : SpellScriptLoader("spell_mage_ring_of_frost") { }
+
+ class spell_mage_ring_of_frost_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_ring_of_frost_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_FREEZE))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_DUMMY))
+ return false;
+ return true;
+ }
+
+ bool Load()
+ {
+ ringOfFrost = NULL;
+ return true;
+ }
+
+ void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (ringOfFrost)
+ if (GetMaxDuration() - (int32)ringOfFrost->GetTimer() >= sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_DUMMY)->GetDuration())
+ GetTarget()->CastSpell(ringOfFrost->GetPositionX(), ringOfFrost->GetPositionY(), ringOfFrost->GetPositionZ(), SPELL_MAGE_RING_OF_FROST_FREEZE, true);
+ }
+
+ void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ std::list<Creature*> MinionList;
+ GetTarget()->GetAllMinionsByEntry(MinionList, GetSpellInfo()->Effects[EFFECT_0].MiscValue);
+
+ // Get the last summoned RoF, save it and despawn older ones
+ for (std::list<Creature*>::iterator itr = MinionList.begin(); itr != MinionList.end(); itr++)
+ {
+ TempSummon* summon = (*itr)->ToTempSummon();
+
+ if (ringOfFrost && summon)
+ {
+ if (summon->GetTimer() > ringOfFrost->GetTimer())
+ {
+ ringOfFrost->DespawnOrUnsummon();
+ ringOfFrost = summon;
+ }
+ else
+ summon->DespawnOrUnsummon();
+ }
+ else if (summon)
+ ringOfFrost = summon;
+ }
+ }
+
+ TempSummon* ringOfFrost;
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_mage_ring_of_frost_AuraScript::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ OnEffectApply += AuraEffectApplyFn(spell_mage_ring_of_frost_AuraScript::Apply, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_ring_of_frost_AuraScript();
+ }
+};
+
+// 82691 - Ring of Frost (freeze efect)
+/// Updated 4.3.4
+class spell_mage_ring_of_frost_freeze : public SpellScriptLoader
+{
+ public:
+ spell_mage_ring_of_frost_freeze() : SpellScriptLoader("spell_mage_ring_of_frost_freeze") { }
+
+ class spell_mage_ring_of_frost_freeze_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_ring_of_frost_freeze_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_FREEZE))
+ return false;
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ float outRadius = sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON)->Effects[EFFECT_0].CalcRadius();
+ float inRadius = 4.7f;
+
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ if (Unit* unit = (*itr)->ToUnit())
+ if (unit->HasAura(SPELL_MAGE_RING_OF_FROST_DUMMY) || unit->HasAura(SPELL_MAGE_RING_OF_FROST_FREEZE) || unit->GetExactDist(GetExplTargetDest()) > outRadius || unit->GetExactDist(GetExplTargetDest()) < inRadius)
+ targets.erase(itr--);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mage_ring_of_frost_freeze_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_ring_of_frost_freeze_SpellScript();
+ }
+
+ class spell_mage_ring_of_frost_freeze_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_ring_of_frost_freeze_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_DUMMY))
+ return false;
+ return true;
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
+ if (GetCaster())
+ GetCaster()->CastSpell(GetTarget(), SPELL_MAGE_RING_OF_FROST_DUMMY, true);
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_mage_ring_of_frost_freeze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_ring_of_frost_freeze_AuraScript();
+ }
+};
+
// 31687 - Summon Water Elemental
class spell_mage_summon_water_elemental : public SpellScriptLoader
{
@@ -608,6 +1057,14 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
+
+ if (Player* player = caster->ToPlayer())
+ if (Guardian* elemental = player->GetGuardianPet())
+ // Check if the pet we are going to unsummon is the mage's water elemental
+ if (elemental->GetEntry() == uint32(sSpellMgr->GetSpellInfo(SPELL_MAGE_SUMMON_WATER_ELEMENTAL_TEMPORARY)->Effects[EFFECT_0].MiscValue) ||
+ elemental->GetEntry() == uint32(sSpellMgr->GetSpellInfo(SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT)->Effects[EFFECT_0].MiscValue))
+ elemental->UnSummon();
+
// Glyph of Eternal Water
if (caster->HasAura(SPELL_MAGE_GLYPH_OF_ETERNAL_WATER))
caster->CastSpell(caster, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT, true);
@@ -617,6 +1074,7 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader
void Register()
{
+ // add dummy effect spell handler to Summon Water Elemental
OnEffectHit += SpellEffectFn(spell_mage_summon_water_elemental_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -627,18 +1085,82 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader
}
};
+// 33395 Water Elemental's Freeze
+/// Updated 4.3.4
+class spell_mage_water_elemental_freeze : public SpellScriptLoader
+{
+ public:
+ spell_mage_water_elemental_freeze() : SpellScriptLoader("spell_mage_water_elemental_freeze") { }
+
+ class spell_mage_water_elemental_freeze_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mage_water_elemental_freeze_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FINGERS_OF_FROST))
+ return false;
+ return true;
+ }
+
+ void CountTargets(std::list<WorldObject*>& targetList)
+ {
+ _didHit = !targetList.empty();
+ }
+
+ void HandleImprovedFreeze()
+ {
+ if (!_didHit)
+ return;
+
+ Unit* owner = GetCaster()->GetOwner();
+ if (!owner)
+ return;
+
+ if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, ICON_MAGE_IMPROVED_FREEZE, EFFECT_0))
+ {
+ if (roll_chance_i(aurEff->GetAmount()))
+ owner->CastCustomSpell(SPELL_MAGE_FINGERS_OF_FROST, SPELLVALUE_AURA_STACK, 2, owner, true);
+ }
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mage_water_elemental_freeze_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ AfterCast += SpellCastFn(spell_mage_water_elemental_freeze_SpellScript::HandleImprovedFreeze);
+ }
+
+ private:
+ bool _didHit;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mage_water_elemental_freeze_SpellScript();
+ }
+};
+
void AddSC_mage_spell_scripts()
{
new spell_mage_blast_wave();
+ new spell_mage_blizzard();
new spell_mage_burnout();
new spell_mage_cold_snap();
+ new spell_mage_cone_of_cold();
+ new spell_mage_conjure_refreshment();
new spell_mage_fire_frost_ward();
new spell_mage_focus_magic();
+ new spell_mage_frostbolt();
new spell_mage_ice_barrier();
new spell_mage_ignite();
new spell_mage_living_bomb();
+ new spell_mage_mage_ward();
new spell_mage_mana_shield();
new spell_mage_master_of_elements();
new spell_mage_polymorph_cast_visual();
+ new spell_mage_replenish_mana();
+ new spell_mage_ring_of_frost();
+ new spell_mage_ring_of_frost_freeze();
new spell_mage_summon_water_elemental();
+ new spell_mage_water_elemental_freeze();
}
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 6be2453affb..ac9b861f584 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -55,6 +55,8 @@ enum PaladinSpells
SPELL_PALADIN_HAND_OF_SACRIFICE = 6940,
SPELL_PALADIN_DIVINE_SACRIFICE = 64205,
+ SPELL_PALADIN_DIVINE_PURPOSE_PROC = 90174,
+
SPELL_PALADIN_GLYPH_OF_SALVATION = 63225,
SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT = 31790,
@@ -66,7 +68,7 @@ enum PaladinSpells
};
// 31850 - Ardent Defender
-class spell_pal_ardent_defender : public SpellScriptLoader
+/*class spell_pal_ardent_defender : public SpellScriptLoader
{
public:
spell_pal_ardent_defender() : SpellScriptLoader("spell_pal_ardent_defender") { }
@@ -89,7 +91,7 @@ class spell_pal_ardent_defender : public SpellScriptLoader
return GetUnitOwner()->GetTypeId() == TYPEID_PLAYER;
}
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
+ void CalculateAmount(AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated)
{
// Set absorbtion amount to unlimited
amount = -1;
@@ -139,7 +141,7 @@ class spell_pal_ardent_defender : public SpellScriptLoader
{
return new spell_pal_ardent_defender_AuraScript();
}
-};
+};*/
// 37877 - Blessing of Faith
class spell_pal_blessing_of_faith : public SpellScriptLoader
@@ -807,47 +809,105 @@ class spell_pal_righteous_defense : public SpellScriptLoader
}
};
-// 58597 - Sacred Shield
+// 85285 - Sacred Shield
class spell_pal_sacred_shield : public SpellScriptLoader
{
public:
spell_pal_sacred_shield() : SpellScriptLoader("spell_pal_sacred_shield") { }
- class spell_pal_sacred_shield_AuraScript : public AuraScript
+ class spell_pal_sacred_shield_SpellScript : public SpellScript
{
- PrepareAuraScript(spell_pal_sacred_shield_AuraScript);
+ PrepareSpellScript(spell_pal_sacred_shield_SpellScript);
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
+ SpellCastResult CheckCast()
{
- if (Unit* caster = GetCaster())
- {
- // +75.00% from sp bonus
- float bonus = CalculatePct(caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()), 75.0f);
+ Unit* caster = GetCaster();
+ if (caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_DONT_REPORT;
+
+ if (!caster->HealthBelowPct(30))
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+
+ return SPELL_CAST_OK;
+ }
+
+ void Register()
+ {
+ OnCheckCast += SpellCheckCastFn(spell_pal_sacred_shield_SpellScript::CheckCast);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_pal_sacred_shield_SpellScript();
+ }
+};
+
+// 85256 - Templar's Verdict
+/// Updated 4.3.4
+class spell_pal_templar_s_verdict : public SpellScriptLoader
+{
+ public:
+ spell_pal_templar_s_verdict() : SpellScriptLoader("spell_pal_templar_s_verdict") { }
+
+ class spell_pal_templar_s_verdict_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_pal_templar_s_verdict_SpellScript);
- // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage
- bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus);
- bonus *= caster->CalculateLevelPenalty(GetSpellInfo());
+ bool Validate (SpellInfo const* /*spellEntry*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_DIVINE_PURPOSE_PROC))
+ return false;
+
+ return true;
+ }
+
+ bool Load()
+ {
+ if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
+ return false;
- amount += int32(bonus);
+ if (GetCaster()->ToPlayer()->getClass() != CLASS_PALADIN)
+ return false;
- // Arena - Dampening
- if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_ARENA_DAMPENING, EFFECT_0))
- AddPct(amount, dampening->GetAmount());
- // Battleground - Dampening
- else if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_BATTLEGROUND_DAMPENING, EFFECT_0))
- AddPct(amount, dampening->GetAmount());
+ return true;
+ }
+
+ void ChangeDamage(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ int32 damage = GetHitDamage();
+
+ if (caster->HasAura(SPELL_PALADIN_DIVINE_PURPOSE_PROC))
+ damage *= 7.5; // 7.5*30% = 225%
+ else
+ {
+ switch (caster->GetPower(POWER_HOLY_POWER))
+ {
+ case 0: // 1 Holy Power
+ damage = damage;
+ break;
+ case 1: // 2 Holy Power
+ damage *= 3; // 3*30 = 90%
+ break;
+ case 2: // 3 Holy Power
+ damage *= 7.5; // 7.5*30% = 225%
+ break;
+ }
}
+
+ SetHitDamage(damage);
}
void Register()
{
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_sacred_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
+ OnEffectHitTarget += SpellEffectFn(spell_pal_templar_s_verdict_SpellScript::ChangeDamage, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE);
}
};
- AuraScript* GetAuraScript() const
+ SpellScript* GetSpellScript() const
{
- return new spell_pal_sacred_shield_AuraScript();
+ return new spell_pal_templar_s_verdict_SpellScript();
}
};
@@ -897,9 +957,10 @@ class spell_pal_seal_of_righteousness : public SpellScriptLoader
}
};
+
void AddSC_paladin_spell_scripts()
{
- new spell_pal_ardent_defender();
+ //new spell_pal_ardent_defender();
new spell_pal_blessing_of_faith();
new spell_pal_blessing_of_sanctuary();
new spell_pal_divine_sacrifice();
@@ -915,5 +976,6 @@ void AddSC_paladin_spell_scripts()
new spell_pal_lay_on_hands();
new spell_pal_righteous_defense();
new spell_pal_sacred_shield();
+ new spell_pal_templar_s_verdict();
new spell_pal_seal_of_righteousness();
}
diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp
index c4d5562ab39..e137ef955db 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -1347,24 +1347,6 @@ public:
return;
if (GetCaster()->GetOwner()->ToPlayer())
{
- // Pet's base damage changes depending on happiness
- if (GetCaster()->isPet() && GetCaster()->ToPet()->isHunterPet())
- {
- switch (GetCaster()->ToPet()->GetHappinessState())
- {
- case HAPPY:
- // 125% of normal damage
- amount += 25.0f;
- break;
- case CONTENT:
- // 100% of normal damage, nothing to modify
- break;
- case UNHAPPY:
- // 75% of normal damage
- amount += -25.0f;
- break;
- }
- }
// Cobra Reflexes
if (AuraEffect* cobraReflexes = GetCaster()->GetAuraEffectOfRankedSpell(61682, EFFECT_0))
amount -= cobraReflexes->GetAmount();
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 4e86a895484..c2bfc913893 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -33,13 +33,20 @@ enum PriestSpells
SPELL_PRIEST_EMPOWERED_RENEW = 63544,
SPELL_PRIEST_GLYPH_OF_LIGHTWELL = 55673,
SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL = 56161,
+ SPELL_PRIEST_GLYPH_OF_SHADOW = 107906,
SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153,
+ SPELL_PRIEST_LEAP_OF_FAITH = 73325,
+ SPELL_PRIEST_LEAP_OF_FAITH_EFFECT = 92832,
+ SPELL_PRIEST_LEAP_OF_FAITH_EFFECT_TRIGGER = 92833,
+ SPELL_PRIEST_LEAP_OF_FAITH_TRIGGERED = 92572,
SPELL_PRIEST_MANA_LEECH_PROC = 34650,
SPELL_PRIEST_PENANCE_R1 = 47540,
SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758,
SPELL_PRIEST_PENANCE_R1_HEAL = 47757,
- SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619,
SPELL_PRIEST_REFLECTIVE_SHIELD_R1 = 33201,
+ SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619,
+ SPELL_PRIEST_SHADOWFORM_VISUAL_WITHOUT_GLYPH = 107903,
+ SPELL_PRIEST_SHADOWFORM_VISUAL_WITH_GLYPH = 107904,
SPELL_PRIEST_SHADOW_WORD_DEATH = 32409,
SPELL_PRIEST_T9_HEALING_2P = 67201,
SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085,
@@ -140,7 +147,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader
}
};
-// -47788 - Guardian Spirit
+// 47788 - Guardian Spirit
class spell_pri_guardian_spirit : public SpellScriptLoader
{
public:
@@ -197,6 +204,46 @@ class spell_pri_guardian_spirit : public SpellScriptLoader
}
};
+// 92833 - Leap of Faith
+class spell_pri_leap_of_faith_effect_trigger : public SpellScriptLoader
+{
+ public:
+ spell_pri_leap_of_faith_effect_trigger() : SpellScriptLoader("spell_pri_leap_of_faith_effect_trigger") { }
+
+ class spell_pri_leap_of_faith_effect_trigger_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_pri_leap_of_faith_effect_trigger_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_LEAP_OF_FAITH_EFFECT))
+ return false;
+ return true;
+ }
+
+ void HandleEffectDummy(SpellEffIndex /*effIndex*/)
+ {
+ Position destPos;
+ GetHitDest()->GetPosition(&destPos);
+
+ SpellCastTargets targets;
+ targets.SetDst(destPos);
+ targets.SetUnitTarget(GetCaster());
+ GetHitUnit()->CastSpell(targets, sSpellMgr->GetSpellInfo(GetEffectValue()), NULL);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_pri_leap_of_faith_effect_trigger_SpellScript::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_pri_leap_of_faith_effect_trigger_SpellScript();
+ }
+};
+
// -7001 - Lightwell Renew
class spell_pri_lightwell_renew : public SpellScriptLoader
{
@@ -229,7 +276,7 @@ class spell_pri_lightwell_renew : public SpellScriptLoader
}
};
-// -8129 - Mana Burn
+// 8129 - Mana Burn
class spell_pri_mana_burn : public SpellScriptLoader
{
public:
@@ -308,7 +355,7 @@ class spell_pri_mana_leech : public SpellScriptLoader
}
};
-// -49821 - Mind Sear
+// 49821 - Mind Sear
class spell_pri_mind_sear : public SpellScriptLoader
{
public:
@@ -365,7 +412,7 @@ class spell_pri_pain_and_suffering_proc : public SpellScriptLoader
}
};
-// -47540 - Penance
+// 47540 - Penance
class spell_pri_penance : public SpellScriptLoader
{
public:
@@ -547,7 +594,50 @@ class spell_pri_prayer_of_mending_heal : public SpellScriptLoader
}
};
-// -139 - Renew
+// 17 - Reflective Shield
+class spell_pri_reflective_shield_trigger : public SpellScriptLoader
+{
+ public:
+ spell_pri_reflective_shield_trigger() : SpellScriptLoader("spell_pri_reflective_shield_trigger") { }
+
+ class spell_pri_reflective_shield_trigger_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_pri_reflective_shield_trigger_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_R1))
+ return false;
+ return true;
+ }
+
+ void Trigger(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+ {
+ Unit* target = GetTarget();
+ if (dmgInfo.GetAttacker() == target)
+ return;
+
+ if (GetCaster())
+ if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_PRIEST_REFLECTIVE_SHIELD_R1, EFFECT_0))
+ {
+ int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount());
+ target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff);
+ }
+ }
+
+ void Register()
+ {
+ AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_reflective_shield_trigger_AuraScript::Trigger, EFFECT_0);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_pri_reflective_shield_trigger_AuraScript();
+ }
+};
+
+// 139 - Renew
class spell_pri_renew : public SpellScriptLoader
{
public:
@@ -590,7 +680,7 @@ class spell_pri_renew : public SpellScriptLoader
}
};
-// -32379 - Shadow Word Death
+// 32379 - Shadow Word Death
class spell_pri_shadow_word_death : public SpellScriptLoader
{
public:
@@ -623,7 +713,48 @@ class spell_pri_shadow_word_death : public SpellScriptLoader
}
};
-// -34914 - Vampiric Touch
+// 15473 - Shadowform
+class spell_pri_shadowform : public SpellScriptLoader
+{
+ public:
+ spell_pri_shadowform() : SpellScriptLoader("spell_pri_shadowform") { }
+
+ class spell_pri_shadowform_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_pri_shadowform_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_SHADOWFORM_VISUAL_WITHOUT_GLYPH) ||
+ !sSpellMgr->GetSpellInfo(SPELL_PRIEST_SHADOWFORM_VISUAL_WITH_GLYPH))
+ return false;
+ return true;
+ }
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), GetTarget()->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOW) ? SPELL_PRIEST_SHADOWFORM_VISUAL_WITH_GLYPH : SPELL_PRIEST_SHADOWFORM_VISUAL_WITHOUT_GLYPH, true);
+ }
+
+ void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(GetTarget()->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOW) ? SPELL_PRIEST_SHADOWFORM_VISUAL_WITH_GLYPH : SPELL_PRIEST_SHADOWFORM_VISUAL_WITHOUT_GLYPH);
+ }
+
+ void Register()
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_pri_shadowform_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_pri_shadowform_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_pri_shadowform_AuraScript();
+ }
+};
+
+// 34914 - Vampiric Touch
class spell_pri_vampiric_touch : public SpellScriptLoader
{
public:
@@ -633,7 +764,7 @@ class spell_pri_vampiric_touch : public SpellScriptLoader
{
PrepareAuraScript(spell_pri_vampiric_touch_AuraScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL))
return false;
@@ -669,6 +800,7 @@ void AddSC_priest_spell_scripts()
new spell_pri_divine_aegis();
new spell_pri_glyph_of_prayer_of_healing();
new spell_pri_guardian_spirit();
+ new spell_pri_leap_of_faith_effect_trigger();
new spell_pri_lightwell_renew();
new spell_pri_mana_burn();
new spell_pri_mana_leech();
@@ -677,7 +809,9 @@ void AddSC_priest_spell_scripts()
new spell_pri_penance();
new spell_pri_power_word_shield();
new spell_pri_prayer_of_mending_heal();
+ new spell_pri_reflective_shield_trigger();
new spell_pri_renew();
new spell_pri_shadow_word_death();
+ new spell_pri_shadowform();
new spell_pri_vampiric_touch();
}
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index 7a5f0c9fd5b..867d619018c 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -37,6 +37,11 @@ enum RogueSpells
SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628,
};
+enum RogueSpellIcons
+{
+ ICON_ROGUE_IMPROVED_RECUPERATE = 4819
+};
+
// 13877, 33735, (check 51211, 65956) - Blade Flurry
class spell_rog_blade_flurry : public SpellScriptLoader
{
@@ -92,7 +97,7 @@ class spell_rog_blade_flurry : public SpellScriptLoader
}
};
-// -31228 - Cheat Death
+// 31228 - Cheat Death
class spell_rog_cheat_death : public SpellScriptLoader
{
public:
@@ -155,7 +160,7 @@ class spell_rog_cheat_death : public SpellScriptLoader
}
};
-// -2818 - Deadly Poison
+// 2818 - Deadly Poison
class spell_rog_deadly_poison : public SpellScriptLoader
{
public:
@@ -201,6 +206,9 @@ class spell_rog_deadly_poison : public SpellScriptLoader
// item combat enchantments
for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
{
+ if (slot > PRISMATIC_ENCHANTMENT_SLOT || slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
if (!enchant)
continue;
@@ -249,7 +257,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader
}
};
-// -31130 - Nerves of Steel
+// 31130 - Nerves of Steel
class spell_rog_nerves_of_steel : public SpellScriptLoader
{
public:
@@ -319,7 +327,7 @@ class spell_rog_preparation : public SpellScriptLoader
{
Player* caster = GetCaster()->ToPlayer();
- //immediately finishes the cooldown on certain Rogue abilities
+ // immediately finishes the cooldown on certain Rogue abilities
const SpellCooldowns& cm = caster->GetSpellCooldownMap();
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
@@ -327,13 +335,13 @@ class spell_rog_preparation : public SpellScriptLoader
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
{
- if (spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_COLDB_SHADOWSTEP || // Cold Blood, Shadowstep
- spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VAN_EVAS_SPRINT) // Vanish, Evasion, Sprint
+ if (spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_COLDB_SHADOWSTEP || // Cold Blood, Shadowstep
+ spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VAN_EVAS_SPRINT) // Vanish, Evasion, Sprint
caster->RemoveSpellCooldown((itr++)->first, true);
else if (caster->HasAura(SPELL_ROGUE_GLYPH_OF_PREPARATION))
{
- if (spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_DISMANTLE || // Dismantle
- spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_KICK || // Kick
+ if (spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_DISMANTLE || // Dismantle
+ spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_KICK || // Kick
(spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_BLADE_FLURRY && // Blade Flurry
spellInfo->SpellFamilyFlags[1] & SPELLFAMILYFLAG1_ROGUE_BLADE_FLURRY))
caster->RemoveSpellCooldown((itr++)->first, true);
@@ -360,7 +368,7 @@ class spell_rog_preparation : public SpellScriptLoader
}
};
-// -51685 - Prey on the Weak
+// 51685 - Prey on the Weak
class spell_rog_prey_on_the_weak : public SpellScriptLoader
{
public:
@@ -405,6 +413,55 @@ class spell_rog_prey_on_the_weak : public SpellScriptLoader
}
};
+// 73651 - Recuperate
+class spell_rog_recuperate : public SpellScriptLoader
+{
+ public:
+ spell_rog_recuperate() : SpellScriptLoader("spell_rog_recuperate") { }
+
+ class spell_rog_recuperate_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rog_recuperate_AuraScript);
+
+ bool Load()
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_0))
+ effect->RecalculateAmount(caster);
+ }
+
+ void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
+ {
+ canBeRecalculated = false;
+ if (Unit* caster = GetCaster())
+ {
+ int32 baseAmount = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster) * 1000;
+ // Improved Recuperate
+ if (AuraEffect const* auraEffect = caster->GetDummyAuraEffect(SPELLFAMILY_ROGUE, ICON_ROGUE_IMPROVED_RECUPERATE, EFFECT_0))
+ baseAmount += auraEffect->GetAmount();
+
+ amount = CalculatePct(caster->GetMaxHealth(), float(baseAmount) / 1000.0f);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_recuperate_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_recuperate_AuraScript::CalculateBonus, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_rog_recuperate_AuraScript();
+ }
+};
+
// -1943 - Rupture
class spell_rog_rupture : public SpellScriptLoader
{
@@ -597,6 +654,7 @@ void AddSC_rogue_spell_scripts()
new spell_rog_nerves_of_steel();
new spell_rog_preparation();
new spell_rog_prey_on_the_weak();
+ new spell_rog_recuperate();
new spell_rog_rupture();
new spell_rog_shiv();
new spell_rog_tricks_of_the_trade();
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index f970807bb94..045227a8f99 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -30,21 +30,20 @@
enum ShamanSpells
{
+ SPELL_HUNTER_INSANITY = 95809,
+ SPELL_MAGE_TEMPORAL_DISPLACEMENT = 80354,
SPELL_SHAMAN_ANCESTRAL_AWAKENING_PROC = 52752,
SPELL_SHAMAN_BIND_SIGHT = 6277,
- SPELL_SHAMAN_CLEANSING_TOTEM_EFFECT = 52025,
SPELL_SHAMAN_EARTH_SHIELD_HEAL = 379,
SPELL_SHAMAN_EXHAUSTION = 57723,
- SPELL_SHAMAN_FIRE_NOVA_R1 = 1535,
SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1 = 8349,
+ SPELL_SHAMAN_FLAME_SHOCK = 8050,
SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD = 63279,
SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM = 55456,
SPELL_SHAMAN_GLYPH_OF_MANA_TIDE = 55441,
SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM = 62132,
SPELL_SHAMAN_LAVA_FLOWS_R1 = 51480,
- SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694,
- SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE = 52032,
- SPELL_SHAMAN_MANA_TIDE_TOTEM = 39609,
+ SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 65264,
SPELL_SHAMAN_SATED = 57724,
SPELL_SHAMAN_STORM_EARTH_AND_FIRE = 51483,
SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB = 64695,
@@ -55,11 +54,12 @@ enum ShamanSpells
enum ShamanSpellIcons
{
- SHAMAN_ICON_ID_RESTORATIVE_TOTEMS = 338,
- SHAMAN_ICON_ID_SHAMAN_LAVA_FLOW = 3087
+ SHAMAN_ICON_ID_SOOTHING_RAIN = 2011,
+ SHAMAN_ICON_ID_SHAMAN_LAVA_FLOW = 3087
};
-// 52759 - Ancestral Awakening (Proc)
+// 52759 - Ancestral Awakening
+/// Updated 4.3.4
class spell_sha_ancestral_awakening_proc : public SpellScriptLoader
{
public:
@@ -79,7 +79,7 @@ class spell_sha_ancestral_awakening_proc : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
int32 damage = GetEffectValue();
- if (GetHitUnit())
+ if (GetCaster() && GetHitUnit())
GetCaster()->CastCustomSpell(GetHitUnit(), SPELL_SHAMAN_ANCESTRAL_AWAKENING_PROC, &damage, NULL, NULL, true);
}
@@ -95,51 +95,8 @@ class spell_sha_ancestral_awakening_proc : public SpellScriptLoader
}
};
-// 51474 - Astral Shift
-class spell_sha_astral_shift : public SpellScriptLoader
-{
- public:
- spell_sha_astral_shift() : SpellScriptLoader("spell_sha_astral_shift") { }
-
- class spell_sha_astral_shift_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_sha_astral_shift_AuraScript);
-
- uint32 absorbPct;
-
- bool Load()
- {
- absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
- return true;
- }
-
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
- {
- // Set absorbtion amount to unlimited
- amount = -1;
- }
-
- void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
- {
- // reduces all damage taken while stun, fear or silence
- if (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_FLEEING | UNIT_FLAG_SILENCED) || (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN)))
- absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
- }
-
- void Register()
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_astral_shift_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_sha_astral_shift_AuraScript::Absorb, EFFECT_0);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_sha_astral_shift_AuraScript();
- }
-};
-
// 2825 - Bloodlust
+/// Updated 4.3.4
class spell_sha_bloodlust : public SpellScriptLoader
{
public:
@@ -159,6 +116,8 @@ class spell_sha_bloodlust : public SpellScriptLoader
void RemoveInvalidTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SHAMAN_SATED));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HUNTER_INSANITY));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_MAGE_TEMPORAL_DISPLACEMENT));
}
void ApplyDebuff()
@@ -182,7 +141,8 @@ class spell_sha_bloodlust : public SpellScriptLoader
}
};
-// -1064 - Chain Heal
+// 1064 - Chain Heal
+/// Updated 4.3.4
class spell_sha_chain_heal : public SpellScriptLoader
{
public:
@@ -196,6 +156,7 @@ class spell_sha_chain_heal : public SpellScriptLoader
{
firstHeal = true;
riptide = false;
+ amount = 0;
return true;
}
@@ -207,6 +168,7 @@ class spell_sha_chain_heal : public SpellScriptLoader
if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, GetCaster()->GetGUID()))
{
riptide = true;
+ amount = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue();
// Consume it
GetHitUnit()->RemoveAura(aurEff->GetBase());
}
@@ -214,7 +176,10 @@ class spell_sha_chain_heal : public SpellScriptLoader
}
// Riptide increases the Chain Heal effect by 25%
if (riptide)
- SetHitHeal(GetHitHeal() * 1.25f);
+ {
+ uint32 bonus = CalculatePct(GetHitHeal(), amount);
+ SetHitHeal(GetHitHeal() + bonus);
+ }
}
void Register()
@@ -224,6 +189,7 @@ class spell_sha_chain_heal : public SpellScriptLoader
bool firstHeal;
bool riptide;
+ uint32 amount;
};
SpellScript* GetSpellScript() const
@@ -232,42 +198,6 @@ class spell_sha_chain_heal : public SpellScriptLoader
}
};
-// 8171 - Cleansing Totem (Pulse)
-class spell_sha_cleansing_totem_pulse : public SpellScriptLoader
-{
- public:
- spell_sha_cleansing_totem_pulse() : SpellScriptLoader("spell_sha_cleansing_totem_pulse") { }
-
- class spell_sha_cleansing_totem_pulse_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_sha_cleansing_totem_pulse_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_CLEANSING_TOTEM_EFFECT))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- int32 bp = 1;
- if (GetCaster() && GetHitUnit() && GetOriginalCaster())
- GetCaster()->CastCustomSpell(GetHitUnit(), SPELL_SHAMAN_CLEANSING_TOTEM_EFFECT, NULL, &bp, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID());
- }
-
- void Register()
- {
- OnEffectHitTarget += SpellEffectFn(spell_sha_cleansing_totem_pulse_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_sha_cleansing_totem_pulse_SpellScript();
- }
-};
-
// -974 - Earth Shield
class spell_sha_earth_shield : public SpellScriptLoader
{
@@ -330,7 +260,8 @@ class spell_sha_earth_shield : public SpellScriptLoader
}
};
-// 6474 - Earthbind Totem - Fix Talent: Earthen Power
+// 6474 - Earthbind Totem - Fix Talent:Earthen Power, Earth's Grasp
+/// Updated 4.3.4
class spell_sha_earthbind_totem : public SpellScriptLoader
{
public:
@@ -364,7 +295,7 @@ class spell_sha_earthbind_totem : public SpellScriptLoader
Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!owner)
return;
- // Storm, Earth and Fire
+ // Earth's Grasp
if (AuraEffect* aurEff = owner->GetAuraEffectOfRankedSpell(SPELL_SHAMAN_STORM_EARTH_AND_FIRE, EFFECT_1))
{
if (roll_chance_i(aurEff->GetAmount()))
@@ -429,7 +360,8 @@ class spell_sha_earthen_power : public SpellScriptLoader
}
};
-// -1535 - Fire Nova
+// 1535 Fire Nova
+/// Updated 4.3.4
class spell_sha_fire_nova : public SpellScriptLoader
{
public:
@@ -439,46 +371,21 @@ class spell_sha_fire_nova : public SpellScriptLoader
{
PrepareSpellScript(spell_sha_fire_nova_SpellScript);
- bool Validate(SpellInfo const* spellInfo)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_FIRE_NOVA_R1) || sSpellMgr->GetFirstSpellInChain(SPELL_SHAMAN_FIRE_NOVA_R1) != sSpellMgr->GetFirstSpellInChain(spellInfo->Id))
- return false;
-
- uint8 rank = sSpellMgr->GetSpellRank(spellInfo->Id);
- if (!sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1, rank, true))
- return false;
- return true;
- }
-
- SpellCastResult CheckFireTotem()
- {
- // fire totem
- if (!GetCaster()->m_SummonSlot[1])
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
-
- return SPELL_CAST_OK;
- }
-
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- if (Unit* caster = GetCaster())
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
{
- uint8 rank = sSpellMgr->GetSpellRank(GetSpellInfo()->Id);
- if (uint32 spellId = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1, rank))
+ if (target->HasAura(SPELL_SHAMAN_FLAME_SHOCK))
{
- Creature* totem = caster->GetMap()->GetCreature(caster->m_SummonSlot[1]);
- if (totem && totem->isTotem())
- caster->CastSpell(totem, spellId, true);
+ caster->CastSpell(target, SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1, true);
+ target->RemoveAurasDueToSpell(SPELL_SHAMAN_FLAME_SHOCK);
}
}
}
void Register()
{
- OnCheckCast += SpellCheckCastFn(spell_sha_fire_nova_SpellScript::CheckFireTotem);
OnEffectHitTarget += SpellEffectFn(spell_sha_fire_nova_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -489,7 +396,8 @@ class spell_sha_fire_nova : public SpellScriptLoader
}
};
-// -8050 - Flame Shock
+// 8050 -Flame Shock
+/// Updated 4.3.4
class spell_sha_flame_shock : public SpellScriptLoader
{
public:
@@ -511,15 +419,17 @@ class spell_sha_flame_shock : public SpellScriptLoader
void HandleDispel(DispelInfo* /*dispelInfo*/)
{
if (Unit* caster = GetCaster())
+ {
// Lava Flows
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, SHAMAN_ICON_ID_SHAMAN_LAVA_FLOW, EFFECT_0))
{
if (sSpellMgr->GetFirstSpellInChain(SPELL_SHAMAN_LAVA_FLOWS_R1) != sSpellMgr->GetFirstSpellInChain(aurEff->GetId()))
return;
- uint8 rank = sSpellMgr->GetSpellRank(aurEff->GetId());
- caster->CastSpell(caster, sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1, rank), true);
+ int32 basepoints = aurEff->GetAmount();
+ caster->CastCustomSpell(caster, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1, &basepoints, NULL, NULL, true);
}
+ }
}
void Register()
@@ -534,7 +444,8 @@ class spell_sha_flame_shock : public SpellScriptLoader
}
};
-// 52041, 52046, 52047, 52048, 52049, 52050, 58759, 58760, 58761 - Healing Stream Totem
+// 52041 - Healing Stream Totem
+/// Updated 4.3.4
class spell_sha_healing_stream_totem : public SpellScriptLoader
{
public:
@@ -546,12 +457,10 @@ class spell_sha_healing_stream_totem : public SpellScriptLoader
bool Validate(SpellInfo const* /*spellInfo*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM) || !sSpellMgr->GetSpellInfo(SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL))
- return false;
- return true;
+ return sSpellMgr->GetSpellInfo(SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL);
}
- void HandleDummy(SpellEffIndex /*effIndex*/)
+ void HandleDummy(SpellEffIndex /* effIndex */)
{
int32 damage = GetEffectValue();
SpellInfo const* triggeringSpell = GetTriggeringSpell();
@@ -563,14 +472,10 @@ class spell_sha_healing_stream_totem : public SpellScriptLoader
if (triggeringSpell)
damage = int32(owner->SpellHealingBonusDone(target, triggeringSpell, damage, HEAL));
- // Restorative Totems
- if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, SHAMAN_ICON_ID_RESTORATIVE_TOTEMS, 1))
+ // Soothing Rains
+ if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, SHAMAN_ICON_ID_SOOTHING_RAIN, EFFECT_0))
AddPct(damage, dummy->GetAmount());
- // Glyph of Healing Stream Totem
- if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM, EFFECT_0))
- AddPct(damage, aurEff->GetAmount());
-
damage = int32(target->SpellHealingBonusTaken(owner, triggeringSpell, damage, HEAL));
}
caster->CastCustomSpell(target, SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
@@ -590,6 +495,7 @@ class spell_sha_healing_stream_totem : public SpellScriptLoader
};
// 32182 - Heroism
+/// Updated 4.3.4
class spell_sha_heroism : public SpellScriptLoader
{
public:
@@ -609,6 +515,8 @@ class spell_sha_heroism : public SpellScriptLoader
void RemoveInvalidTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SHAMAN_EXHAUSTION));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HUNTER_INSANITY));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_MAGE_TEMPORAL_DISPLACEMENT));
}
void ApplyDebuff()
@@ -633,6 +541,7 @@ class spell_sha_heroism : public SpellScriptLoader
};
// 60103 - Lava Lash
+/// Updated 4.3.4
class spell_sha_lava_lash : public SpellScriptLoader
{
public:
@@ -676,135 +585,34 @@ class spell_sha_lava_lash : public SpellScriptLoader
}
};
-// 52031, 52033, 52034, 52035, 52036, 58778, 58779, 58780 - Mana Spring Totem
-class spell_sha_mana_spring_totem : public SpellScriptLoader
-{
- public:
- spell_sha_mana_spring_totem() : SpellScriptLoader("spell_sha_mana_spring_totem") { }
-
- class spell_sha_mana_spring_totem_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_sha_mana_spring_totem_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- int32 damage = GetEffectValue();
- if (Unit* target = GetHitUnit())
- if (Unit* caster = GetCaster())
- if (target->getPowerType() == POWER_MANA)
- caster->CastCustomSpell(target, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
- }
-
- void Register()
- {
- OnEffectHitTarget += SpellEffectFn(spell_sha_mana_spring_totem_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
-
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_sha_mana_spring_totem_SpellScript();
- }
-};
-
-// 39610 - Mana Tide Totem
+// 16191 - Mana Tide
+/// Updated 4.3.4
class spell_sha_mana_tide_totem : public SpellScriptLoader
{
public:
spell_sha_mana_tide_totem() : SpellScriptLoader("spell_sha_mana_tide_totem") { }
- class spell_sha_mana_tide_totem_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_sha_mana_tide_totem_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_GLYPH_OF_MANA_TIDE) || !sSpellMgr->GetSpellInfo(SPELL_SHAMAN_MANA_TIDE_TOTEM))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex /*effIndex*/)
- {
- if (Unit* caster = GetCaster())
- if (Unit* unitTarget = GetHitUnit())
- {
- if (unitTarget->getPowerType() == POWER_MANA)
- {
- int32 effValue = GetEffectValue();
- // Glyph of Mana Tide
- if (Unit* owner = caster->GetOwner())
- if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_MANA_TIDE, 0))
- effValue += dummy->GetAmount();
- // Regenerate 6% of Total Mana Every 3 secs
- int32 effBasePoints0 = int32(CalculatePct(unitTarget->GetMaxPower(POWER_MANA), effValue));
- caster->CastCustomSpell(unitTarget, SPELL_SHAMAN_MANA_TIDE_TOTEM, &effBasePoints0, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID());
- }
- }
- }
-
- void Register()
- {
- OnEffectHitTarget += SpellEffectFn(spell_sha_mana_tide_totem_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const
+ class spell_sha_mana_tide_totem_AuraScript : public AuraScript
{
- return new spell_sha_mana_tide_totem_SpellScript();
- }
-};
-
-// 6495 - Sentry Totem
-class spell_sha_sentry_totem : public SpellScriptLoader
-{
- public:
- spell_sha_sentry_totem() : SpellScriptLoader("spell_sha_sentry_totem") { }
-
- class spell_sha_sentry_totem_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_sha_sentry_totem_AuraScript);
-
- bool Validate(SpellInfo const* /*spell*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_BIND_SIGHT))
- return false;
- return true;
- }
-
- void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- if (Creature* totem = caster->GetMap()->GetCreature(caster->m_SummonSlot[4]))
- if (totem->isTotem())
- caster->CastSpell(totem, SPELL_SHAMAN_BIND_SIGHT, true);
- }
+ PrepareAuraScript(spell_sha_mana_tide_totem_AuraScript);
- void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
{
+ ///@TODO: Exclude the "short term" buffs from the stat value
if (Unit* caster = GetCaster())
- if (caster->GetTypeId() == TYPEID_PLAYER)
- caster->ToPlayer()->StopCastingBindSight();
+ if (Unit* owner = caster->GetOwner())
+ amount = CalculatePct(owner->GetStat(STAT_SPIRIT), aurEff->GetAmount());
}
void Register()
{
- AfterEffectApply += AuraEffectApplyFn(spell_sha_sentry_totem_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_sha_sentry_totem_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_mana_tide_totem_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_STAT);
}
};
AuraScript* GetAuraScript() const
{
- return new spell_sha_sentry_totem_AuraScript();
+ return new spell_sha_mana_tide_totem_AuraScript();
}
};
@@ -840,10 +648,8 @@ class spell_sha_thunderstorm : public SpellScriptLoader
void AddSC_shaman_spell_scripts()
{
new spell_sha_ancestral_awakening_proc();
- new spell_sha_astral_shift();
new spell_sha_bloodlust();
new spell_sha_chain_heal();
- new spell_sha_cleansing_totem_pulse();
new spell_sha_earth_shield();
new spell_sha_earthbind_totem();
new spell_sha_earthen_power();
@@ -852,8 +658,6 @@ void AddSC_shaman_spell_scripts()
new spell_sha_healing_stream_totem();
new spell_sha_heroism();
new spell_sha_lava_lash();
- new spell_sha_mana_spring_totem();
new spell_sha_mana_tide_totem();
- new spell_sha_sentry_totem();
new spell_sha_thunderstorm();
}
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 7b2e5c02bfa..853e494ec1f 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -25,32 +25,41 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
+#include "SpellAuras.h"
enum WarlockSpells
{
+ SPELL_WARLOCK_BANE_OF_DOOM_EFFECT = 18662,
SPELL_WARLOCK_CURSE_OF_DOOM_EFFECT = 18662,
+ SPELL_WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST = 62388,
SPELL_WARLOCK_DEMONIC_CIRCLE_SUMMON = 48018,
SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT = 48020,
- SPELL_WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST = 62388,
- SPELL_WARLOCK_DEMONIC_EMPOWERMENT_SUCCUBUS = 54435,
- SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER = 54443,
SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELGUARD = 54508,
SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELHUNTER = 54509,
SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP = 54444,
+ SPELL_WARLOCK_DEMONIC_EMPOWERMENT_SUCCUBUS = 54435,
+ SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER = 54443,
+ SPELL_WARLOCK_DEMON_SOUL_IMP = 79459,
+ SPELL_WARLOCK_DEMON_SOUL_FELHUNTER = 79460,
+ SPELL_WARLOCK_DEMON_SOUL_FELGUARD = 79452,
+ SPELL_WARLOCK_DEMON_SOUL_SUCCUBUS = 79453,
+ SPELL_WARLOCK_DEMON_SOUL_VOIDWALKER = 79454,
SPELL_WARLOCK_FEL_SYNERGY_HEAL = 54181,
SPELL_WARLOCK_GLYPH_OF_SIPHON_LIFE = 63106,
+ SPELL_WARLOCK_HAUNT = 48181,
+ SPELL_WARLOCK_HAUNT_HEAL = 48210,
+ SPELL_WARLOCK_IMMOLATE = 348,
SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R1 = 18692,
SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R2 = 18693,
- SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703,
- SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R2 = 18704,
SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R1 = 60955,
SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2 = 60956,
- SPELL_WARLOCK_HAUNT = 48181,
- SPELL_WARLOCK_HAUNT_HEAL = 48210,
+ SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703,
+ SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R2 = 18704,
SPELL_WARLOCK_LIFE_TAP_ENERGIZE = 31818,
SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553,
- SPELL_WARLOCK_SOULSHATTER = 32835,
SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106,
+ SPELL_WARLOCK_SOULSHATTER = 32835,
+ SPELL_WARLOCK_UNSTABLE_AFFLICTION = 30108,
SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117
};
@@ -60,7 +69,8 @@ enum WarlockSpellIcons
WARLOCK_ICON_ID_MANA_FEED = 1982
};
-// 710, 18647 - Banish
+// 710 - Banish
+/// Updated 4.3.4
class spell_warl_banish : public SpellScriptLoader
{
public:
@@ -78,6 +88,8 @@ class spell_warl_banish : public SpellScriptLoader
void HandleBanish()
{
+ /// Casting Banish on a banished target will cancel the effect
+ /// Check if the target already has Banish, if so, do nothing.
if (Unit* target = GetHitUnit())
{
if (target->GetAuraEffect(SPELL_AURA_SCHOOL_IMMUNITY, SPELLFAMILY_WARLOCK, 0, 0x08000000, 0))
@@ -112,7 +124,42 @@ class spell_warl_banish : public SpellScriptLoader
}
};
-// 6201 - Create Healthstone (and ranks)
+// 17962 - Conflagrate - Updated to 4.3.4
+class spell_warl_conflagrate : public SpellScriptLoader
+{
+ public:
+ spell_warl_conflagrate() : SpellScriptLoader("spell_warl_conflagrate") { }
+
+ class spell_warl_conflagrate_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_warl_conflagrate_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_IMMOLATE))
+ return false;
+ return true;
+ }
+
+ void HandleHit(SpellEffIndex /*effIndex*/)
+ {
+ if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffect(SPELL_WARLOCK_IMMOLATE, EFFECT_2, GetCaster()->GetGUID()))
+ SetHitDamage(CalculatePct(aurEff->GetAmount(), GetSpellInfo()->Effects[EFFECT_1].CalcValue(GetCaster())));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_warl_conflagrate_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_warl_conflagrate_SpellScript();
+ }
+};
+
+// 6201 - Create Healthstone
class spell_warl_create_healthstone : public SpellScriptLoader
{
public:
@@ -184,7 +231,8 @@ class spell_warl_create_healthstone : public SpellScriptLoader
}
};
-uint32 const spell_warl_create_healthstone::spell_warl_create_healthstone_SpellScript::iTypes[8][3] = {
+uint32 const spell_warl_create_healthstone::spell_warl_create_healthstone_SpellScript::iTypes[8][3] =
+{
{ 5512, 19004, 19005}, // Minor Healthstone
{ 5511, 19006, 19007}, // Lesser Healthstone
{ 5509, 19008, 19009}, // Healthstone
@@ -195,19 +243,20 @@ uint32 const spell_warl_create_healthstone::spell_warl_create_healthstone_SpellS
{36892, 36893, 36894} // Fel Healthstone
};
-// -603 - Curse of Doom
-class spell_warl_curse_of_doom : public SpellScriptLoader
+// 603 - Bane of Doom
+/// Updated 4.3.4
+class spell_warl_bane_of_doom : public SpellScriptLoader
{
public:
- spell_warl_curse_of_doom() : SpellScriptLoader("spell_warl_curse_of_doom") { }
+ spell_warl_bane_of_doom() : SpellScriptLoader("spell_warl_bane_of_doom") { }
class spell_warl_curse_of_doom_AuraScript : public AuraScript
{
PrepareAuraScript(spell_warl_curse_of_doom_AuraScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_CURSE_OF_DOOM_EFFECT))
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_BANE_OF_DOOM_EFFECT))
return false;
return true;
}
@@ -227,7 +276,7 @@ class spell_warl_curse_of_doom : public SpellScriptLoader
return;
if (GetCaster()->ToPlayer()->isHonorOrXPTarget(GetTarget()))
- GetCaster()->CastSpell(GetTarget(), SPELL_WARLOCK_CURSE_OF_DOOM_EFFECT, true, NULL, aurEff);
+ GetCaster()->CastSpell(GetTarget(), SPELL_WARLOCK_BANE_OF_DOOM_EFFECT, true, NULL, aurEff);
}
void Register()
@@ -242,7 +291,8 @@ class spell_warl_curse_of_doom : public SpellScriptLoader
}
};
-// 48018 - Demonic Circle Summon
+// 48018 - Demonic Circle: Summon
+/// Updated 4.3.4
class spell_warl_demonic_circle_summon : public SpellScriptLoader
{
public:
@@ -294,7 +344,8 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader
}
};
-// 48020 - Demonic Circle Teleport
+// 48020 - Demonic Circle: Teleport
+/// Updated 4.3.4
class spell_warl_demonic_circle_teleport : public SpellScriptLoader
{
public:
@@ -328,7 +379,75 @@ class spell_warl_demonic_circle_teleport : public SpellScriptLoader
}
};
+// 77801 - Demon Soul - Updated to 4.3.4
+class spell_warl_demon_soul : public SpellScriptLoader
+{
+ public:
+ spell_warl_demon_soul() : SpellScriptLoader("spell_warl_demon_soul") { }
+
+ class spell_warl_demon_soul_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_warl_demon_soul_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMON_SOUL_IMP))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMON_SOUL_FELHUNTER))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMON_SOUL_FELGUARD))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMON_SOUL_SUCCUBUS))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMON_SOUL_VOIDWALKER))
+ return false;
+ return true;
+ }
+
+ void OnHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (Creature* targetCreature = GetHitCreature())
+ {
+ if (targetCreature->isPet())
+ {
+ CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(targetCreature->GetEntry());
+ switch (ci->family)
+ {
+ case CREATURE_FAMILY_SUCCUBUS:
+ caster->CastSpell(caster, SPELL_WARLOCK_DEMON_SOUL_SUCCUBUS);
+ break;
+ case CREATURE_FAMILY_VOIDWALKER:
+ caster->CastSpell(caster, SPELL_WARLOCK_DEMON_SOUL_VOIDWALKER);
+ break;
+ case CREATURE_FAMILY_FELGUARD:
+ caster->CastSpell(caster, SPELL_WARLOCK_DEMON_SOUL_FELGUARD);
+ break;
+ case CREATURE_FAMILY_FELHUNTER:
+ caster->CastSpell(caster, SPELL_WARLOCK_DEMON_SOUL_FELHUNTER);
+ break;
+ case CREATURE_FAMILY_IMP:
+ caster->CastSpell(caster, SPELL_WARLOCK_DEMON_SOUL_IMP);
+ break;
+ }
+ }
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_warl_demon_soul_SpellScript::OnHitTarget, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_warl_demon_soul_SpellScript;
+ }
+};
+
// 47193 - Demonic Empowerment
+/// Updated 4.3.4
class spell_warl_demonic_empowerment : public SpellScriptLoader
{
public:
@@ -362,7 +481,6 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER);
int32 hp = int32(targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(targetCreature, spellInfo, 0)));
targetCreature->CastCustomSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, &hp, NULL, NULL, true);
- //unitTarget->CastSpell(unitTarget, 54441, true);
break;
}
case CREATURE_FAMILY_FELGUARD:
@@ -392,6 +510,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader
};
// 47422 - Everlasting Affliction
+/// Updated 4.3.4
class spell_warl_everlasting_affliction : public SpellScriptLoader
{
public:
@@ -421,6 +540,43 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader
}
};
+// 77799 - Fel Flame - Updated to 4.3.4
+class spell_warl_fel_flame : public SpellScriptLoader
+{
+ public:
+ spell_warl_fel_flame() : SpellScriptLoader("spell_warl_fel_flame") { }
+
+ class spell_warl_fel_flame_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_warl_fel_flame_SpellScript);
+
+ void OnHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ Unit* target = GetHitUnit();
+ Aura* aura = target->GetAura(SPELL_WARLOCK_UNSTABLE_AFFLICTION, caster->GetGUID());
+ if (!aura)
+ aura = target->GetAura(SPELL_WARLOCK_IMMOLATE, caster->GetGUID());
+
+ if (!aura)
+ return;
+
+ int32 newDuration = aura->GetDuration() + GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 1000;
+ aura->SetDuration(std::min(newDuration, aura->GetMaxDuration()));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_warl_fel_flame_SpellScript::OnHitTarget, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_warl_fel_flame_SpellScript;
+ }
+};
+
// -47230 - Fel Synergy
class spell_warl_fel_synergy : public SpellScriptLoader
{
@@ -464,7 +620,8 @@ class spell_warl_fel_synergy : public SpellScriptLoader
}
};
-// -48181 - Haunt
+// 48181 - Haunt
+/// Updated 4.3.4
class spell_warl_haunt : public SpellScriptLoader
{
public:
@@ -491,7 +648,7 @@ class spell_warl_haunt : public SpellScriptLoader
{
PrepareAuraScript(spell_warl_haunt_AuraScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_HAUNT_HEAL))
return false;
@@ -524,7 +681,8 @@ class spell_warl_haunt : public SpellScriptLoader
}
};
-// -755 - Health Funnel
+// 755 - Health Funnel
+/// Updated 4.3.4
class spell_warl_health_funnel : public SpellScriptLoader
{
public:
@@ -567,7 +725,8 @@ class spell_warl_health_funnel : public SpellScriptLoader
}
};
-// -1454 - Life Tap
+// 1454 - Life Tap
+/// Updated 4.3.4
class spell_warl_life_tap : public SpellScriptLoader
{
public:
@@ -582,7 +741,7 @@ class spell_warl_life_tap : public SpellScriptLoader
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_LIFE_TAP_ENERGIZE) || !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2))
return false;
@@ -594,8 +753,8 @@ class spell_warl_life_tap : public SpellScriptLoader
Player* caster = GetCaster()->ToPlayer();
if (Unit* target = GetHitUnit())
{
- int32 damage = GetEffectValue();
- int32 mana = int32(damage + (caster->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+SPELL_SCHOOL_SHADOW) * 0.5f));
+ int32 damage = caster->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue());
+ int32 mana = CalculatePct(damage, GetSpellInfo()->Effects[EFFECT_1].CalcValue());
// Shouldn't Appear in Combat Log
target->ModifyHealth(-damage);
@@ -607,12 +766,9 @@ class spell_warl_life_tap : public SpellScriptLoader
caster->CastCustomSpell(target, SPELL_WARLOCK_LIFE_TAP_ENERGIZE, &mana, NULL, NULL, false);
// Mana Feed
- int32 manaFeedVal = 0;
if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, WARLOCK_ICON_ID_MANA_FEED, 0))
- manaFeedVal = aurEff->GetAmount();
-
- if (manaFeedVal > 0)
{
+ int32 manaFeedVal = aurEff->GetAmount();
ApplyPct(manaFeedVal, mana);
caster->CastCustomSpell(caster, SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2, &manaFeedVal, NULL, NULL, true, NULL);
}
@@ -621,7 +777,7 @@ class spell_warl_life_tap : public SpellScriptLoader
SpellCastResult CheckCast()
{
- if ((int32(GetCaster()->GetHealth()) > int32(GetSpellInfo()->Effects[EFFECT_0].CalcValue() + (6.3875 * GetSpellInfo()->BaseLevel))))
+ if (int32(GetCaster()->GetHealth()) > int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue())))
return SPELL_CAST_OK;
return SPELL_FAILED_FIZZLE;
}
@@ -667,7 +823,8 @@ class spell_warl_ritual_of_doom_effect : public SpellScriptLoader
}
};
-// -27285 - Seed of Corruption
+// 27285 - Seed of Corruption
+/// Updated 4.3.4
class spell_warl_seed_of_corruption : public SpellScriptLoader
{
public:
@@ -782,6 +939,7 @@ class spell_warl_siphon_life : public SpellScriptLoader
};
// 29858 - Soulshatter
+/// Updated 4.3.4
class spell_warl_soulshatter : public SpellScriptLoader
{
public:
@@ -791,7 +949,7 @@ class spell_warl_soulshatter : public SpellScriptLoader
{
PrepareSpellScript(spell_warl_soulshatter_SpellScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_SOULSHATTER))
return false;
@@ -802,10 +960,8 @@ class spell_warl_soulshatter : public SpellScriptLoader
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
- {
if (target->CanHaveThreatList() && target->getThreatManager().getThreat(caster) > 0.0f)
caster->CastSpell(target, SPELL_WARLOCK_SOULSHATTER, true);
- }
}
void Register()
@@ -820,7 +976,8 @@ class spell_warl_soulshatter : public SpellScriptLoader
}
};
-// -30108 - Unstable Affliction
+// 30108, 34438, 34439, 35183 - Unstable Affliction
+/// Updated 4.3.4
class spell_warl_unstable_affliction : public SpellScriptLoader
{
public:
@@ -830,7 +987,7 @@ class spell_warl_unstable_affliction : public SpellScriptLoader
{
PrepareAuraScript(spell_warl_unstable_affliction_AuraScript);
- bool Validate(SpellInfo const* /*spell*/)
+ bool Validate(SpellInfo const* /*spellInfo*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL))
return false;
@@ -840,7 +997,7 @@ class spell_warl_unstable_affliction : public SpellScriptLoader
void HandleDispel(DispelInfo* dispelInfo)
{
if (Unit* caster = GetCaster())
- if (AuraEffect const* aurEff = GetEffect(EFFECT_0))
+ if (AuraEffect const* aurEff = GetEffect(EFFECT_1))
{
int32 damage = aurEff->GetAmount() * 9;
// backfire damage and silence
@@ -862,13 +1019,16 @@ class spell_warl_unstable_affliction : public SpellScriptLoader
void AddSC_warlock_spell_scripts()
{
+ new spell_warl_bane_of_doom();
new spell_warl_banish();
+ new spell_warl_conflagrate();
new spell_warl_create_healthstone();
- new spell_warl_curse_of_doom();
new spell_warl_demonic_circle_summon();
new spell_warl_demonic_circle_teleport();
new spell_warl_demonic_empowerment();
+ new spell_warl_demon_soul();
new spell_warl_everlasting_affliction();
+ new spell_warl_fel_flame();
new spell_warl_fel_synergy();
new spell_warl_haunt();
new spell_warl_health_funnel();
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 7136f046873..9e2cb8aad71 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -31,7 +31,6 @@ enum WarriorSpells
SPELL_WARRIOR_BLOODTHIRST = 23885,
SPELL_WARRIOR_BLOODTHIRST_DAMAGE = 23881,
SPELL_WARRIOR_CHARGE = 34846,
- SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE = 59653,
SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162,
SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850,
SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868,
@@ -42,7 +41,7 @@ enum WarriorSpells
SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156,
SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976,
SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976,
- SPELL_WARRIOR_SLAM = 50783,
+ SPELL_WARRIOR_SLAM = 50782,
SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK = 26654,
SPELL_WARRIOR_TAUNT = 355,
SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859,
@@ -60,10 +59,10 @@ enum WarriorSpells
enum WarriorSpellIcons
{
- WARRIOR_ICON_ID_SUDDEN_DEATH = 1989,
+ WARRIOR_ICON_ID_SUDDEN_DEATH = 1989,
};
-// 23881 - Bloodthirst
+/// Updated 4.3.4
class spell_warr_bloodthirst : public SpellScriptLoader
{
public:
@@ -105,7 +104,7 @@ class spell_warr_bloodthirst : public SpellScriptLoader
}
};
-// 23880 - Bloodthirst (Heal)
+/// Updated 4.3.4
class spell_warr_bloodthirst_heal : public SpellScriptLoader
{
public:
@@ -118,7 +117,7 @@ class spell_warr_bloodthirst_heal : public SpellScriptLoader
void HandleHeal(SpellEffIndex /*effIndex*/)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_BLOODTHIRST_DAMAGE))
- SetHitHeal(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster())));
+ SetHitHeal(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster())) / 100);
}
void Register()
@@ -133,7 +132,7 @@ class spell_warr_bloodthirst_heal : public SpellScriptLoader
}
};
-// -100 - Charge
+/// Updated 4.3.4
class spell_warr_charge : public SpellScriptLoader
{
public:
@@ -173,7 +172,7 @@ class spell_warr_charge : public SpellScriptLoader
}
};
-// 12809 - Concussion Blow
+/// Updated 4.3.4
class spell_warr_concussion_blow : public SpellScriptLoader
{
public:
@@ -200,45 +199,7 @@ class spell_warr_concussion_blow : public SpellScriptLoader
}
};
-// -58872 - Damage Shield
-class spell_warr_damage_shield : public SpellScriptLoader
-{
- public:
- spell_warr_damage_shield() : SpellScriptLoader("spell_warr_damage_shield") { }
-
- class spell_warr_damage_shield_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_warr_damage_shield_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE))
- return false;
- return true;
- }
-
- void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
-
- // % of amount blocked
- int32 damage = CalculatePct(int32(GetTarget()->GetShieldBlockValue()), aurEff->GetAmount());
- GetTarget()->CastCustomSpell(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, NULL, aurEff);
- }
-
- void Register()
- {
- OnEffectProc += AuraEffectProcFn(spell_warr_damage_shield_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_warr_damage_shield_AuraScript();
- }
-};
-
-// -12162 - Deep Wounds
+/// Updated 4.3.4
class spell_warr_deep_wounds : public SpellScriptLoader
{
public:
@@ -293,7 +254,7 @@ class spell_warr_deep_wounds : public SpellScriptLoader
}
};
-// -5308 - Execute
+/// Updated 4.3.4
class spell_warr_execute : public SpellScriptLoader
{
public:
@@ -303,43 +264,35 @@ class spell_warr_execute : public SpellScriptLoader
{
PrepareSpellScript(spell_warr_execute_SpellScript);
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_EXECUTE) || !sSpellMgr->GetSpellInfo(SPELL_WARRIOR_GLYPH_OF_EXECUTION))
- return false;
- return true;
- }
-
- void HandleDummy(SpellEffIndex effIndex)
+ void HandleEffect(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
- if (Unit* target = GetHitUnit())
+ if (GetHitUnit())
{
SpellInfo const* spellInfo = GetSpellInfo();
- int32 rageUsed = std::min<int32>(300 - spellInfo->CalcPowerCost(caster, SpellSchoolMask(spellInfo->SchoolMask)), caster->GetPower(POWER_RAGE));
+ int32 rageUsed = std::min<int32>(200 - spellInfo->CalcPowerCost(caster, SpellSchoolMask(spellInfo->SchoolMask)), caster->GetPower(POWER_RAGE));
int32 newRage = std::max<int32>(0, caster->GetPower(POWER_RAGE) - rageUsed);
// Sudden Death rage save
if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_GENERIC, WARRIOR_ICON_ID_SUDDEN_DEATH, EFFECT_0))
{
- int32 ragesave = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 10;
+ int32 ragesave = aurEff->GetSpellInfo()->Effects[EFFECT_0].CalcValue() * 10;
newRage = std::max(newRage, ragesave);
}
caster->SetPower(POWER_RAGE, uint32(newRage));
- // Glyph of Execution bonus
- if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_WARRIOR_GLYPH_OF_EXECUTION, EFFECT_0))
- rageUsed += aurEff->GetAmount() * 10;
-
- int32 bp = GetEffectValue() + int32(rageUsed * spellInfo->Effects[effIndex].DamageMultiplier + caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.2f);
- caster->CastCustomSpell(target, SPELL_WARRIOR_EXECUTE, &bp, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID());
+ /// Formula taken from the DBC: "${10+$AP*0.437*$m1/100}"
+ int32 baseDamage = int32(10 + caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.437f * GetEffectValue() / 100.0f);
+ /// Formula taken from the DBC: "${$ap*0.874*$m1/100-1} = 20 rage"
+ int32 moreDamage = int32(rageUsed * (caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.874f * GetEffectValue() / 100.0f - 1) / 200);
+ SetHitDamage(baseDamage + moreDamage);
}
}
void Register()
{
- OnEffectHitTarget += SpellEffectFn(spell_warr_execute_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnEffectHitTarget += SpellEffectFn(spell_warr_execute_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
@@ -405,7 +358,7 @@ class spell_warr_intimidating_shout : public SpellScriptLoader
}
};
-// 12975 - Last Stand
+/// Updated 4.3.4
class spell_warr_last_stand : public SpellScriptLoader
{
public:
@@ -426,13 +379,14 @@ class spell_warr_last_stand : public SpellScriptLoader
{
if (Unit* caster = GetCaster())
{
- int32 healthModSpellBasePoints0 = int32(caster->CountPctFromMaxHealth(30));
+ int32 healthModSpellBasePoints0 = int32(caster->CountPctFromMaxHealth(GetEffectValue()));
caster->CastCustomSpell(caster, SPELL_WARRIOR_LAST_STAND_TRIGGERED, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
}
}
void Register()
{
+ // add dummy effect spell handler to Last Stand
OnEffectHit += SpellEffectFn(spell_warr_last_stand_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -558,7 +512,7 @@ class spell_warr_shattering_throw : public SpellScriptLoader
}
};
-// -1464 - Slam
+/// Updated 4.3.4
class spell_warr_slam : public SpellScriptLoader
{
public:
@@ -776,7 +730,6 @@ void AddSC_warrior_spell_scripts()
new spell_warr_bloodthirst_heal();
new spell_warr_charge();
new spell_warr_concussion_blow();
- new spell_warr_damage_shield();
new spell_warr_deep_wounds();
new spell_warr_execute();
new spell_warr_improved_spell_reflection();
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index a6e82f31914..23b1c5e22e9 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -76,7 +76,7 @@ public:
return false;
// error
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
return true;
}
};
@@ -119,7 +119,7 @@ public:
targets.GetUnitTarget()->GetEntry() == 20748 && !targets.GetUnitTarget()->HasAura(32578))
return false;
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
return true;
}
};
@@ -268,15 +268,13 @@ class item_petrov_cluster_bombs : public ItemScript
public:
item_petrov_cluster_bombs() : ItemScript("item_petrov_cluster_bombs") { }
- bool OnUse(Player* player, Item* item, const SpellCastTargets & /*targets*/)
+ bool OnUse(Player* player, Item* /*item*/, const SpellCastTargets & /*targets*/)
{
if (player->GetZoneId() != ZONE_ID_HOWLING)
return false;
if (!player->GetTransport() || player->GetAreaId() != AREA_ID_SHATTERED_STRAITS)
{
- player->SendEquipError(EQUIP_ERR_NONE, item, NULL);
-
if (const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(SPELL_PETROV_BOMB))
Spell::SendCastResult(player, spellInfo, 1, SPELL_FAILED_NOT_HERE);
@@ -381,7 +379,7 @@ public:
} else
player->SendEquipError(EQUIP_ERR_OUT_OF_RANGE, item, NULL);
} else
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
return true;
}
};
@@ -407,7 +405,7 @@ public:
player->SendEquipError(EQUIP_ERR_OUT_OF_RANGE, item, NULL);
}
else
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
return true;
}
};
diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp
index 0933d092f1f..c403fe74d12 100644
--- a/src/server/scripts/World/npc_professions.cpp
+++ b/src/server/scripts/World/npc_professions.cpp
@@ -214,7 +214,7 @@ int32 DoLowUnlearnCost(Player* player) //blacksmith
void ProcessCastaction(Player* player, Creature* creature, uint32 spellId, uint32 triggeredSpellId, int32 cost)
{
- if (!(spellId && player->HasSpell(spellId)) && player->HasEnoughMoney(cost))
+ if (!(spellId && player->HasSpell(spellId)) && player->HasEnoughMoney((int64)cost))
{
player->CastSpell(player, triggeredSpellId, true);
player->ModifyMoney(-cost);
@@ -352,11 +352,11 @@ void ProcessUnlearnAction(Player* player, Creature* creature, uint32 spellId, ui
{
if (EquippedOk(player, spellId))
{
- if (player->HasEnoughMoney(cost))
+ if (player->HasEnoughMoney(int64(cost)))
{
player->CastSpell(player, spellId, true);
ProfessionUnlearnSpells(player, spellId);
- player->ModifyMoney(-cost);
+ player->ModifyMoney(-int64(cost));
if (alternativeSpellId)
creature->CastSpell(player, alternativeSpellId, true);
}
@@ -364,7 +364,7 @@ void ProcessUnlearnAction(Player* player, Creature* creature, uint32 spellId, ui
player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, 0, 0);
}
else
- player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, NULL, NULL);
+ player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, NULL, NULL);
player->CLOSE_GOSSIP_MENU();
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 6bd2132bf16..960a3fce7cd 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -439,9 +439,6 @@ public:
me->Relocate(x, y, z + 0.94f);
me->SetDisableGravity(true);
me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE);
- WorldPacket data; //send update position to client
- me->BuildHeartBeatMsg(&data);
- me->SendMessageToSet(&data, true);
}
void UpdateAI(uint32 diff)
@@ -468,9 +465,6 @@ public:
me->SetInFront(player);
Active = false;
- WorldPacket data;
- me->BuildHeartBeatMsg(&data);
- me->SendMessageToSet(&data, true);
switch (emote)
{
case TEXT_EMOTE_KISS:
@@ -1298,7 +1292,7 @@ public:
case GOSSIP_OPTION_LEARNDUALSPEC:
if (player->GetSpecsCount() == 1 && !(player->getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)))
{
- if (!player->HasEnoughMoney(10000000))
+ if (!player->HasEnoughMoney(uint64(10000000)))
{
player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
player->PlayerTalkClass->SendCloseGossip();
@@ -1306,7 +1300,7 @@ public:
}
else
{
- player->ModifyMoney(-10000000);
+ player->ModifyMoney(int64(-10000000));
// Cast spells that teach dual spec
// Both are also ImplicitTarget self and must be cast by player
@@ -2562,11 +2556,11 @@ public:
}
if (doSwitch)
{
- if (!player->HasEnoughMoney(EXP_COST))
+ if (!player->HasEnoughMoney(uint64(EXP_COST)))
player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
else if (noXPGain)
{
- player->ModifyMoney(-EXP_COST);
+ player->ModifyMoney(-int64(EXP_COST));
player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
}
else if (!noXPGain)
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index 70ee32d2868..779eb95e291 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -181,6 +181,23 @@ LocaleConstant GetLocaleByName(const std::string& name);
typedef std::vector<std::string> StringVector;
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+struct LocalizedString
+{
+ char const* Str[TOTAL_LOCALES];
+};
+
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms)
#ifdef max
#undef max
diff --git a/src/server/shared/DataStores/DB2FileLoader.cpp b/src/server/shared/DataStores/DB2FileLoader.cpp
new file mode 100644
index 00000000000..7a27072dd20
--- /dev/null
+++ b/src/server/shared/DataStores/DB2FileLoader.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DB2FileLoader.h"
+
+DB2FileLoader::DB2FileLoader()
+{
+ data = NULL;
+ fieldsOffset = NULL;
+}
+
+bool DB2FileLoader::Load(const char *filename, const char *fmt)
+{
+ if (data)
+ {
+ delete [] data;
+ data = NULL;
+ }
+
+ FILE* f = fopen(filename, "rb");
+ if (!f)
+ return false;
+
+ uint32 header;
+ if (fread(&header, 4, 1, f) != 1) // Signature
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(header);
+
+ if (header != 0x32424457)
+ {
+ fclose(f);
+ return false; //'WDB2'
+ }
+
+ if (fread(&recordCount, 4, 1, f) != 1) // Number of records
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(recordCount);
+
+ if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(fieldCount);
+
+ if (fread(&recordSize, 4, 1, f) != 1) // Size of a record
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(recordSize);
+
+ if (fread(&stringSize, 4, 1, f) != 1) // String size
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(stringSize);
+
+ /* NEW WDB2 FIELDS*/
+ if (fread(&tableHash, 4, 1, f) != 1) // Table hash
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(tableHash);
+
+ if (fread(&build, 4, 1, f) != 1) // Build
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(build);
+
+ if (fread(&unk1, 4, 1, f) != 1) // Unknown WDB2
+ {
+ fclose(f);
+ return false;
+ }
+
+ EndianConvert(unk1);
+
+ if (build > 12880)
+ {
+ if (fread(&minIndex, 4, 1, f) != 1) // MinIndex WDB2
+ {
+ fclose(f);
+ return false;
+ }
+ EndianConvert(minIndex);
+
+ if (fread(&maxIndex, 4, 1, f) != 1) // MaxIndex WDB2
+ {
+ fclose(f);
+ return false;
+ }
+ EndianConvert(maxIndex);
+
+ if (fread(&locale, 4, 1, f) != 1) // Locales
+ {
+ fclose(f);
+ return false;
+ }
+ EndianConvert(locale);
+
+ if (fread(&unk5, 4, 1, f) != 1) // Unknown WDB2
+ {
+ fclose(f);
+ return false;
+ }
+ EndianConvert(unk5);
+ }
+
+ if (maxIndex != 0)
+ {
+ int32 diff = maxIndex - minIndex + 1;
+ fseek(f, diff * 4 + diff * 2, SEEK_CUR); // diff * 4: an index for rows, diff * 2: a memory allocation bank
+ }
+
+ fieldsOffset = new uint32[fieldCount];
+ fieldsOffset[0] = 0;
+ for (uint32 i = 1; i < fieldCount; i++)
+ {
+ fieldsOffset[i] = fieldsOffset[i - 1];
+ if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X')
+ fieldsOffset[i] += 1;
+ else
+ fieldsOffset[i] += 4;
+ }
+
+ data = new unsigned char[recordSize*recordCount+stringSize];
+ stringTable = data + recordSize*recordCount;
+
+ if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
+ {
+ fclose(f);
+ return false;
+ }
+
+ fclose(f);
+ return true;
+}
+
+DB2FileLoader::~DB2FileLoader()
+{
+ if (data)
+ delete [] data;
+ if (fieldsOffset)
+ delete [] fieldsOffset;
+}
+
+DB2FileLoader::Record DB2FileLoader::getRecord(size_t id)
+{
+ assert(data);
+ return Record(*this, data + id*recordSize);
+}
+
+uint32 DB2FileLoader::GetFormatRecordSize(const char * format, int32* index_pos)
+{
+ uint32 recordsize = 0;
+ int32 i = -1;
+ for (uint32 x=0; format[x]; ++x)
+ {
+ switch (format[x])
+ {
+ case FT_FLOAT:
+ case FT_INT:
+ recordsize += 4;
+ break;
+ case FT_STRING:
+ recordsize += sizeof(char*);
+ break;
+ case FT_SORT:
+ i = x;
+ break;
+ case FT_IND:
+ i = x;
+ recordsize += 4;
+ break;
+ case FT_BYTE:
+ recordsize += 1;
+ break;
+ }
+ }
+
+ if (index_pos)
+ *index_pos = i;
+
+ return recordsize;
+}
+
+uint32 DB2FileLoader::GetFormatStringsFields(const char * format)
+{
+ uint32 stringfields = 0;
+ for (uint32 x=0; format[x]; ++x)
+ if (format[x] == FT_STRING)
+ ++stringfields;
+
+ return stringfields;
+}
+
+char* DB2FileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable)
+{
+
+ typedef char * ptr;
+ if (strlen(format) != fieldCount)
+ return NULL;
+
+ //get struct size and index pos
+ int32 i;
+ uint32 recordsize=GetFormatRecordSize(format, &i);
+
+ if (i >= 0)
+ {
+ uint32 maxi = 0;
+ //find max index
+ for (uint32 y = 0; y < recordCount; y++)
+ {
+ uint32 ind=getRecord(y).getUInt(i);
+ if (ind>maxi)
+ maxi = ind;
+ }
+
+ ++maxi;
+ records = maxi;
+ indexTable = new ptr[maxi];
+ memset(indexTable, 0, maxi * sizeof(ptr));
+ }
+ else
+ {
+ records = recordCount;
+ indexTable = new ptr[recordCount];
+ }
+
+ char* dataTable = new char[recordCount * recordsize];
+
+ uint32 offset=0;
+
+ for (uint32 y =0; y < recordCount; y++)
+ {
+ if (i>=0)
+ {
+ indexTable[getRecord(y).getUInt(i)] = &dataTable[offset];
+ }
+ else
+ indexTable[y] = &dataTable[offset];
+
+ for (uint32 x = 0; x < fieldCount; x++)
+ {
+ switch (format[x])
+ {
+ case FT_FLOAT:
+ *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x);
+ offset += 4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x);
+ offset += 4;
+ break;
+ case FT_BYTE:
+ *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x);
+ offset += 1;
+ break;
+ case FT_STRING:
+ *((char**)(&dataTable[offset])) = NULL; // will be replaces non-empty or "" strings in AutoProduceStrings
+ offset += sizeof(char*);
+ break;
+ }
+ }
+ }
+
+ return dataTable;
+}
+
+static char const* const nullStr = "";
+
+char* DB2FileLoader::AutoProduceStringsArrayHolders(const char* format, char* dataTable)
+{
+ if (strlen(format) != fieldCount)
+ return NULL;
+
+ // we store flat holders pool as single memory block
+ size_t stringFields = GetFormatStringsFields(format);
+ // each string field at load have array of string for each locale
+ size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES;
+ size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize;
+ size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * recordCount;
+
+ char* stringHoldersPool = new char[stringHoldersPoolSize];
+
+ // DB2 strings expected to have at least empty string
+ for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i)
+ ((char const**)stringHoldersPool)[i] = nullStr;
+
+ uint32 offset=0;
+
+ // assign string holders to string field slots
+ for (uint32 y = 0; y < recordCount; y++)
+ {
+ uint32 stringFieldNum = 0;
+
+ for (uint32 x = 0; x < fieldCount; x++)
+ switch (format[x])
+ {
+ case FT_FLOAT:
+ case FT_IND:
+ case FT_INT:
+ offset += 4;
+ break;
+ case FT_BYTE:
+ offset += 1;
+ break;
+ case FT_STRING:
+ {
+ // init db2 string field slots by pointers to string holders
+ char const*** slot = (char const***)(&dataTable[offset]);
+ *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringHolderSize*stringFieldNum]);
+ ++stringFieldNum;
+ offset += sizeof(char*);
+ break;
+ }
+ case FT_NA:
+ case FT_NA_BYTE:
+ case FT_SORT:
+ break;
+ default:
+ assert(false && "unknown format character");
+ }
+ }
+
+ //send as char* for store in char* pool list for free at unload
+ return stringHoldersPool;
+}
+
+char* DB2FileLoader::AutoProduceStrings(const char* format, char* dataTable, uint32 locale)
+{
+ if (strlen(format) != fieldCount)
+ return NULL;
+
+ char* stringPool= new char[stringSize];
+ memcpy(stringPool, stringTable, stringSize);
+
+ uint32 offset = 0;
+
+ for (uint32 y =0; y < recordCount; y++)
+ {
+ for (uint32 x = 0; x < fieldCount; x++)
+ switch (format[x])
+ {
+ case FT_FLOAT:
+ case FT_IND:
+ case FT_INT:
+ offset += 4;
+ break;
+ case FT_BYTE:
+ offset += 1;
+ break;
+ case FT_STRING:
+ {
+ // fill only not filled entries
+ LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]);
+ if (db2str->Str[locale] == nullStr)
+ {
+ const char * st = getRecord(y).getString(x);
+ db2str->Str[locale] = stringPool + (st - (const char*)stringTable);
+ }
+
+ offset += sizeof(char*);
+ break;
+ }
+ }
+ }
+
+ return stringPool;
+}
diff --git a/src/server/shared/DataStores/DB2FileLoader.h b/src/server/shared/DataStores/DB2FileLoader.h
new file mode 100644
index 00000000000..86350ebf1d6
--- /dev/null
+++ b/src/server/shared/DataStores/DB2FileLoader.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DB2_FILE_LOADER_H
+#define DB2_FILE_LOADER_H
+
+#include "Define.h"
+#include "Utilities/ByteConverter.h"
+#include <cassert>
+
+class DB2FileLoader
+{
+ public:
+ DB2FileLoader();
+ ~DB2FileLoader();
+
+ bool Load(const char *filename, const char *fmt);
+
+ class Record
+ {
+ public:
+ float getFloat(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
+ EndianConvert(val);
+ return val;
+ }
+ uint32 getUInt(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
+ EndianConvert(val);
+ return val;
+ }
+ uint8 getUInt8(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
+ }
+
+ const char *getString(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ size_t stringOffset = getUInt(field);
+ assert(stringOffset < file.stringSize);
+ return reinterpret_cast<char*>(file.stringTable + stringOffset);
+ }
+
+ private:
+ Record(DB2FileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {}
+ unsigned char *offset;
+ DB2FileLoader &file;
+
+ friend class DB2FileLoader;
+ };
+
+ // Get record by id
+ Record getRecord(size_t id);
+ /// Get begin iterator over records
+
+ uint32 GetNumRows() const { return recordCount;}
+ uint32 GetCols() const { return fieldCount; }
+ uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
+ uint32 GetHash() const { return tableHash; }
+ bool IsLoaded() const { return (data != NULL); }
+ char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable);
+ char* AutoProduceStringsArrayHolders(const char* fmt, char* dataTable);
+ char* AutoProduceStrings(const char* fmt, char* dataTable, uint32 locale);
+ static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
+ static uint32 GetFormatStringsFields(const char * format);
+private:
+
+ uint32 recordSize;
+ uint32 recordCount;
+ uint32 fieldCount;
+ uint32 stringSize;
+ uint32 *fieldsOffset;
+ unsigned char *data;
+ unsigned char *stringTable;
+
+ // WDB2 / WCH2 fields
+ uint32 tableHash; // WDB2
+ uint32 build; // WDB2
+
+ int unk1; // WDB2 (Unix time in WCH2)
+ int minIndex; // WDB2
+ int maxIndex; // WDB2 (index table)
+ int locale; // WDB2
+ int unk5; // WDB2
+};
+
+#endif \ No newline at end of file
diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h
new file mode 100644
index 00000000000..77d6c4144e5
--- /dev/null
+++ b/src/server/shared/DataStores/DB2Store.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DB2STORE_H
+#define DB2STORE_H
+
+#include "DB2FileLoader.h"
+#include "Common.h"
+#include "ByteBuffer.h"
+#include <vector>
+
+/// Interface class for common access
+class DB2StorageBase
+{
+public:
+ virtual ~DB2StorageBase() { }
+
+ uint32 GetHash() const { return tableHash; }
+
+ virtual bool HasRecord(uint32 id) const = 0;
+
+ virtual void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const = 0;
+
+protected:
+ uint32 tableHash;
+};
+
+template<class T>
+class DB2Storage;
+
+template<class T>
+bool DB2StorageHasEntry(DB2Storage<T> const& store, uint32 id)
+{
+ return store.LookupEntry(id) != NULL;
+}
+
+template<class T>
+void WriteDB2RecordToPacket(DB2Storage<T> const& store, uint32 id, uint32 locale, ByteBuffer& buffer)
+{
+ uint8 const* entry = (uint8 const*)store.LookupEntry(id);
+ ASSERT(entry);
+
+ std::string format = store.GetFormat();
+ for (uint32 i = 0; i < format.length(); ++i)
+ {
+ switch (format[i])
+ {
+ case FT_IND:
+ case FT_INT:
+ buffer << *(uint32*)entry;
+ entry += 4;
+ break;
+ case FT_FLOAT:
+ buffer << *(float*)entry;
+ entry += 4;
+ break;
+ case FT_BYTE:
+ buffer << *(uint8*)entry;
+ entry += 1;
+ break;
+ case FT_STRING:
+ {
+ LocalizedString* locStr = *(LocalizedString**)entry;
+ if (locStr->Str[locale][0] == '\0')
+ locale = 0;
+
+ char const* str = locStr->Str[locale];
+ size_t len = strlen(str);
+ buffer << uint16(len);
+ if (len)
+ buffer << str;
+ entry += sizeof(char*);
+ break;
+ }
+ case FT_NA:
+ case FT_SORT:
+ buffer << uint32(0);
+ break;
+ case FT_NA_BYTE:
+ buffer << uint8(0);
+ break;
+ }
+ }
+}
+
+template<class T>
+class DB2Storage : public DB2StorageBase
+{
+ typedef std::list<char*> StringPoolList;
+ typedef std::vector<T*> DataTableEx;
+ typedef bool(*EntryChecker)(DB2Storage<T> const&, uint32);
+ typedef void(*PacketWriter)(DB2Storage<T> const&, uint32, uint32, ByteBuffer&);
+public:
+ DB2Storage(char const* f, EntryChecker checkEntry = NULL, PacketWriter writePacket = NULL) :
+ nCount(0), fieldCount(0), fmt(f), m_dataTable(NULL)
+ {
+ indexTable.asT = NULL;
+ CheckEntry = checkEntry ? checkEntry : (EntryChecker)&DB2StorageHasEntry<T>;
+ WritePacket = writePacket ? writePacket : (PacketWriter)&WriteDB2RecordToPacket<T>;
+ }
+
+ ~DB2Storage() { Clear(); }
+
+ bool HasRecord(uint32 id) const { return CheckEntry(*this, id); }
+ T const* LookupEntry(uint32 id) const { return (id >= nCount) ? NULL : indexTable.asT[id]; }
+ uint32 GetNumRows() const { return nCount; }
+ char const* GetFormat() const { return fmt; }
+ uint32 GetFieldCount() const { return fieldCount; }
+ void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const
+ {
+ WritePacket(*this, id, locale, buffer);
+ }
+
+ T* CreateEntry(uint32 id, bool evenIfExists = false)
+ {
+ if (evenIfExists && LookupEntry(id))
+ return NULL;
+
+ if (id >= nCount)
+ {
+ // reallocate index table
+ char** tmpIdxTable = new char*[id + 1];
+ memset(tmpIdxTable, 0, (id + 1) * sizeof(char*));
+ memcpy(tmpIdxTable, indexTable.asChar, nCount * sizeof(char*));
+ delete[] reinterpret_cast<char*>(indexTable.asT);
+ nCount = id + 1;
+ indexTable.asChar = tmpIdxTable;
+ }
+
+ T* entryDst = new T;
+ m_dataTableEx.push_back(entryDst);
+ indexTable.asT[id] = entryDst;
+ return entryDst;
+ }
+
+ void EraseEntry(uint32 id) { indexTable.asT[id] = NULL; }
+
+ bool Load(char const* fn, uint32 locale)
+ {
+ DB2FileLoader db2;
+ // Check if load was sucessful, only then continue
+ if (!db2.Load(fn, fmt))
+ return false;
+
+ fieldCount = db2.GetCols();
+ tableHash = db2.GetHash();
+
+ // load raw non-string data
+ m_dataTable = reinterpret_cast<T*>(db2.AutoProduceData(fmt, nCount, indexTable.asChar));
+
+ // create string holders for loaded string fields
+ m_stringPoolList.push_back(db2.AutoProduceStringsArrayHolders(fmt, (char*)m_dataTable));
+
+ // load strings from dbc data
+ m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable, locale));
+
+ // error in dbc file at loading if NULL
+ return indexTable.asT != NULL;
+ }
+
+ bool LoadStringsFrom(char const* fn, uint32 locale)
+ {
+ // DBC must be already loaded using Load
+ if (!indexTable.asT)
+ return false;
+
+ DB2FileLoader db2;
+ // Check if load was successful, only then continue
+ if (!db2.Load(fn, fmt))
+ return false;
+
+ // load strings from another locale dbc data
+ m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable, locale));
+
+ return true;
+ }
+
+ void Clear()
+ {
+ if (!indexTable.asT)
+ return;
+
+ delete[] reinterpret_cast<char*>(indexTable.asT);
+ indexTable.asT = NULL;
+
+ delete[] reinterpret_cast<char*>(m_dataTable);
+ m_dataTable = NULL;
+
+ for (typename DataTableEx::iterator itr = m_dataTableEx.begin(); itr != m_dataTableEx.end(); ++itr)
+ delete *itr;
+ m_dataTableEx.clear();
+
+ while (!m_stringPoolList.empty())
+ {
+ delete[] m_stringPoolList.front();
+ m_stringPoolList.pop_front();
+ }
+
+ nCount = 0;
+ }
+
+ EntryChecker CheckEntry;
+ PacketWriter WritePacket;
+
+private:
+ uint32 nCount;
+ uint32 fieldCount;
+ char const* fmt;
+ union
+ {
+ T** asT;
+ char** asChar;
+ } indexTable;
+ T* m_dataTable;
+ DataTableEx m_dataTableEx;
+ StringPoolList m_stringPoolList;
+};
+
+#endif
diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp
index 5e82579d29d..3a61057510e 100644
--- a/src/server/shared/DataStores/DBCFileLoader.cpp
+++ b/src/server/shared/DataStores/DBCFileLoader.cpp
@@ -157,9 +157,6 @@ uint32 DBCFileLoader::GetFormatRecordSize(const char* format, int32* index_pos)
case FT_NA:
case FT_NA_BYTE:
break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
default:
ASSERT(false && "Unknown field format character in DBCfmt.h");
break;
@@ -251,9 +248,6 @@ char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**
*((char**)(&dataTable[offset])) = NULL; // will replace non-empty or "" strings in AutoProduceStrings
offset += sizeof(char*);
break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
case FT_NA:
case FT_NA_BYTE:
case FT_SORT:
@@ -308,9 +302,6 @@ char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable)
offset += sizeof(char*);
break;
}
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
case FT_NA:
case FT_NA_BYTE:
case FT_SORT:
diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h
index 1756b635635..884418f6896 100644
--- a/src/server/shared/DataStores/DBCFileLoader.h
+++ b/src/server/shared/DataStores/DBCFileLoader.h
@@ -22,21 +22,6 @@
#include "Utilities/ByteConverter.h"
#include <cassert>
-enum
-{
- FT_NA='x', //not used or unknown, 4 byte size
- FT_NA_BYTE='X', //not used or unknown, byte
- FT_STRING='s', //char*
- FT_FLOAT='f', //float
- FT_INT='i', //uint32
- FT_BYTE='b', //uint8
- FT_SORT='d', //sorted by this field, field is not included
- FT_IND='n', //the same, but parsed to data
- FT_LOGIC='l', //Logical (boolean)
- FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc
- FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
-};
-
class DBCFileLoader
{
public:
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index fdbf0f2bb01..1ddd790cc46 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -20,7 +20,7 @@
#define DBCSTORE_H
#include "DBCFileLoader.h"
-#include "Logging/Log.h"
+#include "Log.h"
#include "Field.h"
#include "DatabaseWorkerPool.h"
#include "Implementation/WorldDatabase.h"
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 427ccfd5ebf..23e9d09eb1d 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -43,14 +43,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
- "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid "
+ "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
- "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
+ "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
- "cb.guid, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
+ "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
- "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
+ "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
@@ -73,9 +73,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// Start LoginQueryHolder content
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
- "resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
- "arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, "
- "health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels "
+ "resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
+ "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
+ "health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels "
"FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
@@ -113,7 +113,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, "
"item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, spec FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_RANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
@@ -181,7 +181,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// 0: uint32, 1: uint8, 3: string, 4: uint32
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
- PrepareStatement(CHAR_DEL_GUILD_LOWEST_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid >= ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_DEL_GUILD_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_INS_GUILD_BANK_TAB, "INSERT INTO guild_bank_tab (guildid, TabId) VALUES (?, ?)", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_DEL_GUILD_BANK_TAB, "DELETE FROM guild_bank_tab WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_DEL_GUILD_BANK_TABS, "DELETE FROM guild_bank_tab WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
@@ -221,12 +221,24 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_GUILD_BANK_TAB_TEXT, "UPDATE guild_bank_tab SET TabText = ? WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: string, 1: uint32, 2: uint8
PrepareStatement(CHAR_INS_GUILD_MEMBER_WITHDRAW,
- "INSERT INTO guild_member_withdraw (guid, tab0, tab1, tab2, tab3, tab4, tab5, money) VALUES (?, ?, ?, ?, ?, ?, ?, ?) "
- "ON DUPLICATE KEY UPDATE tab0 = VALUES (tab0), tab1 = VALUES (tab1), tab2 = VALUES (tab2), tab3 = VALUES (tab3), tab4 = VALUES (tab4), tab5 = VALUES (tab5)", CONNECTION_ASYNC);
+ "INSERT INTO guild_member_withdraw (guid, tab0, tab1, tab2, tab3, tab4, tab5, tab6, tab7, money) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
+ "ON DUPLICATE KEY UPDATE tab0 = VALUES (tab0), tab1 = VALUES (tab1), tab2 = VALUES (tab2), tab3 = VALUES (tab3), tab4 = VALUES (tab4), tab5 = VALUES (tab5), tab6 = VALUES (tab6), tab7 = VALUES (tab7), money = VALUES (money)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_MEMBER_WITHDRAW, "TRUNCATE guild_member_withdraw", CONNECTION_ASYNC);
// 0: uint32, 1: uint32, 2: uint32
PrepareStatement(CHAR_SEL_CHAR_DATA_FOR_GUILD, "SELECT name, level, class, zone, account FROM characters WHERE guid = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_DEL_GUILD_ACHIEVEMENT, "DELETE FROM guild_achievement WHERE guildId = ? AND achievement = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_ACHIEVEMENT, "INSERT INTO guild_achievement (guildId, achievement, date, guids) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ? AND criteria = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA, "INSERT INTO guild_achievement_progress (guildId, criteria, counter, date, completedGuid) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS, "DELETE FROM guild_achievement WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT, "SELECT achievement, date, guids FROM guild_achievement WHERE guildId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA, "SELECT criteria, counter, date, completedGuid FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_UPD_GUILD_EXPERIENCE, "UPDATE guild SET level = ?, experience = ?, todayExperience = ? WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE, "UPDATE guild SET todayExperience = 0", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_NEWS, "INSERT INTO guild_newslog (guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)"
+ " ON DUPLICATE KEY UPDATE LogGuid = VALUES (LogGuid), EventType = VALUES (EventType), PlayerGuid = VALUES (PlayerGuid), Flags = VALUES (Flags), Value = VALUES (Value), Timestamp = VALUES (Timestamp)", CONNECTION_ASYNC);
// Chat channel handling
PrepareStatement(CHAR_SEL_CHANNEL, "SELECT announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH);
@@ -249,6 +261,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, caster_guid, item_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ // Currency
+ PrepareStatement(CHAR_SEL_PLAYER_CURRENCY, "SELECT currency, week_count, total_count FROM character_currency WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_PLAYER_CURRENCY, "UPDATE character_currency SET week_count = ?, total_count = ? WHERE guid = ? AND currency = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_PLAYER_CURRENCY, "REPLACE INTO character_currency (guid, currency, week_count, total_count) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
+
// Account data
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_REP_ACCOUNT_DATA, "REPLACE INTO account_data (accountId, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
@@ -314,8 +331,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PLAYER_HOMEBIND, "DELETE FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
// Corpse
- PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH);
- PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE corpseGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PLAYER_CORPSES, "DELETE FROM corpse WHERE guid = ? AND corpseType <> 0", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC);
@@ -355,18 +372,18 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
"map, instance_id, instance_mode_mask, position_x, position_y, position_z, orientation, "
"taximask, cinematic, "
- "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, "
+ "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, talentTree, "
"extra_flags, stable_slots, at_login, zone, "
- "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, "
- "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, "
- "power4, power5, power6, power7, latency, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels) VALUES "
- "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
+ "death_expire_time, taxi_path, totalKills, "
+ "todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
+ "power4, power5, latency, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,playerBytes=?,playerBytes2=?,playerFlags=?,"
"map=?,instance_id=?,instance_mode_mask=?,position_x=?,position_y=?,position_z=?,orientation=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
- "logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
- "arenaPoints=?,totalHonorPoints=?,todayHonorPoints=?,yesterdayHonorPoints=?,totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,knownCurrencies=?,"
- "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,power6=?,power7=?,latency=?,speccount=?,activespec=?,exploredZones=?,"
- "equipmentCache=?,ammoId=?,knownTitles=?,actionBars=?,grantableLevels=?,online=? WHERE guid=?", CONNECTION_ASYNC);
+ "logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,talentTree=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
+ "totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,"
+ "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,latency=?,speccount=?,activespec=?,exploredZones=?,"
+ "equipmentCache=?,knownTitles=?,actionBars=?,grantableLevels=?,online=? WHERE guid=?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
@@ -393,6 +410,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_ZONE, "UPDATE characters SET zone = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_LEVEL, "UPDATE characters SET level = ?, xp = 0 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM character_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD, "DELETE FROM guild_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_ACHIEVMENT, "DELETE FROM character_achievement WHERE achievement = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ADDON, "INSERT INTO addons (name, crc) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_PET_SPELL, "DELETE FROM pet_spell WHERE spell = ?", CONNECTION_ASYNC);
@@ -460,7 +478,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS, "DELETE FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_REPUTATION_BY_FACTION, "DELETE FROM character_reputation WHERE guid = ? AND faction = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION, "INSERT INTO character_reputation (guid, faction, standing, flags) VALUES (?, ?, ? , ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = (arenaPoints + ?) WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ITEM_REFUND_INSTANCE, "DELETE FROM item_refund_instance WHERE item_guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ITEM_REFUND_INSTANCE, "INSERT INTO item_refund_instance (item_guid, player_guid, paidMoney, paidExtendedCost) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GROUP, "DELETE FROM groups WHERE guid = ?", CONNECTION_ASYNC);
@@ -515,8 +532,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_TALENT, "DELETE FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILLS, "DELETE FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_HONOR_POINTS, "UPDATE characters SET totalHonorPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UDP_CHAR_MONEY, "UPDATE characters SET money = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_ACTION, "INSERT INTO character_action (guid, spec, button, action, type) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_ACTION, "UPDATE character_action SET action = ?, type = ? WHERE guid = ? AND button = ? AND spec = ?", CONNECTION_ASYNC);
@@ -536,17 +551,34 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UDP_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SPELL, "INSERT INTO character_spell (guid, spell, active, disabled) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_STATS, "DELETE FROM character_stats WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, strength, agility, stamina, intellect, spirit, "
+ PrepareStatement(CHAR_INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, strength, agility, stamina, intellect, spirit, "
"armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, "
- "spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ "spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER, "DELETE FROM petition WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER_AND_TYPE, "DELETE FROM petition WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER_AND_TYPE, "DELETE FROM petition_sign WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs VALUES(?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs (guid, spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and spell = ? and spec = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, spell, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ?", CONNECTION_ASYNC);
+
+ // Void Storage
+ PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomProperty, suffixFactor) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?", CONNECTION_ASYNC);
+
+ // CompactUnitFrame profiles
+ PrepareStatement(CHAR_SEL_CHAR_CUF_PROFILES, "SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_CHAR_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?", CONNECTION_ASYNC);
+
+ // Guild Finder
+ PrepareStatement(CHAR_REP_GUILD_FINDER_APPLICANT, "REPLACE INTO guild_finder_applicant (guildId, playerGuid, availability, classRole, interests, comment, submitTime) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_FINDER_APPLICANT, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS, "REPLACE INTO guild_finder_guild_settings (guildId, availability, classRoles, interests, level, listed, comment) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?", CONNECTION_ASYNC);
// Items that hold loot or money
PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, rnd_suffix FROM item_loot_items WHERE container_id = ?", CONNECTION_SYNCH);
@@ -586,10 +618,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_PET_SPELL, "INSERT INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, "
"base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_OWNER, "DELETE FROM character_pet WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_PET_NAME, "UPDATE character_pet SET name = ?, renamed = 1 WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ? AND id <> ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index f97dd63064d..53c309f9ba0 100644..100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -173,7 +173,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_GUILD_MEMBERS,
CHAR_INS_GUILD_RANK,
CHAR_DEL_GUILD_RANKS,
- CHAR_DEL_GUILD_LOWEST_RANK,
+ CHAR_DEL_GUILD_RANK,
CHAR_INS_GUILD_BANK_TAB,
CHAR_DEL_GUILD_BANK_TAB,
CHAR_DEL_GUILD_BANK_TABS,
@@ -206,6 +206,17 @@ enum CharacterDatabaseStatements
CHAR_INS_GUILD_MEMBER_WITHDRAW,
CHAR_DEL_GUILD_MEMBER_WITHDRAW,
CHAR_SEL_CHAR_DATA_FOR_GUILD,
+ CHAR_DEL_GUILD_ACHIEVEMENT,
+ CHAR_INS_GUILD_ACHIEVEMENT,
+ CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_DEL_ALL_GUILD_ACHIEVEMENTS,
+ CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_SEL_GUILD_ACHIEVEMENT,
+ CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_UPD_GUILD_EXPERIENCE,
+ CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE,
+ CHAR_INS_GUILD_NEWS,
CHAR_SEL_CHANNEL,
CHAR_INS_CHANNEL,
@@ -220,6 +231,10 @@ enum CharacterDatabaseStatements
CHAR_INS_AURA,
+ CHAR_SEL_PLAYER_CURRENCY,
+ CHAR_UPD_PLAYER_CURRENCY,
+ CHAR_REP_PLAYER_CURRENCY,
+
CHAR_SEL_ACCOUNT_DATA,
CHAR_REP_ACCOUNT_DATA,
CHAR_DEL_ACCOUNT_DATA,
@@ -330,6 +345,7 @@ enum CharacterDatabaseStatements
CHAR_UPD_ZONE,
CHAR_UPD_LEVEL,
CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA,
+ CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD,
CHAR_DEL_INVALID_ACHIEVMENT,
CHAR_INS_ADDON,
CHAR_DEL_INVALID_PET_SPELL,
@@ -396,7 +412,6 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS,
CHAR_DEL_CHAR_REPUTATION_BY_FACTION,
CHAR_INS_CHAR_REPUTATION_BY_FACTION,
- CHAR_UPD_CHAR_ARENA_POINTS,
CHAR_DEL_ITEM_REFUND_INSTANCE,
CHAR_INS_ITEM_REFUND_INSTANCE,
CHAR_DEL_GROUP,
@@ -451,8 +466,6 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_QUESTSTATUS_DAILY,
CHAR_DEL_CHAR_TALENT,
CHAR_DEL_CHAR_SKILLS,
- CHAR_UDP_CHAR_HONOR_POINTS,
- CHAR_UDP_CHAR_ARENA_POINTS,
CHAR_UDP_CHAR_MONEY,
CHAR_INS_CHAR_ACTION,
CHAR_UPD_CHAR_ACTION,
@@ -481,6 +494,20 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC,
CHAR_INS_CHAR_TALENT,
CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC,
+ CHAR_UPD_CHAR_LIST_SLOT,
+
+ CHAR_SEL_CHAR_VOID_STORAGE,
+ CHAR_REP_CHAR_VOID_STORAGE_ITEM,
+ CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
+
+ CHAR_SEL_CHAR_CUF_PROFILES,
+ CHAR_REP_CHAR_CUF_PROFILES,
+ CHAR_DEL_CHAR_CUF_PROFILES,
+
+ CHAR_REP_GUILD_FINDER_APPLICANT,
+ CHAR_DEL_GUILD_FINDER_APPLICANT,
+ CHAR_REP_GUILD_FINDER_GUILD_SETTINGS,
+ CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS,
CHAR_REP_CALENDAR_EVENT,
CHAR_DEL_CALENDAR_EVENT,
diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp
index a36023a23b0..75bafb571e9 100644
--- a/src/server/shared/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp
@@ -34,9 +34,9 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM game_graveyard_zone WHERE id = ? AND ghost_zone = ? AND faction = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GAME_TELE, "INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?", CONNECTION_ASYNC);
- PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ?", CONNECTION_ASYNC);
- PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = ? ORDER BY slot ASC", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost, type) VALUES(?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ? AND type = ?", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor WHERE entry = ? AND type = ? ORDER BY slot ASC", CONNECTION_SYNCH);
PrepareStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE, "UPDATE creature SET MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_FACTION, "UPDATE creature_template SET faction_A = ?, faction_H = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_NPCFLAG, "UPDATE creature_template SET npcflag = ? WHERE entry = ?", CONNECTION_ASYNC);
@@ -78,7 +78,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_INS_CREATURE_TRANSPORT, "INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_TRANSPORT_EMOTE, "UPDATE creature_transport SET emote = ? WHERE transport_entry = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h
index 682167a96e3..ab3a743315d 100644
--- a/src/server/shared/Define.h
+++ b/src/server/shared/Define.h
@@ -87,4 +87,18 @@ typedef ACE_UINT32 uint32;
typedef ACE_UINT16 uint16;
typedef ACE_UINT8 uint8;
+enum DBCFormer
+{
+ FT_NA='x', //not used or unknown, 4 byte size
+ FT_NA_BYTE='X', //not used or unknown, byte
+ FT_STRING='s', //char*
+ FT_FLOAT='f', //float
+ FT_INT='i', //uint32
+ FT_BYTE='b', //uint8
+ FT_SORT='d', //sorted by this field, field is not included
+ FT_IND='n', //the same, but parsed to data
+ FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc
+ FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
+};
+
#endif //TRINITY_DEFINE_H
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 7777842af17..51b1a615bf1 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -68,19 +68,19 @@ class ByteBuffer
const static size_t DEFAULT_SIZE = 0x1000;
// constructor
- ByteBuffer() : _rpos(0), _wpos(0)
+ ByteBuffer() : _rpos(0), _wpos(0), _bitpos(8), _curbitval(0)
{
_storage.reserve(DEFAULT_SIZE);
}
- ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
+ ByteBuffer(size_t reserve) : _rpos(0), _wpos(0), _bitpos(8), _curbitval(0)
{
_storage.reserve(reserve);
}
// copy constructor
ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos),
- _storage(buf._storage)
+ _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf._storage)
{
}
@@ -92,16 +92,115 @@ class ByteBuffer
template <typename T> void append(T value)
{
+ FlushBits();
EndianConvert(value);
append((uint8 *)&value, sizeof(value));
}
+ void FlushBits()
+ {
+ if (_bitpos == 8)
+ return;
+
+ append((uint8 *)&_curbitval, sizeof(uint8));
+ _curbitval = 0;
+ _bitpos = 8;
+ }
+
+ bool WriteBit(uint32 bit)
+ {
+ --_bitpos;
+ if (bit)
+ _curbitval |= (1 << (_bitpos));
+
+ if (_bitpos == 0)
+ {
+ _bitpos = 8;
+ append((uint8 *)&_curbitval, sizeof(_curbitval));
+ _curbitval = 0;
+ }
+
+ return (bit != 0);
+ }
+
+ bool ReadBit()
+ {
+ ++_bitpos;
+ if (_bitpos > 7)
+ {
+ _bitpos = 0;
+ _curbitval = read<uint8>();
+ }
+
+ return ((_curbitval >> (7-_bitpos)) & 1) != 0;
+ }
+
+ template <typename T> void WriteBits(T value, size_t bits)
+ {
+ for (int32 i = bits-1; i >= 0; --i)
+ WriteBit((value >> i) & 1);
+ }
+
+ uint32 ReadBits(size_t bits)
+ {
+ uint32 value = 0;
+ for (int32 i = bits-1; i >= 0; --i)
+ if (ReadBit())
+ value |= (1 << (i));
+
+ return value;
+ }
+
+ // Reads a byte (if needed) in-place
+ void ReadByteSeq(uint8& b)
+ {
+ if (b != 0)
+ b ^= read<uint8>();
+ }
+
+ void WriteByteSeq(uint8 b)
+ {
+ if (b != 0)
+ append<uint8>(b ^ 1);
+ }
+
template <typename T> void put(size_t pos, T value)
{
EndianConvert(value);
put(pos, (uint8 *)&value, sizeof(value));
}
+ /**
+ * @name PutBits
+ * @brief Places specified amount of bits of value at specified position in packet.
+ * To ensure all bits are correctly written, only call this method after
+ * bit flush has been performed
+
+ * @param pos Position to place the value at, in bits. The entire value must fit in the packet
+ * It is advised to obtain the position using bitwpos() function.
+
+ * @param value Data to write.
+ * @param bitCount Number of bits to store the value on.
+ */
+ template <typename T> void PutBits(size_t pos, T value, uint32 bitCount)
+ {
+ if (!bitCount)
+ throw ByteBufferSourceException((pos + bitCount) / 8, size(), 0);
+
+ if (pos + bitCount > size() * 8)
+ throw ByteBufferPositionException(false, (pos + bitCount) / 8, size(), (bitCount - 1) / 8 + 1);
+
+ for (uint32 i = 0; i < bitCount; ++i)
+ {
+ size_t wp = (pos + i) / 8;
+ size_t bit = (pos + i) % 8;
+ if ((value >> (bitCount - i - 1)) & 1)
+ _storage[wp] |= 1 << (7 - bit);
+ else
+ _storage[wp] &= ~(1 << (7 - bit));
+ }
+ }
+
ByteBuffer &operator<<(uint8 value)
{
append<uint8>(value);
@@ -295,6 +394,16 @@ class ByteBuffer
return _wpos;
}
+ /// Returns position of last written bit
+ size_t bitwpos() const { return _wpos * 8 + 8 - _bitpos; }
+
+ size_t bitwpos(size_t newPos)
+ {
+ _wpos = newPos / 8;
+ _bitpos = 8 - (newPos % 8);
+ return _wpos * 8 + 8 - _bitpos;
+ }
+
template<typename T>
void read_skip() { read_skip(sizeof(T)); }
@@ -353,6 +462,25 @@ class ByteBuffer
}
}
+ std::string ReadString(uint32 length)
+ {
+ if (!length)
+ return std::string();
+ char* buffer = new char[length + 1]();
+ read((uint8*)buffer, length);
+ std::string retval = buffer;
+ delete[] buffer;
+ return retval;
+ }
+
+ //! Method for writing strings that have their length sent separately in packet
+ //! without null-terminating the string
+ void WriteString(std::string const& str)
+ {
+ if (size_t len = str.length())
+ append(str.c_str(), len);
+ }
+
uint32 ReadPackedTime()
{
uint32 packedDate = read<uint32>();
@@ -479,7 +607,8 @@ class ByteBuffer
void hexlike() const;
protected:
- size_t _rpos, _wpos;
+ size_t _rpos, _wpos, _bitpos;
+ uint8 _curbitval;
std::vector<uint8> _storage;
};
diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp
index 1bba3c2db09..32ff396e1c1 100644
--- a/src/server/shared/Utilities/Util.cpp
+++ b/src/server/shared/Utilities/Util.cpp
@@ -150,9 +150,9 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
return ss.str();
}
-int32 MoneyStringToMoney(const std::string& moneyString)
+int64 MoneyStringToMoney(const std::string& moneyString)
{
- int32 money = 0;
+ int64 money = 0;
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
@@ -169,7 +169,7 @@ int32 MoneyStringToMoney(const std::string& moneyString)
if (gCount + sCount + cCount != 1)
return 0;
- uint32 amount = atoi(*itr);
+ uint64 amount = atol(*itr);
if (gCount == 1)
money += amount * 100 * 100;
else if (sCount == 1)
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index a379bfd32fc..5d1ce862d21 100644
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -67,7 +67,7 @@ private:
void stripLineInvisibleChars(std::string &src);
-int32 MoneyStringToMoney(const std::string& moneyString);
+int64 MoneyStringToMoney(const std::string& moneyString);
std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
uint32 TimeStringToSecs(const std::string& timestring);
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index 17c9d596568..e461a019af5 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -72,7 +72,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Addons
${CMAKE_SOURCE_DIR}/src/server/game/AI
${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI
- ${CMAKE_SOURCE_DIR}/src/server/game/AI/EventAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
@@ -87,6 +86,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/DataStores
${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding
${CMAKE_SOURCE_DIR}/src/server/game/Entities
+ ${CMAKE_SOURCE_DIR}/src/server/game/Entities/AreaTrigger
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse
${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject
@@ -116,6 +116,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous
${CMAKE_SOURCE_DIR}/src/server/game/Movement
${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators
+ ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline
${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints
${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP
${CMAKE_SOURCE_DIR}/src/server/game/Pools
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 9577b3d841f..ac52c95202e 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -28,6 +28,7 @@
# CHARACTER DELETE OPTIONS
# CUSTOM SERVER OPTIONS
# LOGGING SYSTEM SETTINGS
+# CURRENCIES SETTINGS
#
###################################################################################################
@@ -579,8 +580,7 @@ StrictPetNames = 0
#
# DBC.Locale
# Description: DBC language settings.
-# Default: 255 - (Auto Detect)
-# 0 - (English)
+# Default: 0 - (English)
# 1 - (Korean)
# 2 - (French)
# 3 - (German)
@@ -590,7 +590,7 @@ StrictPetNames = 0
# 7 - (Spanish Mexico)
# 8 - (Russian)
-DBC.Locale = 255
+DBC.Locale = 0
#
# DeclinedNames
@@ -604,11 +604,12 @@ DeclinedNames = 0
# Expansion
# Description: Allow server to use content from expansions. Checks for expansion-related
# map files, client compatibility and class/race character creation.
-# Default: 2 - (Expansion 2)
+# Default: 3 - (Expansion 3)
+# 2 - (Expansion 2)
# 1 - (Expansion 1)
# 0 - (Disabled, Ignore and disable expansion content (maps, races, classes)
-Expansion = 2
+Expansion = 3
#
# MinPlayerName
@@ -735,16 +736,16 @@ SkipCinematics = 0
# Description: Maximum level that can be reached by players.
# Important: Levels beyond 100 are not recommended at all.
# Range: 1-255
-# Default: 80
+# Default: 85
-MaxPlayerLevel = 80
+MaxPlayerLevel = 85
#
# MinDualSpecLevel
# Description: Level requirement for Dual Talent Specialization
-# Default: 40
+# Default: 30
-MinDualSpecLevel = 40
+MinDualSpecLevel = 30
#
# StartPlayerLevel
@@ -771,40 +772,12 @@ StartHeroicPlayerLevel = 55
StartPlayerMoney = 0
#
-# MaxHonorPoints
-# Description: Maximum honor points a character can have.
-# Default: 75000
-
-MaxHonorPoints = 75000
-
-#
-# StartHonorPoints
-# Description: Amount of honor points that characters have after creation.
-# Default: 0
-
-StartHonorPoints = 0
-
-#
-# MaxArenaPoints
-# Description: Maximum arena points a character can have.
-# Default: 10000
-
-MaxArenaPoints = 10000
-
-#
-# StartArenaPoints
-# Description: Amount of arena points that characters has after creation.
-# Default: 0
-
-StartArenaPoints = 0
-
-#
# RecruitAFriend.MaxLevel
# Description: Highest level up to which a character can benefit from the Recruit-A-Friend
# experience multiplier.
-# Default: 60
+# Default: 80
-RecruitAFriend.MaxLevel = 60
+RecruitAFriend.MaxLevel = 80
#
# RecruitAFriend.MaxDifference
@@ -843,15 +816,6 @@ AllFlightPaths = 0
InstantFlightPaths = 0
#
-# AlwaysMaxSkillForLevel
-# Description: Players will automatically gain max skill level when logging in or leveling
-# up.
-# Default: 0 - (Disabled)
-# 1 - (Enabled)
-
-AlwaysMaxSkillForLevel = 0
-
-#
# ActivateWeather
# Description: Activate the weather system.
# Default: 1 - (Enabled)
@@ -974,6 +938,16 @@ Guild.ResetHour = 6
Guild.BankEventLogRecordsCount = 25
#
+# Guild.NewsLogRecordsCount
+# Description: Number of log entries for guild news that are stored per guild. Old
+# entries will be overwritten if the number of log entries exceed the
+# configured value. High numbers prevent this behavior but may have performance
+# impacts.
+# Default: 250
+
+Guild.NewsLogRecordsCount = 250
+
+#
# MaxPrimaryTradeSkill
# Description: Maximum number of primary professions a character can learn.
# Range: 0-10
@@ -984,10 +958,10 @@ MaxPrimaryTradeSkill = 2
#
# MinPetitionSigns
# Description: Number of required signatures on charters to create a guild.
-# Range: 0-9
-# Default: 9
+# Range: 0-4
+# Default: 4
-MinPetitionSigns = 9
+MinPetitionSigns = 4
#
# MaxGroupXPDistance
@@ -1873,19 +1847,13 @@ Rate.InstanceResetTime = 1
#
# SkillGain.Crafting
-# SkillGain.Defense
# SkillGain.Gathering
-# SkillGain.Weapon
# Description: Crafting/defense/gathering/weapon skills gain rate.
# Default: 1 - (SkillGain.Crafting)
-# 1 - (SkillGain.Defense)
# 1 - (SkillGain.Gathering)
-# 1 - (SkillGain.Weapon)
SkillGain.Crafting = 1
-SkillGain.Defense = 1
SkillGain.Gathering = 1
-SkillGain.Weapon = 1
#
# SkillChance.Orange
@@ -2791,3 +2759,151 @@ Log.Async.Enable = 0
#
###################################################################################################
+
+###################################################################################################
+#
+# GUILD LEVELING SETTINGS
+#
+# Guild.LevelingEnabled
+# Description: Controls whether guild can gain levels
+# Default: 1
+#
+
+Guild.LevelingEnabled = 1
+
+#
+# Guild.SaveInterval
+# Description: Time (in minutes) between guild experience saves
+# Default: 15
+#
+
+Guild.SaveInterval = 15
+
+#
+# Guild.MaxLevel
+# Description: Defines max level a guild can reach
+# Default: 25
+#
+
+Guild.MaxLevel = 25
+
+#
+# Guild.UndeletableLevel
+# Description: Guild reaching this level (and higher) cannot be disbanded anymore
+# Default: 4
+#
+
+Guild.UndeletableLevel = 4
+
+#
+# Guild.XPModifier
+# Description: Multiplier for guild experience gained from quests
+# Default: 0.25
+#
+
+Guild.XPModifier = 0.25
+
+#
+# Guild.DailyXPCap
+# Description: Maximum experience points a guild can earn each day
+# Default: 7807500
+#
+
+Guild.DailyXPCap = 7807500
+
+#
+# Guild.WeeklyReputationCap
+# Description: Maximum guild reputation a player can earn every week
+# Default: 4375
+#
+
+Guild.WeeklyReputationCap = 4375
+
+#
+###################################################################################################
+
+###################################################################################################
+#
+# CURRENCIES SETTINGS
+#
+# Currency.ResetInterval
+# How often should currency week count reset (days)
+# Default: 7 (weekly)
+#
+
+Currency.ResetInterval = 7
+
+#
+# Currency.ResetWeekDay
+# Week day when currency week count is reset (0..6) 0 == Sunday
+# Default: 3 (Wednesday)
+#
+
+Currency.ResetWeekDay = 3
+
+#
+# Currency.ResetHour
+# Hour of a day when currency week count is reset (0..23)
+# Default: 6
+#
+
+Currency.ResetHour = 6
+
+#
+# Currency.StartHonorPoints
+# Amount of honor points that new players will start with
+# Default: 0 (with precision)
+#
+
+Currency.StartHonorPoints = 0
+
+#
+# Currency.MaxHonorPoints
+# Amount honor points a player can have
+# Default: 4000
+#
+
+Currency.MaxHonorPoints = 4000
+
+#
+# Currency.StartJusticePoints
+# Amount of justice points that new players will start with
+# Default: 0 (with precision)
+#
+
+Currency.StartJusticePoints = 0
+
+#
+# Currency.MaxJusticePoints
+# Amount justice points a player can have
+# Default: 4000
+#
+
+Currency.MaxJusticePoints = 4000
+
+#
+# Currency.StartConquestPoints
+# Amount of conquest points that new players will start with
+# Default: 0 (with precision)
+#
+
+Currency.StartConquestPoints = 0
+
+#
+# Currency.ConquestPointsDefaultWeekCap
+# Amount of conquest points that player can earn per week
+# Default: 1350
+#
+
+Currency.ConquestPointsDefaultWeekCap = 1350
+
+#
+# Currency.ConquestPointsArenaReward
+# Amount of conquest points rewarded by winning arenas
+# Default: 180
+#
+
+Currency.ConquestPointsArenaReward = 180
+
+#
+###################################################################################################
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 3adccf105de..09f23b844cf 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -12,6 +12,6 @@ add_subdirectory(map_extractor)
add_subdirectory(vmap4_assembler)
add_subdirectory(vmap4_extractor)
add_subdirectory(mmaps_generator)
-if (WITH_MESHEXTRACTOR)
- add_subdirectory(mesh_extractor)
-endif()
+#if (WITH_MESHEXTRACTOR)
+# add_subdirectory(mesh_extractor)
+#endif()
diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt
index ea073456680..64d0573147c 100644
--- a/src/tools/map_extractor/CMakeLists.txt
+++ b/src/tools/map_extractor/CMakeLists.txt
@@ -11,20 +11,13 @@
file(GLOB_RECURSE sources *.cpp *.h)
-set(include_Dirs
- ${CMAKE_SOURCE_DIR}/src/server/shared
- ${CMAKE_SOURCE_DIR}/dep/libmpq
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/loadlib
+include_directories (
+ ${CMAKE_SOURCE_DIR}/src/server/shared
+ ${CMAKE_SOURCE_DIR}/dep/StormLib/src
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/loadlib
)
-if( WIN32 )
- set(include_Dirs
- ${include_Dirs}
- ${CMAKE_SOURCE_DIR}/dep/libmpq/win
- )
-endif()
-
include_directories(${include_Dirs})
add_executable(mapextractor
@@ -32,11 +25,13 @@ add_executable(mapextractor
)
target_link_libraries(mapextractor
- mpq
${BZIP2_LIBRARIES}
${ZLIB_LIBRARIES}
+ storm
)
+add_dependencies(mapextractor storm)
+
if( UNIX )
install(TARGETS mapextractor DESTINATION bin)
elseif( WIN32 )
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index bf88a92c32a..7f92cd56564 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -2,7 +2,7 @@
#include <stdio.h>
#include <deque>
-#include <set>
+#include <list>
#include <cstdlib>
#ifdef _WIN32
@@ -10,10 +10,11 @@
#else
#include <sys/stat.h>
#include <unistd.h>
+#define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
#endif
+#include "StormLib.h"
#include "dbcfile.h"
-#include "mpq_libmpq04.h"
#include "adt.h"
#include "wdt.h"
@@ -30,11 +31,13 @@
#endif
#ifdef O_LARGEFILE
- #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
+ #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
#else
#define OPEN_FLAGS (O_RDONLY | O_BINARY)
#endif
-extern ArchiveSet gOpenArchives;
+
+HANDLE WorldMpq = NULL;
+HANDLE LocaleMpq = NULL;
typedef struct
{
@@ -60,6 +63,7 @@ enum Extract
// Select data for extract
int CONF_extract = EXTRACT_MAP | EXTRACT_DBC;
+
// This option allow limit minimum height to some value (Allow save some memory)
bool CONF_allow_height_limit = true;
float CONF_use_minHeight = -500.0f;
@@ -71,34 +75,57 @@ float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536
float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat
float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat
-// List MPQ for extract from
-const char *CONF_mpq_list[]={
- "common.MPQ",
- "common-2.MPQ",
- "lichking.MPQ",
- "expansion.MPQ",
- "patch.MPQ",
- "patch-2.MPQ",
- "patch-3.MPQ",
- "patch-4.MPQ",
- "patch-5.MPQ",
+uint32 CONF_TargetBuild = 15595; // 4.3.4.15595
+
+// List MPQ for extract maps from
+char const* CONF_mpq_list[]=
+{
+ "world.MPQ",
+ "art.MPQ",
+ "world2.MPQ",
+ "expansion1.MPQ",
+ "expansion2.MPQ",
+ "expansion3.MPQ",
};
-static const char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
-#define LANG_COUNT 12
+uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0};
+#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder
+#define NEW_BASE_SET_BUILD 15211
-void CreateDir( const std::string& Path )
+char const* Locales[] =
{
- #ifdef _WIN32
- _mkdir( Path.c_str());
- #else
- mkdir( Path.c_str(), 0777 );
- #endif
+ "enGB", "enUS",
+ "deDE", "esES",
+ "frFR", "koKR",
+ "zhCN", "zhTW",
+ "enCN", "enTW",
+ "esMX", "ruRU"
+};
+
+TCHAR const* LocalesT[] =
+{
+ _T("enGB"), _T("enUS"),
+ _T("deDE"), _T("esES"),
+ _T("frFR"), _T("koKR"),
+ _T("zhCN"), _T("zhTW"),
+ _T("enCN"), _T("enTW"),
+ _T("esMX"), _T("ruRU"),
+};
+
+#define LOCALES_COUNT 12
+
+void CreateDir(std::string const& path)
+{
+#ifdef _WIN32
+ _mkdir(path.c_str());
+#else
+ mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 0777
+#endif
}
-bool FileExists( const char* FileName )
+bool FileExists(TCHAR const* fileName)
{
- int fp = _open(FileName, OPEN_FLAGS);
+ int fp = _open(fileName, OPEN_FLAGS);
if(fp != -1)
{
_close(fp);
@@ -108,7 +135,7 @@ bool FileExists( const char* FileName )
return false;
}
-void Usage(char* prg)
+void Usage(char const* prg)
{
printf(
"Usage:\n"\
@@ -117,52 +144,62 @@ void Usage(char* prg)
"-o set output path\n"\
"-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\
"-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
- "Example: %s -f 0 -i \"c:\\games\\game\"", prg, prg);
+ "-b target build (default %u)\n"\
+ "Example: %s -f 0 -i \"c:\\games\\game\"", prg, CONF_TargetBuild, prg);
exit(1);
}
-void HandleArgs(int argc, char * arg[])
+void HandleArgs(int argc, char* arg[])
{
- for(int c = 1; c < argc; ++c)
+ for (int c = 1; c < argc; ++c)
{
// i - input path
// o - output path
// e - extract only MAP(1)/DBC(2) - standard both(3)
// f - use float to int conversion
// h - limit minimum height
- if(arg[c][0] != '-')
+ // b - target client build
+ if (arg[c][0] != '-')
Usage(arg[0]);
- switch(arg[c][1])
+ switch (arg[c][1])
{
case 'i':
- if(c + 1 < argc) // all ok
- strcpy(input_path, arg[(c++) + 1]);
+ if (c + 1 < argc) // all ok
+ strcpy(input_path, arg[c++ + 1]);
else
Usage(arg[0]);
break;
case 'o':
- if(c + 1 < argc) // all ok
- strcpy(output_path, arg[(c++) + 1]);
+ if (c + 1 < argc) // all ok
+ strcpy(output_path, arg[c++ + 1]);
else
Usage(arg[0]);
break;
case 'f':
- if(c + 1 < argc) // all ok
- CONF_allow_float_to_int=atoi(arg[(c++) + 1])!=0;
+ if (c + 1 < argc) // all ok
+ CONF_allow_float_to_int = atoi(arg[c++ + 1])!=0;
else
Usage(arg[0]);
break;
case 'e':
- if(c + 1 < argc) // all ok
+ if (c + 1 < argc) // all ok
{
- CONF_extract=atoi(arg[(c++) + 1]);
- if(!(CONF_extract > 0 && CONF_extract < 4))
+ CONF_extract = atoi(arg[c++ + 1]);
+ if (!(CONF_extract > 0 && CONF_extract < 4))
Usage(arg[0]);
}
else
Usage(arg[0]);
break;
+ case 'b':
+ if (c + 1 < argc) // all ok
+ CONF_TargetBuild = atoi(arg[c++ + 1]);
+ else
+ Usage(arg[0]);
+ break;
+ default:
+ break;
}
}
}
@@ -170,22 +207,31 @@ void HandleArgs(int argc, char * arg[])
uint32 ReadBuild(int locale)
{
// include build info file also
- std::string filename = std::string("component.wow-")+langs[locale]+".txt";
+ std::string filename = std::string("component.wow-") + Locales[locale] + ".txt";
//printf("Read %s file... ", filename.c_str());
- MPQFile m(filename.c_str());
- if(m.isEof())
+ HANDLE dbcFile;
+ if (!SFileOpenFileEx(LocaleMpq, filename.c_str(), SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Fatal error: Not found %s file!\n", filename.c_str());
+ exit(1);
+ }
+
+ char buff[512];
+ DWORD readBytes = 0;
+ SFileReadFile(dbcFile, buff, 512, &readBytes, NULL);
+ if (!readBytes)
{
printf("Fatal error: Not found %s file!\n", filename.c_str());
exit(1);
}
- std::string text = m.getPointer();
- m.close();
+ std::string text = buff;
+ SFileCloseFile(dbcFile);
size_t pos = text.find("version=\"");
size_t pos1 = pos + strlen("version=\"");
- size_t pos2 = text.find("\"",pos1);
+ size_t pos2 = text.find("\"", pos1);
if (pos == text.npos || pos2 == text.npos || pos1 >= pos2)
{
printf("Fatal error: Invalid %s file format!\n", filename.c_str());
@@ -207,9 +253,16 @@ uint32 ReadBuild(int locale)
uint32 ReadMapDBC()
{
printf("Read Map.dbc file... ");
- DBCFile dbc("DBFilesClient\\Map.dbc");
- if(!dbc.open())
+ HANDLE dbcFile;
+ if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\Map.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Fatal error: Cannot find Map.dbc in archive!\n");
+ exit(1);
+ }
+
+ DBCFile dbc(dbcFile);
+ if (!dbc.open())
{
printf("Fatal error: Invalid Map.dbc file format!\n");
exit(1);
@@ -222,15 +275,23 @@ uint32 ReadMapDBC()
map_ids[x].id = dbc.getRecord(x).getUInt(0);
strcpy(map_ids[x].name, dbc.getRecord(x).getString(1));
}
- printf("Done! (%u maps loaded)\n", (uint32)map_count);
+
+ SFileCloseFile(dbcFile);
+ printf("Done! (%u maps loaded)\n", uint32(map_count));
return map_count;
}
void ReadAreaTableDBC()
{
printf("Read AreaTable.dbc file...");
- DBCFile dbc("DBFilesClient\\AreaTable.dbc");
+ HANDLE dbcFile;
+ if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\AreaTable.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Fatal error: Cannot find AreaTable.dbc in archive!\n");
+ exit(1);
+ }
+ DBCFile dbc(dbcFile);
if(!dbc.open())
{
printf("Fatal error: Invalid AreaTable.dbc file format!\n");
@@ -238,22 +299,27 @@ void ReadAreaTableDBC()
}
size_t area_count = dbc.getRecordCount();
- size_t maxid = dbc.getMaxId();
- areas = new uint16[maxid + 1];
- memset(areas, 0xff, (maxid + 1) * sizeof(uint16));
+ maxAreaId = dbc.getMaxId();
+ areas = new uint16[maxAreaId + 1];
- for(uint32 x = 0; x < area_count; ++x)
+ for (uint32 x = 0; x < area_count; ++x)
areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
- maxAreaId = dbc.getMaxId();
-
- printf("Done! (%u areas loaded)\n", (uint32)area_count);
+ SFileCloseFile(dbcFile);
+ printf("Done! (%u areas loaded)\n", uint32(area_count));
}
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
- DBCFile dbc("DBFilesClient\\LiquidType.dbc");
+ HANDLE dbcFile;
+ if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\LiquidType.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Fatal error: Cannot find LiquidType.dbc in archive!\n");
+ exit(1);
+ }
+
+ DBCFile dbc(dbcFile);
if(!dbc.open())
{
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
@@ -268,6 +334,7 @@ void ReadLiquidTypeTableDBC()
for(uint32 x = 0; x < liqTypeCount; ++x)
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
+ SFileCloseFile(dbcFile);
printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount);
}
@@ -371,15 +438,8 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
{
ADT_file adt;
- if (!adt.loadFile(filename))
- return false;
-
- adt_MCIN *cells = adt.a_grid->getMCIN();
- if (!cells)
- {
- printf("Can't find cells in '%s'\n", filename);
+ if (!adt.loadFile(WorldMpq, filename))
return false;
- }
memset(liquid_show, 0, sizeof(liquid_show));
memset(liquid_flags, 0, sizeof(liquid_flags));
@@ -392,24 +452,27 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
map.buildMagic = build;
// Get area flags data
- for (int i=0;i<ADT_CELLS_PER_GRID;i++)
+ for (int i = 0; i < ADT_CELLS_PER_GRID; ++i)
{
- for(int j=0;j<ADT_CELLS_PER_GRID;j++)
+ for (int j = 0; j < ADT_CELLS_PER_GRID; ++j)
{
- adt_MCNK * cell = cells->getMCNK(i,j);
+ adt_MCNK* cell = adt.cells[i][j];
uint32 areaid = cell->areaid;
- if(areaid && areaid <= maxAreaId)
+ if (areaid && areaid <= maxAreaId)
{
- if(areas[areaid] != 0xffff)
+ if (areas[areaid] != 0xFFFF)
{
area_flags[i][j] = areas[areaid];
continue;
}
+
printf("File: %s\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy);
}
+
area_flags[i][j] = 0xffff;
}
}
+
//============================================
// Try pack area data
//============================================
@@ -451,7 +514,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
- adt_MCNK * cell = cells->getMCNK(i,j);
+ adt_MCNK * cell = adt.cells[i][j];
if (!cell)
continue;
// Height values for triangles stored in order:
@@ -622,7 +685,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
{
for(int j = 0; j < ADT_CELLS_PER_GRID; j++)
{
- adt_MCNK *cell = cells->getMCNK(i, j);
+ adt_MCNK *cell = adt.cells[i][j];
if (!cell)
continue;
@@ -722,7 +785,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// Dark water detect
if (LiqType[h->liquidType] == LIQUID_TYPE_OCEAN)
{
- uint8 *lm = h2o->getLiquidLightMap(h);
+ uint8* lm = h2o->getLiquidLightMap(h);
if (!lm)
liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
}
@@ -730,34 +793,37 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
if (!count && liquid_flags[i][j])
printf("Wrong liquid detect in MH2O chunk");
- float *height = h2o->getLiquidHeightMap(h);
+ float* height = h2o->getLiquidHeightMap(h);
int pos = 0;
- for (int y=0; y<=h->height;y++)
+ for (int y = 0; y <= h->height; y++)
{
- int cy = i*ADT_CELL_SIZE + y + h->yOffset;
- for (int x=0; x<= h->width; x++)
+ int cy = i * ADT_CELL_SIZE + y + h->yOffset;
+ for (int x = 0; x <= h->width; x++)
{
- int cx = j*ADT_CELL_SIZE + x + h->xOffset;
+ int cx = j * ADT_CELL_SIZE + x + h->xOffset;
+
if (height)
liquid_height[cy][cx] = height[pos];
else
liquid_height[cy][cx] = h->heightLevel1;
+
pos++;
}
}
}
}
}
+
//============================================
// Pack liquid data
//============================================
uint8 type = liquid_flags[0][0];
bool fullType = false;
- for (int y=0;y<ADT_CELLS_PER_GRID;y++)
+ for (int y = 0; y < ADT_CELLS_PER_GRID; y++)
{
- for(int x=0;x<ADT_CELLS_PER_GRID;x++)
+ for (int x = 0; x < ADT_CELLS_PER_GRID; x++)
{
- if (liquid_flags[y][x]!=type)
+ if (liquid_flags[y][x] != type)
{
fullType = true;
y = ADT_CELLS_PER_GRID;
@@ -844,7 +910,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
{
for (int j = 0; j < ADT_CELLS_PER_GRID; ++j)
{
- adt_MCNK * cell = cells->getMCNK(i,j);
+ adt_MCNK * cell = adt.cells[i][j];
if (!cell)
continue;
holes[i][j] = cell->holes;
@@ -896,15 +962,16 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
if (map.liquidMapOffset)
{
fwrite(&liquidHeader, sizeof(liquidHeader), 1, output);
- if (!(liquidHeader.flags&MAP_LIQUID_NO_TYPE))
+ if (!(liquidHeader.flags & MAP_LIQUID_NO_TYPE))
{
fwrite(liquid_entry, sizeof(liquid_entry), 1, output);
fwrite(liquid_flags, sizeof(liquid_flags), 1, output);
}
- if (!(liquidHeader.flags&MAP_LIQUID_NO_HEIGHT))
+
+ if (!(liquidHeader.flags & MAP_LIQUID_NO_HEIGHT))
{
- for (int y=0; y<liquidHeader.height;y++)
- fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output);
+ for (int y = 0; y < liquidHeader.height; y++)
+ fwrite(&liquid_height[y + liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output);
}
}
@@ -935,183 +1002,326 @@ void ExtractMapsFromMpq(uint32 build)
CreateDir(path);
printf("Convert map files\n");
- for(uint32 z = 0; z < map_count; ++z)
+ for (uint32 z = 0; z < map_count; ++z)
{
printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count);
// Loadup map grid data
sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
WDT_file wdt;
- if (!wdt.loadFile(mpq_map_name, false))
- {
-// printf("Error loading %s map wdt data\n", map_ids[z].name);
+ if (!wdt.loadFile(WorldMpq, mpq_map_name, false))
continue;
- }
- for(uint32 y = 0; y < WDT_MAP_SIZE; ++y)
+ for (uint32 y = 0; y < WDT_MAP_SIZE; ++y)
{
- for(uint32 x = 0; x < WDT_MAP_SIZE; ++x)
+ for (uint32 x = 0; x < WDT_MAP_SIZE; ++x)
{
- if (!wdt.main->adt_list[y][x].exist)
+ if (!(wdt.main->adt_list[y][x].flag & 0x1))
continue;
+
sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpq_filename, output_filename, y, x, build);
}
+
// draw progress bar
printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE);
}
}
+
printf("\n");
delete [] areas;
delete [] map_ids;
}
-bool ExtractFile( char const* mpq_name, std::string const& filename )
+bool ExtractFile(HANDLE fileInArchive, char const* filename)
{
- FILE *output = fopen(filename.c_str(), "wb");
+ FILE* output = fopen(filename, "wb");
if(!output)
{
- printf("Can't create the output file '%s'\n", filename.c_str());
+ printf("Can't create the output file '%s'\n", filename);
return false;
}
- MPQFile m(mpq_name);
- if(!m.isEof())
- fwrite(m.getPointer(), 1, m.getSize(), output);
+
+ char buffer[0x10000];
+ DWORD readBytes = 1;
+
+ while (readBytes > 0)
+ {
+ SFileReadFile(fileInArchive, buffer, sizeof(buffer), &readBytes, NULL);
+ if (readBytes > 0)
+ fwrite(buffer, 1, readBytes, output);
+ }
fclose(output);
return true;
}
-void ExtractDBCFiles(int locale, bool basicLocale)
+void ExtractDBCFiles(int l, bool basicLocale)
{
printf("Extracting dbc files...\n");
- std::set<std::string> dbcfiles;
-
- // get DBC file list
- for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i)
+ SFILE_FIND_DATA foundFile;
+ memset(&foundFile, 0, sizeof(foundFile));
+ HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*dbc", &foundFile, NULL);
+ HANDLE dbcFile = NULL;
+ uint32 count = 0;
+ if (listFile)
{
- vector<string> files;
- (*i)->GetFileListTo(files);
- for (vector<string>::iterator iter = files.begin(); iter != files.end(); ++iter)
- if (iter->rfind(".dbc") == iter->length() - strlen(".dbc"))
- dbcfiles.insert(*iter);
- }
+ std::string outputPath = output_path;
+ outputPath += "/dbc/";
- std::string path = output_path;
- path += "/dbc/";
- CreateDir(path);
- if(!basicLocale)
- {
- path += langs[locale];
- path += "/";
- CreateDir(path);
- }
+ CreateDir(outputPath);
+ if (!basicLocale)
+ {
+ outputPath += Locales[l];
+ outputPath += "/";
+ CreateDir(outputPath);
+ }
- // extract Build info file
- {
- string mpq_name = std::string("component.wow-") + langs[locale] + ".txt";
- string filename = path + mpq_name;
+ std::string filename;
- ExtractFile(mpq_name.c_str(), filename);
- }
+ do
+ {
+ if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Unable to open file %s in the archive\n", foundFile.cFileName);
+ continue;
+ }
- // extract DBCs
- uint32 count = 0;
- for (set<string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter)
- {
- string filename = path;
- filename += (iter->c_str() + strlen("DBFilesClient\\"));
+ filename = foundFile.cFileName;
+ filename = outputPath + filename.substr(filename.rfind('\\'));
+ if (ExtractFile(dbcFile, filename.c_str()))
+ ++count;
+
+ SFileCloseFile(dbcFile);
+ } while (SFileFindNextFile(listFile, &foundFile));
- if (ExtractFile(iter->c_str(), filename))
- ++count;
+ SFileFindClose(listFile);
}
+
printf("Extracted %u DBC files\n\n", count);
}
-void LoadLocaleMPQFiles(int const locale)
+void ExtractDB2Files(int l, bool basicLocale)
{
- char filename[512];
-
- sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
- new MPQArchive(filename);
+ printf("Extracting db2 files...\n");
- for(int i = 1; i < 5; ++i)
+ SFILE_FIND_DATA foundFile;
+ memset(&foundFile, 0, sizeof(foundFile));
+ HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*db2", &foundFile, NULL);
+ HANDLE dbcFile = NULL;
+ uint32 count = 0;
+ if (listFile)
{
- char ext[3] = "";
- if(i > 1)
- sprintf(ext, "-%i", i);
+ std::string outputPath = output_path;
+ outputPath += "/dbc/";
+ if (!basicLocale)
+ {
+ outputPath += Locales[l];
+ outputPath += "/";
+ }
+
+ std::string filename;
- sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext);
- if(FileExists(filename))
- new MPQArchive(filename);
+ do
+ {
+ if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_PATCHED_FILE, &dbcFile))
+ {
+ printf("Unable to open file %s in the archive\n", foundFile.cFileName);
+ continue;
+ }
+
+ filename = foundFile.cFileName;
+ filename = outputPath + filename.substr(filename.rfind('\\'));
+ if (ExtractFile(dbcFile, filename.c_str()))
+ ++count;
+
+ SFileCloseFile(dbcFile);
+ } while (SFileFindNextFile(listFile, &foundFile));
+
+ SFileFindClose(listFile);
}
+
+ printf("Extracted %u DB2 files\n\n", count);
}
-void LoadCommonMPQFiles()
+bool LoadLocaleMPQFile(int locale)
{
- char filename[512];
- int count = sizeof(CONF_mpq_list)/sizeof(char*);
- for(int i = 0; i < count; ++i)
+ TCHAR buff[512];
+ memset(buff, 0, sizeof(buff));
+ _stprintf(buff, _T("%s/Data/%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]);
+ if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ {
+ _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]);
+ _tprintf(_T("Cannot open archive %s\n"), buff);
+ }
+ return false;
+ }
+
+ _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]);
+ char const* prefix = NULL;
+ for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
{
- sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]);
- if(FileExists(filename))
- new MPQArchive(filename);
+ // Do not attempt to read older MPQ patch archives past this build, they were merged with base
+ // and trying to read them together with new base will not end well
+ if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
+ continue;
+
+ memset(buff, 0, sizeof(buff));
+ if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
+ {
+ prefix = "";
+ _stprintf(buff, _T("%s/Data/%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]);
+ }
+ else
+ {
+ prefix = Locales[locale];
+ _stprintf(buff, _T("%s/Data/wow-update-%u.MPQ"), input_path, Builds[i]);
+ }
+
+ if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
+ {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ _tprintf(_T("Cannot open patch archive %s\n"), buff);
+ continue;
+ }
+ else
+ _tprintf(_T("Loaded %s\n"), buff);
}
+
+ printf("\n");
+ return true;
}
-inline void CloseMPQFiles()
+void LoadCommonMPQFiles(uint32 build)
{
- for(ArchiveSet::iterator j = gOpenArchives.begin(); j != gOpenArchives.end();++j) (*j)->close();
- gOpenArchives.clear();
+ TCHAR filename[512];
+ _stprintf(filename, _T("%s/Data/world.MPQ"), input_path);
+ _tprintf(_T("Loading common MPQ files\n"));
+ if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open archive %s\n"), filename);
+ return;
+ }
+
+ int count = sizeof(CONF_mpq_list) / sizeof(char*);
+ for (int i = 1; i < count; ++i)
+ {
+ if (build < NEW_BASE_SET_BUILD && !strcmp("world2.MPQ", CONF_mpq_list[i])) // 4.3.2 and higher MPQ
+ continue;
+
+ _stprintf(filename, _T("%s/Data/%s"), input_path, CONF_mpq_list[i]);
+ if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open archive %s\n"), filename);
+ else
+ _tprintf(_T("Not found %s\n"), filename);
+ }
+ else
+ _tprintf(_T("Loaded %s\n"), filename);
+
+ }
+
+ char const* prefix = NULL;
+ for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
+ {
+ // Do not attempt to read older MPQ patch archives past this build, they were merged with base
+ // and trying to read them together with new base will not end well
+ if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
+ continue;
+
+ memset(filename, 0, sizeof(filename));
+ if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
+ {
+ prefix = "";
+ _stprintf(filename, _T("%s/Data/wow-update-base-%u.MPQ"), input_path, Builds[i]);
+ }
+ else
+ {
+ prefix = "base";
+ _stprintf(filename, _T("%s/Data/wow-update-%u.MPQ"), input_path, Builds[i]);
+ }
+
+ if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open patch archive %s\n"), filename);
+ else
+ _tprintf(_T("Not found %s\n"), filename);
+ continue;
+ }
+ else
+ _tprintf(_T("Loaded %s\n"), filename);
+ }
+
+ printf("\n");
}
int main(int argc, char * arg[])
{
printf("Map & DBC Extractor\n");
- printf("===================\n\n");
+ printf("===================\n");
HandleArgs(argc, arg);
int FirstLocale = -1;
uint32 build = 0;
- for (int i = 0; i < LANG_COUNT; i++)
+ for (int i = 0; i < LOCALES_COUNT; ++i)
{
- char tmp1[512];
- sprintf(tmp1, "%s/Data/%s/locale-%s.MPQ", input_path, langs[i], langs[i]);
- if (FileExists(tmp1))
+ //Open MPQs
+ if (!LoadLocaleMPQFile(i))
{
- printf("Detected locale: %s\n", langs[i]);
-
- //Open MPQs
- LoadLocaleMPQFiles(i);
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ printf("Unable to load %s locale archives!\n", Locales[i]);
+ continue;
+ }
- if((CONF_extract & EXTRACT_DBC) == 0)
+ printf("Detected locale: %s\n", Locales[i]);
+ if ((CONF_extract & EXTRACT_DBC) == 0)
+ {
+ FirstLocale = i;
+ build = ReadBuild(i);
+ if (build > CONF_TargetBuild)
{
- FirstLocale = i;
- build = ReadBuild(FirstLocale);
- printf("Detected client build: %u\n", build);
- break;
+ printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], build, CONF_TargetBuild);
+ return 0;
}
- //Extract DBC files
- if(FirstLocale < 0)
- {
- FirstLocale = i;
- build = ReadBuild(FirstLocale);
- printf("Detected client build: %u\n", build);
- ExtractDBCFiles(i, true);
- }
- else
- ExtractDBCFiles(i, false);
+ printf("Detected client build: %u\n", build);
+ printf("\n");
+ break;
+ }
+
+ //Extract DBC files
+ uint32 tempBuild = ReadBuild(i);
+ printf("Detected client build %u for locale %s\n", tempBuild, Locales[i]);
+ if (tempBuild > CONF_TargetBuild)
+ {
+ SFileCloseArchive(LocaleMpq);
+ printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], tempBuild, CONF_TargetBuild);
+ continue;
+ }
+
+ printf("\n");
+ ExtractDBCFiles(i, FirstLocale < 0);
+ ExtractDB2Files(i, FirstLocale < 0);
- //Close MPQs
- CloseMPQFiles();
+ if (FirstLocale < 0)
+ {
+ FirstLocale = i;
+ build = tempBuild;
}
+
+ //Close MPQs
+ SFileCloseArchive(LocaleMpq);
}
- if(FirstLocale < 0)
+ if (FirstLocale < 0)
{
printf("No locales detected\n");
return 0;
@@ -1119,17 +1329,18 @@ int main(int argc, char * arg[])
if (CONF_extract & EXTRACT_MAP)
{
- printf("Using locale: %s\n", langs[FirstLocale]);
+ printf("Using locale: %s\n", Locales[FirstLocale]);
// Open MPQs
- LoadLocaleMPQFiles(FirstLocale);
- LoadCommonMPQFiles();
+ LoadLocaleMPQFile(FirstLocale);
+ LoadCommonMPQFiles(build);
// Extract maps
ExtractMapsFromMpq(build);
// Close MPQs
- CloseMPQFiles();
+ SFileCloseArchive(WorldMpq);
+ SFileCloseArchive(LocaleMpq);
}
return 0;
diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp
index 30524dbd640..b235e2c1638 100644
--- a/src/tools/map_extractor/adt.cpp
+++ b/src/tools/map_extractor/adt.cpp
@@ -51,10 +51,31 @@ bool ADT_file::prepareLoadedData()
return false;
// Check and prepare MHDR
- a_grid = (adt_MHDR *)(GetData()+8+version->size);
+ a_grid = (adt_MHDR*)(GetData()+8+version->size);
if (!a_grid->prepareLoadedData())
return false;
+ // funny offsets calculations because there is no mapping for them and they have variable lengths
+ uint8* ptr = (uint8*)a_grid + a_grid->size + 8;
+ uint32 mcnk_count = 0;
+ memset(cells, 0, ADT_CELLS_PER_GRID * ADT_CELLS_PER_GRID * sizeof(adt_MCNK*));
+ while (ptr < GetData() + GetDataSize())
+ {
+ uint32 header = *(uint32*)ptr;
+ uint32 size = *(uint32*)(ptr + 4);
+ if (header == MCNKMagic.fcc)
+ {
+ cells[mcnk_count / ADT_CELLS_PER_GRID][mcnk_count % ADT_CELLS_PER_GRID] = (adt_MCNK*)ptr;
+ ++mcnk_count;
+ }
+
+ // move to next chunk
+ ptr += size + 8;
+ }
+
+ if (mcnk_count != ADT_CELLS_PER_GRID * ADT_CELLS_PER_GRID)
+ return false;
+
return true;
}
diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h
index 5daf5820c3f..20b5ac93540 100644
--- a/src/tools/map_extractor/adt.h
+++ b/src/tools/map_extractor/adt.h
@@ -245,15 +245,18 @@ public:
//
// Adt file header chunk
//
+class ADT_file;
class adt_MHDR
{
+ friend class ADT_file;
+
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
- uint32 pad;
+ uint32 flags;
uint32 offsMCIN; // MCIN
uint32 offsTex; // MTEX
uint32 offsModels; // MMDX
@@ -271,9 +274,8 @@ class adt_MHDR
uint32 data5;
public:
bool prepareLoadedData();
- adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);}
- adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;}
-
+ adt_MCIN* getMCIN() { return offsMCIN ? (adt_MCIN *)((uint8 *)&flags+offsMCIN) : NULL; }
+ adt_MH2O* getMH2O() { return offsMH2O ? (adt_MH2O *)((uint8 *)&flags+offsMH2O) : NULL; }
};
class ADT_file : public FileLoader{
@@ -283,7 +285,8 @@ public:
~ADT_file();
void free();
- adt_MHDR *a_grid;
+ adt_MHDR* a_grid;
+ adt_MCNK* cells[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
};
#endif
diff --git a/src/tools/map_extractor/dbcfile.cpp b/src/tools/map_extractor/dbcfile.cpp
index c1cab7ddb2f..021dc6f6e33 100644
--- a/src/tools/map_extractor/dbcfile.cpp
+++ b/src/tools/map_extractor/dbcfile.cpp
@@ -1,83 +1,91 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "dbcfile.h"
-#include "mpq_libmpq04.h"
-DBCFile::DBCFile(const std::string& filename):
- filename(filename), recordSize(0), recordCount(0), fieldCount(0), stringSize(0), data(NULL), stringTable(NULL)
+DBCFile::DBCFile(HANDLE file) :
+ _file(file), _data(NULL), _stringTable(NULL)
{
-
}
bool DBCFile::open()
{
- MPQFile f(filename.c_str());
char header[4];
- unsigned int na,nb,es,ss;
+ unsigned int na, nb, es, ss;
- if(f.read(header,4)!=4) // Number of records
+ DWORD readBytes = 0;
+ SFileReadFile(_file, header, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of records
return false;
- if(header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3]!='C')
+ if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C')
return false;
- if(f.read(&na,4)!=4) // Number of records
+ SFileReadFile(_file, &na, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of records
return false;
- if(f.read(&nb,4)!=4) // Number of fields
+
+ SFileReadFile(_file, &nb, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of fields
return false;
- if(f.read(&es,4)!=4) // Size of a record
+
+ SFileReadFile(_file, &es, 4, &readBytes, NULL);
+ if (readBytes != 4) // Size of a record
return false;
- if(f.read(&ss,4)!=4) // String size
+
+ SFileReadFile(_file, &ss, 4, &readBytes, NULL);
+ if (readBytes != 4) // String size
return false;
- recordSize = es;
- recordCount = na;
- fieldCount = nb;
- stringSize = ss;
- if(fieldCount*4 != recordSize)
+ _recordSize = es;
+ _recordCount = na;
+ _fieldCount = nb;
+ _stringSize = ss;
+ if (_fieldCount * 4 != _recordSize)
return false;
- data = new unsigned char[recordSize*recordCount+stringSize];
- stringTable = data + recordSize*recordCount;
+ _data = new unsigned char[_recordSize * _recordCount + _stringSize];
+ _stringTable = _data + _recordSize*_recordCount;
- size_t data_size = recordSize*recordCount+stringSize;
- if(f.read(data,data_size)!=data_size)
+ size_t data_size = _recordSize * _recordCount + _stringSize;
+ SFileReadFile(_file, _data, data_size, &readBytes, NULL);
+ if (readBytes != data_size)
return false;
- f.close();
+
return true;
}
+
DBCFile::~DBCFile()
{
- delete [] data;
+ delete [] _data;
}
DBCFile::Record DBCFile::getRecord(size_t id)
{
- assert(data);
- return Record(*this, data + id*recordSize);
+ assert(_data);
+ return Record(*this, _data + id*_recordSize);
}
size_t DBCFile::getMaxId()
{
- assert(data);
+ assert(_data);
size_t maxId = 0;
for(size_t i = 0; i < getRecordCount(); ++i)
- {
- if(maxId < getRecord(i).getUInt(0))
+ if (maxId < getRecord(i).getUInt(0))
maxId = getRecord(i).getUInt(0);
- }
+
return maxId;
}
DBCFile::Iterator DBCFile::begin()
{
- assert(data);
- return Iterator(*this, data);
+ assert(_data);
+ return Iterator(*this, _data);
}
+
DBCFile::Iterator DBCFile::end()
{
- assert(data);
- return Iterator(*this, stringTable);
+ assert(_data);
+ return Iterator(*this, _stringTable);
}
diff --git a/src/tools/map_extractor/dbcfile.h b/src/tools/map_extractor/dbcfile.h
index 6862678a73b..fa8734d9d63 100644
--- a/src/tools/map_extractor/dbcfile.h
+++ b/src/tools/map_extractor/dbcfile.h
@@ -2,118 +2,125 @@
#define DBCFILE_H
#include <cassert>
#include <string>
+#include "StormLib.h"
class DBCFile
{
-public:
- DBCFile(const std::string &filename);
- ~DBCFile();
+ public:
+ DBCFile(HANDLE file);
+ ~DBCFile();
- // Open database. It must be openened before it can be used.
- bool open();
+ // Open database. It must be openened before it can be used.
+ bool open();
- // Database exceptions
- class Exception
- {
- public:
- Exception(const std::string &message): message(message)
- { }
- virtual ~Exception()
- { }
- const std::string &getMessage() {return message;}
- private:
- std::string message;
- };
- class NotFound: public Exception
- {
- public:
- NotFound(): Exception("Key was not found")
- { }
- };
- // Iteration over database
- class Iterator;
- class Record
- {
- public:
- float getFloat(size_t field) const
- {
- assert(field < file.fieldCount);
- return *reinterpret_cast<float*>(offset+field*4);
- }
- unsigned int getUInt(size_t field) const
+ // Database exceptions
+ class Exception
{
- assert(field < file.fieldCount);
- return *reinterpret_cast<unsigned int*>(offset+field*4);
- }
- int getInt(size_t field) const
- {
- assert(field < file.fieldCount);
- return *reinterpret_cast<int*>(offset+field*4);
- }
- const char *getString(size_t field) const
+ public:
+ Exception(const std::string &message) : message(message) { }
+ virtual ~Exception() { }
+ const std::string &getMessage() { return message; }
+ private:
+ std::string message;
+ };
+
+ class NotFound: public Exception
{
- assert(field < file.fieldCount);
- size_t stringOffset = getUInt(field);
- assert(stringOffset < file.stringSize);
- return reinterpret_cast<char*>(file.stringTable + stringOffset);
- }
- private:
- Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {}
- DBCFile &file;
- unsigned char *offset;
-
- friend class DBCFile;
- friend class DBCFile::Iterator;
- };
- /** Iterator that iterates over records
- */
- class Iterator
- {
- public:
- Iterator(DBCFile &file, unsigned char *offset):
- record(file, offset) {}
- /// Advance (prefix only)
- Iterator & operator++() {
- record.offset += record.file.recordSize;
- return *this;
- }
- /// Return address of current instance
- Record const & operator*() const { return record; }
- const Record* operator->() const {
- return &record;
- }
- /// Comparison
- bool operator==(const Iterator &b) const
+ public:
+ NotFound(): Exception("Key was not found") { }
+ };
+
+ // Iteration over database
+ class Iterator;
+ class Record
{
- return record.offset == b.record.offset;
- }
- bool operator!=(const Iterator &b) const
+ public:
+ float getFloat(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<float*>(offset + field * 4);
+ }
+
+ unsigned int getUInt(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<unsigned int*>(offset + field * 4);
+ }
+
+ int getInt(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<int*>(offset + field * 4);
+ }
+
+ char const* getString(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ size_t stringOffset = getUInt(field);
+ assert(stringOffset < file._stringSize);
+ return reinterpret_cast<char*>(file._stringTable + stringOffset);
+ }
+
+ private:
+ Record(DBCFile& file, unsigned char* offset): file(file), offset(offset) {}
+ DBCFile& file;
+ unsigned char* offset;
+
+ friend class DBCFile;
+ friend class DBCFile::Iterator;
+ };
+ /** Iterator that iterates over records
+ */
+ class Iterator
{
- return record.offset != b.record.offset;
- }
+ public:
+ Iterator(DBCFile &file, unsigned char* offset) : record(file, offset) { }
+
+ /// Advance (prefix only)
+ Iterator& operator++()
+ {
+ record.offset += record.file._recordSize;
+ return *this;
+ }
+
+ /// Return address of current instance
+ Record const& operator*() const { return record; }
+ Record const* operator->() const { return &record; }
+
+ /// Comparison
+ bool operator==(Iterator const& b) const
+ {
+ return record.offset == b.record.offset;
+ }
+
+ bool operator!=(Iterator const& b) const
+ {
+ return record.offset != b.record.offset;
+ }
+
+ private:
+ Record record;
+ };
+
+ // Get record by id
+ Record getRecord(size_t id);
+ /// Get begin iterator over records
+ Iterator begin();
+ /// Get begin iterator over records
+ Iterator end();
+ /// Trivial
+ size_t getRecordCount() const { return _recordCount; }
+ size_t getFieldCount() const { return _fieldCount; }
+ size_t getMaxId();
+
private:
- Record record;
- };
-
- // Get record by id
- Record getRecord(size_t id);
- /// Get begin iterator over records
- Iterator begin();
- /// Get begin iterator over records
- Iterator end();
- /// Trivial
- size_t getRecordCount() const { return recordCount;}
- size_t getFieldCount() const { return fieldCount; }
- size_t getMaxId();
-private:
- std::string filename;
- size_t recordSize;
- size_t recordCount;
- size_t fieldCount;
- size_t stringSize;
- unsigned char *data;
- unsigned char *stringTable;
+ HANDLE _file;
+ size_t _recordSize;
+ size_t _recordCount;
+ size_t _fieldCount;
+ size_t _stringSize;
+ unsigned char* _data;
+ unsigned char* _stringTable;
};
#endif
-
diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp
index 5dcb479a11c..6a47f2d2a30 100644
--- a/src/tools/map_extractor/loadlib.cpp
+++ b/src/tools/map_extractor/loadlib.cpp
@@ -1,11 +1,8 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "loadlib.h"
-#include "mpq_libmpq04.h"
#include <cstdio>
-class MPQFile;
-
u_map_fcc MverMagic = { {'R','E','V','M'} };
FileLoader::FileLoader()
@@ -20,29 +17,31 @@ FileLoader::~FileLoader()
free();
}
-bool FileLoader::loadFile(char *filename, bool log)
+bool FileLoader::loadFile(HANDLE mpq, char* filename, bool log)
{
free();
- MPQFile mf(filename);
- if(mf.isEof())
+ HANDLE file;
+ if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file))
{
if (log)
printf("No such file %s\n", filename);
return false;
}
- data_size = mf.getSize();
-
- data = new uint8 [data_size];
+ data_size = SFileGetFileSize(file, NULL);
+ data = new uint8[data_size];
if (data)
{
- mf.read(data, data_size);
- mf.close();
+ SFileReadFile(file, data, data_size, NULL/*bytesRead*/, NULL);
if (prepareLoadedData())
+ {
+ SFileCloseFile(file);
return true;
+ }
}
- printf("Error loading %s", filename);
- mf.close();
+
+ printf("Error loading %s\n", filename);
+ SFileCloseFile(file);
free();
return false;
}
diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h
index f32f46c63b9..dd8a205a7b2 100644
--- a/src/tools/map_extractor/loadlib/loadlib.h
+++ b/src/tools/map_extractor/loadlib/loadlib.h
@@ -1,6 +1,8 @@
#ifndef LOAD_LIB_H
#define LOAD_LIB_H
+#include "StormLib.h"
+
#ifdef _WIN32
typedef __int64 int64;
typedef __int32 int32;
@@ -48,6 +50,7 @@ struct file_MVER
uint32 ver;
};
+
class FileLoader{
uint8 *data;
uint32 data_size;
@@ -59,7 +62,7 @@ public:
file_MVER *version;
FileLoader();
~FileLoader();
- bool loadFile(char *filename, bool log = true);
+ bool loadFile(HANDLE mpq, char *filename, bool log = true);
virtual void free();
};
#endif
diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp
deleted file mode 100644
index 1c1a12e7b85..00000000000
--- a/src/tools/map_extractor/mpq_libmpq.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "mpq_libmpq04.h"
-#include <deque>
-#include <cstdio>
-
-ArchiveSet gOpenArchives;
-
-MPQArchive::MPQArchive(const char* filename)
-{
- int result = libmpq__archive_open(&mpq_a, filename, -1);
- printf("Opening %s\n", filename);
- if(result) {
- switch(result) {
- case LIBMPQ_ERROR_OPEN :
- printf("Error opening archive '%s': Does file really exist?\n", filename);
- break;
- case LIBMPQ_ERROR_FORMAT : /* bad file format */
- printf("Error opening archive '%s': Bad file format\n", filename);
- break;
- case LIBMPQ_ERROR_SEEK : /* seeking in file failed */
- printf("Error opening archive '%s': Seeking in file failed\n", filename);
- break;
- case LIBMPQ_ERROR_READ : /* Read error in archive */
- printf("Error opening archive '%s': Read error in archive\n", filename);
- break;
- case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */
- printf("Error opening archive '%s': Maybe not enough memory\n", filename);
- break;
- default:
- printf("Error opening archive '%s': Unknown error\n", filename);
- break;
- }
- return;
- }
- gOpenArchives.push_front(this);
-}
-
-void MPQArchive::close()
-{
- //gOpenArchives.erase(erase(&mpq_a);
- libmpq__archive_close(mpq_a);
-}
-
-MPQFile::MPQFile(const char* filename):
- eof(false),
- buffer(0),
- pointer(0),
- size(0)
-{
- for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
- {
- mpq_archive *mpq_a = (*i)->mpq_a;
-
- uint32_t filenum;
- if(libmpq__file_number(mpq_a, filename, &filenum)) continue;
- libmpq__off_t transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
-
- // HACK: in patch.mpq some files don't want to open and give 1 for filesize
- if (size<=1) {
-// printf("warning: file %s has size %d; cannot read.\n", filename, size);
- eof = true;
- buffer = 0;
- return;
- }
- buffer = new char[size];
-
- //libmpq_file_getdata
- libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
- /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/
- return;
-
- }
- eof = true;
- buffer = 0;
-}
-
-size_t MPQFile::read(void* dest, size_t bytes)
-{
- if (eof) return 0;
-
- size_t rpos = pointer + bytes;
- if (rpos > size_t(size)) {
- bytes = size - pointer;
- eof = true;
- }
-
- memcpy(dest, &(buffer[pointer]), bytes);
-
- pointer = rpos;
-
- return bytes;
-}
-
-void MPQFile::seek(int offset)
-{
- pointer = offset;
- eof = (pointer >= size);
-}
-
-void MPQFile::seekRelative(int offset)
-{
- pointer += offset;
- eof = (pointer >= size);
-}
-
-void MPQFile::close()
-{
- if (buffer) delete[] buffer;
- buffer = 0;
- eof = true;
-}
diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/map_extractor/mpq_libmpq04.h
deleted file mode 100644
index 9f0163067c4..00000000000
--- a/src/tools/map_extractor/mpq_libmpq04.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef MPQ_H
-#define MPQ_H
-
-#include "loadlib/loadlib.h"
-#include "libmpq/mpq.h"
-#include <string.h>
-#include <ctype.h>
-#include <vector>
-#include <iostream>
-#include <deque>
-
-using namespace std;
-
-class MPQArchive
-{
-
-public:
- mpq_archive_s *mpq_a;
-
- MPQArchive(const char* filename);
- void close();
-
- void GetFileListTo(vector<string>& filelist) {
- uint32_t filenum;
- if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return;
- libmpq__off_t size, transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
-
- char *buffer = new char[size];
-
- libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
-
- char seps[] = "\n";
- char *token;
-
- token = strtok( buffer, seps );
- uint32 counter = 0;
- while ((token != NULL) && (counter < size)) {
- //cout << token << endl;
- token[strlen(token) - 1] = 0;
- string s = token;
- filelist.push_back(s);
- counter += strlen(token) + 2;
- token = strtok(NULL, seps);
- }
-
- delete[] buffer;
- }
-};
-typedef std::deque<MPQArchive*> ArchiveSet;
-
-class MPQFile
-{
- //MPQHANDLE handle;
- bool eof;
- char *buffer;
- libmpq__off_t pointer,size;
-
- // disable copying
- MPQFile(const MPQFile& /*f*/) {}
- void operator=(const MPQFile& /*f*/) {}
-
-public:
- MPQFile(const char* filename); // filenames are not case sensitive
- ~MPQFile() { close(); }
- size_t read(void* dest, size_t bytes);
- size_t getSize() { return size; }
- size_t getPos() { return pointer; }
- char* getBuffer() { return buffer; }
- char* getPointer() { return buffer + pointer; }
- bool isEof() { return eof; }
- void seek(int offset);
- void seekRelative(int offset);
- void close();
-};
-
-inline void flipcc(char *fcc)
-{
- char t;
- t=fcc[0];
- fcc[0]=fcc[3];
- fcc[3]=t;
- t=fcc[1];
- fcc[1]=fcc[2];
- fcc[2]=t;
-}
-
-#endif
diff --git a/src/tools/map_extractor/wdt.cpp b/src/tools/map_extractor/wdt.cpp
index ff255145583..f9f1d8a163c 100644
--- a/src/tools/map_extractor/wdt.cpp
+++ b/src/tools/map_extractor/wdt.cpp
@@ -61,6 +61,6 @@ bool WDT_file::prepareLoadedData()
return false;
wmo = (wdt_MWMO *)((uint8*)main+ main->size+8);
if (!wmo->prepareLoadedData())
- return false;
+ wmo = NULL; // optional as of cataclysm
return true;
}
diff --git a/src/tools/map_extractor/wdt.h b/src/tools/map_extractor/wdt.h
index fcee8ac64f2..be6df3f173d 100644
--- a/src/tools/map_extractor/wdt.h
+++ b/src/tools/map_extractor/wdt.h
@@ -45,7 +45,7 @@ public:
uint32 size;
struct adtData{
- uint32 exist;
+ uint32 flag;
uint32 data1;
} adt_list[64][64];
diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt
index 8d455eae6ee..97a83c4c482 100644
--- a/src/tools/vmap4_assembler/CMakeLists.txt
+++ b/src/tools/vmap4_assembler/CMakeLists.txt
@@ -21,10 +21,7 @@ include_directories(
)
add_executable(vmap4assembler VMapAssembler.cpp)
-
-if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
- set_target_properties(vmap4assembler PROPERTIES LINK_FLAGS "-framework Carbon")
-endif()
+add_dependencies(vmap4assembler storm)
target_link_libraries(vmap4assembler
collision
diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt
index 023f5447f85..201f32ab630 100644
--- a/src/tools/vmap4_extractor/CMakeLists.txt
+++ b/src/tools/vmap4_extractor/CMakeLists.txt
@@ -11,27 +11,30 @@
file(GLOB_RECURSE sources *.cpp *.h)
-set(include_Dirs
- ${CMAKE_SOURCE_DIR}/dep/libmpq
-)
+# uncomment next line to disable debug mode
+add_definitions("-DIOMAP_DEBUG")
-if( WIN32 )
- set(include_Dirs
- ${include_Dirs}
- ${CMAKE_SOURCE_DIR}/dep/libmpq/win
- )
+# build setup currently only supports libmpq 0.4.x
+if( NOT MSVC )
+ add_definitions("-Wall")
+ add_definitions("-ggdb")
+ add_definitions("-O3")
endif()
-include_directories(${include_Dirs})
+include_directories(
+ ${CMAKE_SOURCE_DIR}/dep/StormLib/src
+)
add_executable(vmap4extractor ${sources})
target_link_libraries(vmap4extractor
- mpq
${BZIP2_LIBRARIES}
${ZLIB_LIBRARIES}
+ storm
)
+add_dependencies(vmap4extractor storm)
+
if( UNIX )
install(TARGETS vmap4extractor DESTINATION bin)
elseif( WIN32 )
diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp
index 56e62d474d1..652b162189b 100644
--- a/src/tools/vmap4_extractor/adtfile.cpp
+++ b/src/tools/vmap4_extractor/adtfile.cpp
@@ -74,7 +74,9 @@ char* GetExtension(char* FileName)
return NULL;
}
-ADTFile::ADTFile(char* filename): ADT(filename), nWMO(0), nMDX(0), WmoInstansName(NULL), ModelInstansName(NULL)
+extern HANDLE WorldMpq;
+
+ADTFile::ADTFile(char* filename) : ADT(WorldMpq, filename, false)
{
Adtfilename.append(filename);
}
diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h
index 3de1dccfacd..0aefdff4bf8 100644
--- a/src/tools/vmap4_extractor/adtfile.h
+++ b/src/tools/vmap4_extractor/adtfile.h
@@ -19,7 +19,7 @@
#ifndef ADT_H
#define ADT_H
-#include "mpq_libmpq04.h"
+#include "mpqfile.h"
#include "wmo.h"
#include "model.h"
diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp
index a651456d916..efc8aeabe8c 100644
--- a/src/tools/vmap4_extractor/dbcfile.cpp
+++ b/src/tools/vmap4_extractor/dbcfile.cpp
@@ -16,81 +16,104 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "dbcfile.h"
-#include "mpq_libmpq04.h"
-#undef min
-#undef max
+#define _CRT_SECURE_NO_DEPRECATE
-#include <cstdio>
+#include "dbcfile.h"
-DBCFile::DBCFile(const std::string& filename):
- filename(filename), recordSize(0), recordCount(0), fieldCount(0), stringSize(0), data(NULL), stringTable(NULL)
+DBCFile::DBCFile(HANDLE mpq, const char* filename) :
+ _mpq(mpq), _filename(filename), _file(NULL), _data(NULL), _stringTable(NULL)
{
-
}
bool DBCFile::open()
{
- MPQFile f(filename.c_str());
+ if (!SFileOpenFileEx(_mpq, _filename, SFILE_OPEN_PATCHED_FILE, &_file))
+ return false;
+
+ char header[4];
+ unsigned int na, nb, es, ss;
+
+ DWORD readBytes = 0;
+ SFileReadFile(_file, header, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of records
+ return false;
+
+ if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C')
+ return false;
- // Need some error checking, otherwise an unhandled exception error occurs
- // if people screw with the data path.
- if (f.isEof() == true)
+ readBytes = 0;
+ SFileReadFile(_file, &na, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of records
return false;
- unsigned char header[4];
- unsigned int na,nb,es,ss;
+ readBytes = 0;
+ SFileReadFile(_file, &nb, 4, &readBytes, NULL);
+ if (readBytes != 4) // Number of fields
+ return false;
- f.read(header,4); // File Header
+ readBytes = 0;
+ SFileReadFile(_file, &es, 4, &readBytes, NULL);
+ if (readBytes != 4) // Size of a record
+ return false;
- if (header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3] != 'C')
- {
- f.close();
- data = NULL;
- printf("Critical Error: An error occured while trying to read the DBCFile %s.", filename.c_str());
+ readBytes = 0;
+ SFileReadFile(_file, &ss, 4, &readBytes, NULL);
+ if (readBytes != 4) // String size
return false;
- }
-
- //assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C');
-
- f.read(&na,4); // Number of records
- f.read(&nb,4); // Number of fields
- f.read(&es,4); // Size of a record
- f.read(&ss,4); // String size
-
- recordSize = es;
- recordCount = na;
- fieldCount = nb;
- stringSize = ss;
- //assert(fieldCount*4 == recordSize);
- assert(fieldCount*4 >= recordSize);
-
- data = new unsigned char[recordSize*recordCount+stringSize];
- stringTable = data + recordSize*recordCount;
- f.read(data,recordSize*recordCount+stringSize);
- f.close();
+
+ _recordSize = es;
+ _recordCount = na;
+ _fieldCount = nb;
+ _stringSize = ss;
+ if (_fieldCount * 4 != _recordSize)
+ return false;
+
+ _data = new unsigned char[_recordSize * _recordCount + _stringSize];
+ _stringTable = _data + _recordSize*_recordCount;
+
+ size_t data_size = _recordSize * _recordCount + _stringSize;
+ readBytes = 0;
+ SFileReadFile(_file, _data, data_size, &readBytes, NULL);
+ if (readBytes != data_size)
+ return false;
+
return true;
}
DBCFile::~DBCFile()
{
- delete [] data;
+ delete [] _data;
+ if (_file != NULL)
+ SFileCloseFile(_file);
}
DBCFile::Record DBCFile::getRecord(size_t id)
{
- assert(data);
- return Record(*this, data + id*recordSize);
+ assert(_data);
+ return Record(*this, _data + id*_recordSize);
+}
+
+size_t DBCFile::getMaxId()
+{
+ assert(_data);
+
+ size_t maxId = 0;
+ for(size_t i = 0; i < getRecordCount(); ++i)
+ if (maxId < getRecord(i).getUInt(0))
+ maxId = getRecord(i).getUInt(0);
+
+ return maxId;
}
DBCFile::Iterator DBCFile::begin()
{
- assert(data);
- return Iterator(*this, data);
+ assert(_data);
+ return Iterator(*this, _data);
}
DBCFile::Iterator DBCFile::end()
{
- assert(data);
- return Iterator(*this, stringTable);
+ assert(_data);
+ return Iterator(*this, _stringTable);
}
+
diff --git a/src/tools/vmap4_extractor/dbcfile.h b/src/tools/vmap4_extractor/dbcfile.h
index 56cce9a521c..2c43cb1a808 100644
--- a/src/tools/vmap4_extractor/dbcfile.h
+++ b/src/tools/vmap4_extractor/dbcfile.h
@@ -18,138 +18,129 @@
#ifndef DBCFILE_H
#define DBCFILE_H
-
#include <cassert>
#include <string>
+#include "StormLib.h"
class DBCFile
{
-public:
- DBCFile(const std::string &filename);
- ~DBCFile();
-
- // Open database. It must be openened before it can be used.
- bool open();
-
- // TODO: Add a close function?
-
- // Database exceptions
- class Exception
- {
public:
- Exception(const std::string &message): message(message)
- { }
- virtual ~Exception()
- { }
- const std::string &getMessage() {return message;}
- private:
- std::string message;
- };
+ DBCFile(HANDLE mpq, const char* filename);
+ ~DBCFile();
- //
- class NotFound: public Exception
- {
- public:
- NotFound(): Exception("Key was not found")
- { }
- };
-
- // Iteration over database
- class Iterator;
- class Record
- {
- public:
- Record& operator= (const Record& r)
- {
- file = r.file;
- offset = r.offset;
- return *this;
- }
- float getFloat(size_t field) const
- {
- assert(field < file.fieldCount);
- return *reinterpret_cast<float*>(offset+field*4);
- }
- unsigned int getUInt(size_t field) const
- {
- assert(field < file.fieldCount);
- return *reinterpret_cast<unsigned int*>(offset+(field*4));
- }
- int getInt(size_t field) const
+ // Open database. It must be openened before it can be used.
+ bool open();
+
+ // Database exceptions
+ class Exception
{
- assert(field < file.fieldCount);
- return *reinterpret_cast<int*>(offset+field*4);
- }
- unsigned char getByte(size_t ofs) const
+ public:
+ Exception(const std::string &message) : message(message) { }
+ virtual ~Exception() { }
+ const std::string &getMessage() { return message; }
+ private:
+ std::string message;
+ };
+
+ class NotFound: public Exception
{
- assert(ofs < file.recordSize);
- return *reinterpret_cast<unsigned char*>(offset+ofs);
- }
- const char *getString(size_t field) const
+ public:
+ NotFound(): Exception("Key was not found") { }
+ };
+
+ // Iteration over database
+ class Iterator;
+ class Record
{
- assert(field < file.fieldCount);
- size_t stringOffset = getUInt(field);
- assert(stringOffset < file.stringSize);
- //char * tmp = (char*)file.stringTable + stringOffset;
- //unsigned char * tmp2 = file.stringTable + stringOffset;
- return reinterpret_cast<char*>(file.stringTable + stringOffset);
- }
- private:
- Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {}
- DBCFile &file;
- unsigned char *offset;
+ public:
+ float getFloat(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<float*>(offset + field * 4);
+ }
- friend class DBCFile;
- friend class Iterator;
- };
+ unsigned int getUInt(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<unsigned int*>(offset + field * 4);
+ }
- /* Iterator that iterates over records */
- class Iterator
- {
- public:
- Iterator(DBCFile &file, unsigned char *offset):
- record(file, offset) {}
- /// Advance (prefix only)
- Iterator & operator++() {
- record.offset += record.file.recordSize;
- return *this;
- }
- /// Return address of current instance
- Record const & operator*() const { return record; }
- const Record* operator->() const {
- return &record;
- }
- /// Comparison
- bool operator==(const Iterator &b) const
- {
- return record.offset == b.record.offset;
- }
- bool operator!=(const Iterator &b) const
+ int getInt(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ return *reinterpret_cast<int*>(offset + field * 4);
+ }
+
+ char const* getString(size_t field) const
+ {
+ assert(field < file._fieldCount);
+ size_t stringOffset = getUInt(field);
+ assert(stringOffset < file._stringSize);
+ return reinterpret_cast<char*>(file._stringTable + stringOffset);
+ }
+
+ private:
+ Record(DBCFile& file, unsigned char* offset): file(file), offset(offset) {}
+ DBCFile& file;
+ unsigned char* offset;
+
+ friend class DBCFile;
+ friend class DBCFile::Iterator;
+ };
+ /** Iterator that iterates over records
+ */
+ class Iterator
{
- return record.offset != b.record.offset;
- }
+ public:
+ Iterator(DBCFile &file, unsigned char* offset) : record(file, offset) { }
+
+ /// Advance (prefix only)
+ Iterator& operator++()
+ {
+ record.offset += record.file._recordSize;
+ return *this;
+ }
+
+ /// Return address of current instance
+ Record const& operator*() const { return record; }
+ Record const* operator->() const { return &record; }
+
+ /// Comparison
+ bool operator==(Iterator const& b) const
+ {
+ return record.offset == b.record.offset;
+ }
+
+ bool operator!=(Iterator const& b) const
+ {
+ return record.offset != b.record.offset;
+ }
+
+ private:
+ Record record;
+ };
+
+ // Get record by id
+ Record getRecord(size_t id);
+ /// Get begin iterator over records
+ Iterator begin();
+ /// Get begin iterator over records
+ Iterator end();
+ /// Trivial
+ size_t getRecordCount() const { return _recordCount; }
+ size_t getFieldCount() const { return _fieldCount; }
+ size_t getMaxId();
+
private:
- Record record;
- };
-
- // Get record by id
- Record getRecord(size_t id);
- /// Get begin iterator over records
- Iterator begin();
- /// Get begin iterator over records
- Iterator end();
- /// Trivial
- size_t getRecordCount() const { return recordCount;}
- size_t getFieldCount() const { return fieldCount; }
-
-private:
- std::string filename;
- size_t recordSize;
- size_t recordCount;
- size_t fieldCount;
- size_t stringSize;
- unsigned char *data;
- unsigned char *stringTable;
+ HANDLE _mpq;
+ const char* _filename;
+ HANDLE _file;
+ size_t _recordSize;
+ size_t _recordCount;
+ size_t _fieldCount;
+ size_t _stringSize;
+ unsigned char *_data;
+ unsigned char* _stringTable;
};
#endif
diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp
index 8a1f67cd2c2..4c8e423bfc4 100644
--- a/src/tools/vmap4_extractor/gameobject_extract.cpp
+++ b/src/tools/vmap4_extractor/gameobject_extract.cpp
@@ -35,10 +35,12 @@ bool ExtractSingleModel(std::string& fname)
return mdl.ConvertToVMAPModel(output.c_str());
}
+extern HANDLE LocaleMpq;
+
void ExtractGameobjectModels()
{
printf("Extracting GameObject models...");
- DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc");
+ DBCFile dbc(LocaleMpq, "DBFilesClient\\GameObjectDisplayInfo.dbc");
if(!dbc.open())
{
printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n");
diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h
deleted file mode 100644
index 61865c4b436..00000000000
--- a/src/tools/vmap4_extractor/loadlib/loadlib.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef LOAD_LIB_H
-#define LOAD_LIB_H
-
-#ifdef WIN32
-typedef __int64 int64;
-typedef __int32 int32;
-typedef __int16 int16;
-typedef __int8 int8;
-typedef unsigned __int64 uint64;
-typedef unsigned __int32 uint32;
-typedef unsigned __int16 uint16;
-typedef unsigned __int8 uint8;
-#else
-#include <stdint.h>
-#ifndef uint64_t
-#ifdef __linux__
-#include <linux/types.h>
-#endif
-#endif
-typedef int64_t int64;
-typedef int32_t int32;
-typedef int16_t int16;
-typedef int8_t int8;
-typedef uint64_t uint64;
-typedef uint32_t uint32;
-typedef uint16_t uint16;
-typedef uint8_t uint8;
-#endif
-
-#define FILE_FORMAT_VERSION 18
-
-//
-// File version chunk
-//
-struct file_MVER
-{
- union{
- uint32 fcc;
- char fcc_txt[4];
- };
- uint32 size;
- uint32 ver;
-};
-
-class FileLoader{
- uint8 *data;
- uint32 data_size;
-public:
- virtual bool prepareLoadedData();
- uint8 *GetData() {return data;}
- uint32 GetDataSize() {return data_size;}
-
- file_MVER *version;
- FileLoader();
- ~FileLoader();
- bool loadFile(char *filename, bool log = true);
- virtual void free();
-};
-#endif
diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp
index b950db023fe..68b839c4a6d 100644
--- a/src/tools/vmap4_extractor/model.cpp
+++ b/src/tools/vmap4_extractor/model.cpp
@@ -19,11 +19,13 @@
#include "vmapexport.h"
#include "model.h"
#include "wmo.h"
-#include "mpq_libmpq04.h"
+#include "mpqfile.h"
#include <cassert>
#include <algorithm>
#include <cstdio>
+extern HANDLE WorldMpq;
+
Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0)
{
memset(&header, 0, sizeof(header));
@@ -31,7 +33,7 @@ Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0
bool Model::open()
{
- MPQFile f(filename.c_str());
+ MPQFile f(WorldMpq, filename.c_str());
if (f.isEof())
{
diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h
index bf15d813ce8..a45da99d762 100644
--- a/src/tools/vmap4_extractor/model.h
+++ b/src/tools/vmap4_extractor/model.h
@@ -19,7 +19,6 @@
#ifndef MODEL_H
#define MODEL_H
-#include "loadlib/loadlib.h"
#include "vec3d.h"
#include "modelheaders.h"
#include <vector>
diff --git a/src/tools/vmap4_extractor/modelheaders.h b/src/tools/vmap4_extractor/modelheaders.h
index d859fd3511e..7fd908d7442 100644
--- a/src/tools/vmap4_extractor/modelheaders.h
+++ b/src/tools/vmap4_extractor/modelheaders.h
@@ -19,12 +19,7 @@
#ifndef MODELHEADERS_H
#define MODELHEADERS_H
-/* typedef unsigned char uint8;
-typedef char int8;
-typedef unsigned short uint16;
-typedef short int16;
-typedef unsigned int uint32;
-typedef int int32; */
+#include "mpqfile.h" // integer typedefs
#pragma pack(push,1)
diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp
deleted file mode 100644
index ffa097d9a22..00000000000
--- a/src/tools/vmap4_extractor/mpq_libmpq.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "mpq_libmpq04.h"
-#include <deque>
-#include <cstdio>
-
-ArchiveSet gOpenArchives;
-
-MPQArchive::MPQArchive(const char* filename)
-{
- int result = libmpq__archive_open(&mpq_a, filename, -1);
- printf("Opening %s\n", filename);
- if(result) {
- switch(result) {
- case LIBMPQ_ERROR_OPEN :
- printf("Error opening archive '%s': Does file really exist?\n", filename);
- break;
- case LIBMPQ_ERROR_FORMAT : /* bad file format */
- printf("Error opening archive '%s': Bad file format\n", filename);
- break;
- case LIBMPQ_ERROR_SEEK : /* seeking in file failed */
- printf("Error opening archive '%s': Seeking in file failed\n", filename);
- break;
- case LIBMPQ_ERROR_READ : /* Read error in archive */
- printf("Error opening archive '%s': Read error in archive\n", filename);
- break;
- case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */
- printf("Error opening archive '%s': Maybe not enough memory\n", filename);
- break;
- default:
- printf("Error opening archive '%s': Unknown error\n", filename);
- break;
- }
- return;
- }
- gOpenArchives.push_front(this);
-}
-
-void MPQArchive::close()
-{
- //gOpenArchives.erase(erase(&mpq_a);
- libmpq__archive_close(mpq_a);
-}
-
-MPQFile::MPQFile(const char* filename):
- eof(false),
- buffer(0),
- pointer(0),
- size(0)
-{
- for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
- {
- mpq_archive *mpq_a = (*i)->mpq_a;
-
- uint32 filenum;
- if(libmpq__file_number(mpq_a, filename, &filenum)) continue;
- libmpq__off_t transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
-
- // HACK: in patch.mpq some files don't want to open and give 1 for filesize
- if (size<=1) {
- // printf("info: file %s has size %d; considered dummy file.\n", filename, size);
- eof = true;
- buffer = 0;
- return;
- }
- buffer = new char[size];
-
- //libmpq_file_getdata
- libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
- /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/
- return;
-
- }
- eof = true;
- buffer = 0;
-}
-
-size_t MPQFile::read(void* dest, size_t bytes)
-{
- if (eof) return 0;
-
- size_t rpos = pointer + bytes;
- if (rpos > size_t(size)) {
- bytes = size - pointer;
- eof = true;
- }
-
- memcpy(dest, &(buffer[pointer]), bytes);
-
- pointer = rpos;
-
- return bytes;
-}
-
-void MPQFile::seek(int offset)
-{
- pointer = offset;
- eof = (pointer >= size);
-}
-
-void MPQFile::seekRelative(int offset)
-{
- pointer += offset;
- eof = (pointer >= size);
-}
-
-void MPQFile::close()
-{
- if (buffer) delete[] buffer;
- buffer = 0;
- eof = true;
-}
diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h
deleted file mode 100644
index 9f0163067c4..00000000000
--- a/src/tools/vmap4_extractor/mpq_libmpq04.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef MPQ_H
-#define MPQ_H
-
-#include "loadlib/loadlib.h"
-#include "libmpq/mpq.h"
-#include <string.h>
-#include <ctype.h>
-#include <vector>
-#include <iostream>
-#include <deque>
-
-using namespace std;
-
-class MPQArchive
-{
-
-public:
- mpq_archive_s *mpq_a;
-
- MPQArchive(const char* filename);
- void close();
-
- void GetFileListTo(vector<string>& filelist) {
- uint32_t filenum;
- if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return;
- libmpq__off_t size, transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
-
- char *buffer = new char[size];
-
- libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
-
- char seps[] = "\n";
- char *token;
-
- token = strtok( buffer, seps );
- uint32 counter = 0;
- while ((token != NULL) && (counter < size)) {
- //cout << token << endl;
- token[strlen(token) - 1] = 0;
- string s = token;
- filelist.push_back(s);
- counter += strlen(token) + 2;
- token = strtok(NULL, seps);
- }
-
- delete[] buffer;
- }
-};
-typedef std::deque<MPQArchive*> ArchiveSet;
-
-class MPQFile
-{
- //MPQHANDLE handle;
- bool eof;
- char *buffer;
- libmpq__off_t pointer,size;
-
- // disable copying
- MPQFile(const MPQFile& /*f*/) {}
- void operator=(const MPQFile& /*f*/) {}
-
-public:
- MPQFile(const char* filename); // filenames are not case sensitive
- ~MPQFile() { close(); }
- size_t read(void* dest, size_t bytes);
- size_t getSize() { return size; }
- size_t getPos() { return pointer; }
- char* getBuffer() { return buffer; }
- char* getPointer() { return buffer + pointer; }
- bool isEof() { return eof; }
- void seek(int offset);
- void seekRelative(int offset);
- void close();
-};
-
-inline void flipcc(char *fcc)
-{
- char t;
- t=fcc[0];
- fcc[0]=fcc[3];
- fcc[3]=t;
- t=fcc[1];
- fcc[1]=fcc[2];
- fcc[2]=t;
-}
-
-#endif
diff --git a/src/tools/vmap4_extractor/mpqfile.cpp b/src/tools/vmap4_extractor/mpqfile.cpp
new file mode 100644
index 00000000000..4e690aabee3
--- /dev/null
+++ b/src/tools/vmap4_extractor/mpqfile.cpp
@@ -0,0 +1,87 @@
+#include "mpqfile.h"
+#include <deque>
+#include <cstdio>
+#include "StormLib.h"
+
+MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/) :
+ eof(false),
+ buffer(0),
+ pointer(0),
+ size(0)
+{
+ HANDLE file;
+ if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file))
+ {
+ if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND)
+ fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError());
+ eof = true;
+ return;
+ }
+
+ DWORD hi = 0;
+ size = SFileGetFileSize(file, &hi);
+
+ if (hi)
+ {
+ fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, uint32(hi));
+ SFileCloseFile(file);
+ eof = true;
+ return;
+ }
+
+ if (size <= 1)
+ {
+ fprintf(stderr, "Can't open %s, size = %u!\n", filename, uint32(size));
+ SFileCloseFile(file);
+ eof = true;
+ return;
+ }
+
+ DWORD read = 0;
+ buffer = new char[size];
+ if (!SFileReadFile(file, buffer, size, &read) || size != read)
+ {
+ fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, uint32(size), uint32(read));
+ SFileCloseFile(file);
+ eof = true;
+ return;
+ }
+
+ SFileCloseFile(file);
+}
+
+size_t MPQFile::read(void* dest, size_t bytes)
+{
+ if (eof) return 0;
+
+ size_t rpos = pointer + bytes;
+ if (rpos > size) {
+ bytes = size - pointer;
+ eof = true;
+ }
+
+ memcpy(dest, &(buffer[pointer]), bytes);
+
+ pointer = rpos;
+
+ return bytes;
+}
+
+void MPQFile::seek(int offset)
+{
+ pointer = offset;
+ eof = (pointer >= size);
+}
+
+void MPQFile::seekRelative(int offset)
+{
+ pointer += offset;
+ eof = (pointer >= size);
+}
+
+void MPQFile::close()
+{
+ if (buffer) delete[] buffer;
+ buffer = 0;
+ eof = true;
+}
diff --git a/src/tools/vmap4_extractor/mpqfile.h b/src/tools/vmap4_extractor/mpqfile.h
new file mode 100644
index 00000000000..e7379c4f7a0
--- /dev/null
+++ b/src/tools/vmap4_extractor/mpqfile.h
@@ -0,0 +1,81 @@
+#define _CRT_SECURE_NO_DEPRECATE
+#ifndef _CRT_SECURE_NO_WARNINGS // fuck the police^Wwarnings
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#ifndef MPQ_H
+#define MPQ_H
+
+#include <string.h>
+#include <ctype.h>
+#include <vector>
+#include <iostream>
+#include <deque>
+#include "StormLib.h"
+
+#ifdef _WIN32
+#include <Windows.h> // mainly only HANDLE definition is required
+typedef __int64 int64;
+typedef __int32 int32;
+typedef __int16 int16;
+typedef __int8 int8;
+typedef unsigned __int64 uint64;
+typedef unsigned __int32 uint32;
+typedef unsigned __int16 uint16;
+typedef unsigned __int8 uint8;
+#else
+#include <stdint.h>
+#ifndef uint64_t
+#ifdef __linux__
+#include <linux/types.h>
+#endif
+#endif
+typedef int64_t int64;
+typedef int32_t int32;
+typedef int16_t int16;
+typedef int8_t int8;
+typedef uint64_t uint64;
+typedef uint32_t uint32;
+typedef uint16_t uint16;
+typedef uint8_t uint8;
+#endif
+
+using namespace std;
+
+class MPQFile
+{
+ //MPQHANDLE handle;
+ bool eof;
+ char *buffer;
+ size_t pointer,size;
+
+ // disable copying
+ MPQFile(const MPQFile &f);
+ void operator=(const MPQFile &f);
+
+public:
+ MPQFile(HANDLE mpq, const char* filename, bool warnNoExist = true); // filenames are not case sensitive
+ ~MPQFile() { close(); }
+ size_t read(void* dest, size_t bytes);
+ size_t getSize() { return size; }
+ size_t getPos() { return pointer; }
+ char* getBuffer() { return buffer; }
+ char* getPointer() { return buffer + pointer; }
+ bool isEof() { return eof; }
+ void seek(int offset);
+ void seekRelative(int offset);
+ void close();
+};
+
+inline void flipcc(char *fcc)
+{
+ char t;
+ t=fcc[0];
+ fcc[0]=fcc[3];
+ fcc[3]=t;
+ t=fcc[1];
+ fcc[1]=fcc[2];
+ fcc[2]=t;
+}
+
+#endif
diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp
index 89e4b850dac..84390a5fc9a 100644
--- a/src/tools/vmap4_extractor/vmapexport.cpp
+++ b/src/tools/vmap4_extractor/vmapexport.cpp
@@ -30,6 +30,7 @@
#define mkdir _mkdir
#else
#include <sys/stat.h>
+ #define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
#endif
#undef min
@@ -45,7 +46,7 @@
#include "wdtfile.h"
#include "dbcfile.h"
#include "wmo.h"
-#include "mpq_libmpq04.h"
+#include "mpqfile.h"
#include "vmapexport.h"
@@ -56,7 +57,47 @@
//-----------------------------------------------------------------------------
-extern ArchiveSet gOpenArchives;
+HANDLE WorldMpq = NULL;
+HANDLE LocaleMpq = NULL;
+
+uint32 CONF_TargetBuild = 15595; // 4.3.4.15595
+
+// List MPQ for extract maps from
+char const* CONF_mpq_list[]=
+{
+ "world.MPQ",
+ "art.MPQ",
+ "expansion1.MPQ",
+ "expansion2.MPQ",
+ "expansion3.MPQ",
+ "world2.MPQ",
+};
+
+uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0};
+#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder
+#define NEW_BASE_SET_BUILD 15211
+
+#define LOCALES_COUNT 12
+
+char const* Locales[LOCALES_COUNT] =
+{
+ "enGB", "enUS",
+ "deDE", "esES",
+ "frFR", "koKR",
+ "zhCN", "zhTW",
+ "enCN", "enTW",
+ "esMX", "ruRU"
+};
+
+TCHAR const* LocalesT[LOCALES_COUNT] =
+{
+ _T("enGB"), _T("enUS"),
+ _T("deDE"), _T("esES"),
+ _T("frFR"), _T("koKR"),
+ _T("zhCN"), _T("zhTW"),
+ _T("enCN"), _T("enTW"),
+ _T("esMX"), _T("ruRU"),
+};
typedef struct
{
@@ -69,7 +110,6 @@ uint16 *LiqType = 0;
uint32 map_count;
char output_path[128]=".";
char input_path[1024]=".";
-bool hasInputPathParam = false;
bool preciseVectorData = false;
// Constants
@@ -78,6 +118,120 @@ bool preciseVectorData = false;
const char* szWorkDirWmo = "./Buildings";
const char* szRawVMAPMagic = "VMAP041";
+bool LoadLocaleMPQFile(int locale)
+{
+ TCHAR buff[512];
+ memset(buff, 0, sizeof(buff));
+ _stprintf(buff, _T("%s%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]);
+ if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ {
+ _tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]);
+ _tprintf(_T("Cannot open archive %s\n"), buff);
+ }
+ return false;
+ }
+
+ _tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]);
+ char const* prefix = NULL;
+ for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
+ {
+ // Do not attempt to read older MPQ patch archives past this build, they were merged with base
+ // and trying to read them together with new base will not end well
+ if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
+ continue;
+
+ memset(buff, 0, sizeof(buff));
+ if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
+ {
+ prefix = "";
+ _stprintf(buff, _T("%s%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]);
+ }
+ else
+ {
+ prefix = Locales[locale];
+ _stprintf(buff, _T("%swow-update-%u.MPQ"), input_path, Builds[i]);
+ }
+
+ if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
+ {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ _tprintf(_T("Cannot open patch archive %s\n"), buff);
+ continue;
+ }
+ }
+
+ printf("\n");
+ return true;
+}
+
+void LoadCommonMPQFiles(uint32 build)
+{
+ TCHAR filename[512];
+ _stprintf(filename, _T("%sworld.MPQ"), input_path);
+ _tprintf(_T("Loading common MPQ files\n"));
+ if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open archive %s\n"), filename);
+ return;
+ }
+
+ int count = sizeof(CONF_mpq_list) / sizeof(char*);
+ for (int i = 1; i < count; ++i)
+ {
+ if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i])) // 4.3.2 and higher MPQ
+ continue;
+
+ _stprintf(filename, _T("%s%s"), input_path, CONF_mpq_list[i]);
+ if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open archive %s\n"), filename);
+ else
+ _tprintf(_T("Not found %s\n"), filename);
+ }
+ else
+ _tprintf(_T("Loaded %s\n"), filename);
+ }
+
+ char const* prefix = NULL;
+ for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
+ {
+ // Do not attempt to read older MPQ patch archives past this build, they were merged with base
+ // and trying to read them together with new base will not end well
+ if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
+ continue;
+
+ memset(filename, 0, sizeof(filename));
+ if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
+ {
+ prefix = "";
+ _stprintf(filename, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]);
+ }
+ else
+ {
+ prefix = "base";
+ _stprintf(filename, _T("%swow-update-%u.MPQ"), input_path, Builds[i]);
+ }
+
+ if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ _tprintf(_T("Cannot open patch archive %s\n"), filename);
+ else
+ _tprintf(_T("Not found %s\n"), filename);
+ continue;
+ }
+ else
+ _tprintf(_T("Loaded %s\n"), filename);
+ }
+
+ printf("\n");
+}
+
+
// Local testing functions
bool FileExists(const char* file)
@@ -103,7 +257,8 @@ void strToLower(char* str)
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
- DBCFile dbc("DBFilesClient\\LiquidType.dbc");
+
+ DBCFile dbc(LocaleMpq, "DBFilesClient\\LiquidType.dbc");
if(!dbc.open())
{
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
@@ -123,21 +278,23 @@ void ReadLiquidTypeTableDBC()
bool ExtractWmo()
{
- bool success = true;
+ bool success = false;
//const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
- for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr)
+ SFILE_FIND_DATA data;
+ HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL);
+ if (find != NULL)
{
- vector<string> filelist;
-
- (*ar_itr)->GetFileListTo(filelist);
- for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname)
+ do
{
- if (fname->find(".wmo") != string::npos)
- success = ExtractSingleWmo(*fname);
+ std::string str = data.cFileName;
+ //printf("Extracting wmo %s\n", str.c_str());
+ success |= ExtractSingleWmo(str);
}
+ while (SFileFindNextFile(find, &data));
}
+ SFileFindClose(find);
if (success)
printf("\nExtract wmo complete (No (fatal) errors)\n");
@@ -297,91 +454,10 @@ bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames)
return(true);
}
-bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames)
-{
- if(!hasInputPathParam)
- getGamePath();
-
- printf("\nGame path: %s\n", input_path);
-
- char path[512];
- string in_path(input_path);
- std::vector<std::string> locales, searchLocales;
-
- searchLocales.push_back("enGB");
- searchLocales.push_back("enUS");
- searchLocales.push_back("deDE");
- searchLocales.push_back("esES");
- searchLocales.push_back("frFR");
- searchLocales.push_back("koKR");
- searchLocales.push_back("zhCN");
- searchLocales.push_back("zhTW");
- searchLocales.push_back("enCN");
- searchLocales.push_back("enTW");
- searchLocales.push_back("esMX");
- searchLocales.push_back("ruRU");
-
- for (std::vector<std::string>::iterator i = searchLocales.begin(); i != searchLocales.end(); ++i)
- {
- std::string localePath = in_path + *i;
- // check if locale exists:
- struct stat status;
- if (stat(localePath.c_str(), &status))
- continue;
- if ((status.st_mode & S_IFDIR) == 0)
- continue;
- printf("Found locale '%s'\n", i->c_str());
- locales.push_back(*i);
- }
- printf("\n");
-
- // open locale expansion and common files
- printf("Adding data files from locale directories.\n");
- for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i)
- {
- pArchiveNames.push_back(in_path + *i + "/locale-" + *i + ".MPQ");
- pArchiveNames.push_back(in_path + *i + "/expansion-locale-" + *i + ".MPQ");
- pArchiveNames.push_back(in_path + *i + "/lichking-locale-" + *i + ".MPQ");
- }
-
- // open expansion and common files
- pArchiveNames.push_back(input_path + string("common.MPQ"));
- pArchiveNames.push_back(input_path + string("common-2.MPQ"));
- pArchiveNames.push_back(input_path + string("expansion.MPQ"));
- pArchiveNames.push_back(input_path + string("lichking.MPQ"));
-
- // now, scan for the patch levels in the core dir
- printf("Scanning patch levels from data directory.\n");
- sprintf(path, "%spatch", input_path);
- if (!scan_patches(path, pArchiveNames))
- return(false);
-
- // now, scan for the patch levels in locale dirs
- printf("Scanning patch levels from locale directories.\n");
- bool foundOne = false;
- for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i)
- {
- printf("Locale: %s\n", i->c_str());
- sprintf(path, "%s%s/patch-%s", input_path, i->c_str(), i->c_str());
- if(scan_patches(path, pArchiveNames))
- foundOne = true;
- }
-
- printf("\n");
-
- if(!foundOne)
- {
- printf("no locale found\n");
- return false;
- }
-
- return true;
-}
-
bool processArgv(int argc, char ** argv, const char *versionString)
{
bool result = true;
- hasInputPathParam = false;
+ bool hasInputPathParam = false;
preciseVectorData = false;
for(int i = 1; i < argc; ++i)
@@ -413,12 +489,18 @@ bool processArgv(int argc, char ** argv, const char *versionString)
{
preciseVectorData = true;
}
+ else if(strcmp("-b",argv[i]) == 0)
+ {
+ if (i + 1 < argc) // all ok
+ CONF_TargetBuild = atoi(argv[i++ + 1]);
+ }
else
{
result = false;
break;
}
}
+
if(!result)
{
printf("Extract %s.\n",versionString);
@@ -426,8 +508,13 @@ bool processArgv(int argc, char ** argv, const char *versionString)
printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n");
printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n");
printf(" -d <path>: Path to the vector data source folder.\n");
+ printf(" -b : target build (default %u)\n", CONF_TargetBuild);
printf(" -? : This message.\n");
}
+
+ if(!hasInputPathParam)
+ getGamePath();
+
return result;
}
@@ -465,7 +552,7 @@ int main(int argc, char ** argv)
}
}
- printf("Extract %s. Beginning work ....\n",versionString);
+ printf("Extract %s. Beginning work ....\n\n",versionString);
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Create the working directory
if (mkdir(szWorkDirWmo
@@ -475,21 +562,22 @@ int main(int argc, char ** argv)
))
success = (errno == EEXIST);
- // prepare archive name list
- std::vector<std::string> archiveNames;
- fillArchiveNameVector(archiveNames);
- for (size_t i=0; i < archiveNames.size(); ++i)
- {
- MPQArchive *archive = new MPQArchive(archiveNames[i].c_str());
- if (gOpenArchives.empty() || gOpenArchives.front() != archive)
- delete archive;
- }
+ LoadCommonMPQFiles(CONF_TargetBuild);
- if (gOpenArchives.empty())
+ for (int i = 0; i < LOCALES_COUNT; ++i)
{
- printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n",input_path);
- return 1;
+ //Open MPQs
+ if (!LoadLocaleMPQFile(i))
+ {
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ printf("Unable to load %s locale archives!\n", Locales[i]);
+ continue;
+ }
+
+ printf("Detected and using locale: %s\n", Locales[i]);
+ break;
}
+
ReadLiquidTypeTableDBC();
// extract data
@@ -500,7 +588,7 @@ int main(int argc, char ** argv)
//map.dbc
if (success)
{
- DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc");
+ DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc");
if (!dbc->open())
{
delete dbc;
@@ -521,10 +609,13 @@ int main(int argc, char ** argv)
ParsMapFiles();
delete [] map_ids;
//nError = ERROR_SUCCESS;
- // Extract models, listed in DameObjectDisplayInfo.dbc
+ // Extract models, listed in GameObjectDisplayInfo.dbc
ExtractGameobjectModels();
}
+ SFileCloseArchive(LocaleMpq);
+ SFileCloseArchive(WorldMpq);
+
printf("\n");
if (!success)
{
diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp
index d9216fd77eb..3e503259c83 100644
--- a/src/tools/vmap4_extractor/wdtfile.cpp
+++ b/src/tools/vmap4_extractor/wdtfile.cpp
@@ -30,7 +30,9 @@ char * wdtGetPlainName(char * FileName)
return FileName;
}
-WDTFile::WDTFile(char* file_name, char* file_name1) : WDT(file_name), gWmoInstansName(NULL), gnWMO(0)
+extern HANDLE WorldMpq;
+
+WDTFile::WDTFile(char* file_name, char* file_name1):WDT(WorldMpq, file_name)
{
filename.append(file_name1,strlen(file_name1));
}
@@ -125,6 +127,6 @@ ADTFile* WDTFile::GetMap(int x, int z)
char name[512];
- sprintf(name,"World\\Maps\\%s\\%s_%d_%d.adt", filename.c_str(), filename.c_str(), x, z);
+ sprintf(name,"World\\Maps\\%s\\%s_%d_%d_obj0.adt", filename.c_str(), filename.c_str(), x, z);
return new ADTFile(name);
}
diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h
index 5d6aed8f0bc..31303d62928 100644
--- a/src/tools/vmap4_extractor/wdtfile.h
+++ b/src/tools/vmap4_extractor/wdtfile.h
@@ -1,7 +1,7 @@
#ifndef WDTFILE_H
#define WDTFILE_H
-#include "mpq_libmpq04.h"
+#include "mpqfile.h"
#include "wmo.h"
#include <string>
#include "stdlib.h"
diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp
index 7c9f23c5a95..63187963550 100644
--- a/src/tools/vmap4_extractor/wmo.cpp
+++ b/src/tools/vmap4_extractor/wmo.cpp
@@ -26,7 +26,7 @@
#include <fstream>
#undef min
#undef max
-#include "mpq_libmpq04.h"
+#include "mpqfile.h"
using namespace std;
extern uint16 *LiqType;
@@ -39,9 +39,11 @@ WMORoot::WMORoot(std::string &filename)
memset(bbcorn2, 0, sizeof(bbcorn2));
}
+extern HANDLE WorldMpq;
+
bool WMORoot::open()
{
- MPQFile f(filename.c_str());
+ MPQFile f(WorldMpq, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");
@@ -151,7 +153,7 @@ WMOGroup::WMOGroup(const std::string &filename) :
bool WMOGroup::open()
{
- MPQFile f(filename.c_str());
+ MPQFile f(WorldMpq, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");
diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h
index d0333265851..16d55ffe7de 100644
--- a/src/tools/vmap4_extractor/wmo.h
+++ b/src/tools/vmap4_extractor/wmo.h
@@ -24,7 +24,7 @@
#include <string>
#include <set>
#include "vec3d.h"
-#include "loadlib/loadlib.h"
+#include "mpqfile.h"
// MOPY flags
#define WMO_MATERIAL_NOCAMCOLLIDE 0x01