mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 16:28:28 +00:00
Compare commits
389 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38572fe393 | |||
| 83367ee806 | |||
| f117aafc45 | |||
| 3e0c1bc02e | |||
| f13a1d6351 | |||
| fdde64dcc3 | |||
| f5fa07c8db | |||
| 5ffb6bdee7 | |||
| 8035c6c558 | |||
| fc1eca0f31 | |||
| 28e49801b7 | |||
| 66c171b61b | |||
| 3be7d45d36 | |||
| e5822a0c4a | |||
| b05dd45d62 | |||
| 9f64092606 | |||
| d2acd0505c | |||
| 05ed577e23 | |||
| 7831162235 | |||
| 8567fd928a | |||
| 73a23e9f9d | |||
| f232bf1ccd | |||
| acc6926448 | |||
| 837ce8ab4a | |||
| 2497c719ee | |||
| 31b46efcac | |||
| 9f3a0a3f95 | |||
| 179400c777 | |||
| 0f12a74074 | |||
| 61b784e96e | |||
| 723e5d536a | |||
| 225929d937 | |||
| 763ed7f7a3 | |||
| ea6ef4c283 | |||
| e5a0cc9ef7 | |||
| a79ea9b850 | |||
| 039e321dde | |||
| c57292a9dd | |||
| 9561a3fd3e | |||
| aa021addc1 | |||
| c0cbbf3a65 | |||
| a73ac9cfe8 | |||
| ec8c46abfe | |||
| b9b92762b5 | |||
| 7feb531ff7 | |||
| e67423bba7 | |||
| 531e4b0207 | |||
| 34496c49b4 | |||
| a445d7e39f | |||
| 0d12715d77 | |||
| 9878459049 | |||
| 9be0d3b090 | |||
| 16ba3eb11e | |||
| 973aa94cb5 | |||
| 4cbccfdce2 | |||
| a5e6fa3479 | |||
| 3712d36867 | |||
| 17291e9977 | |||
| 15f57e4a4c | |||
| e58d63bf35 | |||
| f89add9f64 | |||
| e039f6d2c6 | |||
| 7cef4d8fe9 | |||
| 7b85b09f24 | |||
| 413538f1b5 | |||
| c03a70651c | |||
| ec01e6c69b | |||
| 11773208df | |||
| 1f155690d8 | |||
| 36a29dbb9f | |||
| c160b8716f | |||
| 7ffce01260 | |||
| 1170b57fd5 | |||
| fee8a1214a | |||
| c26a6959e4 | |||
| 837b9b7ec7 | |||
| a5a8bfb0f4 | |||
| 69bddef5a0 | |||
| 7d242045ec | |||
| c3035fdf41 | |||
| e34c47414f | |||
| 909dda7c09 | |||
| 22ab145f19 | |||
| cd8e30a2ec | |||
| 03be6b2b6b | |||
| cda2217634 | |||
| 4525b512ac | |||
| db0d1116f8 | |||
| 3ef5d8ef0a | |||
| 4ed88e348e | |||
| ad29fa9cfa | |||
| 388c4bc574 | |||
| b4f3993616 | |||
| f9366553a3 | |||
| 9733f04c9c | |||
| 7140a2054f | |||
| 1049e48aca | |||
| 33b79a3588 | |||
| f82699c39b | |||
| 15eaf4e6d1 | |||
| 7621882b4e | |||
| 9b70b73759 | |||
| 8e43134bda | |||
| 52608d9b2d | |||
| d26782b093 | |||
| a2368b4ea7 | |||
| 3d6bb964df | |||
| 347ae1bc34 | |||
| 64f5bfd5ce | |||
| 3cb02e3b86 | |||
| 34c3b8628e | |||
| 8f921ce919 | |||
| 6754dfdf6d | |||
| 81722962cf | |||
| d169d95ab0 | |||
| 63ca4cac5e | |||
| f30ae9dd5a | |||
| eb49707779 | |||
| 86c1420f6e | |||
| 364ed921ce | |||
| 85e1518856 | |||
| 87bb5deb5c | |||
| 11ce399e0d | |||
| ec0989454d | |||
| e9f6031936 | |||
| 03485ef1e0 | |||
| e256175ce6 | |||
| 0f662bf70c | |||
| 4c959159c2 | |||
| d51241720a | |||
| 873d343529 | |||
| 95969ce67b | |||
| bd5cdf502e | |||
| c6a7d5a96c | |||
| 6bc4ecf390 | |||
| c94ceb5b1d | |||
| e390531dcd | |||
| bb702335e8 | |||
| 863c0c5b58 | |||
| 76e280da4e | |||
| bcca35b7b7 | |||
| 65abaade88 | |||
| 8020e921aa | |||
| f2f5b4c1ad | |||
| 5c6f9fcdc4 | |||
| d7dc733480 | |||
| 9e243a2426 | |||
| 9a889802d3 | |||
| 1420987c4c | |||
| ed4d954ba8 | |||
| 881f937a35 | |||
| ed4e762f03 | |||
| fa1e33783a | |||
| 0c38b46bf1 | |||
| 899cf32e6b | |||
| 2fa31799f6 | |||
| 6c3d5c713c | |||
| f16beddf6e | |||
| 506b3ca4a0 | |||
| 80242bd250 | |||
| 7f7f99cbe3 | |||
| 579294fbf0 | |||
| a3b54e5cae | |||
| b392d16808 | |||
| 1f9597a9e2 | |||
| 54c89d69f6 | |||
| a14371ba5c | |||
| 616e13acac | |||
| b50f660339 | |||
| 4c12d31e4a | |||
| e50cf5c4be | |||
| 84310ec8f0 | |||
| ffed5a9e22 | |||
| 92c9ff6e53 | |||
| 986a424322 | |||
| c3e7c48939 | |||
| b2aa3262a9 | |||
| b1587f0326 | |||
| ca7dd7d741 | |||
| 281b321237 | |||
| ba0e4bfc1d | |||
| 3cda62acf4 | |||
| 2ef43212e1 | |||
| f69eccc42b | |||
| a1e425f936 | |||
| 59618e0038 | |||
| ef1f1562f0 | |||
| 31177b7dc7 | |||
| 5b7aaff150 | |||
| b525a32b6e | |||
| 99fe610f72 | |||
| b5ec35e672 | |||
| 6186c3d866 | |||
| 1d0a6bdc71 | |||
| 15fa2b371c | |||
| da121137e5 | |||
| c953f1dee1 | |||
| 32b595afb4 | |||
| 0799b47c9c | |||
| a216672443 | |||
| d755aa48bc | |||
| f7ecfe7257 | |||
| 89a0bbb8bf | |||
| 822c8425bd | |||
| a6b57a3423 | |||
| 6d4f7413a5 | |||
| 3e041052ee | |||
| 444174ef57 | |||
| 970f7e01a9 | |||
| 4432c07081 | |||
| 221c667a23 | |||
| b710c41c34 | |||
| 8825218361 | |||
| 1bb5c4e0d8 | |||
| 58343480ff | |||
| 399bf96a0c | |||
| b7c409e11b | |||
| fd08e9f2ad | |||
| 37d3daaf9a | |||
| 9a4d01da8f | |||
| 81cf748b2b | |||
| 22742b6a25 | |||
| 7d8d96c049 | |||
| 081905dbc3 | |||
| a8b8f71092 | |||
| 36c1d88eac | |||
| 6eba672013 | |||
| 091c8ea5f1 | |||
| f5e49441b6 | |||
| 610f3ed37f | |||
| f215874486 | |||
| 8e529105cf | |||
| 95dc0c5fc8 | |||
| 73c8d3d09d | |||
| 049a0bf787 | |||
| 2095380ba4 | |||
| 081192d29e | |||
| 2429980fd5 | |||
| 0ac238d762 | |||
| 45320fd8ec | |||
| 6d33a13e23 | |||
| 52d64d03a6 | |||
| fe6e289606 | |||
| 26569ac51d | |||
| 38d04931ba | |||
| 96cf3d967f | |||
| 36325226eb | |||
| 6410f52c9c | |||
| 7ae14fffd0 | |||
| d213e3b106 | |||
| ba612f91c7 | |||
| 8312a8cf3b | |||
| 390dcc9a88 | |||
| cd1b45f0d6 | |||
| b8caa5dc31 | |||
| 53572b4d13 | |||
| cf0c773002 | |||
| 515fe8d9e5 | |||
| 06d1bd632b | |||
| 89f34246f0 | |||
| 7d8e128b5f | |||
| 14c642a3f7 | |||
| a67255475c | |||
| 04045dfc27 | |||
| 510a51e564 | |||
| 54b2c50109 | |||
| fe753f05df | |||
| ab76783f8b | |||
| 364a51b119 | |||
| a486db5e95 | |||
| c8e7d9e005 | |||
| 93aa690a6d | |||
| 87f1f78b67 | |||
| 0574a3db86 | |||
| 0178f3c9bb | |||
| 9eb3907d45 | |||
| 891952eb79 | |||
| e6a0b01f37 | |||
| 118c2a9db9 | |||
| 64c324a42b | |||
| f909e76260 | |||
| b7dfdc5060 | |||
| e25239a50d | |||
| 76d3edc534 | |||
| 7301182b3e | |||
| 832e5e90d1 | |||
| 7ddaabee30 | |||
| 41d57ddab6 | |||
| 8dd00f5288 | |||
| 0a9222e1ee | |||
| e0db3c0b60 | |||
| 15f217b594 | |||
| 8422178233 | |||
| eebe902917 | |||
| 04dc593df9 | |||
| e0a99730e5 | |||
| 6497bdf45a | |||
| ca430e2494 | |||
| f8439fd6e6 | |||
| 8dda7ddd04 | |||
| 5d8ea5752d | |||
| 4071d88290 | |||
| 0996570b78 | |||
| 0a9732a267 | |||
| 1bc06c9c24 | |||
| e0acc937b3 | |||
| 3a10a0129a | |||
| 18dbcf16cc | |||
| bed8dc7d34 | |||
| a0fc9844fd | |||
| 5cf748d135 | |||
| 9ddb56088e | |||
| 44dcf7af7d | |||
| 3262bee6c5 | |||
| 2dbd616725 | |||
| eb98563fa1 | |||
| 7f92e96ae7 | |||
| a48138dfd6 | |||
| 46980e5260 | |||
| 44f9e5495e | |||
| 97f59282cf | |||
| 2a4a5b1beb | |||
| 8369570b50 | |||
| 9ff0c414c1 | |||
| 850d1e7c28 | |||
| 2df823d2db | |||
| 2e84781594 | |||
| 833227f7f6 | |||
| e731cfd48d | |||
| cf7574d9b8 | |||
| 10d384f131 | |||
| 00b8c8ce47 | |||
| cab43f41be | |||
| fc0d589f12 | |||
| 743175d4ff | |||
| b497b07fed | |||
| aab5ed2267 | |||
| 46c9fe46e9 | |||
| e8c92c6fcc | |||
| 765eaf7f4f | |||
| 699c8cc1eb | |||
| 5839921e08 | |||
| a3bde6e1f1 | |||
| 0ece5bf178 | |||
| fbefad9eaf | |||
| 351a7a52fe | |||
| 8441ffda31 | |||
| e79747c919 | |||
| 8525d819c1 | |||
| fe600bb084 | |||
| babaff1985 | |||
| 909ca5440d | |||
| e25f64d03b | |||
| 2df66bd625 | |||
| 2028a5846c | |||
| 2fd2cd4cec | |||
| 17b175daa4 | |||
| 5cabe109da | |||
| c6e82448b6 | |||
| b846d89b5d | |||
| 322cea7342 | |||
| 205e1d404e | |||
| 9769a96ebd | |||
| 74d3192c2e | |||
| 41769a3fa8 | |||
| a7efa9d4e4 | |||
| 9ed69999a5 | |||
| e19a59b269 | |||
| d234016224 | |||
| c160d6d929 | |||
| 62ad60b4ad | |||
| d44d7c6bbd | |||
| efd97bad14 | |||
| bc884f5daf | |||
| 0f47b73a64 | |||
| e9c6e96452 | |||
| 09713311f6 | |||
| c666d9c553 | |||
| 3777e8d1ce | |||
| e60658c684 | |||
| 046da9efae | |||
| 09332f6c26 | |||
| ce507d891a | |||
| 96f122f901 | |||
| 3479525f39 | |||
| 4f9d4b0023 | |||
| bcdfd32bc0 | |||
| 693dde04e3 | |||
| f1bb019933 |
+3
-1
@@ -8,7 +8,9 @@ script:
|
||||
- make
|
||||
- ./bin/tests
|
||||
branches:
|
||||
only: master
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
|
||||
@@ -289,6 +289,7 @@ ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_QUEST=${EQEMU_LOG_LEVEL_QUEST})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH})
|
||||
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
|
||||
|
||||
IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
|
||||
ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true)
|
||||
|
||||
+201
@@ -1,5 +1,206 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 09/30/2014 ==
|
||||
Uleat: Implemented click-casting from bag slots for clients that natively support it (RoF)
|
||||
|
||||
== 09/28/2014 ==
|
||||
demonstar55: Add support for post June 18, 2014 Hundred Hands Effect spells (they changed the formula and stuff)
|
||||
set Spells:Jun182014HundredHandsRevamp to true if you're using a spell file from June 18, 2014+
|
||||
|
||||
== 09/27/2014 ==
|
||||
Kayen: Implemented perl function $mob->GetSpellStat(spell_id, identifier, slot);
|
||||
Note: identifier is the stat field in spells_new, slot is used for certain effects like effectid, base,base2, max ect.
|
||||
Example $mob->GetSpellStat(121, "range"); //Returns spell range
|
||||
Example $mob->GetSpellStat(121, "effectid", 1); //Returns the the value of effectid1
|
||||
This will allow you to pull almost all the data for any spell in quest files.
|
||||
demonstar55: Move the client's SetAttackTimer to the end of Client::CalcBonuses to keep the haste in sync
|
||||
demonstar55: Correct haste/slow "stacking" rules
|
||||
demonstar55: Correct SE_AttackSpeed4 to respect unslowable
|
||||
demonstar55: Make the haste be between 1-225 like the client (<100 = slow, >100 = haste) to ...
|
||||
demonstar55: Correct Hundred Hands effect and use formula provided by devs
|
||||
|
||||
== 09/24/2014 ==
|
||||
Uleat: Re-ordered server opcodes and handlers to give them some predictability of location (I need this for the inventory re-enumeration.)
|
||||
demonstar55: Added helper function bool EQEmu::IsTradeskill(uint32 skill)
|
||||
|
||||
== 09/23/2014 ==
|
||||
Kayen: Spell recourse effects will now be applied AFTER the base spells effects have been applied (consistent with live).
|
||||
Kayen: SE_ApplySpell and SE_TriggerSpell will now be applied based on which effect slot they are used in (instead of always before all spell effects are checked).
|
||||
Note: If a spell has multiple SE_TriggerSpell effects within it. Only one will be able to trigger. (If you want multiple spells use SE_ApplySpell)
|
||||
|
||||
== 09/22/2014 ==
|
||||
Akkadius: #resetaa now covers the function of #resetaa and #refundaa
|
||||
- #resetaa will wipe all AA data, refund the spent points into the available points and send character to character select properly
|
||||
Akkadius: Removed #refundaa
|
||||
Akkadius: Removed a lot of debug code for blob conversion
|
||||
Akkadius: Changed status logging for loads/saves to Debug category
|
||||
|
||||
== 09/21/2014 ==
|
||||
Akkadius: Player Profile Blob to Database Conversion
|
||||
- Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference
|
||||
- The new character storage engine unlike the character_ table before, is able to properly index data and make use of
|
||||
proper MySQL/MariaDB caching optimizations and performance has increased phenominally
|
||||
PERFORMANCE AND STATISTICS FIGURES (Varies on hardware):
|
||||
- EZ Server Character data size of 2.6GB `character_` table alone now takes up approx 600MB
|
||||
- Character Data Loads take approx .03 seconds BEFORE MySQL/MariaDB cache
|
||||
- Character Data Loads take approx .001-.0035 seconds AFTER MySQL/MariaDB cache
|
||||
- Character Data Saves take approx .0001 - .003 for any particular save operation
|
||||
- Database Auto Conversion: When the 'character_' table exists, World boot-up will queue an auto-conversion prompt and convert all of your characters, BACKUP
|
||||
YOUR DATABASE BEFORE CONVERTING, here is an EASY backup script: http://wiki.eqemulator.org/p?MySQL_DB_Backup_Script
|
||||
- On auto conversion, the following tables are created automatically:
|
||||
- Table: `character_skills` - Stores Character Skills
|
||||
- Table: `character_languages` - Stores Character Language
|
||||
- Table: `character_bind` - Stores Character Bind point and Home Bind point designated by is_home bool field
|
||||
- Table: `character_alternate_abilities` - Stores all Character AA
|
||||
- Table: `character_currency` - Stores all Platinum/Gold/Silver/Copper and character related currencies
|
||||
- Table: `character_data` - Stores basic character data (Fields from `character_` table migrated to this table)
|
||||
- Table: `character_spells` - Stores character spells
|
||||
- Table: `character_memmed_spells` - Stores character memorized spells
|
||||
- Table: `character_disciplines` - Stores character disciplines
|
||||
- Table: `character_material` - Stores character armor dye textures
|
||||
- Table: `character_tribute` - Stores character tributes
|
||||
- Table: `character_bandolier` - Stores character bandoliers
|
||||
- Table: `character_inspect_messages` - Stores character inspection messages (Moved from `character_` table)
|
||||
- Table: `character_leadership_abilities` - Stores character Leadership AAs
|
||||
- Loads: Majority of Player profile loads now occur at Client::Handle_Connect_OP_ZoneEntry
|
||||
LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
|
||||
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
- Saves: Occur all over the code now instead of calling full saves
|
||||
SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
|
||||
SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
|
||||
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
|
||||
SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
|
||||
SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
|
||||
SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
|
||||
SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
|
||||
SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
|
||||
SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
- Deletes:
|
||||
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
|
||||
DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
|
||||
DeleteCharacterLeadershipAAs(uint32 character_id);
|
||||
- Now occur all over the code and only trigger when necessary
|
||||
- Two FULL saves when looting a corpse, this has been reduced to just currency saves on initial loot and trimmed to one save since AddToMoneyPP did it already
|
||||
- Every time a player moves coin with any situation (Splits/Trades/Merchant/Skills/Bank Coin Exchange/Coin Moves), a full save is made, this is now just a currency save
|
||||
- Every time a player skilled up at a skill vendor, a full blob save hit was made, this is not just a currency hit
|
||||
- Every time an AA was purchased, a full save was made
|
||||
- Every time a spell was scribed/swapped, disc was trained
|
||||
- When a client exists a zone, when a client enters a zone
|
||||
- NOTE: These amount of excessive saves have caused scalability issues that cause the `character_` table to hang which causes process hangs that affect the whole server
|
||||
because of the slowness of the `character_` table and the blob not allowing any indexing to occur
|
||||
- All functions that once depended on the `character_` table are now rewritten to appropriately read from the `character_data` table
|
||||
- Database query errors that occur during conversion or from and load/save/delete character functions are now leveraged via ThrowDBError and logs now go to
|
||||
Server_Folder_Root/eqemu_query_error_log.txt (You cannot log errors natively through MySQL)
|
||||
- DBASYNC IS NOW COMPLETELY REMOVED - This was mainly for Character data async loads/saves and merchantlist loads
|
||||
- Side implementations:
|
||||
Perl Exports:
|
||||
- quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var) - Sets entity variables world wide with specified npctype_id
|
||||
- quest::crosszonesignalnpcbynpctypeid(npctype_id, data) - Signals all NPC entities world wide with specified npctype_id
|
||||
- $client->GetTaskActivityDoneCount(TaskID, ActivityID) - Gets task activity done count by task id and activity id for client entity
|
||||
|
||||
VIEW TABLE SIZE AFTER CONVERT:
|
||||
|
||||
SELECT CONCAT(table_schema, '.', table_name) as table_name,
|
||||
CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows,
|
||||
CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA,
|
||||
CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx,
|
||||
CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
|
||||
ROUND(index_length / data_length, 2) idxfrac
|
||||
FROM information_schema.TABLES
|
||||
WHERE `table_name` LIKE 'character_%'
|
||||
ORDER BY DATA DESC;
|
||||
|
||||
== 09/20/2014 ==
|
||||
demonstar55: Fix crash in SendEnterWorld on illegally long names
|
||||
demonstar55: The client only lets you enter 15 characters for your name (UF at least)
|
||||
demonstar55: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false
|
||||
KLS: #suspend and #ban now have required messages to record the reason for the ban/suspension.
|
||||
|
||||
== 09/19/2014 ==
|
||||
demonstar55: Added Client::Tell_StringID (used in tell queue messages)
|
||||
demonstar55: Tell queues (and offline) messages now show correctly
|
||||
demonstar55: Fix starting with capital check
|
||||
|
||||
== 09/18/2014==
|
||||
demonstar55: Implement tell queues
|
||||
Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+)
|
||||
The required SQL nukes the old tell queue table, which may or may not be in your DB
|
||||
Optional SQL adds the rule to the DB to allow easy of change
|
||||
Note: this does not play well with multiple sessions with the same name on (crash and relog and have multiple sessions) but normal tells don't play well either
|
||||
|
||||
== 09/16/2014 ==
|
||||
demonstar55: Implement spell formula 137 (BER AA Desperation)
|
||||
Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded.
|
||||
demonstar55: Fix some effect calcs + implement more (derived from the client)
|
||||
|
||||
== 09/15/2014 ==
|
||||
Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades.
|
||||
|
||||
== 09/13/2014 ==
|
||||
demonstar55: Fix rogues not having Thieves' Cant
|
||||
|
||||
== 09/09/2014 ==
|
||||
demonstar55: Incrase Mob kick/bash timer by 3
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
demonstar55: Fix slow effect on NPC special attack reuse timers
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
demonstar55: Slow fixes to bots!
|
||||
demonstar55: Revamped how NPC attack rate is set
|
||||
SQL: 2014_09_09_attack_delay.sql
|
||||
demonstar55: Added attackdelay to #npcedit
|
||||
|
||||
== 09/08/2014 ==
|
||||
demonstar55: Fix slow calc
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
|
||||
== 09/07/2014 ==
|
||||
Akkadius: Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance
|
||||
|
||||
== 09/06/2014 ==
|
||||
Uleat: Tweaked 'Smart' trading code to return main slots before sub slots in stackable and free space search processes. (If enough people ask for it, I'll add an optional rule to allow 'bag packing' - the original implementation behavior)
|
||||
|
||||
== 09/05/2014 ==
|
||||
Uleat: Fix for cursor item loss when zoning. (Thanks to the other devs who traced and fixed the 'macro' issue!)
|
||||
demonstar55: Fix size getting nuked with lua's SendIllusionPacket
|
||||
|
||||
== 09/03/2014 ==
|
||||
Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor.
|
||||
demonstar55: Added work around command to show numhits on your buffs (#shownumhits)
|
||||
Uleat: Fix for timer issue introduced by Zone::ShutDown() fix.
|
||||
|
||||
== 09/02/2014 ==
|
||||
Secrets: Identified OP_GuildPromote for RoF clients.
|
||||
Secrets: Fixed promotion, demotion, transferring a leader and displaying of client ranks in the Rain of Fear client. The rain of fear client, as such, will only have 3 ranks like the other clients, but supports a theoretical 8 ranks later.
|
||||
Secrets/Akkadius: Fixed an issue involving character name lookup in the new DB code.
|
||||
demonstar55: crash fix checking DivineAura in hate_list.cpp
|
||||
Secrets: Reverted some code that got in the main branch that shouldn't have gotten there.
|
||||
Uleat: Changed #loc to report the same precision as /loc for Cartesians
|
||||
|
||||
== 08/31/2014 ==
|
||||
KLS: Fixed a bug in fishing in S3D zones
|
||||
KLS: Fixed a bug in turnins with new any abstraction
|
||||
KLS: Fixed a few quest related inconsistencies.
|
||||
KLS: Added Lua EntityList::ChannelMessage(from, type, msg, language)
|
||||
|
||||
== 08/30/2014 ==
|
||||
demonstar55: (noudess) Merchants should be more descriptive of why they don't sell to you
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ SET(common_sources
|
||||
crc16.cpp
|
||||
crc32.cpp
|
||||
database.cpp
|
||||
dbasync.cpp
|
||||
dbcore.cpp
|
||||
debug.cpp
|
||||
emu_opcodes.cpp
|
||||
@@ -56,8 +55,9 @@ SET(common_sources
|
||||
rulesys.cpp
|
||||
serverinfo.cpp
|
||||
shareddb.cpp
|
||||
skills.cpp
|
||||
spdat.cpp
|
||||
string_util.cpp
|
||||
string_util.cpp
|
||||
struct_strategy.cpp
|
||||
tcp_connection.cpp
|
||||
tcp_server.cpp
|
||||
@@ -103,8 +103,8 @@ SET(common_headers
|
||||
crash.h
|
||||
crc16.h
|
||||
crc32.h
|
||||
data_verification.h
|
||||
database.h
|
||||
dbasync.h
|
||||
dbcore.h
|
||||
debug.h
|
||||
deity.h
|
||||
|
||||
+39
-5
@@ -17,7 +17,8 @@ static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
|
||||
static const uint32 BIT_AllClients = 0xFFFFFFFF;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
EQClientUnknown = 0,
|
||||
EQClient62, // Build: 'Aug 4 2005 15:40:59'
|
||||
EQClientTitanium, // Build: 'Oct 31 2005 10:33:37'
|
||||
@@ -26,17 +27,50 @@ typedef enum {
|
||||
EQClientUnderfoot, // Build: 'Jun 8 2010 16:44:32'
|
||||
EQClientRoF, // Build: 'Dec 10 2012 17:35:44'
|
||||
EQClientRoF2, // Build: 'May 10 2013 23:30:08'
|
||||
|
||||
|
||||
_EQClientCount, // place new clients before this point (preferably, in release/attribute order)
|
||||
|
||||
|
||||
// Values below are not implemented, as yet...
|
||||
|
||||
|
||||
EmuNPC = _EQClientCount,
|
||||
EmuMerc,
|
||||
EmuBot,
|
||||
EmuPet,
|
||||
|
||||
|
||||
_EmuClientCount // array size for EQLimits
|
||||
} EQClientVersion;
|
||||
|
||||
static const char* EQClientVersionName(EQClientVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case EQClientUnknown:
|
||||
return "EQClientUnknown";
|
||||
case EQClient62:
|
||||
return "EQClient62";
|
||||
case EQClientTitanium:
|
||||
return "EQClientTitanium";
|
||||
case EQClientSoF:
|
||||
return "EQClientSoF";
|
||||
case EQClientSoD:
|
||||
return "EQClientSoD";
|
||||
case EQClientUnderfoot:
|
||||
return "EQClientUnderfoot";
|
||||
case EQClientRoF:
|
||||
return "EQClientRoF";
|
||||
case EQClientRoF2:
|
||||
return "EQClientRoF2";
|
||||
case EmuNPC:
|
||||
return "EmuNPC";
|
||||
case EmuMerc:
|
||||
return "EmuMerc";
|
||||
case EmuBot:
|
||||
return "EmuBot";
|
||||
case EmuPet:
|
||||
return "EmuPet";
|
||||
default:
|
||||
return "ERROR: Invalid EQClientVersion";
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CLIENTVERSIONS_H */
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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_DATA_VERIFICATION_H
|
||||
#define COMMON_DATA_VERIFICATION_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T Clamp(const T& value, const T& lower, const T& upper) {
|
||||
return std::max(lower, std::min(value, upper));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampLower(const T& value, const T& lower) {
|
||||
return std::max(lower, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampUpper(const T& value, const T& upper) {
|
||||
return std::min(value, upper);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ValueWithin(const T& value, const T& lower, const T& upper) {
|
||||
return value >= lower && value <= upper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+1575
-521
File diff suppressed because it is too large
Load Diff
+9
-12
@@ -26,12 +26,6 @@
|
||||
#include "dbcore.h"
|
||||
#include "linked_list.h"
|
||||
#include "eq_packet_structs.h"
|
||||
/*#include "eq_stream.h"
|
||||
#include "guilds.h"
|
||||
#include "misc_functions.h"
|
||||
#include "mutex.h"
|
||||
#include "item.h"
|
||||
#include "extprofile.h"*/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -105,10 +99,16 @@ public:
|
||||
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
~Database();
|
||||
bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query);
|
||||
|
||||
|
||||
/*
|
||||
* General Character Related Stuff
|
||||
*/
|
||||
|
||||
/* Character Creation */
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
||||
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename);
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid);
|
||||
bool MoveCharacterToZone(uint32 iCharID, const char* iZonename);
|
||||
@@ -118,9 +118,8 @@ public:
|
||||
bool AddToNameFilter(const char* name);
|
||||
bool ReserveName(uint32 account_id, char* name);
|
||||
bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
|
||||
bool DeleteCharacter(char* name);
|
||||
uint8 CopyCharacter(const char* oldname, const char* newname, uint32 acctid);
|
||||
|
||||
/*
|
||||
* General Information Getting Queries
|
||||
@@ -217,6 +216,8 @@ public:
|
||||
uint32 GetRaidID(const char* name);
|
||||
const char *GetRaidLeaderName(uint32 rid);
|
||||
|
||||
bool CheckDatabaseConversions();
|
||||
|
||||
/*
|
||||
* Database Variables
|
||||
*/
|
||||
@@ -250,10 +251,6 @@ public:
|
||||
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
|
||||
void AddReport(std::string who, std::string against, std::string lines);
|
||||
|
||||
|
||||
protected:
|
||||
void HandleMysqlError(uint32 errnum);
|
||||
|
||||
private:
|
||||
void DBInitVars();
|
||||
|
||||
|
||||
@@ -1,669 +0,0 @@
|
||||
#include "debug.h"
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include "dbasync.h"
|
||||
#include "database.h"
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include "dbcore.h"
|
||||
#include <string.h>
|
||||
//#include "../common/misc_functions.h"
|
||||
#include "string_util.h"
|
||||
#define ASYNC_LOOP_GRANULARITY 4 //# of ms between checking our work
|
||||
|
||||
bool DBAsyncCB_LoadVariables(DBAsyncWork* iWork) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
MYSQL_RES* result = 0;
|
||||
DBAsyncQuery* dbaq = iWork->PopAnswer();
|
||||
if (dbaq->GetAnswer(errbuf, &result))
|
||||
iWork->GetDB()->LoadVariables_result(result);
|
||||
else
|
||||
std::cout << "Error: DBAsyncCB_LoadVariables failed: !GetAnswer: '" << errbuf << "'" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AsyncLoadVariables(DBAsync *dba, Database *db) {
|
||||
char* query = 0;
|
||||
DBAsyncWork* dbaw = new DBAsyncWork(db, &DBAsyncCB_LoadVariables, 0, DBAsync::Read);
|
||||
dbaw->AddQuery(0, &query, db->LoadVariables_MQ(&query));
|
||||
dba->AddWork(&dbaw);
|
||||
}
|
||||
|
||||
|
||||
//we only need to do anything when somebody puts work on the queue
|
||||
//so instead of checking all the time, we will wait on a condition
|
||||
//which will get signaled when somebody puts something on the queue
|
||||
ThreadReturnType DBAsyncLoop(void* tmp) {
|
||||
DBAsync* dba = (DBAsync*) tmp;
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Starting DBAsyncLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
dba->MLoopRunning.lock();
|
||||
while (dba->RunLoop()) {
|
||||
//wait before working so we check the loop condition
|
||||
//as soon as were done working
|
||||
dba->CInList.Wait();
|
||||
//we could check dba->RunLoop() again to see if we
|
||||
//got turned off while we were waiting
|
||||
{
|
||||
dba->Process();
|
||||
}
|
||||
}
|
||||
dba->MLoopRunning.unlock();
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Ending DBAsyncLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
THREAD_RETURN(nullptr);
|
||||
}
|
||||
|
||||
DBAsync::DBAsync(DBcore* iDBC)
|
||||
: Timeoutable(10000)
|
||||
{
|
||||
pDBC = iDBC;
|
||||
pRunLoop = true;
|
||||
pNextID = 1;
|
||||
#ifdef _WINDOWS
|
||||
_beginthread(DBAsyncLoop, 0, this);
|
||||
#else
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, DBAsyncLoop, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
DBAsync::~DBAsync() {
|
||||
StopThread();
|
||||
}
|
||||
|
||||
bool DBAsync::StopThread() {
|
||||
bool ret;
|
||||
MRunLoop.lock();
|
||||
ret = pRunLoop;
|
||||
pRunLoop = false;
|
||||
MRunLoop.unlock();
|
||||
|
||||
//signal the condition so we exit the loop if were waiting
|
||||
CInList.Signal();
|
||||
|
||||
//this effectively waits for the processing thread to finish
|
||||
MLoopRunning.lock();
|
||||
MLoopRunning.unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsync::AddWork(DBAsyncWork** iWork, uint32 iDelay) {
|
||||
MInList.lock();
|
||||
uint32 ret = GetNextID();
|
||||
if (!(*iWork)->SetWorkID(ret)) {
|
||||
MInList.unlock();
|
||||
return 0;
|
||||
}
|
||||
InList.Append(*iWork);
|
||||
(*iWork)->SetStatus(Queued);
|
||||
if (iDelay)
|
||||
(*iWork)->pExecuteAfter = Timer::GetCurrentTime() + iDelay;
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "Adding AsyncWork #" << (*iWork)->GetWorkID() << std::endl;
|
||||
std::cout << "ExecuteAfter = " << (*iWork)->pExecuteAfter << " (" << Timer::GetCurrentTime() << " + " << iDelay << ")" << std::endl;
|
||||
#endif
|
||||
*iWork = 0;
|
||||
MInList.unlock();
|
||||
|
||||
//wake up the processing thread and tell it to get to work.
|
||||
CInList.Signal();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsync::CancelWork(uint32 iWorkID) {
|
||||
if (iWorkID == 0)
|
||||
return false;
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "DBAsync::CancelWork: " << iWorkID << std::endl;
|
||||
#endif
|
||||
MCurrentWork.lock();
|
||||
if (CurrentWork && CurrentWork->GetWorkID() == iWorkID) {
|
||||
CurrentWork->Cancel();
|
||||
MCurrentWork.unlock();
|
||||
return true;
|
||||
}
|
||||
MCurrentWork.unlock();
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->GetWorkID() == iWorkID) {
|
||||
iterator.RemoveCurrent(true);
|
||||
MInList.unlock();
|
||||
return true;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBAsync::RunLoop() {
|
||||
bool ret;
|
||||
MRunLoop.lock();
|
||||
ret = pRunLoop;
|
||||
MRunLoop.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsync::InListPop() {
|
||||
DBAsyncWork* ret = 0;
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->pExecuteAfter <= Timer::GetCurrentTime()) {
|
||||
ret = iterator.GetData();
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "Poping AsyncWork #" << ret->GetWorkID() << std::endl;
|
||||
std::cout << ret->pExecuteAfter << " <= " << Timer::GetCurrentTime() << std::endl;
|
||||
#endif
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsync::InListPopWrite() {
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
DBAsyncWork* ret = 0;
|
||||
DBAsync::Type tmpType;
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
tmpType = iterator.GetData()->Type();
|
||||
if (tmpType == Write || tmpType == Both) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBAsync::AddFQ(DBAsyncFinishedQueue* iDBAFQ) {
|
||||
MFQList.lock();
|
||||
DBAsyncFinishedQueue** tmp = new DBAsyncFinishedQueue*;
|
||||
*tmp = iDBAFQ;
|
||||
FQList.Append(tmp);
|
||||
MFQList.unlock();
|
||||
}
|
||||
|
||||
void DBAsync::Process() {
|
||||
DBAsyncWork* tmpWork;
|
||||
MCurrentWork.lock();
|
||||
while ((CurrentWork = InListPop())) {
|
||||
MCurrentWork.unlock();
|
||||
//move from queued to executing
|
||||
Status tmpStatus = CurrentWork->SetStatus(Executing);
|
||||
if (tmpStatus == Queued) {
|
||||
//execute the work
|
||||
ProcessWork(CurrentWork);
|
||||
tmpWork = CurrentWork;
|
||||
MCurrentWork.lock();
|
||||
CurrentWork = 0;
|
||||
MCurrentWork.unlock();
|
||||
//move from executing to finished
|
||||
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
|
||||
if (tmpStatus != Executing) {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #1" << std::endl;
|
||||
}
|
||||
MCurrentWork.lock();
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
else {
|
||||
//call callbacks or put results on finished queue
|
||||
DispatchWork(tmpWork);
|
||||
Sleep(25);
|
||||
MCurrentWork.lock();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #2" << std::endl;
|
||||
}
|
||||
MCurrentWork.lock();
|
||||
safe_delete(CurrentWork);
|
||||
}
|
||||
}
|
||||
MCurrentWork.unlock();
|
||||
}
|
||||
|
||||
void DBAsync::CheckTimeout() {
|
||||
try{
|
||||
MFQList.lock();
|
||||
LinkedListIterator<DBAsyncFinishedQueue**> iterator(FQList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
(*iterator.GetData())->CheckTimeouts();
|
||||
iterator.Advance();
|
||||
}
|
||||
MFQList.unlock();
|
||||
}
|
||||
catch(...){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::CommitWrites() {
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "DBAsync::CommitWrites() called." << std::endl;
|
||||
#endif
|
||||
DBAsyncWork* tmpWork;
|
||||
while ((tmpWork = InListPopWrite())) {
|
||||
Status tmpStatus = tmpWork->SetStatus(Executing);
|
||||
if (tmpStatus == Queued) {
|
||||
ProcessWork(tmpWork);
|
||||
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
|
||||
if (tmpStatus != Executing) {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #1" << std::endl;
|
||||
}
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
else {
|
||||
DispatchWork(tmpWork);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #2" << std::endl;
|
||||
}
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::ProcessWork(DBAsyncWork* iWork, bool iSleep) {
|
||||
DBAsyncQuery* CurrentQuery;
|
||||
while ((CurrentQuery = iWork->PopQuery())) {
|
||||
CurrentQuery->Process(pDBC);
|
||||
iWork->PushAnswer(CurrentQuery);
|
||||
if (iSleep)
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::DispatchWork(DBAsyncWork* iWork) {
|
||||
//if this work has a callback, call it
|
||||
//otherwise, stick the work on the finish queue
|
||||
if (iWork->pCB) {
|
||||
if (iWork->pCB(iWork))
|
||||
safe_delete(iWork);
|
||||
}
|
||||
else {
|
||||
if (!iWork->pDBAFQ->Push(iWork))
|
||||
safe_delete(iWork);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DBAsyncFinishedQueue::DBAsyncFinishedQueue(uint32 iTimeout) {
|
||||
pTimeout = iTimeout;
|
||||
}
|
||||
|
||||
DBAsyncFinishedQueue::~DBAsyncFinishedQueue() {
|
||||
}
|
||||
|
||||
void DBAsyncFinishedQueue::CheckTimeouts() {
|
||||
if (pTimeout == 0xFFFFFFFF)
|
||||
return;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->CheckTimeout(pTimeout))
|
||||
iterator.RemoveCurrent(true);
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::Pop() {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
ret = list.Pop();
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::Find(uint32 iWorkID) {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->GetWorkID() == iWorkID) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::PopByWPT(uint32 iWPT) {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->WPT() == iWPT) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncFinishedQueue::Push(DBAsyncWork* iDBAW) {
|
||||
if (!this)
|
||||
return false;
|
||||
MLock.lock();
|
||||
list.Append(iDBAW);
|
||||
MLock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DBAsyncWork::DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
|
||||
: m_db(db)
|
||||
{
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pType = iType;
|
||||
pExecuteAfter = 0;
|
||||
pWorkID = 0;
|
||||
pDBAFQ = iDBAFQ;
|
||||
pCB = 0;
|
||||
pWPT = iWPT;
|
||||
pQuestionCount = 0;
|
||||
pAnswerCount = 0;
|
||||
pTimeout = iTimeout;
|
||||
pTSFinish = 0;
|
||||
}
|
||||
|
||||
DBAsyncWork::DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
|
||||
: m_db(db)
|
||||
{
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pType = iType;
|
||||
pExecuteAfter = 0;
|
||||
pWorkID = 0;
|
||||
pDBAFQ = 0;
|
||||
pCB = iCB;
|
||||
pWPT = iWPT;
|
||||
pQuestionCount = 0;
|
||||
pAnswerCount = 0;
|
||||
pTimeout = iTimeout;
|
||||
pTSFinish = 0;
|
||||
}
|
||||
|
||||
DBAsyncWork::~DBAsyncWork() {
|
||||
DBAsyncQuery* dbaq = 0;
|
||||
while ((dbaq = todo.pop()))
|
||||
safe_delete(dbaq);
|
||||
while ((dbaq = done.pop()))
|
||||
safe_delete(dbaq);
|
||||
while ((dbaq = todel.pop()))
|
||||
safe_delete(dbaq);
|
||||
}
|
||||
|
||||
bool DBAsyncWork::AddQuery(DBAsyncQuery** iDBAQ) {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
if (pstatus != DBAsync::AddingWork)
|
||||
ret = false;
|
||||
else {
|
||||
ret = true;
|
||||
pQuestionCount++;
|
||||
todo.push(*iDBAQ);
|
||||
(*iDBAQ)->pstatus = DBAsync::Queued;
|
||||
*iDBAQ = 0;
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
DBAsyncQuery* DBAQ = new DBAsyncQuery(iQPT, iQuery, iQueryLen, iGetResultSet, iGetErrbuf);
|
||||
if (AddQuery(&DBAQ))
|
||||
return true;
|
||||
else {
|
||||
safe_delete(DBAQ);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DBAsyncWork::SetWorkID(uint32 iWorkID) {
|
||||
bool ret = true;
|
||||
MLock.lock();
|
||||
if (pWorkID)
|
||||
ret = false;
|
||||
else
|
||||
pWorkID = iWorkID;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsyncWork::GetWorkID() {
|
||||
uint32 ret;
|
||||
MLock.lock();
|
||||
ret = pWorkID;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsyncWork::WPT() {
|
||||
uint32 ret;
|
||||
MLock.lock();
|
||||
ret = pWPT;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsync::Type DBAsyncWork::Type() {
|
||||
DBAsync::Type ret;
|
||||
MLock.lock();
|
||||
ret = pType;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncQuery* DBAsyncWork::PopAnswer() {
|
||||
DBAsyncQuery* ret;
|
||||
MLock.lock();
|
||||
ret = done.pop();
|
||||
if (ret)
|
||||
pAnswerCount--;
|
||||
todel.push(ret);
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::CheckTimeout(uint32 iFQTimeout) {
|
||||
if (pTimeout == 0xFFFFFFFF)
|
||||
return false;
|
||||
bool ret = false;
|
||||
MLock.lock();
|
||||
if (pTimeout > iFQTimeout)
|
||||
iFQTimeout = pTimeout;
|
||||
if (Timer::GetCurrentTime() > (pTSFinish + iFQTimeout))
|
||||
ret = true;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//sets the work's status to the supplied value and returns
|
||||
//the revious status
|
||||
DBAsync::Status DBAsyncWork::SetStatus(DBAsync::Status iStatus) {
|
||||
DBAsync::Status ret;
|
||||
MLock.lock();
|
||||
if (iStatus == DBAsync::Finished)
|
||||
pTSFinish = Timer::GetCurrentTime();
|
||||
ret = pstatus;
|
||||
pstatus = iStatus;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::Cancel() {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
if (pstatus != DBAsync::Finished) {
|
||||
pstatus = DBAsync::Canceled;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::IsCancled() {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
ret = (bool) (pstatus == DBAsync::Canceled);
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncQuery* DBAsyncWork::PopQuery() {
|
||||
DBAsyncQuery* ret = 0;
|
||||
MLock.lock();
|
||||
ret = todo.pop();
|
||||
if (ret)
|
||||
pQuestionCount--;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBAsyncWork::PushAnswer(DBAsyncQuery* iDBAQ) {
|
||||
MLock.lock();
|
||||
done.push(iDBAQ);
|
||||
pAnswerCount++;
|
||||
MLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
if (iQueryLen == 0xFFFFFFFF)
|
||||
pQueryLen = strlen(*iQuery);
|
||||
else
|
||||
pQueryLen = iQueryLen;
|
||||
pQuery = *iQuery;
|
||||
*iQuery = 0;
|
||||
Init(iQPT, iGetResultSet, iGetErrbuf);
|
||||
}
|
||||
|
||||
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
if (iQueryLen == 0xFFFFFFFF)
|
||||
pQueryLen = strlen(iQuery);
|
||||
else
|
||||
pQueryLen = iQueryLen;
|
||||
pQuery = strn0cpy(new char[pQueryLen+1], iQuery, pQueryLen+1);
|
||||
Init(iQPT, iGetResultSet, iGetErrbuf);
|
||||
}
|
||||
|
||||
void DBAsyncQuery::Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf) {
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pQPT = iQPT;
|
||||
pGetResultSet = iGetResultSet;
|
||||
pGetErrbuf = iGetErrbuf;
|
||||
|
||||
pmysqlsuccess = false;
|
||||
perrbuf = 0;
|
||||
perrnum = 0;
|
||||
presult = 0;
|
||||
paffected_rows = 0;
|
||||
plast_insert_id = 0;
|
||||
}
|
||||
|
||||
DBAsyncQuery::~DBAsyncQuery() {
|
||||
safe_delete_array(perrbuf);
|
||||
safe_delete_array(pQuery);
|
||||
if (presult)
|
||||
mysql_free_result(presult);
|
||||
}
|
||||
|
||||
bool DBAsyncQuery::GetAnswer(char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum) {
|
||||
if (pstatus != DBAsync::Finished) {
|
||||
if (errbuf)
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error: Query not finished.");
|
||||
if (errnum)
|
||||
*errnum = UINT_MAX;
|
||||
return false;
|
||||
}
|
||||
if (errbuf) {
|
||||
if (pGetErrbuf) {
|
||||
if (perrbuf)
|
||||
strn0cpy(errbuf, perrbuf, MYSQL_ERRMSG_SIZE);
|
||||
else
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message should've been saved, but hasnt. errno: %u", perrnum);
|
||||
}
|
||||
else
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message not saved. errno: %u", perrnum);
|
||||
}
|
||||
if (errnum)
|
||||
*errnum = perrnum;
|
||||
if (affected_rows)
|
||||
*affected_rows = paffected_rows;
|
||||
if (last_insert_id)
|
||||
*last_insert_id = plast_insert_id;
|
||||
if (result)
|
||||
*result = presult;
|
||||
return pmysqlsuccess;
|
||||
}
|
||||
|
||||
void DBAsyncQuery::Process(DBcore* iDBC) {
|
||||
pstatus = DBAsync::Executing;
|
||||
if (pGetErrbuf)
|
||||
perrbuf = new char[MYSQL_ERRMSG_SIZE];
|
||||
MYSQL_RES** resultPP = 0;
|
||||
if (pGetResultSet)
|
||||
resultPP = &presult;
|
||||
pmysqlsuccess = iDBC->RunQuery(pQuery, pQueryLen, perrbuf, resultPP, &paffected_rows, &plast_insert_id, &perrnum);
|
||||
pstatus = DBAsync::Finished;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
#ifndef DBASYNC_H
|
||||
#define DBASYNC_H
|
||||
#include "../common/dbcore.h"
|
||||
#include "../common/timeoutmgr.h"
|
||||
|
||||
|
||||
class DBAsyncFinishedQueue;
|
||||
class DBAsyncWork;
|
||||
class DBAsyncQuery;
|
||||
class Database;
|
||||
|
||||
// Big daddy that owns the threads and does the work
|
||||
class DBAsync : private Timeoutable {
|
||||
public:
|
||||
enum Status { AddingWork, Queued, Executing, Finished, Canceled };
|
||||
enum Type { Read, Write, Both };
|
||||
|
||||
DBAsync(DBcore* iDBC);
|
||||
~DBAsync();
|
||||
bool StopThread();
|
||||
|
||||
uint32 AddWork(DBAsyncWork** iWork, uint32 iDelay = 0);
|
||||
bool CancelWork(uint32 iWorkID);
|
||||
void CommitWrites();
|
||||
|
||||
void AddFQ(DBAsyncFinishedQueue* iDBAFQ);
|
||||
protected:
|
||||
//things related to the processing thread:
|
||||
friend ThreadReturnType DBAsyncLoop(void* tmp);
|
||||
Mutex MLoopRunning;
|
||||
Condition CInList;
|
||||
bool RunLoop();
|
||||
void Process();
|
||||
|
||||
private:
|
||||
virtual void CheckTimeout();
|
||||
|
||||
void ProcessWork(DBAsyncWork* iWork, bool iSleep = true);
|
||||
void DispatchWork(DBAsyncWork* iWork);
|
||||
inline uint32 GetNextID() { return pNextID++; }
|
||||
DBAsyncWork* InListPop();
|
||||
DBAsyncWork* InListPopWrite(); // Ignores delay
|
||||
void OutListPush(DBAsyncWork* iDBAW);
|
||||
|
||||
Mutex MRunLoop;
|
||||
bool pRunLoop;
|
||||
|
||||
DBcore* pDBC;
|
||||
uint32 pNextID;
|
||||
Mutex MInList;
|
||||
LinkedList<DBAsyncWork*> InList;
|
||||
|
||||
Mutex MFQList;
|
||||
LinkedList<DBAsyncFinishedQueue**> FQList;
|
||||
|
||||
// Mutex for outside access to current work & when current work is being changed.
|
||||
// NOT locked when CurrentWork is being accessed by the DBAsync thread.
|
||||
// Never change pointer from outside DBAsync thread!
|
||||
// Only here for access to thread-safe DBAsyncWork functions.
|
||||
Mutex MCurrentWork;
|
||||
DBAsyncWork* CurrentWork;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
DB Work Complete Callback:
|
||||
This will be called under the DBAsync thread! Never access any non-threadsafe
|
||||
data/functions/classes. (ie: zone, entitylist, client, etc are not threadsafe)
|
||||
Function prototype:
|
||||
return value: true if we should delete the data, false if we should keep it
|
||||
*/
|
||||
typedef bool(*DBWorkCompleteCallBack)(DBAsyncWork*);
|
||||
|
||||
class DBAsyncFinishedQueue {
|
||||
public:
|
||||
DBAsyncFinishedQueue(uint32 iTimeout = 90000);
|
||||
~DBAsyncFinishedQueue();
|
||||
|
||||
DBAsyncWork* Pop();
|
||||
DBAsyncWork* PopByWPT(uint32 iWPT);
|
||||
DBAsyncWork* Find(uint32 iWPT);
|
||||
bool Push(DBAsyncWork* iDBAW);
|
||||
|
||||
void CheckTimeouts();
|
||||
private:
|
||||
Mutex MLock;
|
||||
uint32 pTimeout;
|
||||
LinkedList<DBAsyncWork*> list;
|
||||
};
|
||||
|
||||
// Container class for multiple queries
|
||||
class DBAsyncWork {
|
||||
public:
|
||||
DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
|
||||
DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
|
||||
~DBAsyncWork();
|
||||
|
||||
bool AddQuery(DBAsyncQuery** iDBAQ);
|
||||
bool AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
uint32 WPT();
|
||||
DBAsync::Type Type();
|
||||
|
||||
// Pops finished queries off the work
|
||||
DBAsyncQuery* PopAnswer();
|
||||
uint32 QueryCount();
|
||||
|
||||
Database *GetDB() const { return(m_db); }
|
||||
|
||||
bool CheckTimeout(uint32 iFQTimeout);
|
||||
bool SetWorkID(uint32 iWorkID);
|
||||
uint32 GetWorkID();
|
||||
protected:
|
||||
friend class DBAsync;
|
||||
DBAsync::Status SetStatus(DBAsync::Status iStatus);
|
||||
bool Cancel();
|
||||
bool IsCancled();
|
||||
DBAsyncQuery* PopQuery(); // Get query to be run
|
||||
void PushAnswer(DBAsyncQuery* iDBAQ); // Push answer back into workset
|
||||
|
||||
// not mutex'd cause only to be accessed from dbasync class
|
||||
uint32 pExecuteAfter;
|
||||
private:
|
||||
Mutex MLock;
|
||||
uint32 pQuestionCount;
|
||||
uint32 pAnswerCount;
|
||||
uint32 pWorkID;
|
||||
uint32 pWPT;
|
||||
uint32 pTimeout;
|
||||
uint32 pTSFinish; // timestamp when finished
|
||||
DBAsyncFinishedQueue* pDBAFQ; //we do now own this pointer
|
||||
DBWorkCompleteCallBack pCB;
|
||||
DBAsync::Status pstatus;
|
||||
DBAsync::Type pType;
|
||||
MyQueue<DBAsyncQuery> todo;
|
||||
MyQueue<DBAsyncQuery> done;
|
||||
MyQueue<DBAsyncQuery> todel;
|
||||
Database *const m_db; //we do now own this pointer
|
||||
};
|
||||
|
||||
// Container class for the query information
|
||||
class DBAsyncQuery {
|
||||
public:
|
||||
DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
~DBAsyncQuery();
|
||||
|
||||
bool GetAnswer(char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0);
|
||||
inline uint32 QPT() { return pQPT; }
|
||||
protected:
|
||||
friend class DBAsyncWork;
|
||||
uint32 pQPT;
|
||||
|
||||
friend class DBAsync;
|
||||
void Process(DBcore* iDBC);
|
||||
|
||||
void Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf);
|
||||
DBAsync::Status pstatus;
|
||||
char* pQuery;
|
||||
uint32 pQueryLen;
|
||||
bool pGetResultSet;
|
||||
bool pGetErrbuf;
|
||||
|
||||
bool pmysqlsuccess;
|
||||
char* perrbuf;
|
||||
uint32 perrnum;
|
||||
uint32 paffected_rows;
|
||||
uint32 plast_insert_id;
|
||||
MYSQL_RES* presult;
|
||||
};
|
||||
|
||||
|
||||
void AsyncLoadVariables(DBAsync *dba, Database *db);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+10
-8
@@ -80,14 +80,15 @@ public:
|
||||
~EQEMuLog();
|
||||
|
||||
enum LogIDs {
|
||||
Status = 0, //this must stay the first entry in this list
|
||||
Normal,
|
||||
Error,
|
||||
Debug,
|
||||
Quest,
|
||||
Commands,
|
||||
Crash,
|
||||
MaxLogID
|
||||
Status = 0, /* This must stay the first entry in this list */
|
||||
Normal, /* Normal Logs */
|
||||
Error, /* Error Logs */
|
||||
Debug, /* Debug Logs */
|
||||
Quest, /* Quest Logs */
|
||||
Commands, /* Issued Comamnds */
|
||||
Crash, /* Crash Logs */
|
||||
Save, /* Client Saves */
|
||||
MaxLogID /* Max, used in functions to get the max log ID */
|
||||
};
|
||||
|
||||
//these are callbacks called for each
|
||||
@@ -113,6 +114,7 @@ private:
|
||||
Mutex MOpen;
|
||||
Mutex MLog[MaxLogID];
|
||||
FILE* fp[MaxLogID];
|
||||
|
||||
/* LogStatus: bitwise variable
|
||||
1 = output to file
|
||||
2 = output to stdout
|
||||
|
||||
+504
-501
File diff suppressed because it is too large
Load Diff
@@ -1024,6 +1024,26 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
|
||||
//return local[ValidateMobVersion(version)];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsClickCastFromBag(uint32 version) {
|
||||
static const bool local[_EmuClientCount] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ Client62::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*RoF2*/ false,
|
||||
|
||||
/*NPC*/ false,
|
||||
/*Merc*/ false,
|
||||
/*Bot*/ false,
|
||||
/*Pet*/ false
|
||||
};
|
||||
|
||||
return local[ValidateMobVersion(version)];
|
||||
}
|
||||
|
||||
// items
|
||||
uint16 EQLimits::ItemCommonSize(uint32 version) {
|
||||
static const uint16 local[_EmuClientCount] = {
|
||||
|
||||
@@ -184,6 +184,7 @@ public:
|
||||
static uint64 CursorBitmask(uint32 version);
|
||||
|
||||
static bool AllowsEmptyBagInBag(uint32 version);
|
||||
static bool AllowsClickCastFromBag(uint32 version);
|
||||
|
||||
// items
|
||||
static uint16 ItemCommonSize(uint32 version);
|
||||
|
||||
+9
-6
@@ -97,16 +97,15 @@ protected:
|
||||
};
|
||||
|
||||
class EQApplicationPacket : public EQPacket {
|
||||
// friend class EQProtocolPacket;
|
||||
friend class EQStream;
|
||||
public:
|
||||
EQApplicationPacket() : EQPacket(OP_Unknown,nullptr,0)
|
||||
EQApplicationPacket() : EQPacket(OP_Unknown, nullptr, 0), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op) : EQPacket(op,nullptr,0)
|
||||
EQApplicationPacket(const EmuOpcode op) : EQPacket(op, nullptr, 0), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op,nullptr,len)
|
||||
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op, nullptr, len), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op,buf,len)
|
||||
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
bool combine(const EQApplicationPacket *rhs);
|
||||
uint32 serialize (uint16 opcode, unsigned char *dest) const;
|
||||
@@ -119,12 +118,16 @@ public:
|
||||
virtual void DumpRawHeader(uint16 seq=0xffff, FILE *to = stdout) const;
|
||||
virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const;
|
||||
|
||||
uint16 GetOpcodeBypass() { return opcode_bypass; }
|
||||
void SetOpcodeBypass(uint16 v) { opcode_bypass = v; }
|
||||
|
||||
protected:
|
||||
|
||||
uint8 app_opcode_size;
|
||||
uint16 opcode_bypass;
|
||||
private:
|
||||
|
||||
EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size) { app_opcode_size = p.app_opcode_size; }
|
||||
EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size), opcode_bypass(p.opcode_bypass) { app_opcode_size = p.app_opcode_size; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
+25
-11
@@ -800,9 +800,12 @@ struct SuspendedMinion_Struct
|
||||
** Length: 4308 bytes
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF
|
||||
static const uint32 MAX_PP_MEMSPELL = 9;
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions
|
||||
static const uint32 MAX_PP_MEMSPELL = 9; // Set to latest client so functions can work right
|
||||
static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain
|
||||
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
|
||||
|
||||
static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_AA_ARRAY = 240;
|
||||
static const uint32 MAX_GROUP_MEMBERS = 6;
|
||||
@@ -880,7 +883,7 @@ struct PlayerProfile_Struct
|
||||
/*0245*/ uint8 guildbanker;
|
||||
/*0246*/ uint8 unknown0246[6]; //
|
||||
/*0252*/ uint32 intoxication;
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
|
||||
/*0292*/ uint32 abilitySlotRefresh;
|
||||
/*0296*/ uint8 haircolor; // Player hair color
|
||||
/*0297*/ uint8 beardcolor; // Player beard color
|
||||
@@ -919,9 +922,9 @@ struct PlayerProfile_Struct
|
||||
/*2505*/ uint8 unknown2541[47]; // ?
|
||||
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
|
||||
/*2580*/ uint8 unknown2616[4];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_SPELLBOOK];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
|
||||
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL];
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
|
||||
/*4668*/ uint8 unknown4704[32]; //
|
||||
/*4700*/ float y; // Player y position
|
||||
/*4704*/ float x; // Player x position
|
||||
@@ -2287,10 +2290,13 @@ struct Stun_Struct { // 4 bytes total
|
||||
};
|
||||
|
||||
struct AugmentItem_Struct {
|
||||
/*00*/ int16 container_slot;
|
||||
/*02*/ char unknown02[2];
|
||||
/*04*/ int32 augment_slot;
|
||||
/*08*/
|
||||
/*00*/ uint32 container_index;
|
||||
/*04*/ int32 container_slot;
|
||||
/*08*/ uint32 augment_index;
|
||||
/*12*/ int32 augment_slot;
|
||||
/*16*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented
|
||||
/*20*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug
|
||||
/*24*/
|
||||
};
|
||||
|
||||
// OP_Emote
|
||||
@@ -4061,7 +4067,7 @@ struct GroupInvite_Struct {
|
||||
// uint8 unknown128[65];
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1];
|
||||
};
|
||||
@@ -4461,6 +4467,14 @@ struct GuildBankPromote_Struct
|
||||
/*12*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
|
||||
};
|
||||
|
||||
struct GuildPromoteStruct {
|
||||
/*000*/ char target[64];
|
||||
/*064*/ char name[64];
|
||||
/*128*/ uint32 rank;
|
||||
/*132*/ uint32 myrank;
|
||||
/*136*/
|
||||
};
|
||||
|
||||
struct GuildBankPermissions_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 6
|
||||
|
||||
+6
-48
@@ -532,9 +532,12 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
|
||||
|
||||
_log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size);
|
||||
uint16 opcode = 0;
|
||||
if(pack->GetOpcodeBypass() != 0) {
|
||||
opcode = pack->GetOpcodeBypass();
|
||||
} else {
|
||||
opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
|
||||
}
|
||||
|
||||
if (!ack_req) {
|
||||
NonSequencedPush(new EQProtocolPacket(opcode, pack->pBuffer, pack->size));
|
||||
@@ -877,43 +880,6 @@ sockaddr_in address;
|
||||
AddBytesSent(length);
|
||||
}
|
||||
|
||||
/*
|
||||
commented out since im not sure theres a lot of merit in it.
|
||||
Really it was bitterness towards allocating a 2k buffer on the stack each call.
|
||||
Im sure the thought was client side, but even then, they will
|
||||
likely need a whole thread to call this method, in which case, they should
|
||||
supply the buffer so we dont re-allocate it each time.
|
||||
EQProtocolPacket *EQStream::Read(int eq_fd, sockaddr_in *from)
|
||||
{
|
||||
int socklen;
|
||||
int length=0;
|
||||
EQProtocolPacket *p=nullptr;
|
||||
char temp[15];
|
||||
|
||||
socklen=sizeof(sockaddr);
|
||||
#ifdef _WINDOWS
|
||||
length=recvfrom(eq_fd, (char *)_tempBuffer, 2048, 0, (struct sockaddr*)from, (int *)&socklen);
|
||||
#else
|
||||
length=recvfrom(eq_fd, _tempBuffer, 2048, 0, (struct sockaddr*)from, (socklen_t *)&socklen);
|
||||
#endif
|
||||
|
||||
if (length>=2) {
|
||||
p=new EQProtocolPacket(_tempBuffer[1],&_tempBuffer[2],length-2);
|
||||
|
||||
uint32 ip=from->sin_addr.s_addr;
|
||||
sprintf(temp,"%d.%d.%d.%d:%d",
|
||||
*(unsigned char *)&ip,
|
||||
*((unsigned char *)&ip+1),
|
||||
*((unsigned char *)&ip+2),
|
||||
*((unsigned char *)&ip+3),
|
||||
ntohs(from->sin_port));
|
||||
//std::cout << timestamp() << "Data from: " << temp << " OpCode 0x" << std::hex << std::setw(2) << std::setfill('0') << (int)p->opcode << std::dec << std::endl;
|
||||
//dump_message(p->pBuffer,p->size,timestamp());
|
||||
|
||||
}
|
||||
return p;
|
||||
}*/
|
||||
|
||||
void EQStream::SendSessionResponse()
|
||||
{
|
||||
EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(SessionResponse));
|
||||
@@ -1101,14 +1067,6 @@ EQProtocolPacket *p=nullptr;
|
||||
SequencedQueue.clear();
|
||||
}
|
||||
MOutboundQueue.unlock();
|
||||
|
||||
/*if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||
_log(NET__ERROR, _L "Out-bound Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||
}
|
||||
if(NextSequencedSend > SequencedQueue.size()) {
|
||||
_log(NET__ERROR, _L "Out-bound Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
|
||||
}*/
|
||||
//NOTE: we prolly want to reset counters if we are stupposed to do anything after this.
|
||||
}
|
||||
|
||||
void EQStream::PacketQueueClear()
|
||||
|
||||
+17
-18
@@ -21,7 +21,6 @@
|
||||
#include "eq_packet_structs.h"
|
||||
#include "item.h"
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/*
|
||||
@@ -37,24 +36,24 @@
|
||||
*/
|
||||
struct ExtendedProfile_Struct {
|
||||
// Pet stuff
|
||||
uint16 pet_id;
|
||||
uint16 old_pet_hp;
|
||||
uint16 old_pet_mana;
|
||||
SpellBuff_Struct pet_buffs[BUFF_COUNT];
|
||||
uint32 pet_items[_MaterialCount];
|
||||
char merc_name[64];
|
||||
uint16 pet_id; /* Not Used */
|
||||
uint16 old_pet_hp; /* Not Used */
|
||||
uint16 old_pet_mana; /* Not Used */
|
||||
SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */
|
||||
uint32 pet_items[_MaterialCount]; /* Not Used */
|
||||
char merc_name[64]; /* Used */
|
||||
|
||||
uint32 aa_effects;
|
||||
uint32 perAA; //% of exp going to AAs
|
||||
uint32 expended_aa; // Total of expended AA
|
||||
uint32 pet_hp;
|
||||
uint32 pet_mana;
|
||||
uint32 mercTemplateID;
|
||||
uint32 mercSuspendedTime;
|
||||
bool mercIsSuspended;
|
||||
uint32 mercTimerRemaining;
|
||||
uint8 mercGender;
|
||||
int32 mercState;
|
||||
uint32 aa_effects; /* Used */
|
||||
uint32 perAA; /* Used: % of exp going to AAs */
|
||||
uint32 expended_aa; /* Used: Total of expended AA */
|
||||
uint32 pet_hp; /* Not Used */
|
||||
uint32 pet_mana; /* Not Used */
|
||||
uint32 mercTemplateID; /* Not Used */
|
||||
uint32 mercSuspendedTime; /* Not Used */
|
||||
bool mercIsSuspended; /* Not Used */
|
||||
uint32 mercTimerRemaining; /* Not Used */
|
||||
uint8 mercGender; /* Not Used */
|
||||
int32 mercState; /* Not Used */
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@@ -474,6 +474,11 @@ bool BaseGuildManager::SetBankerFlag(uint32 charid, bool is_banker) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool BaseGuildManager::ForceRankUpdate(uint32 charid) {
|
||||
SendRankUpdate(charid);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool BaseGuildManager::SetAltFlag(uint32 charid, bool is_alt)
|
||||
{
|
||||
if(!DBSetAltFlag(charid, is_alt))
|
||||
@@ -751,7 +756,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
|
||||
std::string query;
|
||||
|
||||
if(guild_id != GUILD_NONE) {
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank) VALUES(%d,%d,%d)", charid, guild_id, rank);
|
||||
query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
@@ -892,10 +897,10 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
|
||||
" FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype "
|
||||
#else
|
||||
#define GuildMemberBaseQuery \
|
||||
"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \
|
||||
"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \
|
||||
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
|
||||
" g.banker,g.public_note,g.alt " \
|
||||
" FROM character_ AS c LEFT JOIN guild_members AS g ON c.id=g.char_id "
|
||||
" FROM `character_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id "
|
||||
#endif
|
||||
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
|
||||
//fields from `characer_`
|
||||
@@ -1236,7 +1241,7 @@ BaseGuildManager::GuildInfo::GuildInfo() {
|
||||
uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID)
|
||||
{
|
||||
std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id IN "
|
||||
"(SELECT id FROM character_ WHERE account_id = %i) AND rank = 2",
|
||||
"(SELECT id FROM `character_data` WHERE account_id = %i) AND rank = 2",
|
||||
AccountID);
|
||||
auto results = m_db->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank);
|
||||
bool SetGuildRank(uint32 charid, uint8 rank);
|
||||
bool SetBankerFlag(uint32 charid, bool is_banker);
|
||||
bool ForceRankUpdate(uint32 charid);
|
||||
bool GetAltFlag(uint32 CharID);
|
||||
bool SetAltFlag(uint32 charid, bool is_alt);
|
||||
bool GetBankerFlag(uint32 CharID);
|
||||
|
||||
+1
-315
@@ -24,318 +24,4 @@
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h> //for htonl
|
||||
#endif
|
||||
|
||||
/*
|
||||
void Database::GetGuildMembers(uint32 guild_id, GuildMember_Struct* gms){
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
uint32 count=0;
|
||||
uint32 length=0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Select name,profile,timelaston,guildrank,publicnote from character_ where guild=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
while( ( row = mysql_fetch_row(result) ) ){
|
||||
strcpy(gms->member[count].name,row[0]);
|
||||
length+=strlen(row[0])+strlen(row[4]);
|
||||
PlayerProfile_Struct* pps=(PlayerProfile_Struct*)row[1];
|
||||
gms->member[count].level=htonl(pps->level);
|
||||
gms->member[count].zoneid=(pps->zone_id*256);
|
||||
gms->member[count].timelaston=htonl(atol(row[2]));
|
||||
gms->member[count].class_=htonl(pps->class_);
|
||||
gms->member[count].rank=atoi(row[3]);
|
||||
strcpy(gms->member[count].publicnote,row[4]);
|
||||
count++;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildMembers query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
gms->count=count;
|
||||
gms->length=length;
|
||||
}
|
||||
|
||||
uint32 Database::NumberInGuild(uint32 guild_id) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Select count(id) from character_ where guild=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
uint32 ret = atoi(row[0]);
|
||||
mysql_free_result(result);
|
||||
return ret;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in NumberInGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool Database::SetGuild(char* name, uint32 guild_id, uint8 guildrank) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE name='%s'", guild_id, guildrank, name), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::SetGuild(uint32 charid, uint32 guild_id, uint8 guildrank) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE id=%i", guild_id, guildrank, charid), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::DeleteGuild(uint32 guild_id)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
char *query2 = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guilds WHERE id=%i;", guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1) {
|
||||
if(!RunQuery(query2, MakeAnyLenString(&query2, "update character_ set guild=0,guildrank=0 where guild=%i", guild_id), errbuf, 0, &affected_rows))
|
||||
LogFile->write(EQEMuLog::Error, "Error in DeleteGuild cleanup query '%s': %s", query2, errbuf);
|
||||
safe_delete_array(query2);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in DeleteGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::RenameGuild(uint32 guild_id, const char* name) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
char buf[65];
|
||||
DoEscapeString(buf, name, strlen(name)) ;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set name='%s' WHERE id=%i;", buf, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in RenameGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Database::EditGuild(uint32 guild_id, uint8 ranknum, GuildRankLevel_Struct* grl)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
int chars = 0;
|
||||
uint32 affected_rows = 0;
|
||||
char buf[203];
|
||||
char buf2[8];
|
||||
DoEscapeString(buf, grl->rankname, strlen(grl->rankname)) ;
|
||||
buf2[GUILD_HEAR] = grl->heargu + '0';
|
||||
buf2[GUILD_SPEAK] = grl->speakgu + '0';
|
||||
buf2[GUILD_INVITE] = grl->invite + '0';
|
||||
buf2[GUILD_REMOVE] = grl->remove + '0';
|
||||
buf2[GUILD_PROMOTE] = grl->promote + '0';
|
||||
buf2[GUILD_DEMOTE] = grl->demote + '0';
|
||||
buf2[GUILD_MOTD] = grl->motd + '0';
|
||||
buf2[GUILD_WARPEACE] = grl->warpeace + '0';
|
||||
|
||||
if (ranknum == 0)
|
||||
chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s' WHERE id=%i;", ranknum, buf, guild_id);
|
||||
else
|
||||
chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s', rank%i='%s' WHERE id=%i;", ranknum, buf, ranknum, buf2, guild_id);
|
||||
|
||||
if (RunQuery(query, chars, errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in EditGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::GetGuildNameByID(uint32 guild_id, char * name) {
|
||||
if (!name || !guild_id) return false;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "select name from guilds where id='%i'", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
sprintf(name,"%s",row[0]);
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildNameByID query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 Database::GetGuildIDbyLeader(uint32 leader)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM guilds WHERE leader=%i", leader), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1)
|
||||
{
|
||||
row = mysql_fetch_row(result);
|
||||
uint32 tmp = atoi(row[0]);
|
||||
mysql_free_result(result);
|
||||
return tmp;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in Getguild_idbyLeader query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Database::SetGuildLeader(uint32 guild_id, uint32 leader)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE guilds SET leader=%i WHERE id=%i", leader, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuildLeader query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::SetGuildMOTD(uint32 guild_id, const char* motd) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
char* motdbuf = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
motdbuf = new char[(strlen(motd)*2)+3];
|
||||
|
||||
DoEscapeString(motdbuf, motd, strlen(motd)) ;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set motd='%s' WHERE id=%i;", motdbuf, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
delete motdbuf;
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuildMOTD query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
delete motdbuf;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string Database::GetGuildMOTD(uint32 guild_id)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
string motd_str;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT motd FROM guilds WHERE id=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
motd_str = row[0];
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildMOTD query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
return motd_str;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
+46
-1
@@ -683,6 +683,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize))
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst)
|
||||
continue;
|
||||
|
||||
if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here...
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
@@ -732,8 +739,12 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
if (!main_inst)
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
if (main_inst->IsType(ItemClassContainer)) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (main_inst && main_inst->IsType(ItemClassContainer)) {
|
||||
if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver))
|
||||
continue;
|
||||
|
||||
@@ -900,6 +911,30 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsClickCasting(int16 slot_id)
|
||||
{
|
||||
// there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END)
|
||||
{
|
||||
if (EQLimits::AllowsClickCastFromBag(m_version))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsPotionBeltCasting(int16 slot_id)
|
||||
{
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test whether a given slot can support a container item
|
||||
bool Inventory::SupportsContainers(int16 slot_id)
|
||||
{
|
||||
@@ -1569,6 +1604,16 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const
|
||||
return (i < EmuConstants::ITEM_COMMON_SIZE) ? i : INVALID_INDEX;
|
||||
}
|
||||
|
||||
bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const {
|
||||
if (m_item->ItemClass != ItemClassCommon || !m_item)
|
||||
return false;
|
||||
|
||||
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve item inside container
|
||||
ItemInst* ItemInst::GetItem(uint8 index) const
|
||||
{
|
||||
|
||||
+26
-2
@@ -121,8 +121,22 @@ public:
|
||||
// Public Methods
|
||||
///////////////////////////////
|
||||
|
||||
Inventory() { m_version = EQClientUnknown; m_versionset = false; }
|
||||
~Inventory();
|
||||
|
||||
// Inventory v2 creep
|
||||
bool SetInventoryVersion(EQClientVersion version) {
|
||||
if (!m_versionset) {
|
||||
m_version = version;
|
||||
return (m_versionset = true);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EQClientVersion GetInventoryVersion() { return m_version; }
|
||||
|
||||
static void CleanDirty();
|
||||
static void MarkDirty(ItemInst *inst);
|
||||
|
||||
@@ -132,7 +146,7 @@ public:
|
||||
|
||||
inline iter_queue cursor_begin() { return m_cursor.begin(); }
|
||||
inline iter_queue cursor_end() { return m_cursor.end(); }
|
||||
inline bool CursorEmpty() { return (m_cursor.size() == 0); }
|
||||
inline bool CursorEmpty() { return (m_cursor.size() == 0); }
|
||||
|
||||
// Retrieve a read-only item from inventory
|
||||
inline const ItemInst* operator[](int16 slot_id) const { return GetItem(slot_id); }
|
||||
@@ -183,6 +197,10 @@ public:
|
||||
|
||||
static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container);
|
||||
|
||||
// Test for valid inventory casting slot
|
||||
bool SupportsClickCasting(int16 slot_id);
|
||||
bool SupportsPotionBeltCasting(int16 slot_id);
|
||||
|
||||
// Test whether a given slot can support a container item
|
||||
static bool SupportsContainers(int16 slot_id);
|
||||
|
||||
@@ -229,7 +247,12 @@ protected:
|
||||
std::map<int16, ItemInst*> m_bank; // Items in character bank
|
||||
std::map<int16, ItemInst*> m_shbank; // Items in character shared bank
|
||||
std::map<int16, ItemInst*> m_trade; // Items in a trade session
|
||||
ItemInstQueue m_cursor; // Items on cursor: FIFO
|
||||
ItemInstQueue m_cursor; // Items on cursor: FIFO
|
||||
|
||||
private:
|
||||
// Active inventory version
|
||||
EQClientVersion m_version;
|
||||
bool m_versionset;
|
||||
};
|
||||
|
||||
class SharedDatabase;
|
||||
@@ -274,6 +297,7 @@ public:
|
||||
inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; }
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augtype) const;
|
||||
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return m_item->AugType; }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); }
|
||||
|
||||
+3
-3
@@ -92,8 +92,8 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_message_mob(LogType type, Mob *who, const char *fmt, ...);
|
||||
#define mlog( type, format, ...) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_message_mob(type, this, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
@@ -150,16 +150,16 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_hex_mob(LogType type, Mob *who, const char *data, uint32 length);
|
||||
#define mhex( type, data, len) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_hex_mob(type, this, data, len); \
|
||||
} \
|
||||
} while(false)
|
||||
extern void log_packet_mob(LogType type, Mob *who, const BasePacket *p);
|
||||
#define mpkt( type, packet) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_packet_mob(type, this, packet); \
|
||||
} \
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//Mail and Chat Channels
|
||||
N(OP_MailLogin),
|
||||
N(OP_Mail),
|
||||
N(OP_Buddy),
|
||||
N(OP_ChannelAnnounceJoin),
|
||||
N(OP_ChannelAnnounceLeave),
|
||||
N(OP_Buddy),
|
||||
N(OP_MailHeaderCount),
|
||||
N(OP_MailHeader),
|
||||
N(OP_MailSendBody),
|
||||
N(OP_MailNew),
|
||||
N(OP_MailDeliveryStatus),
|
||||
N(OP_MailboxChange),
|
||||
N(OP_Ignore),
|
||||
N(OP_Mail),
|
||||
N(OP_MailboxChange),
|
||||
N(OP_MailDeliveryStatus),
|
||||
N(OP_MailHeader),
|
||||
N(OP_MailHeaderCount),
|
||||
N(OP_MailLogin),
|
||||
N(OP_MailNew),
|
||||
N(OP_MailSendBody),
|
||||
|
||||
@@ -387,3 +387,26 @@ float EQHtoFloat(int d)
|
||||
{
|
||||
return(360.0f - float((d * 360) >> 11));
|
||||
}
|
||||
|
||||
// returns a swapped-bit value for use in client translator and inventory functions
|
||||
uint32 SwapBits21and22(uint32 mask)
|
||||
{
|
||||
static const uint32 BIT21 = 1 << 21;
|
||||
static const uint32 BIT22 = 1 << 22;
|
||||
static const uint32 SWAPBITS = (BIT21 | BIT22);
|
||||
|
||||
if ((bool)(mask & BIT21) != (bool)(mask & BIT22))
|
||||
mask ^= SWAPBITS;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
// returns an unset bit 22 value for use in client translators
|
||||
uint32 Catch22(uint32 mask)
|
||||
{
|
||||
static const uint32 KEEPBITS = ~(1 << 22);
|
||||
|
||||
mask &= KEEPBITS;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ int FloatToEQ13(float d);
|
||||
int NewFloatToEQ13(float d);
|
||||
int FloatToEQ19(float d);
|
||||
int FloatToEQH(float d);
|
||||
uint32 SwapBits21and22(uint32 mask);
|
||||
uint32 Catch22(uint32 mask);
|
||||
|
||||
// macro to catch fp errors (provided by noudness)
|
||||
#define FCMP(a,b) (fabs(a-b) < FLT_EPSILON)
|
||||
|
||||
@@ -10,7 +10,7 @@ MySQLRequestResult::MySQLRequestResult()
|
||||
MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer)
|
||||
: m_CurrentRow(result), m_OneBeyondRow()
|
||||
{
|
||||
m_Result = result;
|
||||
m_Result = result;
|
||||
m_RowsAffected = rowsAffected;
|
||||
m_RowCount = rowCount;
|
||||
m_ColumnCount = columnCount;
|
||||
@@ -22,16 +22,17 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u
|
||||
m_ColumnLengths = nullptr;
|
||||
m_Fields = nullptr;
|
||||
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = true;
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = false;
|
||||
|
||||
m_Success = true;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::FreeInternals()
|
||||
{
|
||||
|
||||
safe_delete_array(m_ErrorBuffer);
|
||||
|
||||
if (m_Result != nullptr)
|
||||
@@ -100,6 +101,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem)
|
||||
m_RowsAffected = moveItem.m_RowsAffected;
|
||||
m_LastInsertedID = moveItem.m_LastInsertedID;
|
||||
m_ColumnLengths = moveItem.m_ColumnLengths;
|
||||
m_ColumnCount = moveItem.m_ColumnCount;
|
||||
m_Fields = moveItem.m_Fields;
|
||||
|
||||
// Keeps deconstructor from double freeing
|
||||
@@ -127,6 +129,7 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
|
||||
m_CurrentRow = other.m_CurrentRow;
|
||||
m_OneBeyondRow = other.m_OneBeyondRow;
|
||||
m_ColumnLengths = other.m_ColumnLengths;
|
||||
m_ColumnCount = other.m_ColumnCount;
|
||||
m_Fields = other.m_Fields;
|
||||
|
||||
// Keeps deconstructor from double freeing
|
||||
|
||||
@@ -305,7 +305,7 @@ OUTz(OP_FinishWindow2);
|
||||
//OUTv(OP_AdventureInfo, strlen(p)+1);
|
||||
//OUTv(OP_AdventureMerchantResponse, strlen(msg)+2);
|
||||
OUTv(OP_ItemPacket, ItemPacket_Struct);
|
||||
OUTv(OP_BuffFadeMsg, BuffFadeMsg_Struct);
|
||||
OUTv(OP_ColoredText, ColoredText_Struct);
|
||||
OUTv(OP_FormattedMessage, FormattedMessage_Struct);
|
||||
OUTv(OP_GuildMemberList, uint32); //variable length, but nasty
|
||||
OUTv(OP_InterruptCast, InterruptCast_Struct);
|
||||
|
||||
@@ -160,7 +160,7 @@ void load_opcode_names()
|
||||
opcode_map[0x0192]="LiveOP_YellForHelp";
|
||||
opcode_map[0x00ef]="LiveOP_SafePoint";
|
||||
opcode_map[0x0157]="LiveOP_Buff";
|
||||
opcode_map[0x00c0]="LiveOP_BuffFadeMsg";
|
||||
opcode_map[0x00c0]="LiveOP_ColoredText";
|
||||
opcode_map[0x0440]="LiveOP_MultiLineMsg";
|
||||
opcode_map[0x021c]="LiveOP_SpecialMesg";
|
||||
opcode_map[0x0013]="LiveOP_Consent";
|
||||
|
||||
+988
-979
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef CLIENT62_CONSTANTS_H_
|
||||
#define CLIENT62_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace Client62 {
|
||||
namespace maps {
|
||||
@@ -180,6 +180,7 @@ namespace Client62 {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_CharInventory)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_GuildMemberLevelUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_ReadBook)
|
||||
E(OP_RespondAA)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_CharInventory)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_ZoneServerReady)
|
||||
E(OP_GuildMemberLevelUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Illusion)
|
||||
E(OP_Track)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_RespondAA)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_WearChange)
|
||||
E(OP_Action)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_OnLevelMessage)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZoneServerReady)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ReadBook)
|
||||
D(OP_FaceChange)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ReadBook)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_WearChange)
|
||||
D(OP_WhoAllRequest)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -2969,7 +2969,7 @@ struct GroupInvite_Struct {
|
||||
// uint8 unknown128[65];
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1];
|
||||
};
|
||||
|
||||
+4910
-4750
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef RoF_CONSTANTS_H_
|
||||
#define RoF_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace RoF {
|
||||
namespace maps {
|
||||
@@ -184,6 +184,7 @@ namespace RoF {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = true;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = true;
|
||||
static const bool COIN_HAS_WEIGHT = false;
|
||||
}
|
||||
|
||||
|
||||
+140
-142
@@ -1,162 +1,160 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_CharInventory)
|
||||
E(OP_NewZone)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_ManaChange)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_LogServer)
|
||||
E(OP_Damage)
|
||||
E(OP_Buff)
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_Consider)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_MoveItem)
|
||||
//E(OP_OpenNewTasksWindow)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_LootItem)
|
||||
E(OP_TributeItem)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Stun)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_AdventureMerchantSell)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_Track)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_Barter)
|
||||
E(OP_AltCurrency)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_Animation)
|
||||
E(OP_ApplyPoison)
|
||||
E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BeginCast)
|
||||
E(OP_BlockedBuffs)
|
||||
E(OP_Buff)
|
||||
E(OP_BuffCreate)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_CastSpell)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_GuildsList)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClickObjectAction)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
E(OP_Damage)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_DisciplineUpdate)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzExpeditionEndsWarning)
|
||||
E(OP_DzExpeditionInfo)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_DzExpeditionList)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_BuffCreate)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_RespondAA)
|
||||
E(OP_DisciplineUpdate)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_AltCurrency)
|
||||
E(OP_RequestClientZoneChange)
|
||||
E(OP_ZoneChange)
|
||||
E(OP_WearChange)
|
||||
E(OP_ShopRequest)
|
||||
E(OP_CastSpell)
|
||||
E(OP_InterruptCast)
|
||||
E(OP_SendMembership)
|
||||
E(OP_Animation)
|
||||
E(OP_HPUpdate)
|
||||
E(OP_BlockedBuffs)
|
||||
E(OP_RemoveBlockedBuffs)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_ClickObjectAction)
|
||||
E(OP_RecipeAutoCombine)
|
||||
E(OP_GMTrainSkillConfirm)
|
||||
E(OP_SkillUpdate)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TaskHistoryReply)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_SetGuildRank)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_GuildMemberUpdate)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_GMLastName)
|
||||
E(OP_BeginCast)
|
||||
E(OP_GMTrainSkillConfirm)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_GuildMemberUpdate)
|
||||
E(OP_GuildsList)
|
||||
E(OP_HPUpdate)
|
||||
E(OP_Illusion)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_InterruptCast)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_NewZone)
|
||||
E(OP_OnLevelMessage)
|
||||
//E(OP_OpenNewTasksWindow)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_RecipeAutoCombine)
|
||||
E(OP_RemoveBlockedBuffs)
|
||||
E(OP_RequestClientZoneChange)
|
||||
E(OP_RespondAA)
|
||||
E(OP_RezzRequest)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consider)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_MoveItem)
|
||||
D(OP_WhoAllRequest)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendMembership)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_SetGuildRank)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_ShopRequest)
|
||||
E(OP_SkillUpdate)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_TaskDescription)
|
||||
E(OP_TaskHistoryReply)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeInfo)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_ZoneChange)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_BlockedBuffs)
|
||||
D(OP_Buff)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_Consume)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_CastSpell)
|
||||
D(OP_Save)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_Damage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GMLastName)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_LootItem)
|
||||
D(OP_TributeItem)
|
||||
D(OP_ReadBook)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_FaceChange)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_LoadSpellSet)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_Damage)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_PetCommands)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
D(OP_ShopRequest)
|
||||
D(OP_BlockedBuffs)
|
||||
D(OP_RemoveBlockedBuffs)
|
||||
D(OP_RecipeAutoCombine)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_GuildDemote)
|
||||
D(OP_GuildRemove)
|
||||
D(OP_GuildStatus)
|
||||
D(OP_Trader)
|
||||
D(OP_GMLastName)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_LoadSpellSet)
|
||||
D(OP_LootItem)
|
||||
D(OP_MoveItem)
|
||||
D(OP_PetCommands)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_ReadBook)
|
||||
D(OP_RecipeAutoCombine)
|
||||
D(OP_RemoveBlockedBuffs)
|
||||
D(OP_RezzAnswer)
|
||||
D(OP_Save)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_ShopRequest)
|
||||
D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ZoneChange)
|
||||
D(OP_ZoneEntry)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -2519,10 +2519,10 @@ struct Stun_Struct { // 8 bytes total
|
||||
|
||||
struct AugmentItem_Struct {
|
||||
/*00*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented
|
||||
/*04*/ uint32 unknown04; // Seen 0
|
||||
/*04*/ uint32 container_index; // Seen 0
|
||||
/*08*/ ItemSlotStruct container_slot; // Slot of the item being augmented
|
||||
/*20*/ uint32 unknown20; // Seen 0
|
||||
/*24*/ ItemSlotStruct distiller_slot; // Slot of the distiller to use (if one applies)
|
||||
/*20*/ uint32 augment_index; // Seen 0
|
||||
/*24*/ ItemSlotStruct augment_slot; // Slot of the distiller to use (if one applies)
|
||||
/*36*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug
|
||||
/*36*/ //int32 augment_slot;
|
||||
/*40*/
|
||||
@@ -4106,7 +4106,7 @@ struct GMToggle_Struct {
|
||||
uint32 toggle;
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1]; //was 1
|
||||
/*0???*/ uint8 paddingXXX[3]; // always 0's
|
||||
|
||||
+3225
-3160
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef SoD_CONSTANTS_H_
|
||||
#define SoD_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace SoD {
|
||||
namespace maps {
|
||||
@@ -181,6 +181,7 @@ namespace SoD {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = false;
|
||||
}
|
||||
|
||||
|
||||
+98
-100
@@ -1,117 +1,115 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_CharInventory)
|
||||
E(OP_NewZone)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_ManaChange)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_LogServer)
|
||||
E(OP_Damage)
|
||||
E(OP_Buff)
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_Consider)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_MoveItem)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_LootItem)
|
||||
E(OP_TributeItem)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Stun)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_AdventureMerchantSell)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_Track)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_Barter)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_ApplyPoison)
|
||||
E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Buff)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
E(OP_Damage)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzExpeditionEndsWarning)
|
||||
E(OP_DzExpeditionInfo)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_DzExpeditionList)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_WearChange)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consider)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_MoveItem)
|
||||
D(OP_WhoAllRequest)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_NewZone)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_Buff)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_Consume)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
D(OP_Save)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_LootItem)
|
||||
D(OP_TributeItem)
|
||||
D(OP_ReadBook)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_FaceChange)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_WearChange)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_LoadSpellSet)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_Bug)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_LootItem)
|
||||
D(OP_MoveItem)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_ReadBook)
|
||||
D(OP_Save)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WearChange)
|
||||
D(OP_WhoAllRequest)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -3693,7 +3693,7 @@ struct GMToggle_Struct {
|
||||
uint32 toggle;
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1]; //was 1
|
||||
/*0???*/ uint8 paddingXXX[3]; // always 0's
|
||||
|
||||
+2834
-2752
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef SoF_CONSTANTS_H_
|
||||
#define SoF_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace SoF {
|
||||
namespace maps {
|
||||
@@ -181,6 +181,7 @@ namespace SoF {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
0x1ee9,
|
||||
0x7f5d, OP_CastSpell
|
||||
0x0659, OP_ManaChange
|
||||
0x3bc7, OP_BuffFadeMsg
|
||||
0x3bc7, OP_ColoredText
|
||||
0x3209,
|
||||
0x6a93, OP_MemorizeSpell
|
||||
0x1237,
|
||||
|
||||
+81
-83
@@ -1,100 +1,98 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_CharInventory)
|
||||
E(OP_NewZone)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_ManaChange)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_LogServer)
|
||||
E(OP_Damage)
|
||||
E(OP_Buff)
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_Consider)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_MoveItem)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_LootItem)
|
||||
E(OP_TributeItem)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Stun)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_AdventureMerchantSell)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_Track)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_ApplyPoison)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_Buff)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
E(OP_Damage)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzExpeditionEndsWarning)
|
||||
E(OP_DzExpeditionInfo)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_DzExpeditionList)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_NewZone)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_Stun)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consider)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_MoveItem)
|
||||
D(OP_WhoAllRequest)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_Buff)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_Consume)
|
||||
D(OP_CastSpell)
|
||||
D(OP_Save)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_LootItem)
|
||||
D(OP_TributeItem)
|
||||
D(OP_ReadBook)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_FaceChange)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_LootItem)
|
||||
D(OP_MoveItem)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_ReadBook)
|
||||
D(OP_Save)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WearChange)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_WhoAllRequest)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -3556,7 +3556,7 @@ struct GMToggle_Struct {
|
||||
uint32 toggle;
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1]; //was 1
|
||||
/*0???*/ uint8 paddingXXX[3]; // always 0's
|
||||
|
||||
+1419
-1396
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef Titanium_CONSTANTS_H_
|
||||
#define Titanium_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace Titanium {
|
||||
namespace maps {
|
||||
@@ -180,6 +180,7 @@ namespace Titanium {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +1,52 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_ZoneServerReady)
|
||||
E(OP_GuildMemberLevelUpdate)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Illusion)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_InspectAnswer)
|
||||
E(OP_Track)
|
||||
E(OP_RespondAA)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_CharInventory)
|
||||
E(OP_DeleteSpawn)
|
||||
E(OP_WearChange)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzExpeditionEndsWarning)
|
||||
E(OP_DzExpeditionInfo)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_DzExpeditionList)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_Action)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_GuildMemberLevelUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_InspectAnswer)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LFGuild)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ReadBook)
|
||||
E(OP_RespondAA)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZoneServerReady)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_WhoAllRequest)
|
||||
D(OP_ReadBook)
|
||||
D(OP_FaceChange)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_InspectAnswer)
|
||||
D(OP_WearChange)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_LFGuild)
|
||||
D(OP_ReadBook)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_WearChange)
|
||||
D(OP_WhoAllRequest)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -3046,7 +3046,7 @@ struct GroupInvite_Struct {
|
||||
// uint8 unknown128[65];
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1];
|
||||
};
|
||||
|
||||
+3543
-3470
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef Underfoot_CONSTANTS_H_
|
||||
#define Underfoot_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace Underfoot {
|
||||
namespace maps {
|
||||
@@ -181,6 +181,7 @@ namespace Underfoot {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = false;
|
||||
}
|
||||
|
||||
|
||||
+107
-109
@@ -1,128 +1,126 @@
|
||||
|
||||
//list of packets we need to encode on the way out:
|
||||
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_CharInventory)
|
||||
E(OP_NewZone)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_ZoneSpawns)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_Illusion)
|
||||
E(OP_ManaChange)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_LogServer)
|
||||
E(OP_Damage)
|
||||
E(OP_Buff)
|
||||
// out-going packets that require an ENCODE translation:
|
||||
E(OP_Action)
|
||||
E(OP_Consider)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_MoveItem)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_LootItem)
|
||||
E(OP_TributeItem)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_ReadBook)
|
||||
E(OP_Stun)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_AdventureMerchantSell)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_Track)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_Barter)
|
||||
E(OP_AltCurrency)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_ApplyPoison)
|
||||
E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Buff)
|
||||
E(OP_BuffCreate)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_GuildsList)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
E(OP_Damage)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
E(OP_DisciplineUpdate)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzExpeditionEndsWarning)
|
||||
E(OP_DzExpeditionInfo)
|
||||
E(OP_DzCompass)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_DzExpeditionList)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzJoinExpeditionConfirm)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_BuffCreate)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_RespondAA)
|
||||
E(OP_DisciplineUpdate)
|
||||
E(OP_AltCurrencySell)
|
||||
E(OP_AltCurrency)
|
||||
E(OP_WearChange)
|
||||
E(OP_DzLeaderStatus)
|
||||
E(OP_DzMemberList)
|
||||
E(OP_ExpansionInfo)
|
||||
E(OP_GroundSpawn)
|
||||
E(OP_GroupCancelInvite)
|
||||
E(OP_GroupFollow)
|
||||
E(OP_GroupFollow2)
|
||||
E(OP_GroupInvite)
|
||||
E(OP_GroupUpdate)
|
||||
E(OP_GuildMemberList)
|
||||
E(OP_GuildsList)
|
||||
E(OP_Illusion)
|
||||
E(OP_InspectRequest)
|
||||
E(OP_ItemLinkResponse)
|
||||
E(OP_ItemPacket)
|
||||
E(OP_ItemVerifyReply)
|
||||
E(OP_LeadershipExpUpdate)
|
||||
E(OP_LogServer)
|
||||
E(OP_LootItem)
|
||||
E(OP_ManaChange)
|
||||
E(OP_MercenaryDataResponse)
|
||||
E(OP_MercenaryDataUpdate)
|
||||
//list of packets we need to decode on the way in:
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consider)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_MoveItem)
|
||||
D(OP_WhoAllRequest)
|
||||
E(OP_MoveItem)
|
||||
E(OP_NewSpawn)
|
||||
E(OP_NewZone)
|
||||
E(OP_OnLevelMessage)
|
||||
E(OP_OpenNewTasksWindow)
|
||||
E(OP_PetBuffWindow)
|
||||
E(OP_PlayerProfile)
|
||||
E(OP_RaidJoin)
|
||||
E(OP_RaidUpdate)
|
||||
E(OP_ReadBook)
|
||||
E(OP_RespondAA)
|
||||
E(OP_SendAATable)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendZonepoints)
|
||||
E(OP_ShopPlayerBuy)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
E(OP_WhoAllResponse)
|
||||
E(OP_ZoneEntry)
|
||||
E(OP_ZonePlayerToBind)
|
||||
E(OP_ZoneServerInfo)
|
||||
E(OP_ZoneSpawns)
|
||||
// incoming packets that require a DECODE translation:
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_Buff)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_Consume)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_CastSpell)
|
||||
D(OP_Save)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
D(OP_ConsiderCorpse)
|
||||
D(OP_Consume)
|
||||
D(OP_Damage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_FaceChange)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupFollow)
|
||||
D(OP_GroupFollow2)
|
||||
D(OP_GroupDisband)
|
||||
D(OP_GroupCancelInvite)
|
||||
D(OP_FindPersonRequest)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_LootItem)
|
||||
D(OP_TributeItem)
|
||||
D(OP_ReadBook)
|
||||
D(OP_AugmentInfo)
|
||||
D(OP_FaceChange)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_GroupInvite)
|
||||
D(OP_GroupInvite2)
|
||||
D(OP_InspectRequest)
|
||||
D(OP_WearChange)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_ItemLinkClick)
|
||||
D(OP_ItemVerifyRequest)
|
||||
D(OP_LoadSpellSet)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_Damage)
|
||||
D(OP_EnvDamage)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_DeleteItem)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_LootItem)
|
||||
D(OP_MoveItem)
|
||||
D(OP_PetCommands)
|
||||
D(OP_BuffRemoveRequest)
|
||||
D(OP_AltCurrencySellSelection)
|
||||
D(OP_AltCurrencySell)
|
||||
D(OP_RaidInvite)
|
||||
D(OP_ReadBook)
|
||||
D(OP_Save)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WearChange)
|
||||
D(OP_WhoAllRequest)
|
||||
#undef E
|
||||
#undef D
|
||||
|
||||
@@ -766,7 +766,7 @@ struct BindStruct {
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 25; //
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Underfoot now
|
||||
static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now
|
||||
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Underfoot
|
||||
static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
|
||||
@@ -879,7 +879,6 @@ struct PlayerProfile_Struct
|
||||
/*04216*/ uint8 face; // Player face - Actually uint32?
|
||||
/*04217*/ uint8 unknown04217[147]; // was [175]
|
||||
/*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920]
|
||||
/*06284*/ uint8 unknown06284[960]; // Spacer for the end of the book for now (pages 60 to 90)
|
||||
/*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized
|
||||
/*07284*/ uint8 unknown07284[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||
/*07312*/ uint32 platinum; // Platinum Pieces on player
|
||||
@@ -3736,7 +3735,7 @@ struct GMToggle_Struct {
|
||||
uint32 toggle;
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1]; //was 1
|
||||
/*0???*/ uint8 paddingXXX[3]; // always 0's
|
||||
|
||||
+3
-4
@@ -171,6 +171,7 @@ RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = R
|
||||
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
|
||||
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
|
||||
RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||
RULE_INT (World, TellQueueSize, 20)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY( Zone )
|
||||
@@ -212,10 +213,6 @@ RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max
|
||||
RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply.
|
||||
RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply.
|
||||
RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply.
|
||||
RULE_BOOL ( Map, UseClosestZ, false) // Move mobs to the nearest Z above or below, rather than just the nearest below.
|
||||
// Only set UseClosestZ true if all your .map files generated from EQGs were created
|
||||
// with azone2.
|
||||
//
|
||||
RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
@@ -324,6 +321,8 @@ RULE_INT ( Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing targe
|
||||
RULE_INT ( Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
|
||||
RULE_INT ( Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
|
||||
RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others.
|
||||
RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
|
||||
RULE_BOOL ( Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014
|
||||
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
|
||||
+25
-6
@@ -83,6 +83,7 @@
|
||||
#define ServerOP_QGlobalUpdate 0x0063
|
||||
#define ServerOP_QGlobalDelete 0x0064
|
||||
#define ServerOP_DepopPlayerCorpse 0x0065
|
||||
#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues
|
||||
|
||||
#define ServerOP_RaidAdd 0x0100 //in use
|
||||
#define ServerOP_RaidRemove 0x0101 //in use
|
||||
@@ -179,13 +180,15 @@
|
||||
#define ServerOP_CZMessagePlayer 0x4008
|
||||
#define ServerOP_ReloadWorld 0x4009
|
||||
|
||||
#define ServerOP_QSPlayerLogTrades 0x4010
|
||||
#define ServerOP_QSPlayerLogHandins 0x4011
|
||||
#define ServerOP_QSPlayerLogNPCKills 0x4012
|
||||
#define ServerOP_QSPlayerLogDeletes 0x4013
|
||||
#define ServerOP_QSPlayerLogMoves 0x4014
|
||||
#define ServerOP_QSPlayerLogTrades 0x4010
|
||||
#define ServerOP_QSPlayerLogHandins 0x4011
|
||||
#define ServerOP_QSPlayerLogNPCKills 0x4012
|
||||
#define ServerOP_QSPlayerLogDeletes 0x4013
|
||||
#define ServerOP_QSPlayerLogMoves 0x4014
|
||||
#define ServerOP_QSPlayerLogMerchantTransactions 0x4015
|
||||
#define ServerOP_QSSendQuery 0x4016
|
||||
#define ServerOP_QSSendQuery 0x4016
|
||||
#define ServerOP_CZSignalNPC 0x4017
|
||||
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x4018
|
||||
|
||||
/* Query Serv Generic Packet Flag/Type Enumeration */
|
||||
enum { QSG_LFGuild = 0 };
|
||||
@@ -346,6 +349,7 @@ struct ServerChannelMessage_Struct {
|
||||
uint16 chan_num;
|
||||
uint32 guilddbid;
|
||||
uint16 language;
|
||||
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
||||
char message[0];
|
||||
};
|
||||
|
||||
@@ -1092,6 +1096,11 @@ struct CZClientSignal_Struct {
|
||||
uint32 data;
|
||||
};
|
||||
|
||||
struct CZNPCSignal_Struct {
|
||||
uint32 npctype_id;
|
||||
uint32 data;
|
||||
};
|
||||
|
||||
struct CZClientSignalByName_Struct {
|
||||
char Name[64];
|
||||
uint32 data;
|
||||
@@ -1233,10 +1242,20 @@ struct CZMessagePlayer_Struct {
|
||||
char Message[512];
|
||||
};
|
||||
|
||||
struct CZSetEntVarByNPCTypeID_Struct {
|
||||
uint32 npctype_id;
|
||||
char id[256];
|
||||
char m_var[256];
|
||||
};
|
||||
|
||||
struct ReloadWorld_Struct{
|
||||
uint32 Option;
|
||||
};
|
||||
|
||||
struct ServerRequestTellQueue_Struct {
|
||||
char name[64];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
+57
-199
@@ -1,6 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include "shareddb.h"
|
||||
#include "mysql.h"
|
||||
@@ -113,49 +114,33 @@ bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed)
|
||||
}
|
||||
|
||||
uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
||||
|
||||
uint32 EntitledTime = 0;
|
||||
|
||||
const char *EntitledQuery = "select sum(ascii(substring(profile, 237, 1)) + (ascii(substring(profile, 238, 1)) * 256) +"
|
||||
"(ascii(substring(profile, 239, 1)) * 65536) + (ascii(substring(profile, 240, 1)) * 16777216))"
|
||||
"from character_ where account_id = %i";
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, EntitledQuery, AccountID), errbuf, &result)) {
|
||||
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
EntitledTime = atoi(row[0]);
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
EntitledTime += atoi(row[0]);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return EntitledTime;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<ItemInst*>::const_iterator &start, std::list<ItemInst*>::const_iterator &end)
|
||||
{
|
||||
iter_queue it;
|
||||
int i;
|
||||
bool ret=true;
|
||||
iter_queue it;
|
||||
int i;
|
||||
bool ret = true;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
// Delete cursor items
|
||||
if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=%i or (slotid>=%i and slotid<=%i))", char_id, MainCursor,EmuConstants::CURSOR_BAG_BEGIN,EmuConstants::CURSOR_BAG_END), errbuf))) {
|
||||
for(it=start,i=8000;it!=end;++it,i++) {
|
||||
ItemInst *inst=*it;
|
||||
if (!(ret=SaveInventory(char_id,inst,(i==8000) ? MainCursor : i)))
|
||||
if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid = %i AND ((slotid >= 8000 AND slotid <= 8999) OR slotid = %i OR (slotid >= %i AND slotid <= %i))",
|
||||
char_id, MainCursor, EmuConstants::CURSOR_BAG_BEGIN, EmuConstants::CURSOR_BAG_END), errbuf))) {
|
||||
|
||||
for (it = start, i = 8000; it != end; ++it, i++) {
|
||||
ItemInst *inst = *it;
|
||||
if (!(ret = SaveInventory(char_id, inst, (i == 8000) ? MainCursor : i)))
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "Clearing cursor failed: " << errbuf << std::endl;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
@@ -345,12 +330,11 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add)
|
||||
{
|
||||
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) {
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `sharedplat` = `sharedplat` + %i WHERE id = %i", amount_to_add, account_id), errbuf)) {
|
||||
std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
@@ -360,37 +344,26 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||
const Item_Struct* myitem;
|
||||
|
||||
RunQuery
|
||||
(
|
||||
query,
|
||||
MakeAnyLenString
|
||||
(
|
||||
&query,
|
||||
"SELECT itemid, item_charges, slot FROM starting_items "
|
||||
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
||||
"(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND "
|
||||
"gm <= %i ORDER BY id",
|
||||
si_race, si_class, si_deity, si_current_zone, admin_level
|
||||
),
|
||||
errbuf,
|
||||
&result
|
||||
);
|
||||
safe_delete_array(query);
|
||||
|
||||
while((row = mysql_fetch_row(result))) {
|
||||
int itemid = atoi(row[0]);
|
||||
int charges = atoi(row[1]);
|
||||
int slot = atoi(row[2]);
|
||||
uint32 itemid = 0;
|
||||
int32 charges = 0;
|
||||
int32 slot = 0;
|
||||
auto query = StringFormat(
|
||||
"SELECT `itemid`, `item_charges`, `slot` FROM `starting_items`"
|
||||
" WHERE (`race` = %i OR `race` = 0)"
|
||||
" AND (`class` = %i OR `class` = 0)"
|
||||
" AND (`deityid` = %i OR `deityid` = 0)"
|
||||
" AND (`zoneid` = %i OR `zoneid` = 0)"
|
||||
" AND gm <= %i ORDER BY id",
|
||||
si_race, si_class, si_deity, si_current_zone, admin_level);
|
||||
auto results = QueryDatabase(query);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
itemid = atoi(row[0]);
|
||||
charges = atoi(row[1]);
|
||||
slot = atoi(row[2]);
|
||||
myitem = GetItem(itemid);
|
||||
if(!myitem)
|
||||
if(!myitem)
|
||||
continue;
|
||||
ItemInst* myinst = CreateBaseItem(myitem, charges);
|
||||
if(slot < 0)
|
||||
@@ -398,9 +371,6 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv,
|
||||
inv->PutItem(slot, *myinst);
|
||||
safe_delete(myinst);
|
||||
}
|
||||
|
||||
if(result) mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -417,7 +387,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) {
|
||||
if (is_charid) {
|
||||
len_query = MakeAnyLenString(&query,
|
||||
"SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb "
|
||||
"INNER JOIN character_ ch ON ch.account_id=sb.acctid "
|
||||
"INNER JOIN character_data ch ON ch.account_id=sb.acctid "
|
||||
"WHERE ch.id=%i", id);
|
||||
}
|
||||
else {
|
||||
@@ -634,8 +604,13 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
|
||||
bool ret = false;
|
||||
|
||||
// Retrieve character inventory
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,"
|
||||
"instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid",
|
||||
if (RunQuery(query, MakeAnyLenString(&query,
|
||||
" SELECT `slotid`, `itemid`, `charges`, `color`, `augslot1`, `augslot2`, `augslot3`, `augslot4`, `augslot5`, `instnodrop`, `custom_data`"
|
||||
" FROM `inventory`"
|
||||
" INNER JOIN `character_data` ch ON ch.id = charid"
|
||||
" WHERE ch.NAME = '%s'"
|
||||
" AND ch.account_id = % i"
|
||||
" ORDER BY `slotid`",
|
||||
name, account_id), errbuf, &result))
|
||||
{
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
@@ -695,7 +670,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (slot_id>=8000 && slot_id <= 8999)
|
||||
if (slot_id >= 8000 && slot_id <= 8999)
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
else
|
||||
put_slot_id = inv->PutItem(slot_id, *inst);
|
||||
@@ -1208,104 +1183,6 @@ bool SharedDatabase::LoadNPCFactionLists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the player profile and inventory for the given account "account_id" and
|
||||
// character name "name". Return true if the character was found, otherwise false.
|
||||
// False will also be returned if there is a database error.
|
||||
bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES* result;
|
||||
MYSQL_ROW row;
|
||||
bool ret = false;
|
||||
|
||||
unsigned long* lengths;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) {
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
lengths = mysql_fetch_lengths(result);
|
||||
if (lengths[0] == sizeof(PlayerProfile_Struct)) {
|
||||
memcpy(pp, row[0], sizeof(PlayerProfile_Struct));
|
||||
|
||||
if (current_zone)
|
||||
strcpy(current_zone, row[1]);
|
||||
pp->zone_id = GetZoneID(row[1]);
|
||||
pp->x = atof(row[2]);
|
||||
pp->y = atof(row[3]);
|
||||
pp->z = atof(row[4]);
|
||||
pp->zoneInstance = atoi(row[6]);
|
||||
if (pp->x == -1 && pp->y == -1 && pp->z == -1)
|
||||
GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z);
|
||||
|
||||
if(current_instance)
|
||||
*current_instance = pp->zoneInstance;
|
||||
|
||||
if(ext) {
|
||||
//SetExtendedProfile handles any conversion
|
||||
SetExtendedProfile(ext, row[5], lengths[5]);
|
||||
}
|
||||
|
||||
// Retrieve character inventory
|
||||
ret = GetInventory(account_id, name, inv);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i",
|
||||
lengths[0], sizeof(PlayerProfile_Struct));
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
bool ret = false;
|
||||
|
||||
if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) {
|
||||
ret = (affected_rows != 0);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Generate SQL for updating player profile
|
||||
uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) {
|
||||
*query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4];
|
||||
char* end = *query;
|
||||
if (!current_zone)
|
||||
current_zone = pp->zone_id;
|
||||
|
||||
if (!current_instance)
|
||||
current_instance = pp->zoneInstance;
|
||||
|
||||
if(strlen(pp->name) == 0) // Sanity check in case pp never loaded
|
||||
return false;
|
||||
|
||||
end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z);
|
||||
end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct));
|
||||
end += sprintf(end,"\', extprofile=\'");
|
||||
end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct));
|
||||
end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid);
|
||||
|
||||
return (uint32) (end - (*query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create appropriate ItemInst class
|
||||
ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5)
|
||||
{
|
||||
@@ -2117,39 +1994,19 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
memcpy(message, row[0], sizeof(InspectMessage_Struct));
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl;
|
||||
safe_delete_array(query);
|
||||
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) {
|
||||
std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
|
||||
auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "SharedDatabase::LoadCharacterInspectMessage", query);
|
||||
auto row = results.begin();
|
||||
memcpy(message, "", sizeof(InspectMessage_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
memcpy(message, row[0], sizeof(InspectMessage_Struct));
|
||||
}
|
||||
}
|
||||
|
||||
void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) {
|
||||
std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) {
|
||||
std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str());
|
||||
auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "SharedDatabase::SaveCharacterInspectMessage", query);
|
||||
}
|
||||
|
||||
void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) {
|
||||
@@ -2180,7 +2037,8 @@ void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Str
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) {
|
||||
std::string msg = EscapeString(message->text);
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", msg.c_str(), botid), errbuf)) {
|
||||
std::cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << std::endl;
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -40,13 +40,10 @@ public:
|
||||
bool SetGMSpeed(uint32 account_id, uint8 gmspeed);
|
||||
uint8 GetGMSpeed(uint32 account_id);
|
||||
bool SetHideMe(uint32 account_id, uint8 hideme);
|
||||
bool GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone = 0, uint32 *current_instance = 0);
|
||||
bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets);
|
||||
uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets);
|
||||
int32 DeleteStalePlayerCorpses();
|
||||
int32 DeleteStalePlayerBackups();
|
||||
void GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message);
|
||||
void SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message);
|
||||
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
||||
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
||||
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
|
||||
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
|
||||
bool GetCommandSettings(std::map<std::string,uint8> &commands);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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
|
||||
*/
|
||||
#include "types.h"
|
||||
#include "skills.h"
|
||||
|
||||
bool EQEmu::IsTradeskill(SkillUseTypes skill)
|
||||
{
|
||||
switch (skill) {
|
||||
case SkillFishing:
|
||||
case SkillMakePoison:
|
||||
case SkillTinkering:
|
||||
case SkillResearch:
|
||||
case SkillAlchemy:
|
||||
case SkillBaking:
|
||||
case SkillTailoring:
|
||||
case SkillBlacksmithing:
|
||||
case SkillFletching:
|
||||
case SkillBrewing:
|
||||
case SkillPottery:
|
||||
case SkillJewelryMaking:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EQEmu::IsSpecializedSkill(SkillUseTypes skill)
|
||||
{
|
||||
// this could be a simple if, but if this is more portable if any IDs change (probably won't)
|
||||
// or any other specialized are added (also unlikely)
|
||||
switch (skill) {
|
||||
case SkillSpecializeAbjure:
|
||||
case SkillSpecializeAlteration:
|
||||
case SkillSpecializeConjuration:
|
||||
case SkillSpecializeDivination:
|
||||
case SkillSpecializeEvocation:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -260,4 +260,10 @@ typedef enum {
|
||||
#define HIGHEST_SKILL FRENZY
|
||||
*/
|
||||
|
||||
// for skill related helper functions
|
||||
namespace EQEmu {
|
||||
bool IsTradeskill(SkillUseTypes skill);
|
||||
bool IsSpecializedSkill(SkillUseTypes skill);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,11 @@ StructStrategy::StructStrategy() {
|
||||
}
|
||||
|
||||
void StructStrategy::Encode(EQApplicationPacket **p, EQStream *dest, bool ack_req) const {
|
||||
if((*p)->GetOpcodeBypass() != 0) {
|
||||
PassEncoder(p, dest, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
EmuOpcode op = (*p)->GetOpcode();
|
||||
Encoder proc = encoders[op];
|
||||
proc(p, dest, ack_req);
|
||||
|
||||
+227
-165
@@ -23,7 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errmsg.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
@@ -96,191 +96,253 @@ Close the connection to the database
|
||||
Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Database::AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
char *S1 = new char[strlen(from) * 2 + 1];
|
||||
char *S2 = new char[strlen(to) * 2 + 1];
|
||||
char *S3 = new char[strlen(message) * 2 + 1];
|
||||
DoEscapeString(S1, from, strlen(from));
|
||||
DoEscapeString(S2, to, strlen(to));
|
||||
DoEscapeString(S3, message, strlen(message));
|
||||
char *escapedFrom = new char[strlen(from) * 2 + 1];
|
||||
char *escapedTo = new char[strlen(to) * 2 + 1];
|
||||
char *escapedMessage = new char[strlen(message) * 2 + 1];
|
||||
DoEscapeString(escapedFrom, from, strlen(from));
|
||||
DoEscapeString(escapedTo, to, strlen(to));
|
||||
DoEscapeString(escapedMessage, message, strlen(message));
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_speech` SET `from`='%s', `to`='%s', `message`='%s', `minstatus`='%i', `guilddbid`='%i', `type`='%i'", S1, S2, S3, minstatus, guilddbid, type), errbuf, 0, 0)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Speech Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_speech` "
|
||||
"SET `from` = '%s', `to` = '%s', `message`='%s', "
|
||||
"`minstatus`='%i', `guilddbid`='%i', `type`='%i'",
|
||||
escapedFrom, escapedTo, escapedMessage, minstatus, guilddbid, type);
|
||||
safe_delete_array(escapedFrom);
|
||||
safe_delete_array(escapedTo);
|
||||
safe_delete_array(escapedMessage);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Speech Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
safe_delete_array(S1);
|
||||
safe_delete_array(S2);
|
||||
safe_delete_array(S3);
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount) {
|
||||
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_trade_record` SET `time`=NOW(), "
|
||||
"`char1_id`='%i', `char1_pp`='%i', `char1_gp`='%i', `char1_sp`='%i', `char1_cp`='%i', `char1_items`='%i', "
|
||||
"`char2_id`='%i', `char2_pp`='%i', `char2_gp`='%i', `char2_sp`='%i', `char2_cp`='%i', `char2_items`='%i'",
|
||||
QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, QS->char1_money.silver, QS->char1_money.copper, QS->char1_count,
|
||||
QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, QS->char2_money.silver, QS->char2_money.copper, QS->char2_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), "
|
||||
"`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', "
|
||||
"`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', "
|
||||
"`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', "
|
||||
"`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'",
|
||||
QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold,
|
||||
QS->char1_money.silver, QS->char1_money.copper, QS->char1_count,
|
||||
QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold,
|
||||
QS->char2_money.silver, QS->char2_money.copper, QS->char2_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(DetailCount > 0) {
|
||||
for(int i = 0; i < DetailCount; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_trade_record_entries` SET `event_id`='%i', "
|
||||
"`from_id`='%i', `from_slot`='%i', `to_id`='%i', `to_slot`='%i', `item_id`='%i', "
|
||||
"`charges`='%i', `aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'",
|
||||
lastid, QS->items[i].from_id, QS->items[i].from_slot, QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
if(detailCount == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < detailCount; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', "
|
||||
"`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', "
|
||||
"`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', "
|
||||
"`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].from_id, QS->items[i].from_slot,
|
||||
QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
|
||||
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) {
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_handin_record` SET `time` = NOW(), "
|
||||
"`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', "
|
||||
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
|
||||
"`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', "
|
||||
"`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', "
|
||||
"`npc_items`='%i'",
|
||||
QS->quest_id, QS->char_id, QS->char_money.platinum,
|
||||
QS->char_money.gold, QS->char_money.silver, QS->char_money.copper,
|
||||
QS->char_count, QS->npc_id, QS->npc_money.platinum,
|
||||
QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper,
|
||||
QS->npc_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(detailCount == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < detailCount; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', "
|
||||
"`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', "
|
||||
"`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', "
|
||||
"`aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].action_type, QS->items[i].char_slot,
|
||||
QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_npc_kill_record` "
|
||||
"SET `npc_id` = '%i', `type` = '%i', "
|
||||
"`zone_id` = '%i', `time` = NOW()",
|
||||
QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(members == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for (int i = 0; i < members; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_npc_kill_record_entries` "
|
||||
"SET `event_id` = '%i', `char_id` = '%i'",
|
||||
lastIndex, QS->Chars[i].char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_handin_record` SET `time`=NOW(), `quest_id`='%i', "
|
||||
"`char_id`='%i', `char_pp`='%i', `char_gp`='%i', `char_sp`='%i', `char_cp`='%i', `char_items`='%i', "
|
||||
"`npc_id`='%i', `npc_pp`='%i', `npc_gp`='%i', `npc_sp`='%i', `npc_cp`='%i', `npc_items`='%i'",
|
||||
QS->quest_id, QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count,
|
||||
QS->npc_id, QS->npc_money.platinum, QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, QS->npc_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) {
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_delete_record` SET `time` = NOW(), "
|
||||
"`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'",
|
||||
QS->char_id, QS->stack_size, QS->char_count, QS->char_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(DetailCount > 0) {
|
||||
for(int i = 0; i < DetailCount; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_handin_record_entries` SET `event_id`='%i', "
|
||||
"`action_type`='%s', `char_slot`='%i', `item_id`='%i', `charges`='%i', "
|
||||
"`aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'",
|
||||
lastid, QS->items[i].action_type, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', "
|
||||
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
|
||||
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members){
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record` SET `npc_id`='%i', `type`='%i', `zone_id`='%i', `time`=NOW()", QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID), errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Members > 0){
|
||||
for (int i = 0; i < Members; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record_entries` SET `event_id`='%i', `char_id`='%i'", lastid, QS->Chars[i].char_id, errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_delete_record` SET `time`=NOW(), "
|
||||
"`char_id`='%i', `stack_size`='%i', `char_items`='%i'",
|
||||
QS->char_id, QS->stack_size, QS->char_count, QS->char_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
for(int i = 0; i < Items; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_delete_record_entries` SET `event_id`='%i', "
|
||||
"`char_slot`='%i', `item_id`='%i', `charges`='%i', `aug_1`='%i', "
|
||||
"`aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'",
|
||||
lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) {
|
||||
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
|
||||
/* These are item moves */
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record` SET `time`=NOW(), "
|
||||
"`char_id`='%i', `from_slot`='%i', `to_slot`='%i', `stack_size`='%i', `char_items`='%i', `postaction`='%i'",
|
||||
QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, QS->char_count, QS->postaction),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
if(Items > 0) {
|
||||
for(int i = 0; i < Items; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record_entries` SET `event_id`='%i', "
|
||||
"`from_slot`='%i', `to_slot`='%i', `item_id`='%i', `charges`='%i', "
|
||||
"`aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", lastid,
|
||||
QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_move_record` SET `time` = NOW(), "
|
||||
"`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', "
|
||||
"`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'",
|
||||
QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size,
|
||||
QS->char_count, QS->postaction);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', "
|
||||
"`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', "
|
||||
"`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
|
||||
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items) {
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player -U */
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_merchant_transaction_record` SET `time`=NOW(), "
|
||||
"`zone_id`='%i', `merchant_id`='%i', `merchant_pp`='%i', `merchant_gp`='%i', `merchant_sp`='%i', `merchant_cp`='%i', `merchant_items`='%i', "
|
||||
"`char_id`='%i', `char_pp`='%i', `char_gp`='%i', `char_sp`='%i', `char_cp`='%i', `char_items`='%i'",
|
||||
QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, QS->merchant_money.gold, QS->merchant_money.silver, QS->merchant_money.copper, QS->merchant_count,
|
||||
QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), "
|
||||
"`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', "
|
||||
"`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', "
|
||||
"`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', "
|
||||
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
|
||||
"`char_items` = '%i'",
|
||||
QS->zone_id, QS->merchant_id, QS->merchant_money.platinum,
|
||||
QS->merchant_money.gold, QS->merchant_money.silver,
|
||||
QS->merchant_money.copper, QS->merchant_count, QS->char_id,
|
||||
QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver,
|
||||
QS->char_money.copper, QS->char_count);
|
||||
auto results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
for(int i = 0; i < Items; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id`='%i', "
|
||||
"`char_slot`='%i', `item_id`='%i', `charges`='%i', `aug_1`='%i', "
|
||||
"`aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'",
|
||||
lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_delete_array(query);
|
||||
if(items == 0)
|
||||
return;
|
||||
|
||||
int lastIndex = results.LastInsertedID();
|
||||
|
||||
for(int i = 0; i < items; i++) {
|
||||
query = StringFormat("INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', "
|
||||
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
|
||||
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
|
||||
QS->items[i].aug_5);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||
_log(QUERYSERV__ERROR, "%s", query.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
@@ -293,11 +355,11 @@ void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, Query), errbuf, 0, 0, &lastid)) {
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, Query), errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
safe_delete(pack);
|
||||
safe_delete(Query);
|
||||
safe_delete(pack);
|
||||
safe_delete(Query);
|
||||
}
|
||||
|
||||
@@ -8,18 +8,22 @@ SET(tests_sources
|
||||
|
||||
SET(tests_headers
|
||||
atobool_test.h
|
||||
data_verification_test.h
|
||||
fixed_memory_test.h
|
||||
fixed_memory_variable_test.h
|
||||
hextoi_32_64_test.h
|
||||
ipc_mutex_test.h
|
||||
memory_mapped_file_test.h
|
||||
string_util_test.h
|
||||
skills_util_test.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers})
|
||||
|
||||
TARGET_LINK_LIBRARIES(tests common cppunit)
|
||||
|
||||
INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(tests PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(tests "Ws2_32.lib")
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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 __EQEMU_TESTS_DATA_VERIFICATION_H
|
||||
#define __EQEMU_TESTS_DATA_VERIFICATION_H
|
||||
|
||||
#include "cppunit/cpptest.h"
|
||||
#include "../common/data_verification.h"
|
||||
|
||||
class DataVerificationTest : public Test::Suite {
|
||||
typedef void(DataVerificationTest::*TestFunction)(void);
|
||||
public:
|
||||
DataVerificationTest() {
|
||||
TEST_ADD(DataVerificationTest::Clamp);
|
||||
TEST_ADD(DataVerificationTest::ClampUpper);
|
||||
TEST_ADD(DataVerificationTest::ClampLower);
|
||||
TEST_ADD(DataVerificationTest::ValueWithin);
|
||||
}
|
||||
|
||||
~DataVerificationTest() {
|
||||
}
|
||||
|
||||
private:
|
||||
void Clamp() {
|
||||
float value_f = 500.0f;
|
||||
int value_i = 500;
|
||||
|
||||
float vf1 = EQEmu::Clamp(value_f, 0.0f, 1000.0f);
|
||||
float vf2 = EQEmu::Clamp(value_f, 0.0f, 250.0f);
|
||||
float vf3 = EQEmu::Clamp(value_f, 750.0f, 1000.0f);
|
||||
|
||||
int vi1 = EQEmu::Clamp(value_i, 0, 1000);
|
||||
int vi2 = EQEmu::Clamp(value_i, 0, 250);
|
||||
int vi3 = EQEmu::Clamp(value_i, 750, 1000);
|
||||
|
||||
TEST_ASSERT_EQUALS(vf1, 500.0f);
|
||||
TEST_ASSERT_EQUALS(vf2, 250.0f);
|
||||
TEST_ASSERT_EQUALS(vf3, 750.0f);
|
||||
|
||||
TEST_ASSERT_EQUALS(vi1, 500);
|
||||
TEST_ASSERT_EQUALS(vi2, 250);
|
||||
TEST_ASSERT_EQUALS(vi3, 750);
|
||||
}
|
||||
|
||||
void ClampUpper() {
|
||||
float value_f = 500.0f;
|
||||
int value_i = 500;
|
||||
|
||||
float vf1 = EQEmu::ClampUpper(value_f, 1000.0f);
|
||||
float vf2 = EQEmu::ClampUpper(value_f, 250.0f);
|
||||
|
||||
int vi1 = EQEmu::ClampUpper(value_i, 1000);
|
||||
int vi2 = EQEmu::ClampUpper(value_i, 250);
|
||||
|
||||
TEST_ASSERT_EQUALS(vf1, 500.0f);
|
||||
TEST_ASSERT_EQUALS(vf2, 250.0f);
|
||||
|
||||
TEST_ASSERT_EQUALS(vi1, 500);
|
||||
TEST_ASSERT_EQUALS(vi2, 250);
|
||||
}
|
||||
|
||||
void ClampLower() {
|
||||
float value_f = 500.0f;
|
||||
int value_i = 500;
|
||||
|
||||
float vf1 = EQEmu::ClampLower(value_f, 0.0f);
|
||||
float vf2 = EQEmu::ClampLower(value_f, 750.0f);
|
||||
|
||||
int vi1 = EQEmu::ClampLower(value_i, 0);
|
||||
int vi2 = EQEmu::ClampLower(value_i, 750);
|
||||
|
||||
TEST_ASSERT_EQUALS(vf1, 500.0f);
|
||||
TEST_ASSERT_EQUALS(vf2, 750.0f);
|
||||
|
||||
TEST_ASSERT_EQUALS(vi1, 500);
|
||||
TEST_ASSERT_EQUALS(vi2, 750);
|
||||
}
|
||||
|
||||
void ValueWithin() {
|
||||
float value_f = 500.0f;
|
||||
int value_i = 500;
|
||||
|
||||
TEST_ASSERT(EQEmu::ValueWithin(value_f, 0.0f, 1000.0f));
|
||||
TEST_ASSERT(!EQEmu::ValueWithin(value_f, 0.0f, 400.0f));
|
||||
TEST_ASSERT(!EQEmu::ValueWithin(value_f, 600.0f, 900.0f));
|
||||
|
||||
TEST_ASSERT(EQEmu::ValueWithin(value_i, 0, 1000));
|
||||
TEST_ASSERT(!EQEmu::ValueWithin(value_i, 0, 400));
|
||||
TEST_ASSERT(!EQEmu::ValueWithin(value_i, 600, 900));
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "atobool_test.h"
|
||||
#include "hextoi_32_64_test.h"
|
||||
#include "string_util_test.h"
|
||||
#include "data_verification_test.h"
|
||||
#include "skills_util_test.h"
|
||||
|
||||
int main() {
|
||||
try {
|
||||
@@ -40,6 +42,8 @@ int main() {
|
||||
tests.add(new atoboolTest());
|
||||
tests.add(new hextoi_32_64_Test());
|
||||
tests.add(new StringUtilTest());
|
||||
tests.add(new DataVerificationTest());
|
||||
tests.add(new SkillsUtilsTest());
|
||||
tests.run(*output, true);
|
||||
} catch(...) {
|
||||
return -1;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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 __EQEMU_TESTS_SKILLS_UTILS_H
|
||||
#define __EQEMU_TESTS_SKILLS_UTILS_H
|
||||
|
||||
#include "cppunit/cpptest.h"
|
||||
#include "../common/skills.h"
|
||||
|
||||
class SkillsUtilsTest: public Test::Suite {
|
||||
typedef void(SkillsUtilsTest::*TestFunction)(void);
|
||||
public:
|
||||
SkillsUtilsTest() {
|
||||
TEST_ADD(SkillsUtilsTest::IsTradeskill);
|
||||
TEST_ADD(SkillsUtilsTest::IsSpecializedSkill);
|
||||
}
|
||||
|
||||
~SkillsUtilsTest() {
|
||||
}
|
||||
|
||||
private:
|
||||
void IsTradeskill() {
|
||||
TEST_ASSERT(EQEmu::IsTradeskill(SkillPottery));
|
||||
TEST_ASSERT(!EQEmu::IsTradeskill(SkillParry));
|
||||
}
|
||||
|
||||
void IsSpecializedSkill() {
|
||||
TEST_ASSERT(EQEmu::IsSpecializedSkill(SkillSpecializeConjuration));
|
||||
TEST_ASSERT(!EQEmu::IsSpecializedSkill(SkillConjuration))
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "../common/string_util.h"
|
||||
|
||||
class StringUtilTest : public Test::Suite {
|
||||
typedef void(IPCMutexTest::*TestFunction)(void);
|
||||
typedef void(StringUtilTest::*TestFunction)(void);
|
||||
public:
|
||||
StringUtilTest() {
|
||||
TEST_ADD(StringUtilTest::StringFormatTest);
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void StringFormatTest() {
|
||||
void StringFormatTest() {
|
||||
const char* fmt = "Test: %c %d %4.2f";
|
||||
char c = 'a';
|
||||
int i = 2014;
|
||||
|
||||
+7
-7
@@ -139,7 +139,7 @@ int Database::FindAccount(const char *characterName, Client *client) {
|
||||
|
||||
client->ClearCharacters();
|
||||
std::string query = StringFormat("SELECT `id`, `account_id`, `level` "
|
||||
"FROM `character_` WHERE `name` = '%s' LIMIT 1",
|
||||
"FROM `character_data` WHERE `name` = '%s' LIMIT 1",
|
||||
characterName);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
@@ -159,7 +159,7 @@ int Database::FindAccount(const char *characterName, Client *client) {
|
||||
|
||||
_log(UCS__TRACE, "Account ID for %s is %i", characterName, accountID);
|
||||
|
||||
query = StringFormat("SELECT `id`, `name`, `level` FROM `character_` "
|
||||
query = StringFormat("SELECT `id`, `name`, `level` FROM `character_data` "
|
||||
"WHERE `account_id` = %i AND `name` != '%s'",
|
||||
accountID, characterName);
|
||||
results = QueryDatabase(query);
|
||||
@@ -174,7 +174,7 @@ int Database::FindAccount(const char *characterName, Client *client) {
|
||||
|
||||
bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::string MailKey) {
|
||||
|
||||
std::string query = StringFormat("SELECT `mailkey` FROM `character_` WHERE `name`='%s' LIMIT 1",
|
||||
std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `name`='%s' LIMIT 1",
|
||||
characterName.c_str());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
@@ -202,7 +202,7 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri
|
||||
int Database::FindCharacter(const char *characterName) {
|
||||
|
||||
char *safeCharName = RemoveApostrophes(characterName);
|
||||
std::string query = StringFormat("SELECT `id` FROM `character_` WHERE `name`='%s' LIMIT 1", safeCharName);
|
||||
std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name`='%s' LIMIT 1", safeCharName);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
_log(UCS__ERROR, "FindCharacter failed. %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
@@ -522,7 +522,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status`=4 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireTrash));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__ERROR, "Error expiring trash messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
else
|
||||
_log(UCS__INIT, "Expired %i trash messages.", results.RowsAffected());
|
||||
@@ -534,7 +534,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status` = 3 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireRead));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__INIT, "Expired %i read messages.", results.RowsAffected());
|
||||
else
|
||||
_log(UCS__ERROR, "Error expiring read messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
@@ -545,7 +545,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status`=1 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireUnread));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__INIT, "Expired %i unread messages.", results.RowsAffected());
|
||||
else
|
||||
_log(UCS__ERROR, "Error expiring unread messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
|
||||
@@ -147,7 +147,7 @@ OP_Begging=0x13e7 # ShowEQ 10/27/05
|
||||
OP_InspectRequest=0x775d # ShowEQ 10/27/05
|
||||
OP_Action2=0x0000
|
||||
OP_BeginCast=0x3990 # ShowEQ 10/27/05
|
||||
OP_BuffFadeMsg=0x0b2d # ShowEQ 10/27/05
|
||||
OP_ColoredText=0x0b2d # ShowEQ 10/27/05
|
||||
OP_Consent=0x1081 # ShowEQ 10/27/05
|
||||
OP_LFGCommand=0x68ac # ShowEQ 10/27/05
|
||||
OP_LFGGetMatchesRequest=0x022f # ShowEQ 10/27/05
|
||||
|
||||
@@ -150,7 +150,7 @@ OP_InspectRequest=0x2403
|
||||
OP_Action2=0x0000 # ShowEQ 06/29/05
|
||||
OP_BeginCast=0x3990 # ShowEQ 06/29/05
|
||||
OP_WhoAllRequest=0x5cdd # ShowEQ 06/29/05
|
||||
OP_BuffFadeMsg=0x4bc6 # ShowEQ 06/29/05
|
||||
OP_ColoredText=0x4bc6 # ShowEQ 06/29/05
|
||||
OP_Consent=0x1081 # ShowEQ 06/29/05
|
||||
OP_LFGCommand=0x022f # ShowEQ 06/29/05
|
||||
OP_LFGGetMatchesRequest=0x6f82 # ShowEQ 06/29/05
|
||||
|
||||
@@ -125,6 +125,7 @@ OP_GuildLeader=0x7c6f
|
||||
OP_GuildDelete=0x241b
|
||||
OP_GuildInviteAccept=0x78a5
|
||||
OP_GuildDemote=0x3100
|
||||
OP_GuildPromote=0x2945
|
||||
OP_GuildPublicNote=0x3c2c
|
||||
OP_GuildManageBanker=0x096d # Was 0x0737
|
||||
OP_GuildBank=0x2ab0 # Was 0x10c3
|
||||
@@ -165,7 +166,7 @@ OP_InspectRequest=0x23f1
|
||||
OP_InspectAnswer=0x5794
|
||||
OP_InspectMessageUpdate=0x3064
|
||||
OP_BeginCast=0x17ff
|
||||
OP_BuffFadeMsg=0x41cb
|
||||
OP_ColoredText=0x41cb
|
||||
OP_ConsentResponse=0x183d
|
||||
OP_MemorizeSpell=0x2fac
|
||||
OP_SwapSpell=0x4736
|
||||
|
||||
@@ -168,7 +168,7 @@ OP_GMLastName=0x3563 # C
|
||||
OP_InspectAnswer=0x4938 # C
|
||||
OP_Action2=0x7e4d # C OP_Damage?
|
||||
OP_BeginCast=0x0d5a # C
|
||||
OP_BuffFadeMsg=0x569a # C
|
||||
OP_ColoredText=0x569a # C
|
||||
OP_ConsentResponse=0x6e47 # C
|
||||
OP_MemorizeSpell=0x8543 # C
|
||||
OP_SwapSpell=0x3fd2 # C
|
||||
@@ -659,4 +659,4 @@ OP_RAWOutOfSession=0x0000 #
|
||||
|
||||
# we need to document the differences between these packets to make identifying them easier
|
||||
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
|
||||
OP_InitialHPUpdate=0x0000 #
|
||||
OP_InitialHPUpdate=0x0000 #
|
||||
|
||||
@@ -164,7 +164,7 @@ OP_GMLastName=0x0375 #/lastname <Name> <New Surname>
|
||||
OP_InspectAnswer=0x084F #SEQ 12/04/08
|
||||
OP_Action2=0x0EF2 #SEQ 12/04/08
|
||||
OP_BeginCast=0x5A50 #SEQ 12/04/08
|
||||
OP_BuffFadeMsg=0x3BC7 #SEQ 12/04/08
|
||||
OP_ColoredText=0x3BC7 #SEQ 12/04/08
|
||||
OP_ConsentResponse=0x4D30 #SEQ 12/04/08
|
||||
OP_MemorizeSpell=0x6A93 #SEQ 12/04/08
|
||||
OP_SwapSpell=0x1418 #SEQ 12/04/08
|
||||
|
||||
@@ -154,7 +154,7 @@ OP_InspectRequest=0x775d # ShowEQ 10/27/05
|
||||
OP_InspectAnswer=0x2403 # ShowEQ 10/27/05
|
||||
OP_Action2=0x0000
|
||||
OP_BeginCast=0x3990 # ShowEQ 10/27/05
|
||||
OP_BuffFadeMsg=0x0b2d # ShowEQ 10/27/05
|
||||
OP_ColoredText=0x0b2d # ShowEQ 10/27/05
|
||||
OP_Consent=0x1081 # ShowEQ 10/27/05
|
||||
OP_ConsentDeny=0x4e8c # ShowEQ 10/27/05
|
||||
OP_ConsentResponse=0x6380 # ShowEQ 10/27/05
|
||||
|
||||
@@ -168,7 +168,7 @@ OP_GMLastName=0x7bfb # C
|
||||
|
||||
OP_InspectAnswer=0x0c2b # C
|
||||
OP_BeginCast=0x0d5a # C
|
||||
OP_BuffFadeMsg=0x71bf # C
|
||||
OP_ColoredText=0x71bf # C
|
||||
OP_ConsentResponse=0x0e87 # C
|
||||
OP_MemorizeSpell=0x3887 # C
|
||||
OP_SwapSpell=0x5805 # C
|
||||
|
||||
@@ -23,8 +23,8 @@ VERBOSE = False # messaging: {False - minimal, True - robust}
|
||||
base_path = os.getcwd()[:-14] # '/utils/scripts'
|
||||
base_path = base_path.replace('\\', '/')
|
||||
|
||||
client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2', 'ClientTest']
|
||||
server_list = ['Login', 'World', 'Zone', 'UCS', 'ServerTest']
|
||||
client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2']
|
||||
server_list = ['Login', 'World', 'Zone', 'UCS']
|
||||
|
||||
client_opcodes = {} # x[key='Client'][key='OP_CodeName'](value='0x####')
|
||||
server_opcodes = {} # x[key='OP_CodeName'](value=<integer>) - opcodes apply to all servers
|
||||
@@ -248,7 +248,7 @@ def loadclientopcodes():
|
||||
|
||||
for client in client_list:
|
||||
try:
|
||||
short_name = '/patch_{0}.conf'.format(client)
|
||||
short_name = '/patch_{0}.conf'.format(client).lower()
|
||||
|
||||
file_name = '{0}/utils/patches{1}'.format(
|
||||
base_path,
|
||||
@@ -455,9 +455,9 @@ def loadclienttranslators():
|
||||
for client in client_list:
|
||||
try:
|
||||
if client == '6.2':
|
||||
short_name = '/Client62_ops.h'
|
||||
short_name = '/client62_ops.h'
|
||||
else:
|
||||
short_name = '/{0}_ops.h'.format(client)
|
||||
short_name = '/{0}_ops.h'.format(client).lower()
|
||||
|
||||
file_name = '{0}/common/patches{1}'.format(
|
||||
base_path,
|
||||
@@ -734,15 +734,15 @@ def discoverserverhandlers():
|
||||
locations[server] = []
|
||||
|
||||
if 'Login' in locations:
|
||||
locations['Login'].append('/loginserver/Client.cpp')
|
||||
locations['Login'].append('/loginserver/ServerManager.cpp')
|
||||
locations['Login'].append('/loginserver/WorldServer.cpp')
|
||||
locations['Login'].append('/loginserver/client.cpp')
|
||||
locations['Login'].append('/loginserver/server_manager.cpp')
|
||||
locations['Login'].append('/loginserver/world_server.cpp')
|
||||
|
||||
if 'World' in locations:
|
||||
locations['World'].append('/world/client.cpp')
|
||||
|
||||
if 'Zone' in locations:
|
||||
locations['Zone'].append('/zone/AA.cpp')
|
||||
locations['Zone'].append('/zone/aa.cpp')
|
||||
locations['Zone'].append('/zone/attack.cpp')
|
||||
locations['Zone'].append('/zone/bot.cpp')
|
||||
locations['Zone'].append('/zone/client.cpp')
|
||||
@@ -762,8 +762,8 @@ def discoverserverhandlers():
|
||||
locations['Zone'].append('/zone/loottables.cpp')
|
||||
locations['Zone'].append('/zone/merc.cpp')
|
||||
locations['Zone'].append('/zone/mob.cpp')
|
||||
locations['Zone'].append('/zone/MobAI.cpp')
|
||||
locations['Zone'].append('/zone/Object.cpp')
|
||||
locations['Zone'].append('/zone/mob_ai.cpp')
|
||||
locations['Zone'].append('/zone/object.cpp')
|
||||
locations['Zone'].append('/zone/pathing.cpp')
|
||||
locations['Zone'].append('/zone/petitions.cpp')
|
||||
locations['Zone'].append('/zone/questmgr.cpp')
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'World:TellQueueSize', '20', 'Maximum tell queue size.');
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:SHDProcIDOffByOne', 'true', 'SHD procs are off by 1. Set true for pre-UF spell files, false for UF+.');
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:Jun182014HundredHandsRevamp', 'false', 'Set this to true if your spell file is from after June 18, 2014.');
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `npc_types` ADD `attack_delay` TINYINT(3) UNSIGNED DEFAULT '30' NOT NULL AFTER `attack_speed`;
|
||||
UPDATE `npc_types` SET `attack_delay` = 36 + 36 * (`attack_speed` / 100);
|
||||
UPDATE `npc_types` SET `attack_delay` = 30 WHERE `attack_speed` = 0;
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE `tellque`;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `account` ADD COLUMN `ban_reason` TEXT NULL DEFAULT NULL AFTER `expansion`, ADD COLUMN `suspend_reason` TEXT NULL DEFAULT NULL AFTER `ban_reason`;
|
||||
@@ -715,7 +715,7 @@ bool AdventureManager::LoadAdventureEntries()
|
||||
|
||||
std::list<AdventureTemplate*> temp;
|
||||
auto iter = adventure_entries.find(id);
|
||||
if(iter == adventure_entries.end())
|
||||
if(iter != adventure_entries.end())
|
||||
temp = adventure_entries[id];
|
||||
|
||||
temp.push_back(tid);
|
||||
@@ -1069,7 +1069,7 @@ void AdventureManager::LoadLeaderboardInfo()
|
||||
leaderboard_info_percentage_tak.clear();
|
||||
|
||||
std::string query = "SELECT ch.name, ch.id, adv_stats.* FROM adventure_stats "
|
||||
"AS adv_stats LEFT JOIN character_ AS ch ON adv_stats.player_id = ch.id;";
|
||||
"AS adv_stats LEFT JOIN `character_data` AS ch ON adv_stats.player_id = ch.id;";
|
||||
auto results = database.QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::GetLeaderboardInfo: %s (%s)", query.c_str(), results.ErrorMessage().c_str());
|
||||
|
||||
+88
-130
@@ -64,8 +64,6 @@ extern ClientList client_list;
|
||||
extern uint32 numclients;
|
||||
extern volatile bool RunLoops;
|
||||
|
||||
|
||||
|
||||
Client::Client(EQStreamInterface* ieqs)
|
||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||
CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)),
|
||||
@@ -130,7 +128,7 @@ void Client::SendLogServer()
|
||||
|
||||
void Client::SendEnterWorld(std::string name)
|
||||
{
|
||||
char char_name[32]= { 0 };
|
||||
char char_name[64] = { 0 };
|
||||
if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) {
|
||||
if(database.GetAccountIDByChar(char_name) != GetAccountID()) {
|
||||
eqs->Close();
|
||||
@@ -174,7 +172,7 @@ void Client::SendCharInfo() {
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
|
||||
CharacterSelect_Struct* cs = (CharacterSelect_Struct*)outapp->pBuffer;
|
||||
|
||||
database.GetCharSelectInfo(GetAccountID(), cs);
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
@@ -471,8 +469,8 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
|
||||
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app)
|
||||
{
|
||||
if (GetAccountID() == 0) {
|
||||
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
||||
return false;
|
||||
@@ -482,7 +480,7 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
uchar race = app->pBuffer[64];
|
||||
uchar clas = app->pBuffer[68];
|
||||
|
||||
clog(WORLD__CLIENT,"Name approval request. Name=%s, race=%s, class=%s",char_name,GetRaceName(race),GetEQClassName(clas));
|
||||
clog(WORLD__CLIENT, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceName(race), GetEQClassName(clas));
|
||||
|
||||
EQApplicationPacket *outapp;
|
||||
outapp = new EQApplicationPacket;
|
||||
@@ -490,27 +488,27 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
outapp->pBuffer = new uchar[1];
|
||||
outapp->size = 1;
|
||||
|
||||
bool valid;
|
||||
if(!database.CheckNameFilter(char_name)) {
|
||||
valid = false;
|
||||
bool valid = false;
|
||||
if(!database.CheckNameFilter(char_name)) {
|
||||
valid = false;
|
||||
}
|
||||
else if(char_name[0] < 'A' && char_name[0] > 'Z') {
|
||||
//name must begin with an upper-case letter.
|
||||
valid = false;
|
||||
/* Name must begin with an upper-case letter. */
|
||||
else if (islower(char_name[0])) {
|
||||
valid = false;
|
||||
}
|
||||
else if (database.ReserveName(GetAccountID(), char_name)) {
|
||||
valid = true;
|
||||
}
|
||||
else if (database.ReserveName(GetAccountID(), char_name)) {
|
||||
valid = true;
|
||||
}
|
||||
else {
|
||||
valid = false;
|
||||
else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
outapp->pBuffer[0] = valid? 1 : 0;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!valid) {
|
||||
if (!valid)
|
||||
memset(char_name, 0, sizeof(char_name));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -642,13 +640,11 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
if (GetAccountID() == 0)
|
||||
{
|
||||
if (GetAccountID() == 0) {
|
||||
clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character.");
|
||||
return false;
|
||||
}
|
||||
else if (app->size != sizeof(CharCreate_Struct))
|
||||
{
|
||||
else if (app->size != sizeof(CharCreate_Struct)) {
|
||||
clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct));
|
||||
DumpPacket(app);
|
||||
// the previous behavior was essentially returning true here
|
||||
@@ -657,8 +653,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer;
|
||||
if(OPCharCreate(char_name, cc) == false)
|
||||
{
|
||||
if(OPCharCreate(char_name, cc) == false) {
|
||||
database.DeleteCharacter(char_name);
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApproveName, 1);
|
||||
outapp->pBuffer[0] = 0;
|
||||
@@ -675,8 +670,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
|
||||
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if (GetAccountID() == 0) {
|
||||
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
|
||||
eqs->Close();
|
||||
@@ -713,11 +707,10 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!pZoning && ew->return_home && !ew->tutorial)
|
||||
{
|
||||
if(!pZoning && ew->return_home && !ew->tutorial) {
|
||||
CharacterSelect_Struct* cs = new CharacterSelect_Struct;
|
||||
memset(cs, 0, sizeof(CharacterSelect_Struct));
|
||||
database.GetCharSelectInfo(GetAccountID(), cs);
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
bool home_enabled = false;
|
||||
|
||||
for(int x = 0; x < 10; ++x)
|
||||
@@ -733,12 +726,10 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
safe_delete(cs);
|
||||
|
||||
if(home_enabled)
|
||||
{
|
||||
if(home_enabled) {
|
||||
zoneID = database.MoveCharacterToBind(charid,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||
eqs->Close();
|
||||
@@ -749,7 +740,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if(!pZoning && (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial))) {
|
||||
CharacterSelect_Struct* cs = new CharacterSelect_Struct;
|
||||
memset(cs, 0, sizeof(CharacterSelect_Struct));
|
||||
database.GetCharSelectInfo(GetAccountID(), cs);
|
||||
database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit);
|
||||
bool tutorial_enabled = false;
|
||||
|
||||
for(int x = 0; x < 10; ++x)
|
||||
@@ -807,16 +798,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
database.SetLoginFlags(charid, false, false, 1);
|
||||
}
|
||||
else{
|
||||
uint32 groupid=database.GetGroupID(char_name);
|
||||
if(groupid>0){
|
||||
char* leader=0;
|
||||
char leaderbuf[64]={0};
|
||||
if((leader=database.GetGroupLeaderForLogin(char_name,leaderbuf)) && strlen(leader)>1){
|
||||
uint32 groupid = database.GetGroupID(char_name);
|
||||
if(groupid > 0){
|
||||
char* leader = 0;
|
||||
char leaderbuf[64] = {0};
|
||||
if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){
|
||||
EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct));
|
||||
GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer;
|
||||
gj->action=8;
|
||||
strcpy(gj->yourname,char_name);
|
||||
strcpy(gj->membername,leader);
|
||||
strcpy(gj->yourname, char_name);
|
||||
strcpy(gj->membername, leader);
|
||||
QueuePacket(outapp3);
|
||||
safe_delete(outapp3);
|
||||
}
|
||||
@@ -895,8 +886,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
||||
|
||||
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
||||
if(char_acct_id == GetAccountID())
|
||||
{
|
||||
if(char_acct_id == GetAccountID()) {
|
||||
clog(WORLD__CLIENT,"Delete character: %s",app->pBuffer);
|
||||
database.DeleteCharacter((char *)app->pBuffer);
|
||||
SendCharInfo();
|
||||
@@ -1347,8 +1337,7 @@ void Client::SendApproveWorld()
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
{
|
||||
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) {
|
||||
PlayerProfile_Struct pp;
|
||||
ExtendedProfile_Struct ext;
|
||||
Inventory inv;
|
||||
@@ -1356,12 +1345,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
char startzone[50]={0};
|
||||
uint32 i;
|
||||
struct in_addr in;
|
||||
|
||||
|
||||
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX +
|
||||
cc->WIS + cc->INT + cc->CHA;
|
||||
|
||||
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA;
|
||||
|
||||
in.s_addr = GetIP();
|
||||
|
||||
clog(WORLD__CLIENT,"Character creation request from %s LS#%d (%s:%d) : ", GetCLE()->LSName(), GetCLE()->LSID(), inet_ntoa(in), GetPort());
|
||||
clog(WORLD__CLIENT,"Name: %s", name);
|
||||
clog(WORLD__CLIENT,"Race: %d Class: %d Gender: %d Deity: %d Start zone: %d",
|
||||
@@ -1374,38 +1362,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
clog(WORLD__CLIENT,"Hairstyle: %d Haircolor: %d", cc->hairstyle, cc->haircolor);
|
||||
clog(WORLD__CLIENT,"Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor);
|
||||
|
||||
// validate the char creation struct
|
||||
/* Validate the char creation struct */
|
||||
if(ClientVersionBit & BIT_SoFAndLater) {
|
||||
if(!CheckCharCreateInfoSoF(cc))
|
||||
{
|
||||
if(!CheckCharCreateInfoSoF(cc)) {
|
||||
clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!CheckCharCreateInfoTitanium(cc))
|
||||
{
|
||||
if(!CheckCharCreateInfoTitanium(cc)) {
|
||||
clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert incoming cc_s to the new PlayerProfile_Struct
|
||||
/* Convert incoming cc_s to the new PlayerProfile_Struct */
|
||||
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
|
||||
|
||||
InitExtendedProfile(&ext);
|
||||
|
||||
strn0cpy(pp.name, name, 63);
|
||||
// clean the capitalization of the name
|
||||
#if 0 // on second thought, don't - this will just make the creation fail
|
||||
// because the name won't match what was already reserved earlier
|
||||
for (i = 0; pp.name[i] && i < 63; i++)
|
||||
{
|
||||
if(!isalpha(pp.name[i]))
|
||||
return false;
|
||||
pp.name[i] = tolower(pp.name[i]);
|
||||
}
|
||||
pp.name[0] = toupper(pp.name[0]);
|
||||
#endif
|
||||
|
||||
pp.race = cc->race;
|
||||
pp.class_ = cc->class_;
|
||||
@@ -1432,44 +1405,40 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
pp.lastlogin = bday;
|
||||
pp.level = 1;
|
||||
pp.points = 5;
|
||||
pp.cur_hp = 1000; // 1k hp during dev only
|
||||
//what was the point of this? zone dosent handle this:
|
||||
//pp.expAA = 0xFFFFFFFF;
|
||||
|
||||
pp.cur_hp = 1000; // 1k hp during dev only
|
||||
pp.hunger_level = 6000;
|
||||
pp.thirst_level = 6000;
|
||||
|
||||
|
||||
// FIXME: FV roleplay, database goodness...
|
||||
|
||||
// Racial Languages
|
||||
SetRacialLanguages( &pp ); // bUsh
|
||||
SetRaceStartingSkills( &pp ); // bUsh
|
||||
SetClassStartingSkills( &pp ); // bUsh
|
||||
/* Racial Languages */
|
||||
SetRacialLanguages( &pp );
|
||||
SetRaceStartingSkills( &pp );
|
||||
SetClassStartingSkills( &pp );
|
||||
SetClassLanguages(&pp);
|
||||
pp.skills[SkillSenseHeading] = 200;
|
||||
// Some one fucking fix this to use a field name. -Doodman
|
||||
//pp.unknown3596[28] = 15; // @bp: This is to enable disc usage
|
||||
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
|
||||
|
||||
|
||||
for(i = 0; i < MAX_PP_SPELLBOOK; i++)
|
||||
for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++)
|
||||
pp.spell_book[i] = 0xFFFFFFFF;
|
||||
|
||||
for(i = 0; i < MAX_PP_MEMSPELL; i++)
|
||||
for(i = 0; i < MAX_PP_REF_MEMSPELL; i++)
|
||||
pp.mem_spells[i] = 0xFFFFFFFF;
|
||||
|
||||
for(i = 0; i < BUFF_COUNT; i++)
|
||||
pp.buffs[i].spellid = 0xFFFF;
|
||||
|
||||
/*
|
||||
Was memset(pp.unknown3704, 0xffffffff, 8);
|
||||
but I dont think thats what you really wanted to do...
|
||||
memset is byte based
|
||||
*/
|
||||
|
||||
//was memset(pp.unknown3704, 0xffffffff, 8);
|
||||
//but I dont think thats what you really wanted to do...
|
||||
//memset is byte based
|
||||
|
||||
//If server is PVP by default, make all character set to it.
|
||||
/* If server is PVP by default, make all character set to it. */
|
||||
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
|
||||
|
||||
//If it is an SoF Client and the SoF Start Zone rule is set, send new chars there
|
||||
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
|
||||
if((ClientVersionBit & BIT_SoFAndLater) && (RuleI(World, SoFStartZoneID) > 0)) {
|
||||
clog(WORLD__CLIENT,"Found 'SoFStartZoneID' rule setting: %i", (RuleI(World, SoFStartZoneID)));
|
||||
pp.zone_id = (RuleI(World, SoFStartZoneID));
|
||||
@@ -1478,11 +1447,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
else
|
||||
clog(WORLD__CLIENT_ERR,"Error getting zone id for Zone ID %i", (RuleI(World, SoFStartZoneID)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there's a startzone variable put them in there
|
||||
if(database.GetVariable("startzone", startzone, 50))
|
||||
{
|
||||
else {
|
||||
/* if there's a startzone variable put them in there */
|
||||
if(database.GetVariable("startzone", startzone, 50)) {
|
||||
clog(WORLD__CLIENT,"Found 'startzone' variable setting: %s", startzone);
|
||||
pp.zone_id = database.GetZoneID(startzone);
|
||||
if(pp.zone_id)
|
||||
@@ -1490,8 +1457,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
else
|
||||
clog(WORLD__CLIENT_ERR,"Error getting zone id for '%s'", startzone);
|
||||
}
|
||||
else // otherwise use normal starting zone logic
|
||||
{
|
||||
else{ /* otherwise use normal starting zone logic */
|
||||
bool ValidStartZone = false;
|
||||
|
||||
if(ClientVersionBit & BIT_TitaniumAndEarlier)
|
||||
@@ -1504,14 +1470,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
}
|
||||
}
|
||||
|
||||
if(!pp.zone_id)
|
||||
{
|
||||
if(!pp.zone_id) {
|
||||
pp.zone_id = 1; // qeynos
|
||||
pp.x = pp.y = pp.z = -1;
|
||||
}
|
||||
|
||||
if(!pp.binds[0].zoneId)
|
||||
{
|
||||
if(!pp.binds[0].zoneId) {
|
||||
pp.binds[0].zoneId = pp.zone_id;
|
||||
pp.binds[0].x = pp.x;
|
||||
pp.binds[0].y = pp.y;
|
||||
@@ -1519,7 +1483,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
pp.binds[0].heading = pp.heading;
|
||||
}
|
||||
|
||||
// set starting city location to the initial bind point
|
||||
/* Set Starting city */
|
||||
pp.binds[4] = pp.binds[0];
|
||||
|
||||
|
||||
@@ -1528,28 +1492,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
clog(WORLD__CLIENT,"Bind location: %s %0.2f, %0.2f, %0.2f",
|
||||
database.GetZoneName(pp.binds[0].zoneId), pp.binds[0].x, pp.binds[0].y, pp.binds[0].z);
|
||||
|
||||
|
||||
// Starting Items inventory
|
||||
/* Starting Items inventory */
|
||||
database.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
|
||||
|
||||
|
||||
// now we give the pp and the inv we made to StoreCharacter
|
||||
// to see if we can store it
|
||||
if (!database.StoreCharacter(GetAccountID(), &pp, &inv, &ext))
|
||||
{
|
||||
if (!database.StoreCharacter(GetAccountID(), &pp, &inv)) {
|
||||
clog(WORLD__CLIENT_ERR,"Character creation failed: %s", pp.name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
clog(WORLD__CLIENT,"Character creation successful: %s", pp.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if the request is ok, false if there's an error
|
||||
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc)
|
||||
{
|
||||
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) {
|
||||
if(!cc) return false;
|
||||
|
||||
_log(WORLD__CLIENT, "Validating char creation info...");
|
||||
@@ -1831,28 +1790,15 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
return Charerrors == 0;
|
||||
}
|
||||
|
||||
void Client::SetClassStartingSkills( PlayerProfile_Struct *pp )
|
||||
void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
|
||||
{
|
||||
for(uint32 i = 0; i <= HIGHEST_SKILL; ++i) {
|
||||
if(pp->skills[i] == 0) {
|
||||
if(i >= SkillSpecializeAbjure && i <= SkillSpecializeEvocation) {
|
||||
for (uint32 i = 0; i <= HIGHEST_SKILL; ++i) {
|
||||
if (pp->skills[i] == 0) {
|
||||
// Skip specialized, tradeskills (fishing excluded), Alcohol Tolerance, and Bind Wound
|
||||
if (EQEmu::IsSpecializedSkill((SkillUseTypes)i) ||
|
||||
(EQEmu::IsTradeskill((SkillUseTypes)i) && i != SkillFishing) ||
|
||||
i == SkillAlcoholTolerance || i == SkillBindWound)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i == SkillMakePoison ||
|
||||
i == SkillTinkering ||
|
||||
i == SkillResearch ||
|
||||
i == SkillAlchemy ||
|
||||
i == SkillBaking ||
|
||||
i == SkillTailoring ||
|
||||
i == SkillBlacksmithing ||
|
||||
i == SkillFletching ||
|
||||
i == SkillBrewing ||
|
||||
i == SkillPottery ||
|
||||
i == SkillJewelryMaking ||
|
||||
i == SkillBegging) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1);
|
||||
}
|
||||
@@ -2034,3 +1980,15 @@ void Client::SetRacialLanguages( PlayerProfile_Struct *pp )
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
||||
{
|
||||
// we only need to handle one class, but custom server might want to do more
|
||||
switch(pp->class_) {
|
||||
case ROGUE:
|
||||
pp->languages[LANG_THIEVES_CANT] = 100;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ private:
|
||||
void SetClassStartingSkills( PlayerProfile_Struct *pp );
|
||||
void SetRaceStartingSkills( PlayerProfile_Struct *pp );
|
||||
void SetRacialLanguages( PlayerProfile_Struct *pp );
|
||||
void SetClassLanguages(PlayerProfile_Struct *pp);
|
||||
|
||||
ClientListEntry* cle;
|
||||
Timer CLE_keepalive_timer;
|
||||
|
||||
@@ -93,6 +93,7 @@ ClientListEntry::~ClientListEntry() {
|
||||
Camp(); // updates zoneserver's numplayers
|
||||
client_list.RemoveCLEReferances(this);
|
||||
}
|
||||
tell_queue.clear();
|
||||
}
|
||||
|
||||
void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
|
||||
@@ -233,6 +234,7 @@ void ClientListEntry::ClearVars(bool iAll) {
|
||||
pLFG = 0;
|
||||
gm = 0;
|
||||
pClientVersion = 0;
|
||||
tell_queue.clear();
|
||||
}
|
||||
|
||||
void ClientListEntry::Camp(ZoneServer* iZS) {
|
||||
@@ -295,3 +297,21 @@ bool ClientListEntry::CheckAuth(uint32 id, const char* iKey, uint32 ip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientListEntry::ProcessTellQueue()
|
||||
{
|
||||
if (!Server())
|
||||
return;
|
||||
|
||||
ServerPacket *pack;
|
||||
auto it = tell_queue.begin();
|
||||
while (it != tell_queue.end()) {
|
||||
pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1);
|
||||
memcpy(pack->pBuffer, *it, pack->size);
|
||||
pack->Deflate();
|
||||
Server()->SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
it = tell_queue.erase(it);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "../common/md5.h"
|
||||
//#include "../common/eq_packet_structs.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
#define CLE_Status_Never -1
|
||||
@@ -80,6 +82,11 @@ public:
|
||||
inline const char* GetLFGComments() const { return pLFGComments; }
|
||||
inline uint8 GetClientVersion() { return pClientVersion; }
|
||||
|
||||
inline bool TellQueueFull() const { return tell_queue.size() >= RuleI(World, TellQueueSize); }
|
||||
inline bool TellQueueEmpty() const { return tell_queue.empty(); }
|
||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||
void ProcessTellQueue();
|
||||
|
||||
private:
|
||||
void ClearVars(bool iAll = false);
|
||||
|
||||
@@ -120,6 +127,9 @@ private:
|
||||
uint8 pLFGToLevel;
|
||||
bool pLFGMatchFilter;
|
||||
char pLFGComments[64];
|
||||
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||
};
|
||||
|
||||
#endif /*CLIENTENTRY_H_*/
|
||||
|
||||
+4
-1
@@ -113,7 +113,7 @@ bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) {
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
SendMessage(1, "%s tells you, '%s'", scm->from, scm->message);
|
||||
SendMessage(1, "[%s] tells you, '%s'", scm->from, scm->message);
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1);
|
||||
memcpy(pack->pBuffer, scm, pack->size);
|
||||
ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer;
|
||||
@@ -847,6 +847,9 @@ void Console::ProcessCommand(const char* command) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
else if (strcasecmp(sep.arg[0], "") == 0){
|
||||
/* Hit Enter with no command */
|
||||
}
|
||||
else {
|
||||
SendMessage(1, "Command unknown.");
|
||||
}
|
||||
|
||||
+7
-7
@@ -67,7 +67,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
#include "../common/dbasync.h"
|
||||
#include "../common/emu_tcp_server.h"
|
||||
#include "../common/patches/patches.h"
|
||||
#include "zoneserver.h"
|
||||
@@ -98,7 +97,6 @@ UCSConnection UCSLink;
|
||||
QueryServConnection QSLink;
|
||||
LauncherList launcher_list;
|
||||
AdventureManager adventure_manager;
|
||||
DBAsync *dbasync = nullptr;
|
||||
volatile bool RunLoops = true;
|
||||
uint32 numclients = 0;
|
||||
uint32 numzones = 0;
|
||||
@@ -175,7 +173,6 @@ int main(int argc, char** argv) {
|
||||
_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
|
||||
return 1;
|
||||
}
|
||||
dbasync = new DBAsync(&database);
|
||||
guild_mgr.SetDatabase(&database);
|
||||
|
||||
if (argc >= 2) {
|
||||
@@ -222,9 +219,8 @@ int main(int argc, char** argv) {
|
||||
else if (strcasecmp(argv[1], "flag") == 0) {
|
||||
if (argc == 4) {
|
||||
if (Seperator::IsNumber(argv[3])) {
|
||||
|
||||
if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) {
|
||||
if (database.SetAccountStatus(argv[2], atoi(argv[3]))) {
|
||||
if (database.SetAccountStatus(argv[2], atoi(argv[3]))){
|
||||
std::cout << "Account flagged: Username='" << argv[2] << "', status=" << argv[3] << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -276,6 +272,8 @@ int main(int argc, char** argv) {
|
||||
_log(WORLD__INIT, "HTTP world service disabled.");
|
||||
}
|
||||
|
||||
_log(WORLD__INIT, "Checking Database Conversions..");
|
||||
database.CheckDatabaseConversions();
|
||||
_log(WORLD__INIT, "Loading variables..");
|
||||
database.LoadVariables();
|
||||
_log(WORLD__INIT, "Loading zones..");
|
||||
@@ -286,9 +284,11 @@ int main(int argc, char** argv) {
|
||||
database.ClearRaid();
|
||||
database.ClearRaidDetails();
|
||||
_log(WORLD__INIT, "Loading items..");
|
||||
if (!database.LoadItems()) {
|
||||
if (!database.LoadItems())
|
||||
_log(WORLD__INIT_ERR, "Error: Could not load item data. But ignoring");
|
||||
}
|
||||
_log(WORLD__INIT, "Loading skill caps..");
|
||||
if (!database.LoadSkillCaps())
|
||||
_log(WORLD__INIT_ERR, "Error: Could not load skill cap data. But ignoring");
|
||||
_log(WORLD__INIT, "Loading guilds..");
|
||||
guild_mgr.LoadGuilds();
|
||||
//rules:
|
||||
|
||||
+176
-225
@@ -21,7 +21,6 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "../common/item.h"
|
||||
#include "../common/dbasync.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
@@ -34,248 +33,196 @@ extern std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||
|
||||
|
||||
// solar: the current stuff is at the bottom of this function
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs, uint32 ClientVersion) {
|
||||
Inventory *inv;
|
||||
uint8 has_home = 0;
|
||||
uint8 has_bind = 0;
|
||||
|
||||
/* Initialize Variables */
|
||||
for (int i=0; i<10; i++) {
|
||||
strcpy(cs->name[i], "<none>");
|
||||
cs->zone[i] = 0;
|
||||
cs->level[i] = 0;
|
||||
cs->tutorial[i] = 0;
|
||||
cs->tutorial[i] = 0;
|
||||
cs->gohome[i] = 0;
|
||||
}
|
||||
|
||||
int char_num = 0;
|
||||
unsigned long* lengths;
|
||||
/* Get Character Info */
|
||||
std::string cquery = StringFormat(
|
||||
"SELECT "
|
||||
"`id`, " // 0
|
||||
"name, " // 1
|
||||
"gender, " // 2
|
||||
"race, " // 3
|
||||
"class, " // 4
|
||||
"`level`, " // 5
|
||||
"deity, " // 6
|
||||
"last_login, " // 7
|
||||
"time_played, " // 8
|
||||
"hair_color, " // 9
|
||||
"beard_color, " // 10
|
||||
"eye_color_1, " // 11
|
||||
"eye_color_2, " // 12
|
||||
"hair_style, " // 13
|
||||
"beard, " // 14
|
||||
"face, " // 15
|
||||
"drakkin_heritage, " // 16
|
||||
"drakkin_tattoo, " // 17
|
||||
"drakkin_details, " // 18
|
||||
"zone_id " // 19
|
||||
"FROM "
|
||||
"character_data "
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT 10 ", account_id);
|
||||
auto results = database.QueryDatabase(cquery); int char_num = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
PlayerProfile_Struct pp;
|
||||
memset(&pp, 0, sizeof(PlayerProfile_Struct));
|
||||
|
||||
// Populate character info
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT name,profile,zonename,class,level FROM character_ WHERE account_id=%i order by name limit 10", account_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
lengths = mysql_fetch_lengths(result);
|
||||
////////////
|
||||
//////////// This is the current one, the other are for converting
|
||||
////////////
|
||||
if ((lengths[1] == sizeof(PlayerProfile_Struct))) {
|
||||
strcpy(cs->name[char_num], row[0]);
|
||||
PlayerProfile_Struct* pp = (PlayerProfile_Struct*)row[1];
|
||||
uint8 clas = atoi(row[3]);
|
||||
uint8 lvl = atoi(row[4]);
|
||||
uint32 character_id = atoi(row[0]);
|
||||
strcpy(cs->name[char_num], row[1]);
|
||||
uint8 lvl = atoi(row[5]);
|
||||
cs->level[char_num] = lvl;
|
||||
cs->class_[char_num] = atoi(row[4]);
|
||||
cs->race[char_num] = atoi(row[3]);
|
||||
cs->gender[char_num] = atoi(row[2]);
|
||||
cs->deity[char_num] = atoi(row[6]);
|
||||
cs->zone[char_num] = atoi(row[19]);
|
||||
cs->face[char_num] = atoi(row[15]);
|
||||
cs->haircolor[char_num] = atoi(row[9]);
|
||||
cs->beardcolor[char_num] = atoi(row[10]);
|
||||
cs->eyecolor2[char_num] = atoi(row[12]);
|
||||
cs->eyecolor1[char_num] = atoi(row[11]);
|
||||
cs->hairstyle[char_num] = atoi(row[13]);
|
||||
cs->beard[char_num] = atoi(row[14]);
|
||||
cs->drakkin_heritage[char_num] = atoi(row[16]);
|
||||
cs->drakkin_tattoo[char_num] = atoi(row[17]);
|
||||
cs->drakkin_details[char_num] = atoi(row[18]);
|
||||
|
||||
// Character information
|
||||
if(lvl == 0)
|
||||
cs->level[char_num] = pp->level; //no level in DB, trust PP
|
||||
else
|
||||
cs->level[char_num] = lvl;
|
||||
if(clas == 0)
|
||||
cs->class_[char_num] = pp->class_; //no class in DB, trust PP
|
||||
else
|
||||
cs->class_[char_num] = clas;
|
||||
cs->race[char_num] = pp->race;
|
||||
cs->gender[char_num] = pp->gender;
|
||||
cs->deity[char_num] = pp->deity;
|
||||
cs->zone[char_num] = GetZoneID(row[2]);
|
||||
cs->face[char_num] = pp->face;
|
||||
cs->haircolor[char_num] = pp->haircolor;
|
||||
cs->beardcolor[char_num] = pp->beardcolor;
|
||||
cs->eyecolor2[char_num] = pp->eyecolor2;
|
||||
cs->eyecolor1[char_num] = pp->eyecolor1;
|
||||
cs->hairstyle[char_num] = pp->hairstyle;
|
||||
cs->beard[char_num] = pp->beard;
|
||||
cs->drakkin_heritage[char_num] = pp->drakkin_heritage;
|
||||
cs->drakkin_tattoo[char_num] = pp->drakkin_tattoo;
|
||||
cs->drakkin_details[char_num] = pp->drakkin_details;
|
||||
if (RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
|
||||
cs->tutorial[char_num] = 1;
|
||||
|
||||
if(RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
|
||||
cs->tutorial[char_num] = 1;
|
||||
if (RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if ((now - atoi(row[8])) >= RuleI(World, MinOfflineTimeToReturnHome))
|
||||
cs->gohome[char_num] = 1;
|
||||
}
|
||||
|
||||
if(RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if((now - pp->lastlogin) >= RuleI(World, MinOfflineTimeToReturnHome))
|
||||
cs->gohome[char_num] = 1;
|
||||
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
|
||||
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id);
|
||||
auto results_bind = database.QueryDatabase(cquery); has_home = 0; has_bind = 0;
|
||||
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
||||
if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; }
|
||||
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
|
||||
}
|
||||
|
||||
if (has_home == 0 || has_bind == 0){
|
||||
cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
|
||||
cs->class_[char_num], cs->deity[char_num], cs->race[char_num]);
|
||||
auto results_bind = database.QueryDatabase(cquery);
|
||||
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
||||
/* If a bind_id is specified, make them start there */
|
||||
if (atoi(row_d[1]) != 0) {
|
||||
pp.binds[4].zoneId = (uint32)atoi(row_d[1]);
|
||||
GetSafePoints(pp.binds[4].zoneId, 0, &pp.binds[4].x, &pp.binds[4].y, &pp.binds[4].z);
|
||||
}
|
||||
|
||||
|
||||
// This part creates home city entries for characters created before the home bind point was tracked.
|
||||
// Do it here because the player profile is already loaded and it's as good a spot as any. This whole block should
|
||||
// probably be removed at some point, when most accounts are safely converted.
|
||||
if(pp->binds[4].zoneId == 0) {
|
||||
bool altered = false;
|
||||
MYSQL_RES *result2;
|
||||
MYSQL_ROW row2;
|
||||
char startzone[50] = {0};
|
||||
|
||||
// check for start zone variable (I didn't even know any variables were still being used...)
|
||||
if(database.GetVariable("startzone", startzone, 50)) {
|
||||
uint32 zoneid = database.GetZoneID(startzone);
|
||||
if(zoneid) {
|
||||
pp->binds[4].zoneId = zoneid;
|
||||
GetSafePoints(zoneid, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
|
||||
altered = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RunQuery(query,
|
||||
MakeAnyLenString(&query,
|
||||
"SELECT zone_id,bind_id,x,y,z FROM start_zones "
|
||||
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
|
||||
pp->class_,
|
||||
pp->deity,
|
||||
pp->race
|
||||
),
|
||||
errbuf,
|
||||
&result2
|
||||
);
|
||||
safe_delete_array(query);
|
||||
|
||||
// if there is only one possible start city, set it
|
||||
if(mysql_num_rows(result2) == 1) {
|
||||
row2 = mysql_fetch_row(result2);
|
||||
if(atoi(row2[1]) != 0) { // if a bind_id is specified, make them start there
|
||||
pp->binds[4].zoneId = (uint32)atoi(row2[1]);
|
||||
GetSafePoints(pp->binds[4].zoneId, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
|
||||
}
|
||||
else { // otherwise, use the zone and coordinates given
|
||||
pp->binds[4].zoneId = (uint32)atoi(row2[0]);
|
||||
float x = atof(row2[2]);
|
||||
float y = atof(row2[3]);
|
||||
float z = atof(row2[4]);
|
||||
if(x == 0 && y == 0 && z == 0)
|
||||
GetSafePoints(pp->binds[4].zoneId, 0, &x, &y, &z);
|
||||
|
||||
pp->binds[4].x = x;
|
||||
pp->binds[4].y = y;
|
||||
pp->binds[4].z = z;
|
||||
}
|
||||
altered = true;
|
||||
}
|
||||
|
||||
mysql_free_result(result2);
|
||||
}
|
||||
|
||||
// update the player profile
|
||||
if(altered) {
|
||||
uint32 char_id = GetCharacterID(cs->name[char_num]);
|
||||
RunQuery(query,MakeAnyLenString(&query,"SELECT extprofile FROM character_ WHERE id=%i",char_id), errbuf, &result2);
|
||||
safe_delete_array(query);
|
||||
if(result2) {
|
||||
row2 = mysql_fetch_row(result2);
|
||||
ExtendedProfile_Struct* ext = (ExtendedProfile_Struct*)row2[0];
|
||||
SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5);
|
||||
}
|
||||
mysql_free_result(result2);
|
||||
}
|
||||
} // end of "set start zone" block
|
||||
|
||||
|
||||
// Character's equipped items
|
||||
// @merth: Haven't done bracer01/bracer02 yet.
|
||||
// Also: this needs a second look after items are a little more solid
|
||||
// NOTE: items don't have a color, players MAY have a tint, if the
|
||||
// use_tint part is set. otherwise use the regular color
|
||||
inv = new Inventory;
|
||||
if(GetInventory(account_id, cs->name[char_num], inv))
|
||||
{
|
||||
for (uint8 material = 0; material <= 8; material++)
|
||||
{
|
||||
uint32 color;
|
||||
ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
|
||||
if(item == 0)
|
||||
continue;
|
||||
|
||||
cs->equip[char_num][material] = item->GetItem()->Material;
|
||||
|
||||
if(pp->item_tint[material].rgb.use_tint) // they have a tint (LoY dye)
|
||||
color = pp->item_tint[material].color;
|
||||
else // no tint, use regular item color
|
||||
color = item->GetItem()->Color;
|
||||
|
||||
cs->cs_colors[char_num][material].color = color;
|
||||
|
||||
// the weapons are kept elsewhere
|
||||
if ((material==MaterialPrimary) || (material==MaterialSecondary))
|
||||
{
|
||||
if(strlen(item->GetItem()->IDFile) > 2) {
|
||||
uint32 idfile=atoi(&item->GetItem()->IDFile[2]);
|
||||
if (material==MaterialPrimary)
|
||||
cs->primary[char_num]=idfile;
|
||||
else
|
||||
cs->secondary[char_num]=idfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Otherwise, use the zone and coordinates given */
|
||||
else {
|
||||
pp.binds[4].zoneId = (uint32)atoi(row_d[0]);
|
||||
float x = atof(row_d[2]);
|
||||
float y = atof(row_d[3]);
|
||||
float z = atof(row_d[4]);
|
||||
if (x == 0 && y == 0 && z == 0){ GetSafePoints(pp.binds[4].zoneId, 0, &x, &y, &z); }
|
||||
pp.binds[4].x = x; pp.binds[4].y = y; pp.binds[4].z = z;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error loading inventory for %s\n", cs->name[char_num]);
|
||||
}
|
||||
safe_delete(inv);
|
||||
if (++char_num > 10)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Got a bogus character (" << row[0] << ") Ignoring!!!" << std::endl;
|
||||
std::cout << "PP length ="<<lengths[1]<<" but PP should be "<<sizeof(PlayerProfile_Struct) << std::endl;
|
||||
//DeleteCharacter(row[0]);
|
||||
pp.binds[0] = pp.binds[4];
|
||||
/* If no home bind set, set it */
|
||||
if (has_home == 0){
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1);
|
||||
auto results_bset = QueryDatabase(query); ThrowDBError(results_bset.ErrorMessage(), "WorldDatabase::GetCharSelectInfo Set Home Point", query);
|
||||
}
|
||||
/* If no regular bind set, set it */
|
||||
if (has_bind == 0){
|
||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
|
||||
auto results_bset = QueryDatabase(query); ThrowDBError(results_bset.ErrorMessage(), "WorldDatabase::GetCharSelectInfo Set Bind Point", query);
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error in GetCharSelectInfo query '" << query << "' " << errbuf << std::endl;
|
||||
safe_delete_array(query);
|
||||
return;
|
||||
/* Bind End */
|
||||
|
||||
/*
|
||||
Character's equipped items
|
||||
@merth: Haven't done bracer01/bracer02 yet.
|
||||
Also: this needs a second look after items are a little more solid
|
||||
NOTE: items don't have a color, players MAY have a tint, if the
|
||||
use_tint part is set. otherwise use the regular color
|
||||
*/
|
||||
|
||||
/* Load Character Material Data for Char Select */
|
||||
cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
|
||||
auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
|
||||
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
|
||||
slot = atoi(row_b[0]);
|
||||
pp.item_tint[slot].rgb.red = atoi(row_b[1]);
|
||||
pp.item_tint[slot].rgb.green = atoi(row_b[2]);
|
||||
pp.item_tint[slot].rgb.blue = atoi(row_b[3]);
|
||||
pp.item_tint[slot].rgb.use_tint = atoi(row_b[4]);
|
||||
}
|
||||
|
||||
/* Load Inventory */
|
||||
inv = new Inventory;
|
||||
if (GetInventory(account_id, cs->name[char_num], inv)) {
|
||||
for (uint8 material = 0; material <= 8; material++) {
|
||||
uint32 color = 0;
|
||||
ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
|
||||
if (item == 0)
|
||||
continue;
|
||||
|
||||
cs->equip[char_num][material] = item->GetItem()->Material;
|
||||
|
||||
if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; }
|
||||
else{ color = item->GetItem()->Color; }
|
||||
|
||||
cs->cs_colors[char_num][material].color = color;
|
||||
|
||||
/* Weapons are handled a bit differently */
|
||||
if ((material == MaterialPrimary) || (material == MaterialSecondary)) {
|
||||
if (strlen(item->GetItem()->IDFile) > 2) {
|
||||
uint32 idfile = atoi(&item->GetItem()->IDFile[2]);
|
||||
if (material == MaterialPrimary)
|
||||
cs->primary[char_num] = idfile;
|
||||
else
|
||||
cs->secondary[char_num] = idfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Error loading inventory for %s\n", cs->name[char_num]);
|
||||
}
|
||||
safe_delete(inv);
|
||||
if (++char_num > 10)
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) {
|
||||
// if an invalid bind point is specified, use the primary bind
|
||||
if (bindnum > 4)
|
||||
bindnum = 0;
|
||||
/* if an invalid bind point is specified, use the primary bind */
|
||||
if (bindnum > 4){ bindnum = 0; }
|
||||
int is_home = 0;
|
||||
if (bindnum == 4){ is_home = 1; }
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
uint32 affected_rows = 0;
|
||||
PlayerProfile_Struct pp;
|
||||
|
||||
bool PPValid = false;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile from character_ where id='%i'", CharID), errbuf, &result)) {
|
||||
row = mysql_fetch_row(result);
|
||||
unsigned long* lengths = mysql_fetch_lengths(result);
|
||||
if (lengths[0] == sizeof(PlayerProfile_Struct)) {
|
||||
memcpy(&pp, row[0], sizeof(PlayerProfile_Struct));
|
||||
PPValid = true;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
std::string query = StringFormat("SELECT `zone_id` FROM `character_bind` WHERE `id` = %u AND `is_home` = %u LIMIT 1", CharID, is_home);
|
||||
auto results = database.QueryDatabase(query); int i = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
return atoi(row[0]);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
if(!PPValid) return 0;
|
||||
|
||||
const char *BindZoneName = StaticGetZoneName(pp.binds[bindnum].zoneId);
|
||||
|
||||
if(!strcmp(BindZoneName, "UNKNWN")) return pp.zone_id;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=%f, y=%f, z=%f, instanceid=0 WHERE id='%i'",
|
||||
BindZoneName, pp.binds[bindnum].zoneId, pp.binds[bindnum].x, pp.binds[bindnum].y, pp.binds[bindnum].z,
|
||||
CharID), errbuf, 0,&affected_rows)) {
|
||||
|
||||
return pp.zone_id;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
return pp.binds[bindnum].zoneId;
|
||||
}
|
||||
|
||||
bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc)
|
||||
@@ -444,12 +391,16 @@ bool WorldDatabase::GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Stru
|
||||
in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0;
|
||||
in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0;
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "SELECT x,y,z,heading,bind_id FROM start_zones WHERE zone_id=%i AND player_class=%i "
|
||||
"AND player_deity=%i AND player_race=%i",
|
||||
in_cc->start_zone,
|
||||
in_cc->class_,
|
||||
in_cc->deity,
|
||||
in_cc->race), errbuf, &result))
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "SELECT x, y, z, heading, bind_id "
|
||||
" FROM start_zones "
|
||||
" WHERE zone_id = %i "
|
||||
" AND player_class = %i "
|
||||
" AND player_deity = %i"
|
||||
" AND player_race = %i",
|
||||
in_cc->start_zone,
|
||||
in_cc->class_,
|
||||
in_cc->deity,
|
||||
in_cc->race), errbuf, &result))
|
||||
{
|
||||
LogFile->write(EQEMuLog::Status, "SoF Start zone query failed: %s : %s\n", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
@@ -532,7 +483,7 @@ void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) {
|
||||
else
|
||||
sprintf(MailKeyString, "%08X", MailKey);
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET mailkey = '%s' WHERE id='%i'",
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `character_data` SET mailkey = '%s' WHERE id='%i'",
|
||||
MailKeyString, CharID), errbuf))
|
||||
|
||||
LogFile->write(EQEMuLog::Error, "WorldDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, errbuf);
|
||||
@@ -548,7 +499,7 @@ bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if(RunQuery(query, MakeAnyLenString(&query, "SELECT level FROM character_ WHERE name='%s'", name), errbuf, &result))
|
||||
if(RunQuery(query, MakeAnyLenString(&query, "SELECT `level` FROM `character_data` WHERE `name` = '%s'", name), errbuf, &result))
|
||||
{
|
||||
if(row = mysql_fetch_row(result))
|
||||
{
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public:
|
||||
bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
|
||||
bool GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
|
||||
|
||||
void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*);
|
||||
void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*, uint32 ClientVersion);
|
||||
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
||||
|
||||
void GetLauncherList(std::vector<std::string> &result);
|
||||
|
||||
+2
-2
@@ -87,7 +87,7 @@ void ZSList::Process() {
|
||||
CatchSignal(2);
|
||||
}
|
||||
if(reminder && reminder->Check()){
|
||||
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i seconds...",shutdowntimer->GetRemainingTime()/1000);
|
||||
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i minutes...", ((shutdowntimer->GetRemainingTime()/1000) / 60));
|
||||
}
|
||||
LinkedListIterator<ZoneServer*> iterator(list);
|
||||
|
||||
@@ -718,7 +718,7 @@ void ZSList::GetZoneIDList(std::vector<uint32> &zones) {
|
||||
void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
{
|
||||
if( time > 0 ) {
|
||||
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down in %i seconds, everyone log out before this time.",time);
|
||||
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down in %i minutes, everyone log out before this time.", (time / 60));
|
||||
|
||||
time *= 1000;
|
||||
interval *= 1000;
|
||||
|
||||
+86
-107
@@ -437,45 +437,48 @@ bool ZoneServer::Process() {
|
||||
Console* con = 0;
|
||||
con = console_list.FindByAccountName(&scm->deliverto[1]);
|
||||
if (((!con) || (!con->SendChannelMessage(scm))) && (!scm->noreply))
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to);
|
||||
break;
|
||||
}
|
||||
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply)
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
}
|
||||
else if (cle->Online() == CLE_Status_Zoning) {
|
||||
if (!scm->noreply)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
time ( &rawtime );
|
||||
timeinfo = localtime ( &rawtime );
|
||||
char *telldate=asctime(timeinfo);
|
||||
|
||||
std::string query = StringFormat("SELECT name FROM character_ WHERE name = '%s'",scm->deliverto);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
break;
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
break;
|
||||
}
|
||||
|
||||
query = StringFormat("INSERT INTO tellque "
|
||||
"(Date, Receiver, Sender, Message) "
|
||||
"VALUES('%s', '%s', '%s', '%s')",
|
||||
telldate, scm->deliverto, scm->from, scm->message);
|
||||
results = database.QueryDatabase(query);
|
||||
if (results.Success())
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to the %s's que.", scm->to);
|
||||
else
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning ||
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 3; // offline
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
// ideally this would be trimming off the message too, oh well
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
} else if (cle->Online() == CLE_Status_Zoning) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (cle->TellQueueFull()) {
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 2; // queue full
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
sender->Server()->SendPacket(pack);
|
||||
} else {
|
||||
size_t struct_size = sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1;
|
||||
ServerChannelMessage_Struct *temp = (ServerChannelMessage_Struct *) new uchar[struct_size];
|
||||
memset(temp, 0, struct_size); // just in case, was seeing some corrupt messages, but it shouldn't happen
|
||||
memcpy(temp, scm, struct_size);
|
||||
temp->noreply = true;
|
||||
cle->PushToTellQueue(temp); // deallocation is handled in processing or deconstructor
|
||||
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 1; // queued
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
// zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
}
|
||||
else if (cle->Server() == 0) {
|
||||
if (!scm->noreply)
|
||||
@@ -652,17 +655,17 @@ bool ZoneServer::Process() {
|
||||
client->Clearance(wtz->response);
|
||||
}
|
||||
case ServerOP_ZoneToZoneRequest: {
|
||||
//
|
||||
// solar: ZoneChange is received by the zone the player is in, then the
|
||||
// zone sends a ZTZ which ends up here. This code then find the target
|
||||
// (ingress point) and boots it if needed, then sends the ZTZ to it.
|
||||
// The ingress server will decide wether the player can enter, then will
|
||||
// send back the ZTZ to here. This packet is passed back to the egress
|
||||
// server, which will send a ZoneChange response back to the client
|
||||
// which can be an error, or a success, in which case the client will
|
||||
// disconnect, and their zone location will be saved when ~Client is
|
||||
// called, so it will be available when they ask to zone.
|
||||
//
|
||||
//
|
||||
// solar: ZoneChange is received by the zone the player is in, then the
|
||||
// zone sends a ZTZ which ends up here. This code then find the target
|
||||
// (ingress point) and boots it if needed, then sends the ZTZ to it.
|
||||
// The ingress server will decide wether the player can enter, then will
|
||||
// send back the ZTZ to here. This packet is passed back to the egress
|
||||
// server, which will send a ZoneChange response back to the client
|
||||
// which can be an error, or a success, in which case the client will
|
||||
// disconnect, and their zone location will be saved when ~Client is
|
||||
// called, so it will be available when they ask to zone.
|
||||
//
|
||||
|
||||
|
||||
if(pack->size != sizeof(ZoneToZone_Struct))
|
||||
@@ -675,40 +678,31 @@ bool ZoneServer::Process() {
|
||||
zlog(WORLD__ZONE,"ZoneToZone request for %s current zone %d req zone %d\n",
|
||||
ztz->name, ztz->current_zone_id, ztz->requested_zone_id);
|
||||
|
||||
if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) // this is a request from the egress zone
|
||||
{
|
||||
/* This is a request from the egress zone */
|
||||
if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) {
|
||||
zlog(WORLD__ZONE,"Processing ZTZ for egress from zone for client %s\n", ztz->name);
|
||||
|
||||
if
|
||||
(
|
||||
ztz->admin < 80 &&
|
||||
ztz->ignorerestrictions < 2 &&
|
||||
zoneserver_list.IsZoneLocked(ztz->requested_zone_id)
|
||||
)
|
||||
{
|
||||
if (ztz->admin < 80 && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) {
|
||||
ztz->response = 0;
|
||||
SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
|
||||
ZoneServer *ingress_server = nullptr;
|
||||
if(ztz->requested_instance_id > 0)
|
||||
{
|
||||
if(ztz->requested_instance_id > 0) {
|
||||
ingress_server = zoneserver_list.FindByInstanceID(ztz->requested_instance_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id);
|
||||
|
||||
else {
|
||||
ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id);
|
||||
}
|
||||
|
||||
if(ingress_server) // found a zone already running
|
||||
{
|
||||
/* Zone was already running*/
|
||||
if(ingress_server) {
|
||||
_log(WORLD__ZONE,"Found a zone already booted for %s\n", ztz->name);
|
||||
ztz->response = 1;
|
||||
}
|
||||
else // need to boot one
|
||||
{
|
||||
/* Boot the Zone*/
|
||||
else {
|
||||
int server_id;
|
||||
if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id, ztz->requested_instance_id))){
|
||||
_log(WORLD__ZONE,"Successfully booted a zone for %s\n", ztz->name);
|
||||
@@ -716,8 +710,7 @@ bool ZoneServer::Process() {
|
||||
ztz->response = 1;
|
||||
ingress_server = zoneserver_list.FindByID(server_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
_log(WORLD__ZONE_ERR,"FAILED to boot a zone for %s\n", ztz->name);
|
||||
// bootup failed, send back error code 0
|
||||
ztz->response = 0;
|
||||
@@ -725,27 +718,24 @@ bool ZoneServer::Process() {
|
||||
}
|
||||
if(ztz->response!=0 && client)
|
||||
client->LSZoneChange(ztz);
|
||||
SendPacket(pack); // send back to egress server
|
||||
if(ingress_server) // if we couldn't boot one, this is 0
|
||||
{
|
||||
ingress_server->SendPacket(pack); // inform target server
|
||||
}
|
||||
SendPacket(pack); // send back to egress server
|
||||
if(ingress_server) {
|
||||
ingress_server->SendPacket(pack); // inform target server
|
||||
}
|
||||
}
|
||||
else // this is response from the ingress server, route it back to the egress server
|
||||
{
|
||||
/* Response from Ingress server, route back to egress */
|
||||
else{
|
||||
|
||||
zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name);
|
||||
ZoneServer *egress_server = nullptr;
|
||||
if(ztz->current_instance_id > 0)
|
||||
{
|
||||
if(ztz->current_instance_id > 0) {
|
||||
egress_server = zoneserver_list.FindByInstanceID(ztz->current_instance_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
egress_server = zoneserver_list.FindByZoneID(ztz->current_zone_id);
|
||||
}
|
||||
|
||||
if(egress_server)
|
||||
{
|
||||
if(egress_server) {
|
||||
egress_server->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
@@ -783,21 +773,18 @@ bool ZoneServer::Process() {
|
||||
delete whom;
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestOnlineGuildMembers:
|
||||
{
|
||||
case ServerOP_RequestOnlineGuildMembers: {
|
||||
ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*) pack->pBuffer;
|
||||
zlog(GUILDS__IN_PACKETS, "ServerOP_RequestOnlineGuildMembers Recieved. FromID=%i GuildID=%i", srogms->FromID, srogms->GuildID);
|
||||
client_list.SendOnlineGuildMembers(srogms->FromID, srogms->GuildID);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ClientVersionSummary:
|
||||
{
|
||||
case ServerOP_ClientVersionSummary: {
|
||||
ServerRequestClientVersionSummary_Struct *srcvss = (ServerRequestClientVersionSummary_Struct*) pack->pBuffer;
|
||||
client_list.SendClientVersionSummary(srcvss->Name);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadRules:
|
||||
{
|
||||
case ServerOP_ReloadRules: {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
RuleManager::Instance()->LoadRules(&database, "default");
|
||||
break;
|
||||
@@ -1272,37 +1259,19 @@ bool ZoneServer::Process() {
|
||||
case ServerOP_QueryServGeneric:
|
||||
case ServerOP_Speech:
|
||||
case ServerOP_QSPlayerLogTrades:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogHandins:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogNPCKills:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogDeletes:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogMoves:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogMerchantTransactions:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZSignalClientByName:
|
||||
case ServerOP_CZMessagePlayer:
|
||||
case ServerOP_CZMessagePlayer:
|
||||
case ServerOP_CZSignalNPC:
|
||||
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
||||
case ServerOP_CZSignalClient:
|
||||
{
|
||||
zoneserver_list.SendPacket(pack);
|
||||
@@ -1319,6 +1288,16 @@ bool ZoneServer::Process() {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestTellQueue:
|
||||
{
|
||||
ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer;
|
||||
ClientListEntry *cle = client_list.FindCharacter(rtq->name);
|
||||
if (!cle || cle->TellQueueEmpty())
|
||||
break;
|
||||
|
||||
cle->ProcessTellQueue();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
zlog(WORLD__ZONE_ERR,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size);
|
||||
|
||||
@@ -119,7 +119,6 @@ SET(zone_sources
|
||||
zone_logsys.cpp
|
||||
zone_config.cpp
|
||||
zonedb.cpp
|
||||
zonedbasync.cpp
|
||||
zoning.cpp
|
||||
)
|
||||
|
||||
@@ -207,7 +206,6 @@ SET(zone_headers
|
||||
zone.h
|
||||
zone_config.h
|
||||
zonedb.h
|
||||
zonedbasync.h
|
||||
zonedump.h
|
||||
)
|
||||
|
||||
|
||||
+29
-14
@@ -18,6 +18,8 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
// Test 1
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "aa.h"
|
||||
#include "mob.h"
|
||||
@@ -300,7 +302,7 @@ void Client::ActivateAA(aaID activate){
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
|
||||
if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
|
||||
//Reset on failed cast
|
||||
SendAATimer(AATimerID, 0, 0xFFFFFF);
|
||||
Message_StringID(15,ABILITY_FAILED);
|
||||
@@ -316,13 +318,14 @@ void Client::ActivateAA(aaID activate){
|
||||
}
|
||||
}
|
||||
// Check if AA is expendable
|
||||
if (aas_send[activate - activate_val]->special_category == 7)
|
||||
{
|
||||
if (aas_send[activate - activate_val]->special_category == 7) {
|
||||
|
||||
// Add the AA cost to the extended profile to track overall total
|
||||
m_epp.expended_aa += aas_send[activate]->cost;
|
||||
|
||||
SetAA(activate, 0);
|
||||
|
||||
Save();
|
||||
SaveAA(); /* Save Character AA */
|
||||
SendAA(activate);
|
||||
SendAATable();
|
||||
}
|
||||
@@ -525,7 +528,7 @@ void Client::HandleAAAction(aaID activate) {
|
||||
//cast the spell, if we have one
|
||||
if(IsValidSpell(spell_id)) {
|
||||
int aatid = GetAATimerID(activate);
|
||||
if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) {
|
||||
if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) {
|
||||
SendAATimer(aatid, 0, 0xFFFFFF);
|
||||
Message_StringID(15,ABILITY_FAILED);
|
||||
p_timers.Clear(&database, pTimerAAStart + aatid);
|
||||
@@ -1035,8 +1038,7 @@ void Client::BuyAA(AA_Action* action)
|
||||
uint32 real_cost;
|
||||
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability);
|
||||
|
||||
if(RequiredLevel != AARequiredLevelAndCost.end())
|
||||
{
|
||||
if(RequiredLevel != AARequiredLevelAndCost.end()) {
|
||||
real_cost = RequiredLevel->second.Cost;
|
||||
}
|
||||
else
|
||||
@@ -1049,7 +1051,11 @@ void Client::BuyAA(AA_Action* action)
|
||||
|
||||
m_pp.aapoints -= real_cost;
|
||||
|
||||
Save();
|
||||
/* Do Player Profile rank calculations and set player profile */
|
||||
SaveAA();
|
||||
/* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/
|
||||
// database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1));
|
||||
|
||||
if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u))
|
||||
&& ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){
|
||||
SendAA(aa2->id);
|
||||
@@ -1060,8 +1066,10 @@ void Client::BuyAA(AA_Action* action)
|
||||
|
||||
SendAATable();
|
||||
|
||||
//we are building these messages ourself instead of using the stringID to work around patch discrepencies
|
||||
//these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2
|
||||
/*
|
||||
We are building these messages ourself instead of using the stringID to work around patch discrepencies
|
||||
these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2
|
||||
*/
|
||||
|
||||
/* Initial purchase of an AA ability */
|
||||
if (cur_level < 1){
|
||||
@@ -1084,8 +1092,6 @@ void Client::BuyAA(AA_Action* action)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SendAAStats();
|
||||
|
||||
CalcBonuses();
|
||||
@@ -1514,11 +1520,15 @@ bool ZoneDatabase::LoadAAEffects2() {
|
||||
return true;
|
||||
}
|
||||
void Client::ResetAA(){
|
||||
RefundAA();
|
||||
uint32 i;
|
||||
for(i=0;i<MAX_PP_AA_ARRAY;i++){
|
||||
aa[i]->AA = 0;
|
||||
aa[i]->value = 0;
|
||||
m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0;
|
||||
m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0;
|
||||
}
|
||||
|
||||
std::map<uint32,uint8>::iterator itr;
|
||||
for(itr=aa_points.begin();itr!=aa_points.end();++itr)
|
||||
aa_points[itr->first] = 0;
|
||||
@@ -1530,6 +1540,12 @@ void Client::ResetAA(){
|
||||
m_pp.raid_leadership_points = 0;
|
||||
m_pp.group_leadership_exp = 0;
|
||||
m_pp.raid_leadership_exp = 0;
|
||||
|
||||
database.DeleteCharacterAAs(this->CharacterID());
|
||||
SaveAA();
|
||||
SendAATable();
|
||||
database.DeleteCharacterLeadershipAAs(this->CharacterID());
|
||||
Kick();
|
||||
}
|
||||
|
||||
int Client::GroupLeadershipAAHealthEnhancement()
|
||||
@@ -1818,8 +1834,7 @@ void ZoneDatabase::LoadAAs(SendAA_Struct **load){
|
||||
}
|
||||
|
||||
AALevelCost_Struct aalcs;
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
aalcs.Level = atoi(row[1]);
|
||||
aalcs.Cost = atoi(row[2]);
|
||||
AARequiredLevelAndCost[atoi(row[0])] = aalcs;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user