Compare commits

..

389 Commits

Author SHA1 Message Date
Uleat 38572fe393 Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-30 16:18:51 -04:00
Uleat 83367ee806 Added clicky items from bags for clients that support it (RoF, currently) 2014-09-30 16:18:25 -04:00
Michael Cook (mackal) f117aafc45 Added some updownsign to some newer formulas 2014-09-30 13:41:42 -04:00
Alex 3e0c1bc02e Merge pull request #243 from addtheice/RunQueryToDatabaseQuery_zone_npc
Run query to database query zone npc
2014-09-29 17:22:53 -07:00
Alex f13a1d6351 Merge pull request #236 from addtheice/RunQueryToDatabaseQuery_zone_bot
Run query to database query zone bot
2014-09-29 17:20:53 -07:00
Michael Cook (mackal) fdde64dcc3 Merge pull request #255 from noudess/master
Update zone.cpp to fix bug in loading merchantlist_temp
2014-09-29 16:57:35 -04:00
Paul Coene f5fa07c8db Update zone.cpp 2014-09-29 16:38:18 -04:00
Michael Cook (mackal) 5ffb6bdee7 Reworked blind running around
This should be more in line with how we do current fearpath stuff
and with live.
2014-09-29 16:32:48 -04:00
Michael Cook (mackal) 8035c6c558 Correct "cure blindness" catch 2014-09-29 16:16:19 -04:00
Michael Cook (mackal) fc1eca0f31 Merge pull request #254 from noudess/master
Changes so that blind effects like those in Flash of Light work.
2014-09-29 14:26:51 -04:00
Michael Cook (mackal) 28e49801b7 Fix issue with newly inserted saylinks not working correctly
Sadly still silly
2014-09-29 03:08:30 -04:00
Michael Cook (mackal) 66c171b61b Add support for post June 18, 2014 Hundred Hands effects
Set Spells:Jun182014HundredHandsRevamp to true if your spell file is newer
2014-09-28 13:27:38 -04:00
Michael Cook (mackal) 3be7d45d36 Revamp attack delays / hastes / slows based on dev quotes
See changelog
2014-09-27 23:14:11 -04:00
Michael Cook (mackal) e5822a0c4a Fix client SetAttackTimer issue
Moved the call to the end of Client::CalcBonuses() since it depends on
Client::CalcHaste() which requires a bunch of others to be called
before it.
2014-09-27 21:37:14 -04:00
KimLS b05dd45d62 Merge branch 'spell_stats' 2014-09-27 14:45:20 -07:00
KimLS 9f64092606 Merge of kayen's PR as well as some fixes i saw 2014-09-27 14:44:48 -07:00
Paul Coene d2acd0505c is_blind works better as an else to the line that handles cure 2014-09-27 17:39:30 -04:00
Paul Coene 05ed577e23 Fixed issue where blind flag was set for beneficial spells like cure.wq 2014-09-27 17:17:12 -04:00
KayenEQ 7831162235 changelog 2014-09-27 16:39:37 -04:00
KayenEQ 8567fd928a Perl Mob function GetSpellStat(spellid, identifier, slot)
indentifier is the spell_new field
slot is used for effectids,base,base2, max ect where 1 = first slot.
Will add a wiki page
2014-09-27 16:12:10 -04:00
Paul Coene 73a23e9f9d Changes so that blind effects like those in Flash of Light work. 2014-09-27 13:00:07 -04:00
KayenEQ f232bf1ccd Fix for commit failure. 2014-09-27 09:21:37 -04:00
KayenEQ acc6926448 Merge git://github.com/EQEmu/Server into Development 2014-09-27 09:20:27 -04:00
Uleat 837ce8ab4a Re-ordered client patch ENCODES and DECODES - snuck in a bitswap change for SoF+ item_struct::Slots translations 2014-09-26 20:51:42 -04:00
Michael Cook (mackal) 2497c719ee Rename Name variable in SendBazaarResults to temp_buffer fixes #253 2014-09-26 12:43:34 -04:00
KayenEQ 31b46efcac Clean up of perl based NPC spell scaling functions.
Added Perl - $npc->GetSpellFocusDMG(), $npc->GetSpellFocusHeal()
2014-09-26 06:56:42 -04:00
KayenEQ 9f3a0a3f95 Merge git://github.com/EQEmu/Server into Development 2014-09-26 06:54:53 -04:00
Michael Cook (mackal) 179400c777 Client::SetClassStartingSkills should now match live 2014-09-26 00:44:51 -04:00
Michael Cook (mackal) 0f12a74074 Add bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) 2014-09-25 21:40:31 -04:00
Michael Cook (mackal) 61b784e96e Add tests for skills utilities 2014-09-25 21:35:17 -04:00
Michael Cook (mackal) 723e5d536a EQEmu::IsTradeskill uint32 to SkillUseTypes 2014-09-25 21:20:59 -04:00
Alex 225929d937 Merge pull request #240 from addtheice/RunQueryToDatabaseQuery_zone_trading
Run query to database query zone trading
2014-09-25 17:26:48 -07:00
Alex 763ed7f7a3 Merge pull request #242 from addtheice/RunQueryToDatabaseQuery_zone_questmgr
Run query to database query zone questmgr
2014-09-25 17:26:22 -07:00
Alex ea6ef4c283 Merge pull request #245 from addtheice/RunQueryToDatabaseQuery_zone_groups
Run query to database query zone groups
2014-09-25 17:26:13 -07:00
Alex e5a0cc9ef7 Merge pull request #251 from KayenEQ/Development
Fix for calculation for SE_ManaAbsorbPercentDamage
2014-09-25 17:25:45 -07:00
Uleat a79ea9b850 Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-25 18:49:17 -04:00
Uleat 039e321dde More re-enumeration prep work 2014-09-25 18:48:58 -04:00
KimLS c57292a9dd Tired of this GLM warning (and we dont even use glm rotate grr) also reworked how I approached that peq entity process crash after thinking about it a bit 2014-09-25 14:54:40 -07:00
KayenEQ 9561a3fd3e Merge git://github.com/EQEmu/Server into Development 2014-09-25 15:15:32 -04:00
KimLS aa021addc1 Fix for potion belt name loading. 2014-09-25 04:00:06 -07:00
Michael Cook (mackal) c0cbbf3a65 World needs to load skill cap data for char creation 2014-09-25 03:14:43 -04:00
Michael Cook (mackal) a73ac9cfe8 Added helper function bool EQEmu::IsTradeskill(uint32 skill)
Returns true if you pass a tradeskill to it, otherwise false
2014-09-24 23:36:27 -04:00
KimLS ec8c46abfe I keep seeing a crash due to an invalidated iter during mob delete every few days, seeing if this fixes it. 2014-09-24 19:47:27 -07:00
KayenEQ b9b92762b5 Merge git://github.com/EQEmu/Server into Development
Conflicts:
	changelog.txt
2014-09-24 20:51:20 -04:00
Uleat 7feb531ff7 Re-ordered server opcodes and handlers to facilitate the export of client patch structs and handlers 2014-09-24 20:23:01 -04:00
Michael Cook (mackal) e67423bba7 Add raid mob message
"This creature would take an army to defeat!"
Colors may be a bit off due to differences in clients
2014-09-24 14:04:17 -04:00
Michael Cook (mackal) 531e4b0207 Fix function signature of Mob::IsRaidTarget() so its actually a virtual 2014-09-24 13:50:18 -04:00
Michael Cook (mackal) 34496c49b4 Add Client::SendColoredText(uint32 color, std::string message)
This will send a message (arbitrary size limit of 512) to the client
of the provided color. The MT colors should work here.
2014-09-24 13:14:20 -04:00
Michael Cook (mackal) a445d7e39f Rename OP_BuffFadeMsg to OP_ColoredText since it is a generic opcode 2014-09-24 12:22:06 -04:00
KimLS 0d12715d77 Data verification utils, not in use yet. Also added ability for lua packet to bypass the translation layer (dangerous) if a writer so desires (useful for quickly trying packet stuff) 2014-09-24 03:58:46 -07:00
akkadius 9878459049 Fix tribute loading/saving for real 2014-09-23 20:16:19 -05:00
akkadius 9be0d3b090 memset size fix to calc current size of 400 bytes for discipline initialization 2014-09-23 19:19:40 -05:00
akkadius 16ba3eb11e Restoring Disciplines to their original load order (Slot)
Tribute uninitialized value database conversion fix
Tribute load fix (Lost in translation)
Changed Tribute 0 value to 0xFFFFFFFF instead of 0
Sanity check for unitialized tribute value on load
2014-09-23 19:12:31 -05:00
akkadius 973aa94cb5 Fix for database schema conversion where character_ table has 0 characters present. This will allow the tables to still be created properly and the old one renamed. 2014-09-23 18:28:17 -05:00
KimLS 4cbccfdce2 Fix for MoveCharacterToZone using zoneid instead of zone_id 2014-09-23 16:02:04 -07:00
KayenEQ a5e6fa3479 Merge git://github.com/EQEmu/Server into Development 2014-09-23 18:58:59 -04:00
akkadius 3712d36867 Fix for the undye command to properly purge character armor dye 2014-09-23 17:54:07 -05:00
KimLS 17291e9977 Merge branch 'master' of github.com:EQEmu/Server 2014-09-23 15:42:48 -07:00
KimLS 15f57e4a4c Rob's broken skill up bug reported fixed 2014-09-23 15:42:20 -07:00
akkadius e58d63bf35 IncrementAA for scripting functions changed to use SaveAA instead of Save 2014-09-23 17:21:08 -05:00
KimLS f89add9f64 Fix for AA conversion 2014-09-23 15:09:33 -07:00
Michael Cook (mackal) e039f6d2c6 Fix AA issue 2014-09-23 17:40:17 -04:00
KimLS 7cef4d8fe9 Fix for spell books on newer clients not playing well with the tricksy new deblob code 2014-09-23 13:39:05 -07:00
KimLS 7b85b09f24 isnan fix for vs2012 2014-09-23 13:04:18 -07:00
akkadius 413538f1b5 Sending the client a spell value that is more inline with what it expects when no spell is set. 2014-09-23 14:40:09 -05:00
KayenEQ c03a70651c 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)
2014-09-23 09:15:02 -04:00
KayenEQ ec01e6c69b Merge git://github.com/EQEmu/Server into Development 2014-09-23 09:07:14 -04:00
KimLS 11773208df Style cleanup, clamp hunger and thirst values to correct ranges 2014-09-22 16:46:01 -07:00
KayenEQ 1f155690d8 Fix to SE_ApplyEffect - Will now trigger spell from this effect at correct time. 2014-09-22 19:42:59 -04:00
KimLS 36a29dbb9f Fix for creating characters failing at name verification 2014-09-22 15:37:11 -07:00
KayenEQ c160b8716f Kayen: Spell recourse effects / triggerable spell effects will now be applied AFTER the base spells effects have been applied (consistent with live). 2014-09-22 18:02:40 -04:00
KayenEQ 7ffce01260 Merge git://github.com/EQEmu/Server into Development 2014-09-22 17:50:35 -04:00
akkadius 1170b57fd5 Fix starting items for starting_item entries that use slot -1 to find a free slot 2014-09-22 16:23:43 -05:00
akkadius fee8a1214a Putting back in demonstar's lowercase check 2014-09-22 02:52:23 -05:00
akkadius c26a6959e4 #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
Removed #refundaa
Removed a lot of debug code for blob conversion
Changed status logging for loads/saves to Debug category
2014-09-22 01:00:28 -05:00
akkadius 837b9b7ec7 NoRentExpired character_ reference 2014-09-21 23:54:52 -05:00
akkadius a5a8bfb0f4 Bye bye commented old junk 2014-09-21 23:48:51 -05:00
akkadius 69bddef5a0 Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-21 23:35:27 -05:00
akkadius 7d242045ec Another merge aftermath overwriting character_data reference to old table 2014-09-21 23:34:53 -05:00
JJ c3035fdf41 Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-21 20:03:09 -04:00
JJ e34c47414f Consistent directory locations under common. 2014-09-21 20:02:01 -04:00
akkadius 909dda7c09 Array iter fix 2014-09-21 19:01:50 -05:00
KimLS 22ab145f19 Merge branch 'master' of github.com:EQEmu/Server 2014-09-21 15:59:24 -07:00
KimLS cd8e30a2ec Bug with MySQLRequestResult 2014-09-21 15:59:02 -07:00
akkadius 03be6b2b6b Debug message adjustments 2014-09-21 16:24:06 -05:00
akkadius cda2217634 .......................................... 2014-09-21 04:26:26 -05:00
KimLS 4525b512ac Build fix plus future travis update 2014-09-21 02:25:05 -07:00
akkadius db0d1116f8 make travis shut up 2014-09-21 04:12:36 -05:00
akkadius 3ef5d8ef0a gcc fix <stdint.h> vs <limits> 2014-09-21 03:43:27 -05:00
akkadius 4ed88e348e Merge aftermath 2014-09-21 02:58:56 -05:00
akkadius ad29fa9cfa Merge remote-tracking branch 'remotes/origin/master' into blob_conversion
Conflicts:
	changelog.txt
	common/database.cpp
	world/client.cpp
	world/zoneserver.cpp
	zone/command.cpp
2014-09-21 02:32:31 -05:00
akkadius 388c4bc574 Fix where if players instance is expired when logging back into it, they will get sent properly to bind. Issue was players player profile instance ID did not match the bind instance ID. 2014-09-21 02:27:57 -05:00
KimLS b4f3993616 Should compile on gcc now 2014-09-20 23:56:04 -07:00
akkadius f9366553a3 Blob changelog.txt 2014-09-21 01:27:05 -05:00
KimLS 9733f04c9c Merge of changelog, how i hate thee 2014-09-20 15:10:33 -07:00
KimLS 7140a2054f Ban and suspend commands now require a reason that is recorded in the DB 2014-09-20 15:09:43 -07:00
Michael Cook (mackal) 1049e48aca Add Spells:SHDProcIDOffByeOne to support newer spell files
In June 2009 SoE stopped doing a +1 to the base for SHD procs
So UF+ spell files were not working, set this to false to support these spell files
2014-09-20 16:58:35 -04:00
Michael Cook (mackal) 33b79a3588 Limit character length to 15 (the client doesn't let you enter more) 2014-09-20 15:59:34 -04:00
Michael Cook (mackal) f82699c39b Fix crash in SendEnterWorld on illegally long names 2014-09-20 15:55:20 -04:00
Michael Cook (mackal) 15eaf4e6d1 Fix issue with not online message from tells 2014-09-20 14:57:15 -04:00
Michael Cook (mackal) 7621882b4e Fix toon names being allowed with lower case starting char 2014-09-20 02:46:04 -04:00
Michael Cook (mackal) 9b70b73759 Correct tell queue related messages 2014-09-19 18:17:42 -04:00
Michael Cook (mackal) 8e43134bda Add Client::Tell_StringID for tell queue messages 2014-09-19 18:16:52 -04:00
akkadius 52608d9b2d Character armor dye save fix 2014-09-18 22:46:28 -05:00
Michael Cook (mackal) d26782b093 Nuke #viewmessages 2014-09-18 22:56:16 -04:00
Michael Cook (mackal) a2368b4ea7 Implement tell queues
Default queue size 20 (World:TellQueueSize)
This doe not play well with multiple sessions and a toon crashes and relogs
Normal tells have issues as well.
2014-09-18 22:55:06 -04:00
Michael Cook (mackal) 3d6bb964df Stop nuking MySQLRequestResult Success flag 2014-09-18 14:59:50 -04:00
Michael Cook (mackal) 347ae1bc34 Fix error in 64f5bfd 2014-09-18 01:29:30 -04:00
Michael Cook (mackal) 64f5bfd5ce Make tell message a bit more understandable. 2014-09-17 23:46:54 -04:00
akkadius 3cb02e3b86 Merge branch 'blob_conversion' of https://github.com/EQEmu/Server into blob_conversion 2014-09-17 20:19:04 -05:00
akkadius 34c3b8628e Merge from master 2014-09-17 20:16:37 -05:00
KimLS 8f921ce919 Merge branch 'blob_conversion' of github.com:EQEmu/Server into blob_conversion 2014-09-17 17:45:53 -07:00
KimLS 6754dfdf6d Small sanity checks that was causing a few errors 2014-09-17 17:45:40 -07:00
akkadius 81722962cf KLS Nazi Grammar Fix 2014-09-17 14:30:19 -05:00
KayenEQ d169d95ab0 Fix for resource tap when gaining/loosing HP. 2014-09-17 12:08:01 -04:00
KayenEQ 63ca4cac5e Fix for calculation for SE_ManaAbsorbPercentDamage 2014-09-17 05:14:10 -04:00
akkadius f30ae9dd5a Some descriptor adjustments 2014-09-17 02:52:13 -05:00
akkadius eb49707779 Changed conversion routine.
At the end of conversion, character_ table will be renamed to character_old so that it does not get hit with trying to convert next world bootup
Added some file logging during the initial conversion routine
2014-09-17 02:47:13 -05:00
Michael Cook (mackal) 86c1420f6e Fix some effect value calcs and implement more
Derived from the client
2014-09-17 00:01:32 -04:00
Uleat 364ed921ce Fix for LoadBuffs() server crash 2014-09-16 22:57:15 -04:00
Michael Cook (mackal) 85e1518856 Implement spell formula 137
This is only used in the BER AA Desperation
2014-09-16 18:35:49 -04:00
akkadius 87bb5deb5c Added quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var)
Added quest::crosszonesignalnpcbynpctypeid(npctype_id, data)
Added $client->GetTaskActivityDoneCount(THIS, TaskID, ActivityID)
2014-09-16 16:03:27 -05:00
Michael Cook (mackal) 11ce399e0d Mob::ProcessSpecialAbilities pass by reference 2014-09-15 20:31:45 -04:00
Michael Cook (mackal) ec0989454d QGlobalCache::LoadBy to pass by reference 2014-09-15 20:11:56 -04:00
Michael Cook (mackal) e9f6031936 Merge pull request #250 from KayenEQ/Development
Nimbus Updates / Other fixes
2014-09-15 18:57:47 -04:00
KayenEQ 03485ef1e0 Nimbus effects will now be reapplied after zoning.
Nimbus effects will now fade when associated buff is removed.
Fix for ReduceAllDamage function.
2014-09-15 16:05:57 -04:00
Michael Cook (mackal) e256175ce6 Style nits 2014-09-14 16:00:18 -04:00
Michael Cook (mackal) 0f662bf70c Fix ZoneDatabase::LoadTraderItem not returning anything valid 2014-09-14 15:58:08 -04:00
Michael Cook (mackal) 4c959159c2 Fix rogues not starting with Thieves' Cant 2014-09-13 03:20:43 -04:00
Michael Cook (mackal) d51241720a Fix attack_delay for real 2014-09-12 13:10:03 -04:00
Michael Cook (mackal) 873d343529 Fix ZoneDatabase::GetNPCType nuking attack_delay changes 2014-09-12 11:57:09 -04:00
Michael Cook (mackal) 95969ce67b Fix ZoneDatabase::GetZoneCFG for real 2014-09-11 18:28:25 -04:00
Michael Cook (mackal) bd5cdf502e Fix ZoneDatabase::GetZoneCFG errors 2014-09-11 18:24:40 -04:00
Michael Cook (mackal) c6a7d5a96c Revert "GetAccountInfoForLogin_result converted to MySQLRequestResult"
This reverts commit 8369570b50.

Conflicts:
	zone/zonedb.h
2014-09-11 16:57:00 -04:00
Michael Cook (mackal) 6bc4ecf390 Revert "LoadFactionValues converted to QueryDatabase"
This reverts commit 2df823d2db.
2014-09-11 16:56:15 -04:00
Michael Cook (mackal) c94ceb5b1d Revert "LoadFactionValues_result converted to MySQLRequestResult"
This reverts commit 2e84781594.
2014-09-11 16:55:58 -04:00
Akkadius e390531dcd Initial character creation escape sequences
Added initial skill/language/bind saves to character creation
2014-09-11 03:14:34 -05:00
Alex bb702335e8 Merge pull request #247 from KayenEQ/Development
Development
2014-09-11 00:21:45 -07:00
Alex 863c0c5b58 Merge pull request #241 from addtheice/RunQueryToDatabaseQuery_zone_titles
Run query to database query zone titles
2014-09-11 00:21:00 -07:00
Alex 76e280da4e Merge pull request #239 from addtheice/RunQueryToDatabaseQuery_zone_waypoints
GetHighestGrid converted to QueryDatabase
2014-09-11 00:19:43 -07:00
Alex bcca35b7b7 Merge pull request #238 from addtheice/RunQueryToDatabaseQuery_zone_guild_mgr
AddItem converted to QueryDatabase
2014-09-11 00:18:57 -07:00
Alex 65abaade88 Merge pull request #237 from addtheice/RunQueryToDatabaseQuery_zone_guild
Run query to database query zone guild
2014-09-11 00:18:21 -07:00
Alex 8020e921aa Merge pull request #234 from addtheice/RunQueryToDatabaseQuery_queryserv_database
Run query to database query queryserv database
2014-09-11 00:17:56 -07:00
Alex f2f5b4c1ad Merge pull request #222 from addtheice/RunQueryToDatabaseQuery_zone_client
Run query to database query zone client
2014-09-11 00:16:37 -07:00
Alex 5c6f9fcdc4 Merge pull request #215 from addtheice/RunQueryToDatabaseQuery_zone_zonedb
Run query to database query zone zonedb
2014-09-11 00:16:15 -07:00
akkadius d7dc733480 Small db changes 2014-09-11 00:44:12 -05:00
KimLS 9e243a2426 bestz will no longer scale off of model size, also it adjusts up less extremely in general. Fixed super duper attack speed on command spawned npcs 2014-09-10 22:33:30 -07:00
Arthur Ice 9a889802d3 merge upstream. yet again 2014-09-09 21:26:26 -07:00
Michael Cook (mackal) 1420987c4c Fix copy paste error 2014-09-10 00:07:16 -04:00
Michael Cook (mackal) ed4d954ba8 Added attackdelay to #npcedit
Also changelog!
2014-09-10 00:05:00 -04:00
Michael Cook (mackal) 881f937a35 Change scale of GetPermaHaste() 2014-09-09 22:50:50 -04:00
Michael Cook (mackal) ed4e762f03 Change NPCs to have their attack delay set in DB
This gives us a much more straight forward way of setting mob
attack delay with respect to live.

The attack_delay column is in 10ths of seconds, just like weapons are
The attack_speed is left for references for now.
2014-09-09 22:42:54 -04:00
Michael Cook (mackal) fa1e33783a Split Mob::SetAttackTimer into Client and NPC methods
This was the easiest way to NPCs delay settings to be sane in the database.
The functions are cleaner since there is no specific logic to change
behavior depending on if they're a client or not.
2014-09-09 22:13:30 -04:00
akkadius 0c38b46bf1 Remove namespace std 2014-09-09 16:15:25 -05:00
akkadius 899cf32e6b Added some DB logging to catch any potential query errors, this logs to eqemu_query_error_log.txt at the root folder, currently no rule toggling for this
Corrected some character name reservation logic
Adjusted telnet console so it does not throw 'Command Unknown' when simply hitting enter key
Adjusted System MSG for worldshutdown to use minutes instead of seconds
Added warning for when Shared platinum is disabled at the rule level for players to NOT put platinum in the shared bank when they insert platinum in the shared platinum slot
Changed a place in the code where disciplines were trained, someone had uint16 allocated to CharacterID and this was causing issues for characters with large ID's in the database
Added a fix for bind points getting overwritten with invalid zone data, setting everything to 0,0,0,0 - Since I've added this change I've had no issues for players
Fixed some spell book swap logic in the code, removed swap function.
Fixed issue with guild ranks not loading properly
Commented out some of the non-working tell-que code
Took out some of the auto increment settings in the auto database conversion that don't affect anything anyways
Added some additional escape string sequences for queries that needed them
Added ThrowDBError logging to catch any potential query issues with saves or load functions
2014-09-09 16:03:24 -05:00
Michael Cook (mackal) 2fa31799f6 Port slow fixes to bots 2014-09-09 17:02:05 -04:00
Michael Cook (mackal) 6c3d5c713c Fix slow effect on NPC special attack reuse timers 2014-09-09 15:34:30 -04:00
Michael Cook (mackal) f16beddf6e Increase NPC bash/kick delay by 3 (8 total by default) 2014-09-09 15:32:02 -04:00
Michael Cook (mackal) 506b3ca4a0 Fix slow calculation
Full details: http://www.eqemulator.org/forums/showthread.php?t=38734
2014-09-08 21:43:25 -04:00
KimLS 80242bd250 Strange crash hack/workaround that occured on peq 2014-09-08 17:02:37 -07:00
KimLS 7f7f99cbe3 BestZ will now adjust for model size when used to adjust movement z 2014-09-08 16:45:20 -07:00
KimLS 579294fbf0 Fixed many bugs with partial resist calculations, targets with higher resist should have a more natural curve when it comes to resisting spells 2014-09-08 03:04:22 -07:00
KimLS a3b54e5cae Fix for forage crash 2014-09-07 22:41:42 -07:00
akkadius b392d16808 Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance 2014-09-07 05:43:37 -05:00
akkadius 1f9597a9e2 Fix for item dupe via RoF augmenting 2014-09-07 05:35:19 -05:00
akkadius 54c89d69f6 Merge remote-tracking branch 'remotes/origin/master' into blob_conversion
Conflicts:
	common/database.cpp
	common/mysql_request_result.h
	common/shareddb.cpp
2014-09-07 04:11:09 -05:00
akkadius a14371ba5c Removed debugging
Added player profile data loading safety net checking
2014-09-07 04:00:56 -05:00
KayenEQ 616e13acac Calc fix for spell power distance mod effect. 2014-09-07 03:43:34 -04:00
KayenEQ b50f660339 Merge git://github.com/EQEmu/Server into Development 2014-09-07 03:40:12 -04:00
Akkadius 4c12d31e4a Removed command character backup
Changed all remaining references from the character_ table to the character_data
2014-09-06 22:35:19 -05:00
Akkadius e50cf5c4be - Ported inspect_messages to character_inspect_messages
- Ported character leadership abilities to character_leadership_abilities
- Removed player profile debug printing
- Refactored total time entitled on account to load from the sum of time_played from all characters in character_data
2014-09-06 21:50:29 -05:00
KimLS 84310ec8f0 Merge branch 'master' of github.com:EQEmu/Server 2014-09-06 17:09:33 -07:00
KimLS ffed5a9e22 SQL Injection fix on inspect message setting 2014-09-06 16:43:36 -07:00
Michael Cook (mackal) 92c9ff6e53 Fix issue with hpregen in command_npcedit 2014-09-06 17:58:42 -04:00
KimLS 986a424322 Fix for perl api illusion 2014-09-06 14:31:02 -07:00
Uleat c3e7c48939 Fix ItemTimerCheck() range criteria typo 2014-09-06 16:19:32 -04:00
Arthur Ice b2aa3262a9 Update client.cpp
fixed bug with BEGIN_GENERAL to MainCursor being skipped before since it was starting at GENERAL_BAGS_BEGIN
2014-09-06 12:56:35 -07:00
Arthur Ice b1587f0326 Delete client.cpp.orig
not supposed to be in there.
2014-09-06 12:51:50 -07:00
akkadius ca7dd7d741 - Improved speed of character database conversion x1000 by changing query style
- Adjusted AA MySQL saves for 100x speed increase
- Removed StoreCharacter lookup methods as they will no longer be necessary
- Some other cleanup
2014-09-06 13:53:54 -05:00
Uleat 281b321237 Changed trade behavior to prioritize all main slots before sub slots 2014-09-06 12:45:45 -04:00
KimLS ba0e4bfc1d Bizarre issue reported with SendIllusionPacket corrupting size in lua, dunno if this fixes it but fingers crossed. 2014-09-05 21:18:35 -07:00
Michael Cook (mackal) 3cda62acf4 Fix changelog [skip ci] 2014-09-05 22:38:32 -04:00
Michael Cook (mackal) 2ef43212e1 Fix size issue with Lua_Mob::SendIllusionPacket
Mob::SendIllusionPacket was expecting the size to be 0xFFFFFFFF
to default rather than -1.0f
2014-09-05 22:36:44 -04:00
Michael Cook (mackal) f69eccc42b Add missing QueryDatabase in ZoneDatabase::AddWPForSpawn 2014-09-05 21:57:34 -04:00
Michael Cook (mackal) a1e425f936 Fix indentation of ZoneDatabase::AddWPForSpawn 2014-09-05 21:57:34 -04:00
Arthur Ice 59618e0038 UnDelegateMarkNPC converted to QueryDatabase 2014-09-05 16:14:28 -07:00
Arthur Ice ef1f1562f0 DelegateMarkNPC converted to QueryDatabase 2014-09-05 16:13:50 -07:00
Arthur Ice 31177b7dc7 UnDelegatePuller converted to QueryDatabase 2014-09-05 16:04:34 -07:00
Arthur Ice 5b7aaff150 UnDelegateMainAssist converted to QueryDatabase 2014-09-05 15:58:21 -07:00
Arthur Ice b525a32b6e UndelegateMainTank converted to QueryDatabase 2014-09-05 15:54:07 -07:00
Arthur Ice 99fe610f72 DelegatePuller converted to QueryDatabase 2014-09-05 15:46:06 -07:00
Arthur Ice b5ec35e672 DelegateMainTank converted to QueryDatabase 2014-09-05 15:27:12 -07:00
Uleat 6186c3d866 Fix for gcc failure - Can't fix stupid! 2014-09-05 16:46:03 -04:00
Uleat 1d0a6bdc71 Fix for losing 2nd and 3rd cursor items after zoning 2014-09-05 16:16:56 -04:00
Arthur Ice 15fa2b371c LearnMembers converted to QueryDatabase 2014-09-05 10:45:36 -07:00
Michael Cook (mackal) da121137e5 Fix logging macros
macros should be fully wrapped in do { ... } while(false) to prevent
any accidental coding issues (like else being eaten!!!)
2014-09-05 13:26:44 -04:00
Michael Cook (mackal) c953f1dee1 Merge pull request #244 from addtheice/merc_stance_fix
Fix iterator on mercstance crash bug
2014-09-05 02:30:13 -04:00
Arthur Ice 32b595afb4 Fix iterator on mercstance crash bug 2014-09-04 23:15:20 -07:00
Arthur Ice 0799b47c9c AddSpawnFromSpawnGroup converted to QueryDatabase 2014-09-04 19:40:19 -07:00
Arthur Ice a216672443 Moved add spawn from spawn group command case (5) from NPCSpawnDB into method AddSpawnFromSpawnGroup 2014-09-04 18:13:23 -07:00
Arthur Ice d755aa48bc DeleteSpawnRemoveFromNPCTypeTable converted to QueryDatabase 2014-09-04 17:15:09 -07:00
Arthur Ice f7ecfe7257 DeleteSpawnLeaveInNPCType converted to QueryDatabase 2014-09-04 17:01:34 -07:00
Arthur Ice 89a0bbb8bf Moved deleting npc spawn command case (3) from NPCSpawnDB into method DeleteSpawnLeaveInNPCTypeTable 2014-09-04 16:35:01 -07:00
Arthur Ice 822c8425bd UpdateNPCTypeAppearance converted to QueryDatabase 2014-09-04 16:13:43 -07:00
Arthur Ice a6b57a3423 Moved updating npc type appearance command case (2) from NPCSpawnDB into method UpdateNPCTypeAppearance 2014-09-04 15:32:41 -07:00
Arthur Ice 6d4f7413a5 AddNewNPCSpawnGroupCommand converted to QueryDatabase 2014-09-04 15:01:42 -07:00
Arthur Ice 3e041052ee Moved add new NPC spawngroup command case (1) from NPCSpawnDB into method AddNewNPCSpawnGroupCommand 2014-09-04 14:47:02 -07:00
Arthur Ice 444174ef57 CreateNewNPCCommand converted to QueryDatabase 2014-09-04 12:26:05 -07:00
Arthur Ice 970f7e01a9 Moved create new NPC command case (0) from NPCSpawnDB into method CreateNewNPCCommand 2014-09-04 10:08:02 -07:00
Akkadius 4432c07081 State of Commit: Testable if you ask me (Akkadius) what you need to do
- Need to convert a list of functions and columns and should be ready to start intensive testing phase
 - All preliminary tests show things working great

- All of player profile is saved and loaded from the database
- DBAsync has been completely removed from all code
	- Removed zone/dbasync.cpp/.h
	- Removed common/dbasync.cpp/.h
	- Removed dbasync from cmake commmon and zone
- Cleaned up a ton of functions
- Added several tables to world CheckDatabaseConversions script:
	- `character_skills`
	- `character_languages`
	- `character_bind`
	- `character_alternate_abilities`
	- `character_currency`
	- `character_data`
	- `character_spells`
	- `character_memmed_spells`
	- `character_disciplines`
	- `character_material`
	- `character_tribute`
	- `character_bandolier`
	- `character_potionbelt`
- Character select now loads from `character_data`
- Character creation now creates to `character_data`
- Updated function Database::UpdateName to use `character_data`
- Updated function Database::CheckUsedName to use `character_data`
- Updated function Database::MoveCharacterToZone to use `character_data`
- Updated function Database::SetLoginFlags to use `character_data`
- Updated function Database::SetFirstLogon to use `character_data`
- Updated function Database::SetLFG to use `character_data`
- Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with
- Removed SharedDatabase::SetPlayerProfile
- Trimmed down redundant case switch statements for World sendpackets to QueryServ
- Added Character Methods to Database class:
	Loads:
		bool	LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
		bool	LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
		bool	LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
	Saves:
		bool	SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
		bool	SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
		bool	SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
		bool	SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
		bool	SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
		bool	SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
		bool	SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
		bool	SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
		bool	SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
		bool	SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
		bool	SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
		bool	SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
	Deletes:
		bool	DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
		bool	DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
		bool	DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
2014-09-04 07:24:17 -05:00
Arthur Ice 221c667a23 saylink converted to QueryDatabase 2014-09-03 23:26:09 -07:00
Arthur Ice b710c41c34 clearspawntimers converted to QueryDatabase 2014-09-03 23:17:20 -07:00
Arthur Ice 8825218361 showgrid converted to QueryDatabase 2014-09-03 23:14:16 -07:00
Arthur Ice 1bb5c4e0d8 delglobal converted to QueryDatabase 2014-09-03 23:10:42 -07:00
Arthur Ice 58343480ff InsertQuestGlobal converted to QueryDatabase 2014-09-03 23:07:28 -07:00
Arthur Ice 399bf96a0c RemoveTitle converted to QueryDatabase 2014-09-03 21:05:31 -07:00
Arthur Ice b7c409e11b CheckTitle converted to QueryDatabase 2014-09-03 21:03:00 -07:00
Arthur Ice fd08e9f2ad EnableTitle converted to QueryDatabase 2014-09-03 21:00:15 -07:00
Uleat 37d3daaf9a Client timer issue fix 2014-09-03 23:59:55 -04:00
Arthur Ice 9a4d01da8f CreateNewPlayerSuffix converted to QueryDatabase 2014-09-03 20:57:34 -07:00
Arthur Ice 81cf748b2b CreateNewPlayerTitle converted to QueryDatabase 2014-09-03 20:52:00 -07:00
Michael Cook (mackal) 22742b6a25 Add #shownumhits workaround command to show numhits 2014-09-03 23:50:23 -04:00
Arthur Ice 7d8d96c049 LoadTitles converted to QueryDatabase 2014-09-03 20:45:38 -07:00
Arthur Ice 081905dbc3 SendBuyerResults converted to QueryDatabase 2014-09-03 20:34:07 -07:00
Arthur Ice a8b8f71092 ShowBuyLines converted to QueryDatabase 2014-09-03 20:24:30 -07:00
Arthur Ice 36c1d88eac SendBazaarResults converted to QueryDatabase 2014-09-03 20:18:07 -07:00
Arthur Ice 6eba672013 SendBazaarWelcome converted to QueryDatabase 2014-09-03 19:39:50 -07:00
Arthur Ice 091c8ea5f1 BazaarAuditTrail converted to QueryDatabase 2014-09-03 19:33:20 -07:00
Arthur Ice f5e49441b6 GetHighestGrid converted to QueryDatabase 2014-09-03 19:28:25 -07:00
Arthur Ice 610f3ed37f AddItem converted to QueryDatabase 2014-09-03 19:17:55 -07:00
Arthur Ice f215874486 SetGuildDoor converted to QueryDatabase 2014-09-03 19:10:27 -07:00
Arthur Ice 8e529105cf CheckGuildDoor converted to QueryDatabase 2014-09-03 19:07:49 -07:00
Arthur Ice 95dc0c5fc8 GetEquipmentColor converted to QueryDatabase 2014-09-03 18:49:47 -07:00
Arthur Ice 73c8d3d09d ProcessBoyCommands converted to QueryDatabase 2014-09-03 18:46:41 -07:00
Arthur Ice 049a0bf787 LoadGuildMembership converted to QueryDatabase 2014-09-03 18:41:21 -07:00
Arthur Ice 2095380ba4 SetBotGuildMembership converted to QueryDatabase 2014-09-03 18:31:26 -07:00
Arthur Ice 081192d29e GetBotOwnerCharacterID converted to QueryDatabase 2014-09-03 18:24:30 -07:00
Arthur Ice 2429980fd5 CreatedBotCount converted to QueryDatabase 2014-09-03 18:21:17 -07:00
Arthur Ice 0ac238d762 AllowedBotSpawns converted to QueryDatabase 2014-09-03 18:16:22 -07:00
Arthur Ice 45320fd8ec GetBotGroupLeaderIdByBotGroupName converted to QueryDatabase 2014-09-03 18:13:15 -07:00
Arthur Ice 6d33a13e23 GetBotGroupIdByBotGroupName converted to QueryDatabase 2014-09-03 18:09:53 -07:00
Arthur Ice 52d64d03a6 CanLoadBotGroup converted to QueryDatabase 2014-09-03 18:06:05 -07:00
Arthur Ice fe6e289606 DoesBotGroupNameExist converted to QueryDatabase 2014-09-03 18:01:32 -07:00
Arthur Ice 26569ac51d GetBotGroupListByBotOwnerCharacterId converted to QueryDatabase 2014-09-03 17:57:10 -07:00
Arthur Ice 38d04931ba LoadBotGroup converted to QueryDatabase 2014-09-03 17:52:06 -07:00
Arthur Ice 96cf3d967f DeleteBotGroup converted to QueryDatabase 2014-09-03 17:47:38 -07:00
Arthur Ice 36325226eb SaveBotGroup converted to QueryDatabase 2014-09-03 17:43:18 -07:00
Arthur Ice 6410f52c9c ListSpawnedBots converted to QueryDatabase 2014-09-03 17:36:59 -07:00
Arthur Ice 7ae14fffd0 GetBotList converted to QueryDatabase 2014-09-03 17:32:55 -07:00
Arthur Ice d213e3b106 GetGroupedBotsByGroupID converted to QueryDatabase 2014-09-03 17:26:51 -07:00
Arthur Ice ba612f91c7 LoadBot converted to QueryDatabase 2014-09-03 17:18:50 -07:00
Arthur Ice 8312a8cf3b GetBotIDByBotName converted to QueryDatabase 2014-09-03 17:11:06 -07:00
Arthur Ice 390dcc9a88 GetBotItemsCount converted to QueryDatabase 2014-09-03 17:07:11 -07:00
Arthur Ice cd1b45f0d6 GetBotItemBySlot converted to QueryDatabase 2014-09-03 17:04:21 -07:00
Arthur Ice b8caa5dc31 GetBotItems converted to QueryDatabase 2014-09-03 16:52:18 -07:00
Arthur Ice 53572b4d13 RemoveBotItemBySlot converted to QueryDatabase 2014-09-03 16:43:59 -07:00
Arthur Ice cf0c773002 SetBotItemInSlot converted to QueryDatabase 2014-09-03 16:40:31 -07:00
Arthur Ice 515fe8d9e5 DeleteBot converted to QueryDatabase 2014-09-03 16:31:08 -07:00
Arthur Ice 06d1bd632b SaveTimers converted to QueryDatabase 2014-09-03 16:31:08 -07:00
Arthur Ice 89f34246f0 LoadTimers converted to QueryDatabase 2014-09-03 16:31:08 -07:00
Arthur Ice 7d8e128b5f SaveStance converted to QueryDatabase 2014-09-03 16:31:08 -07:00
Arthur Ice 14c642a3f7 LoadStance converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice a67255475c DeletePetStats converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice 04045dfc27 DeletePetItems converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice 510a51e564 DeletePetBuffs converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice 54b2c50109 SavePetItems converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice fe753f05df SavePetBuffs converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice ab76783f8b SavePetStats converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice 364a51b119 LoadPetItems converted to QueryDatabase 2014-09-03 16:31:07 -07:00
Arthur Ice a486db5e95 LoadPetBuffs converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice c8e7d9e005 LoadPetStats converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice 93aa690a6d GetPetSaveId converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice 87f1f78b67 LoadBuffs converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice 0574a3db86 SaveBuffs converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice 0178f3c9bb Save converted to QueryDatabase 2014-09-03 16:31:06 -07:00
Arthur Ice 9eb3907d45 IsBotNameValid converted to QueryDatabase 2014-09-03 16:31:06 -07:00
SecretsOTheP 891952eb79 Bot fixes for previous commit 2014-09-03 18:34:31 -04:00
SecretsOTheP e6a0b01f37 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. 2014-09-03 18:25:21 -04:00
Arthur Ice 118c2a9db9 LoadAAs converted to QueryDatabase 2014-09-03 13:49:04 -07:00
SecretsOTheP 64c324a42b changelog.txt 2014-09-02 22:09:38 -04:00
SecretsOTheP f909e76260 Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-02 22:08:47 -04:00
SecretsOTheP b7dfdc5060 Oops. 2014-09-02 22:07:49 -04:00
Uleat e25239a50d Merge branch 'master' of https://github.com/EQEmu/Server 2014-09-02 21:20:06 -04:00
Uleat 76d3edc534 Changed #loc to report the same precision as /loc for Cartesians 2014-09-02 21:19:30 -04:00
SecretsOTheP 7301182b3e Merge branch 'master' of https://github.com/EQEmu/Server
Conflicts:
	changelog.txt
2014-09-02 21:18:30 -04:00
SecretsOTheP 832e5e90d1 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.
2014-09-02 21:16:20 -04:00
Michael Cook (mackal) 7ddaabee30 Merge pull request #235 from addtheice/guild_mgr_patch
Fixed bug with loading failing on Guild bank areas
2014-09-02 16:11:05 -04:00
Arthur Dene Ice 41d57ddab6 Fixed bug with loading failing on Guild bank areas 2014-09-02 12:43:56 -07:00
Michael Cook (mackal) 8dd00f5288 Fix crash issue in zone/hate_list.cpp 2014-09-02 02:39:03 -04:00
Akkadius 0a9222e1ee - 2014-09-01 23:54:15 -05:00
Akkadius e0db3c0b60 Fixed Character select to be loaded from new character data tables 2014-09-01 22:17:06 -05:00
KimLS 15f217b594 Fixed non-conforming sql files. 2014-09-01 15:48:22 -07:00
Michael Cook (mackal) 8422178233 Fix issue with requesting an adventure 2014-09-01 02:58:52 -04:00
Uleat eebe902917 Script update for opcode_handlers.py - changes in file names. 2014-09-01 00:07:21 -04:00
KimLS 04dc593df9 Various bug fixes 2014-08-31 20:27:02 -07:00
Akkadius e0a99730e5 pp revert 2014-08-31 21:58:04 -05:00
Akkadius 6497bdf45a More stuff 2014-08-31 21:31:44 -05:00
Akkadius ca430e2494 Fix void Database::GetCharName(uint32 char_id, char* name)
Increased MAX_PP_SPELLBOOK to 720 for UF/RoF
Increased MAX_PP_MEMSPELL to 12
Implemented up to 12 spell slots
Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank)
Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h
Fixed Guild Loading from character_data
Fixed #guild list
Refactored Merchantlist loading
Refactored Temp Merchantlist loading
Gutted most of dbasync

Added:
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);

Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result)
Removed Zone::LoadMerchantData_result(MYSQL_RES* result)
Removed SharedDatabase::GetPlayerProfile
Removed SharedDatabase::SetPlayerProfile
Removed SharedDatabase::SetPlayerProfile_MQ
Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp
2014-08-31 17:52:43 -05:00
Akkadius f8439fd6e6 Made many adjustments to character load code.
Removed bool Client::FinishConnState2(DBAsyncWork* dbaw)
Removed all async character loads
Removed bool	GetAccountInfoForLogin
Removed bool	GetAccountInfoForLogin_result
Removed bool	GetCharacterInfoForLogin_result
Removed bool	GetCharacterInfoForLogin

Added:
bool	LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
bool	LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
bool	LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
2014-08-31 07:52:52 -05:00
Akkadius 8dda7ddd04 Added the following tables to player profile automatic conversion during world bootup:
`character_bind_home`;
`character_alternate_abilities`;
`character_currency`;
`character_data`;
`character_spells`;
`character_memmed_spells`;
`character_disciplines`;
2014-08-31 05:52:36 -05:00
Akkadius 5d8ea5752d Added automatic table creation in conversion process.
More will come when more tables are added
2014-08-31 03:23:42 -05:00
akkadius 4071d88290 At point of commit:
Basic character data, currency and AA are being loaded/saved from the database, currently working on the rest right now.
- Character blob removed from load for testing. Lots of cleanup yet to be done so don't judge code yet.

Saves:
- 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
2014-08-31 02:53:59 -05:00
Arthur Ice 0996570b78 merge from upstream 2014-08-28 15:49:16 -07:00
Arthur Ice 0a9732a267 LogMerchantTransaction converted to QueryDatabase 2014-08-28 00:10:55 -07:00
Arthur Ice 1bc06c9c24 LogPlayerMove converted to QueryDatabase 2014-08-28 00:05:28 -07:00
Arthur Ice e0acc937b3 LogPlayerDelete converted to QueryDatabase 2014-08-28 00:04:20 -07:00
Arthur Ice 3a10a0129a LogPlayerNPCKill converted to QueryDatabase 2014-08-27 23:53:37 -07:00
Arthur Ice 18dbcf16cc LogPlayerHandin converted to QueryDatabase 2014-08-27 23:52:36 -07:00
Arthur Ice bed8dc7d34 LogPlayerTrade converted to QueryDatabase 2014-08-27 23:52:35 -07:00
Arthur Ice a0fc9844fd AddSpeech converted to QueryDatabase 2014-08-27 23:21:09 -07:00
Akkadius 5cf748d135 Initial work 2014-08-27 09:55:39 -05:00
Arthur Ice 9ddb56088e merge from master 2014-08-26 18:49:15 -07:00
KayenEQ 44dcf7af7d Merge git://github.com/EQEmu/Server into Development 2014-08-25 09:23:23 -04:00
Arthur Ice 3262bee6c5 ExpeditionSay converted to QueryDatabase 2014-08-23 23:26:45 -07:00
Arthur Ice 2dbd616725 SetAccountFlag converted to QueryDatabase 2014-08-23 23:23:26 -07:00
Arthur Ice eb98563fa1 LoadAccountFlags converted to QueryDatabase 2014-08-23 23:20:55 -07:00
Arthur Ice 7f92e96ae7 TryReward converted to QueryDatabase 2014-08-23 23:15:49 -07:00
Arthur Ice a48138dfd6 SendRewards converted to QueryDatabase 2014-08-23 23:05:58 -07:00
Arthur Ice 46980e5260 DiscoverItem converted to QueryDatabase 2014-08-23 22:59:58 -07:00
Arthur Ice 44f9e5495e IsDiscovered converted to QueryDatabase 2014-08-23 22:59:53 -07:00
Arthur Ice 97f59282cf KeyRingAdd converted to QueryDatabase 2014-08-23 22:49:27 -07:00
Arthur Ice 2a4a5b1beb KeyRingLoad converted to QueryDatabase 2014-08-23 22:46:29 -07:00
Arthur Ice 8369570b50 GetAccountInfoForLogin_result converted to MySQLRequestResult 2014-08-21 17:35:04 -07:00
Arthur Ice 9ff0c414c1 LoadFactionData converted to QueryDatabase 2014-08-21 17:17:27 -07:00
Arthur Ice 850d1e7c28 SetCharacterFactionLevel converted to QueryDatabase 2014-08-21 17:08:31 -07:00
Arthur Ice 2df823d2db LoadFactionValues converted to QueryDatabase 2014-08-21 17:04:08 -07:00
Arthur Ice 2e84781594 LoadFactionValues_result converted to MySQLRequestResult 2014-08-21 17:00:50 -07:00
Arthur Ice 833227f7f6 LoadPetInfo converted to QueryDatabase 2014-08-21 15:58:11 -07:00
Arthur Ice e731cfd48d RemoveTempFactions converted to QueryDatabase 2014-08-21 15:32:20 -07:00
Arthur Ice cf7574d9b8 SavePetInfo converted to QueryDatabase 2014-08-21 15:30:27 -07:00
Arthur Ice 10d384f131 LoadBuffs converted to QueryDatabase 2014-08-21 13:54:18 -07:00
Arthur Ice 00b8c8ce47 SaveBuffs converted to QueryDatabase 2014-08-21 13:42:02 -07:00
Arthur Ice cab43f41be UpdateAltCurrencyValues converted to QueryDatabase 2014-08-21 13:36:01 -07:00
Arthur Ice fc0d589f12 LoadAltCurrencyValues converted to QueryDatabase 2014-08-21 13:34:19 -07:00
Arthur Ice 743175d4ff InsertDoor converted to QueryDatabase 2014-08-21 13:26:38 -07:00
Arthur Ice b497b07fed QGlobalPurge converted to QueryDatabase 2014-08-21 13:22:21 -07:00
Arthur Ice aab5ed2267 ListAllInstances converted to QueryDatabase 2014-08-21 13:19:37 -07:00
Arthur Ice 46c9fe46e9 UpdateKarma converted to QueryDatabase 2014-08-21 13:09:43 -07:00
Arthur Ice e8c92c6fcc GetKarma converted to QueryDatabase 2014-08-21 13:09:43 -07:00
Arthur Ice 765eaf7f4f getZoneShutDownDelay converted to QueryDatabase 2014-08-21 12:51:09 -07:00
Arthur Ice 699c8cc1eb LoadBlockedSpells converted to QueryDatabase 2014-08-21 12:46:52 -07:00
Arthur Ice 5839921e08 GetBlockedSpellsCount converted to QueryDatabase 2014-08-21 12:39:38 -07:00
Arthur Ice a3bde6e1f1 RaidGroupCount converted to QueryDatabase 2014-08-21 12:35:33 -07:00
Arthur Ice 0ece5bf178 GroupCount converted to QueryDatabase 2014-08-21 12:30:06 -07:00
Arthur Ice fbefad9eaf RefreshGroupFromDB converted to QueryDatabase 2014-08-21 12:25:32 -07:00
Arthur Ice 351a7a52fe GetCharacterInfoForLogin removed, unused, unsupported 2014-08-21 12:01:22 -07:00
Arthur Ice 8441ffda31 GetAccountInfoForLogin removed, unused, unsupported 2014-08-21 11:52:15 -07:00
Arthur Ice e79747c919 SetZoneTZ converted to QueryDatabase 2014-08-20 23:26:41 -07:00
Arthur Ice 8525d819c1 GetZoneTZ converted to QueryDatabase 2014-08-20 23:13:59 -07:00
Arthur Ice fe600bb084 Removed Get/SetServerFilters, unused and unsupported 2014-08-20 23:07:19 -07:00
Arthur Ice babaff1985 GetUseCFGSafeCoords converted to QueryDatabase 2014-08-20 22:14:40 -07:00
Arthur Ice 909ca5440d UpdateZoneSafeCoords converted to QueryDatabase 2014-08-20 22:11:14 -07:00
Arthur Ice e25f64d03b SaveMerchantTemp converted to QueryDatabase 2014-08-20 22:06:56 -07:00
Arthur Ice 2df66bd625 GetGridType converted to QueryDatabase 2014-08-20 22:04:40 -07:00
Arthur Ice 2028a5846c LoadMercEquipment converted to QueryDatabase 2014-08-20 22:00:00 -07:00
Arthur Ice 2fd2cd4cec DeleteMerc converted to QueryDatabase 2014-08-20 21:54:28 -07:00
Arthur Ice 17b175daa4 LoadMercBuffs converted to QueryDatabase 2014-08-20 21:46:23 -07:00
Arthur Ice 5cabe109da SaveMercBuffs converted to QueryDatabase 2014-08-20 21:30:51 -07:00
Arthur Ice c6e82448b6 SaveMerc converted to QueryDatabase 2014-08-20 21:17:17 -07:00
Arthur Ice b846d89b5d LoadCurrentMerc converted to QueryDatabase 2014-08-20 21:04:00 -07:00
Arthur Ice 322cea7342 LoadMercInfo converted to QueryDatabase 2014-08-20 20:58:11 -07:00
Arthur Ice 205e1d404e GetMercType converted to QueryDatabase 2014-08-20 20:50:36 -07:00
Arthur Ice 9769a96ebd GetNPCType converted to QueryDatabase 2014-08-20 20:21:39 -07:00
Arthur Ice 74d3192c2e NoRentExpired converted to QueryDatabase 2014-08-20 19:46:44 -07:00
Arthur Ice 41769a3fa8 UpdateBuyLine converted to QueryDatabase 2014-08-20 19:28:53 -07:00
Arthur Ice a7efa9d4e4 RemoveBuyLine converted to QueryDatabase 2014-08-20 19:20:32 -07:00
Arthur Ice 9ed69999a5 AddBuyLine converted to QueryDatabase 2014-08-20 19:02:28 -07:00
Arthur Ice e19a59b269 DeleteBuyLines converted to QueryDatabase 2014-08-20 18:59:17 -07:00
Arthur Ice d234016224 DeleteTraderItem converted to QueryDatabase 2014-08-20 18:55:42 -07:00
Arthur Ice c160d6d929 DeleteTraderItem converted to QueryDatabase 2014-08-20 18:53:05 -07:00
Arthur Ice 62ad60b4ad UpdateTraderItemPrice converted to QueryDatabase 2014-08-20 18:50:10 -07:00
Arthur Ice d44d7c6bbd UpdateTraderItemCharges converted to QueryDatabase 2014-08-20 18:42:25 -07:00
Arthur Ice efd97bad14 SaveTraderItem converted to QueryDatabase 2014-08-20 18:38:57 -07:00
Arthur Ice bc884f5daf LoadSingleTraderItem converted to QueryDatabase 2014-08-20 18:35:54 -07:00
Arthur Ice 0f47b73a64 LoadTraderItemWithCharges converted to QueryDatabase 2014-08-20 18:22:31 -07:00
Arthur Ice e9c6e96452 LoadTraderItem converted to QueryDatabase 2014-08-20 18:22:18 -07:00
Arthur Ice 09713311f6 DeleteWorldContainer converted to QueryDatabase 2014-08-20 18:16:45 -07:00
Arthur Ice c666d9c553 SaveWorldContainer converted to QueryDatabase 2014-08-20 18:03:02 -07:00
Arthur Ice 3777e8d1ce LoadWorldContainer converted to QueryDatabase 2014-08-20 17:57:44 -07:00
Arthur Ice e60658c684 GetEventLogs converted to QueryDatabase 2014-08-20 17:51:52 -07:00
Arthur Ice 046da9efae SetSpecialAttkFlag converted to QueryDatabase 2014-08-20 17:46:12 -07:00
Arthur Ice 09332f6c26 UpdateBug converted to QueryDatabase 2014-08-20 17:43:16 -07:00
Arthur Ice ce507d891a UpdateBug converted to QueryDatabase 2014-08-20 17:43:16 -07:00
Arthur Ice 96f122f901 logevents converted to QueryDatabase 2014-08-20 17:31:16 -07:00
Arthur Ice 3479525f39 UpdateSpawn2Status converted to QueryDatabase 2014-08-20 17:27:19 -07:00
Arthur Ice 4f9d4b0023 GetSpawnTimeLeft converted to QueryDatabase 2014-08-20 17:25:27 -07:00
Arthur Ice bcdfd32bc0 UpdateSpawn2Timeleft converted to QueryDatabase 2014-08-20 17:21:07 -07:00
Arthur Ice 693dde04e3 GetZoneCFG converted to QueryDatabase 2014-08-20 17:16:30 -07:00
Arthur Ice f1bb019933 SaveZoneCFG converted to QueryDatabase 2014-08-20 16:46:17 -07:00
170 changed files with 39534 additions and 38708 deletions
+3 -1
View File
@@ -8,7 +8,9 @@ script:
- make
- ./bin/tests
branches:
only: master
only:
- master
- stable
notifications:
email: false
irc:
+1
View File
@@ -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
View File
@@ -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
+3 -3
View File
@@ -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
View File
@@ -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 */
+48
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+9 -12
View File
@@ -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();
-669
View File
@@ -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;
}
-176
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -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] = {
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+9 -4
View File
@@ -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())
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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); \
} \
+9 -9
View File
@@ -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),
+23
View File
@@ -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;
}
+2
View File
@@ -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)
+8 -5
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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";
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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;
}
+26 -27
View File
@@ -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
+1 -1
View File
@@ -2969,7 +2969,7 @@ struct GroupInvite_Struct {
// uint8 unknown128[65];
};
struct BuffFadeMsg_Struct {
struct ColoredText_Struct {
uint32 color;
char msg[1];
};
+4910 -4750
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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;
}
+1 -1
View File
@@ -187,7 +187,7 @@
0x1ee9,
0x7f5d, OP_CastSpell
0x0659, OP_ManaChange
0x3bc7, OP_BuffFadeMsg
0x3bc7, OP_ColoredText
0x3209,
0x6a93, OP_MemorizeSpell
0x1237,
+81 -83
View File
@@ -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
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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;
}
+39 -40
View File
@@ -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
+1 -1
View File
@@ -3046,7 +3046,7 @@ struct GroupInvite_Struct {
// uint8 unknown128[65];
};
struct BuffFadeMsg_Struct {
struct ColoredText_Struct {
uint32 color;
char msg[1];
};
+3543 -3470
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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
View File
@@ -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
+2 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+56
View File
@@ -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;
}
}
+6
View File
@@ -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
+5
View File
@@ -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
View File
@@ -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);
}
+4
View File
@@ -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")
+108
View File
@@ -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
+4
View File
@@ -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;
+48
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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());
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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
+2 -2
View File
@@ -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 #
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+11 -11
View File
@@ -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`;
+2 -2
View File
@@ -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
View File
@@ -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;
}
}
+1
View File
@@ -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;
+20
View File
@@ -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;
}
+10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
-2
View File
@@ -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
View File
@@ -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