Compare commits

..

465 Commits

Author SHA1 Message Date
KimLS c1bcf4dfeb Merge branch 'master' into lets_move 2016-01-25 14:34:16 -08:00
KimLS ec58d92e42 Update recast 2016-01-25 14:33:40 -08:00
Michael Cook (mackal) 15c92f019a Mob::Charmed() should be useful now
We should really clean this up, but this is quicker
2016-01-25 14:01:03 -05:00
KimLS 913fb6c22e Merge branch 'master' into lets_move 2016-01-22 19:17:38 -08:00
KimLS 76f3bb1ce6 Changed how i calc partial and broken paths 2016-01-22 19:16:14 -08:00
Akkadius c4cdf811e3 Fix for zone controller spawn events where npc isn't inserted into entity list yet 2016-01-22 13:42:14 -06:00
Alex 211306f9be Merge pull request #493 from daerath/master
Loadlootdrops (shareddb.cpp) not exiting on error
2016-01-21 21:46:50 -08:00
Alex a22df6da33 Merge pull request #487 from lwahlmeier/master
fixed else error case for eqtime table
2016-01-21 21:46:36 -08:00
Tim DeLong b4b28e5eb8 If an error occurs (!results.Success()) in loadlootdrops the method continues processing instead of exiting. 2016-01-21 11:53:14 -05:00
Michael Cook (mackal) d86307c720 Rework say links
We now consume 1 item ID for say links, this means you will be able to create
more items! We used ID 0xFFFFF for this, which is the max ID an item can be
in the item links. You have the rest to play with!

Normal say links pass the ID in the first aug slot and silent say links
in the second aug slot. This means we can have MANY more say links as well!
2016-01-20 22:31:35 -05:00
Uleat 04b7ba7a1d Added proxy accessors for all TextLink fields 2016-01-20 21:54:18 -05:00
KimLS 66c952eff0 Merge branch 'master' into lets_move 2016-01-18 20:15:36 -08:00
KimLS 946cee01fc Minor tweak to autoporting code 2016-01-18 20:14:57 -08:00
KimLS 978650eb1f Pathing underwater works a lot better now. 2016-01-18 15:22:17 -08:00
KimLS a6a06de994 Changes to UF and above clients on how spell buff tics are synced. 2016-01-17 17:40:29 -08:00
KimLS 10952932d3 Change how tics happen, support for v2 .nav files 2016-01-17 14:05:34 -08:00
KimLS 14b9b22ca3 Will no longer use bestz snapping every frame if a navmesh is available. Fix for inliquid 2016-01-16 20:35:18 -08:00
KimLS a2136e5ee4 Some work on movement. 2016-01-16 19:37:15 -08:00
Michael Cook (mackal) 1ddbfdf4e9 Fix ItemInst::GetItemElementalDamage 2016-01-16 18:46:32 -05:00
Michael Cook (mackal) 600866f573 Rewrite Bane and Elemental Dmg stuff and GetWeaponDamage (client version) 2016-01-16 18:29:17 -05:00
Michael Cook (mackal) ad1c91f204 Fix bots 2016-01-16 17:52:21 -05:00
Michael Cook (mackal) 8f0d9015be Fix rec/req level issues 2016-01-16 17:17:09 -05:00
Michael Cook (mackal) 281344b049 Add various GetItemStat totallers to ItemInst
The intent of these functions is to simplify various locations in the
code where we need to get a total of some stat on an item, including augs
and we can not just grab the total from the itembonuses struct.

This will also centralize where we need to add the powersource aug scaling
when we implement them. Since they will need the Purity stat from the
item it is in.

Notes:
    - These functions recurse if the augments flag is true, which is false by
      default to make it so you have to be explicit about recursing or not
    - These functions don't take into account if you can equip or if you are
      below recommended level, you will have to do that where you call these
      functions.
2016-01-16 17:10:11 -05:00
KimLS 84dec889da Merge branch 'master' into lets_move 2016-01-15 14:32:27 -08:00
KimLS 1d055b5364 Tweaks to log.out to filter messages at detail level not just cat level before formatting the message, tweaks to pathing, nearly where i want it but not entirely there. 2016-01-15 14:32:00 -08:00
Michael Cook (mackal) d7e44643b5 Fix resist display issue for RoF/RoF2
These need to be found for the other clients
They are most likely a similar amount of bytes away from
the potionbelt in all clients
2016-01-15 17:20:48 -05:00
Michael Cook (mackal) 42f7e03b04 Fix typo in last commit 2016-01-15 17:00:10 -05:00
Michael Cook (mackal) f33f3bd4f5 Fix Drakkin base resists and some missing class bonuses 2016-01-15 16:09:23 -05:00
KimLS 14d8683227 Fix for swapped x and y returns on failure case for FindRoute 2016-01-14 21:55:08 -08:00
KimLS 9c3e957d4e Fix for pathfind.h 2016-01-13 13:57:35 -08:00
KimLS b94b59cf9b Missing string.h 2016-01-13 13:50:17 -08:00
KimLS ca817051e7 removed branch restriction in travis 2016-01-13 13:43:28 -08:00
KimLS 1cb07d055e Pathing is essentially fully functional now, still could use improvements here and there 2016-01-13 13:39:42 -08:00
Uleat e161805bc9 Added changelog entry for #summonitem [itemlink] change 2016-01-13 15:25:22 -05:00
Uleat 6db397f07d Added item link functionality to #summonitem (thanks Kinglykrab!) 2016-01-13 15:10:21 -05:00
Uleat 23758d5e90 Merge pull request #491 from KinglyKrab/master
Modified #flag functionality for target-based account status refresh.
2016-01-13 15:00:21 -05:00
Kinglykrab f8ce556acb Modified #flag functionality for target-based account status refresh. 2016-01-13 08:08:23 -05:00
Michael Cook (mackal) 3048eca5ad Merge pull request #490 from AthrogatePEQ/master
Lua_Client::ClearCompassMark()
2016-01-12 22:56:18 -05:00
Athrogate 11a61f3e35 Merge branch 'master' of github.com:AthrogatePEQ/Server 2016-01-12 19:40:46 -08:00
Athrogate 192dadad8c Merge branch 'master' of github.com:AthrogatePEQ/Server 2016-01-12 19:40:19 -08:00
Athrogate 092fa4a3bc Merge branch 'master' of github.com:AthrogatePEQ/Server 2016-01-12 19:34:04 -08:00
Athrogate 0fec2fdfdd Add Lua_Client::ClearCompassMark(). 2016-01-12 19:33:49 -08:00
Athrogate 09b6adf726 Add Lua_Client::ClearCompassMark(). 2016-01-12 19:19:07 -08:00
Athrogate edeb7d79d1 Add Lua_Client::ClearCompassMark(). 2016-01-12 19:19:07 -08:00
KimLS e61e2e7f02 find command uses new pathing system now which loads .nav files saved by map_edit, still in initial stages of testing. Fixed a bug where find might cause a desync in some cases as well. 2016-01-12 18:33:00 -08:00
Uleat 21fc487c33 World tradeskill objects should now exhibit pre-RoF behavior to all clients 2016-01-12 18:44:51 -05:00
KimLS c6e9fbc878 Merge branch 'master' into lets_move 2016-01-12 00:38:43 -08:00
Natedog2012 acb1d14fbd Cap Underfoot material / IDFile in the spawn packet to 99,9999 MAX. Anything higher will crash client 2016-01-11 13:32:00 -08:00
Michael Cook (mackal) 2cb58e9d02 Merge pull request #488 from daerath/master
* LightProfile_Struct::TypeToLevel.  Incorrect comparision in case statement.
2016-01-11 12:34:44 -05:00
Tim DeLong 1711b06836 * LightProfile_Struct::TypeToLevel. The case statement for lightLevelCandle should be lightTypeCandle as the check is on light types, not light levels. Light levels are used for the return value. 2016-01-11 09:11:38 -05:00
Michael Cook (mackal) 6fc5f8fba2 Fix stacking issues with SE_DamageModifier and SE_MinDamageModifier 2016-01-10 15:31:04 -05:00
KimLS 909cbd8b97 Merge branch 'master' into lets_move 2016-01-09 01:40:54 -08:00
KimLS 2ed348f23d Adding crazy behavior interface. 2016-01-09 01:39:23 -08:00
Uleat 1aa98d34ca Fix for manifest boo-boo 2016-01-08 17:35:50 -05:00
Uleat 2b0ee55752 Add command #findaliases 2016-01-08 17:19:10 -05:00
Michael Cook (mackal) 2f129da08a Add GetAttackDelay to lua's NPC API 2016-01-06 15:48:10 -05:00
Michael Cook (mackal) 17c45c8d36 Move triggered on cast things to after the spell
This appears how live does it
2016-01-06 13:30:50 -05:00
Luke Wahlmeier 3a20bbd834 fixed else error case for eqtime table 2016-01-05 14:18:31 -07:00
Michael Cook (mackal) 20f5c42c3e Fix 60+ resist caps 2016-01-05 02:54:09 -05:00
Akkadius 9174ccd635 Another slight adjustment [skip ci] 2016-01-04 17:11:59 -06:00
Akkadius 2155a53a0d Another slight adjustment [skip ci] 2016-01-04 11:16:26 -06:00
Akkadius 6a404a5a26 Put the zone controller somewhere where people can't see it even with a terrible GlobalLoad.txt [skip ci] 2016-01-04 11:04:56 -06:00
Michael Cook (mackal) 5bcb9f0b35 Fix classic h2h dmg/delay also support for revamp
The revamp was implemented during SoF
Set Combat:UseRevampHandToHand to true to enable
2016-01-03 14:38:50 -05:00
Michael Cook (mackal) 05de206ace Rework quiver haste 2016-01-03 01:58:37 -05:00
Michael Cook (mackal) 28848fa913 Merge pull request #486 from noudess/master
Added runspeed to #mystats window
2016-01-02 17:39:02 -05:00
Paul Coene 51b74f47e3 Merge remote-tracking branch 'upstream/master' 2016-01-02 17:28:23 -05:00
Paul Coene f754f06bec Added runspeed to mystats window. 2016-01-02 17:26:59 -05:00
Alex d1d963df10 Merge pull request #485 from noudess/master
More fixes for SendBuffDuration
2016-01-02 13:43:27 -08:00
Paul Coene a56f17a9e5 Merge remote-tracking branch 'upstream/master' 2016-01-02 09:17:09 -05:00
Paul Coene 11f3e30245 Fixed a ton of buffs when using an EE item (SendBuffDurationPacket). 2016-01-02 09:16:13 -05:00
Akkadius 707d2c8635 Merge branch 'master' of https://github.com/EQEmu/Server 2016-01-01 01:13:37 -06:00
Akkadius dfdfb18a7e VS2012 fix 2016-01-01 01:12:49 -06:00
Akkadius 647fbcd6b6 Adjust an incredibly spammy log message 2016-01-01 01:11:32 -06:00
Akkadius 50a8a3017b Merge pull request #484 from daerath/master
* CheckNameFilter minimum surname check incorrect
2016-01-01 00:55:55 -06:00
Akkadius 9ea9ed2590 Update eqemu_update.pl to include loginserver setup in normal installer routine [skip ci] 2015-12-31 21:45:42 -06:00
Michael Cook (mackal) 3996a70037 2h DB should match client closer
I think the dev missed something when making it pretty for the forums
This should match it better.
2015-12-31 01:08:04 -05:00
Tim DeLong aad1396c73 * CheckNameFilter was enforcing minimum surname length of 3 instead of 4.
* Minor refactoring of CheckNameFilter to eliminate redundant code.
2015-12-30 23:30:52 -05:00
Akkadius 45d81b71d6 Merge pull request #483 from daerath/master
* AddReport's who and against strings were not being escaped properly.
2015-12-30 12:05:55 -06:00
Michael Cook (mackal) e70b34f245 Merge pull request #482 from af4t/master
MSVC 2015 wants <algorithm> #included for std::min.  If any other com…
2015-12-30 12:46:51 -05:00
Tim DeLong fe61abc3cd * AddReport's who and against strings were not being escaped properly. 2015-12-30 11:42:49 -05:00
af4t 2d375eb565 MSVC 2015 wants <algorithm> #included for std::min. If any other compilers require the same, feel free to alter the #if test. 2015-12-30 02:17:09 -05:00
Michael Cook (mackal) 7045581fdc Cap big bags to 10 slots for now 2015-12-29 15:22:09 -05:00
Akkadius 7bf114a0bc Fix Travis 2015-12-29 06:06:12 -06:00
Akkadius 2bf6c2788e eqemu_update.pl - Implement 14) [Remove Duplicate Rule Values] :: Looks for redundant rule_values entries and removes them 2015-12-29 05:40:34 -06:00
Akkadius 8b35ae9921 Change how rules are loaded and inherit values
- When a custom ruleset is loaded, it will always first look for a value present in the ruleset id for that zone, when it is not present, it will load from the default ruleset instead of immediately falling back to the source value. This is to eliminate the excessive amount of duplicate entries in the rule_values tables
2015-12-29 05:21:27 -06:00
Akkadius 8425607460 Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true
- When a zone boots, it will spawn an invisible npc by the name of zone_controller
	- Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua
	- This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10
	- Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC)
		- EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables:
			$spawned_entity_id
			$spawned_npc_id
		- EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables:
			$killer_id
			$killer_damage
			$killer_spell
			$killer_skill
			$killed_npc_id
2015-12-29 04:08:10 -06:00
Akkadius f25246e1a0 Adjust eqemu_update.pl [skip ci] 2015-12-29 01:47:21 -06:00
Akkadius 3af9aeeeaf Adjust manifest [skip ci] 2015-12-29 01:45:53 -06:00
Michael Cook (mackal) c2c08b85f1 Merge pull request #481 from KinglyKrab/master
Added GetInstanceTimerByID(instance_id) to Perl and Lua.
2015-12-29 02:35:19 -05:00
Akkadius 9757c38017 Adjust manifest [skip ci] 2015-12-29 01:30:20 -06:00
Kinglykrab 34e1dc9829 Added UpdateZoneHeader(type, value) to Perl and Lua. 2015-12-29 02:28:31 -05:00
Kinglykrab ff876bd558 Added GetInstanceTimerByID(instance_id) to Perl and Lua. 2015-12-29 00:56:32 -05:00
Akkadius b9d00f91de Merge pull request #480 from KinglyKrab/master
Added GetInstanceTimer to Perl and Lua.
2015-12-28 22:42:14 -06:00
Kinglykrab ce71b6d9f0 Added GetInstanceTimer() to Perl and Lua. 2015-12-28 22:13:54 -05:00
Akkadius 17c41a1364 Merge pull request #479 from KinglyKrab/master
Revert accidental change to SetPseudoRoot in lua_mob.cpp.
2015-12-28 19:18:39 -06:00
Kinglykrab bda39c4f77 Revert accidental change to SetPseudoRoot in lua_mob.cpp. 2015-12-28 20:07:59 -05:00
Akkadius e423165bcb DB Update System :: Implement SVN updates into the manifest (To support older databases) [skip ci] 2015-12-28 02:25:01 -06:00
Akkadius 1b4dbd1ce7 Adjust import_13th_floor.pl to flip slots 21 and 22 [skip ci] 2015-12-27 17:26:39 -06:00
Michael Cook (mackal) 3a7d7c727f AA updates [skip ci] 2015-12-26 13:29:34 -05:00
Akkadius dc58173f15 Remove unused script since we have a newer one now [skip ci] 2015-12-22 01:04:27 -06:00
Akkadius f883e085e3 Merge pull request #477 from KinglyKrab/master
Added GetMeleeMitigation() to Perl and Lua for Mobs (Clients/NPCs).
2015-12-21 15:47:16 -06:00
Akkadius 4b2f12cd67 Linux-ify 13th floor script [skip ci] 2015-12-21 15:32:59 -06:00
Akkadius 7223f2da06 Add 13th floor item import script (Natedog/Akkadius) [skip ci] 2015-12-21 15:31:38 -06:00
Kinglykrab 9a1271805a Added GetMeleeMitigation() to Perl and Lua for Mobs (Clients/NPCs). 2015-12-21 15:45:25 -05:00
Michael Cook (mackal) c168d7b7b6 Fix macro hack? [skip ci] 2015-12-21 12:41:49 -05:00
Michael Cook (mackal) 7ad33f2445 Fix formatting 2015-12-21 12:33:32 -05:00
Natedog2012 fc33a10ec0 Change GetSkill to use SkillModMax for clients 2015-12-21 07:37:43 -08:00
Natedog2012 8133f5312f First step into implementing evolving items, added fields to database that were missing. 2015-12-21 05:39:39 -08:00
Michael Cook (mackal) dfc5699403 Merge pull request #476 from KinglyKrab/master
Exported several Mob-based methods to Perl and Lua.
2015-12-19 19:54:17 -05:00
Kinglykrab 0177c8d7d9 Exported several Mob-based methods to Perl and Lua. 2015-12-19 19:42:35 -05:00
Uleat b4b1324ace Updated client version bitmasks 2015-12-19 12:42:55 -05:00
Michael Cook (mackal) 03592e58f9 Port EQMacEmu's Assist Aggro code
This code also allows you to toggle on Tick Pulling (Aggro:AllowTickPulling)
which was a pulling technique (exploit) fixed sometime in 2006

This code also implements assist caps to cut down on trains (5 by default)
Unsure if live what this number is (it exists) or if it's a per NPC basis

An NPC with Assist Aggro will not call for help, only NPCs with Primary Aggro will
2015-12-18 17:41:57 -05:00
Michael Cook (mackal) f8867ea73d Bump up initial aggro from Yell for Help to match initial aggro
I guess I forgot this one
2015-12-18 13:46:05 -05:00
Michael Cook (mackal) 488be05e0e Add DB manifest for eqtime change 2015-12-17 19:50:33 -05:00
Alex 78c99d0be0 Merge pull request #474 from regneq/master
EQTime will now save to database instead of file.
2015-12-17 16:14:46 -08:00
Alex f4479c5cd7 Merge pull request #469 from Shendare/augmentation
Augmentation Feature Patch; going to merge since there's video evidence you tested it and no one seems to have any problem with it.
2015-12-17 16:14:36 -08:00
regneq d449d4f54c EQTime will now save to the DB once every 10 real world minutes. 2015-12-17 15:49:37 -08:00
regneq 17bbd8dfbe eqtime is now stored in the DB.
required/2015_12_17_eqtime.sql
2015-12-17 14:14:04 -08:00
Alex c1feb93e2e Merge pull request #473 from noudess/master
Repair issue with Bind Wounds when you are binding someone that is binding themselves.
2015-12-17 13:09:33 -08:00
Paul Coene 07ab58483d Updated changelog 2015-12-16 09:16:27 -05:00
Paul Coene 2865278987 Merge remote-tracking branch 'upstream/master' 2015-12-16 09:11:43 -05:00
Paul Coene bc77439d11 When binding someone else's wounds, the code tried to send a bind
would response to client with a type of 2.  The intent (based on
comments was to get the client to display a "stand still" message
on the receiving client.

That reply message was not generating that message, but if the client
you were binding was also binding his own  wounds, it would cause your
target to stand up, interrupting his bind.

I replaced this client reply with a simple, directed client message.  It all
seems to work fine now.
2015-12-16 09:05:27 -05:00
Uleat 78f22599f4 Tweak to commandaliases behavior 2015-12-15 19:03:24 -05:00
Akkadius 24ea7e03f1 Merge branch 'master' of https://github.com/EQEmu/Server 2015-12-15 12:59:46 -06:00
Uleat 101bbdfd29 Merge branch 'master' of https://github.com/EQEmu/Server 2015-12-14 17:38:32 -05:00
Uleat c9ecca1a56 Added 'alias added' message and commmandaliases list (future use) 2015-12-14 17:38:24 -05:00
Natedog2012 f0222bb94b Adjust changelog.txt [skip ci] 2015-12-14 12:37:28 -08:00
Akkadius 2fb63d4d26 Merge pull request #472 from KinglyKrab/master
Adds IsBlind() and IsFeared() functionality to Perl and Lua.
2015-12-14 14:11:26 -06:00
Kinglykrab 6949f29295 Adds IsBlind() and IsFeared() functionality to Perl and Lua. 2015-12-14 15:01:58 -05:00
Natedog2012 b3afc684de Allow updating instance timers through perl and lua. 2015-12-14 11:16:09 -08:00
Natedog2012 baaf5801ff Added ability to manipulate disciplines for perl and lua. Also ability to remove spells from spell bar with spellID. 2015-12-14 01:22:59 -08:00
Uleat ee644f7b3e Make better sense things do, after cups of coffee two 2015-12-12 21:36:14 -05:00
Uleat cfde67fcb3 Missed a 'command' note 2015-12-12 17:22:29 -05:00
Akkadius fa872c6030 Some rule code cleanup 2015-12-12 00:37:31 -06:00
Uleat 6802f2a9e8 Conversion of 2015_09_30_bots.sql fail points to perl script; Added drop bots feature to eqemu_update.pl menu 2015-12-11 22:39:18 -05:00
Akkadius 80ef4c7f9f Adjust default Loginserver log settings [skip ci] 2015-12-09 23:24:53 -06:00
Akkadius c2af87431a Fixed a ridiculous issue where world wasn't trying to reconnect to loginservers 2015-12-09 23:21:19 -06:00
Akkadius ffe46bd4d2 Implement Loginserver auto account creation via login.ini option auto_create_accounts = TRUE 2015-12-09 23:01:07 -06:00
Akkadius d7ca2440d3 More loginserver stuff [skip ci] 2015-12-09 22:24:17 -06:00
Akkadius 7a17089b8a Fix remaining loginserver log things 2015-12-09 20:47:59 -06:00
Akkadius efe09f6fe5 Remove old error_log system from the Loginserver 2015-12-09 20:33:20 -06:00
Akkadius 75cddbea71 Loginserver conversion to new Logging system 2015-12-09 20:30:47 -06:00
Akkadius 22496e2ae2 Update eqemu_update.pl [skip ci] 2015-12-09 19:28:56 -06:00
Akkadius acb8e63d9c Update eqemu_update.pl [skip ci] 2015-12-09 01:14:45 -06:00
Akkadius e297de3830 Update eqemu_update.pl [skip ci] 2015-12-09 01:14:07 -06:00
Akkadius f474e171ed Update eqemu_update.pl [skip ci] 2015-12-09 01:02:42 -06:00
Akkadius b499dcc89d Update eqemu_update.pl [skip ci] 2015-12-09 01:00:27 -06:00
Akkadius 98f7766875 Update eqemu_update.pl 2015-12-09 00:21:30 -06:00
Uleat 2159d18920 Fix for VS2012 command.cpp:501 error 2015-12-08 21:15:41 -05:00
Uleat 6f1ad1fbc1 Major change to how commands are loaded 2015-12-07 19:28:13 -05:00
Uleat 1c0192dce3 Fix for guild rank sql error when using bots (thanks N0ctrnl!) 2015-12-02 18:33:49 -05:00
Akkadius f07e708f22 Update eqemu_update.pl [skip ci] :: Add option 13) [Windows Server Loginserver Setup] :: Download and install Windows Loginserver 2015-12-02 15:41:57 -06:00
Akkadius a936796b45 Some more loginserver refactoring to make things more sane to read 2015-12-02 13:46:16 -06:00
Akkadius 2fbf047853 Merge branch 'master' of https://github.com/EQEmu/Server 2015-12-02 13:14:49 -06:00
Akkadius af18377505 Some loginserver refactoring 2015-12-02 13:14:26 -06:00
Uleat fe48f18f71 Added rule-based check for race/class restriction of spell scribing 2015-12-01 20:30:43 -05:00
Akkadius a483d37c26 Re-add some nuked code eqemu_update.pl [skip ci] 2015-12-01 15:27:07 -06:00
Akkadius 549cabe7e8 Added Options 11) and 12) to eqemu_update.pl, updated to version 12
11) [Windows Server Build] :: Download Latest and Stable Server Build (Overwrites existing .exe's, includes .dll's)
12) [Windows Server .dll's] :: Download Pre-Requisite Server .dll's
2015-12-01 15:25:26 -06:00
Uleat 6f8600b885 Draft versions of bot command spell scripts (may still be tweaked based on actual command implementation) 2015-11-30 20:16:21 -05:00
Uleat 3135c92340 Changed criteria in a few bots scripts from count to null-result check 2015-11-30 18:33:27 -05:00
Akkadius c2b0e00cdd Update eqemu_update.pl [skip ci] 2015-11-30 00:34:10 -06:00
Akkadius c0081a0983 Merge branch 'master' of https://github.com/EQEmu/Server 2015-11-30 00:09:03 -06:00
Akkadius 6016ba5140 Add some things to future installer [skip ci] 2015-11-30 00:08:36 -06:00
Natedog2012 4bc844fe3b Work around for Bot::LoadPetBuffs loading buffs with counters 2015-11-24 16:25:21 -08:00
Alex faa8c35554 Merge pull request #470 from noudess/master
Fix mob overpopulation on "idle" zones
2015-11-22 23:20:13 -08:00
Uleat d383ecc5b7 Fix for loginserver project compile failure 2015-11-22 18:31:32 -05:00
Paul Coene b7dc3db703 wMerge remote-tracking branch 'upstream/master' 2015-11-20 14:46:28 -05:00
Michael Cook (mackal) 0fa5b8d3f2 Merge pull request #467 from Cilraaz/master
Old Race/Class Experience Mods
2015-11-20 14:00:03 -05:00
Paul Coene 0c56660692 Merge remote-tracking branch 'upstream/master' 2015-11-20 12:04:11 -05:00
Paul Coene f3120f26ee Fix issue with mobs no depopping (due to spawn_events) while zone is idle. 2015-11-20 12:03:43 -05:00
Michael Cook (mackal) 8464a0e3b5 Implement Guild Banks for RoF/RoF2
Everything appears to work, but please test!
2015-11-17 18:15:46 -05:00
Michael Cook (mackal) 525a39912f Override Mob::GetEndurancePercent() for Merc
This allows their endurance to show in group!
2015-11-15 16:35:11 -05:00
Shendare 7c41472877 Fixed swapping error message
You now get the error message if the augment swap doesn't work, instead
of when it works. One little bang.
2015-11-14 11:40:28 -08:00
Michael Cook (mackal) 7c4abcc68d Fix int16 spell ID limit with items (click, procs, etc)
See issue #7 (Did we resolve it yet?)
2015-11-14 14:37:24 -05:00
KimLS f188851bfb Wont look for mysql .so on non-root systems 2015-11-11 13:52:52 -08:00
KimLS ee2d8a3d6d Fix for FindMySQL not preferring mysql_root hint. 2015-11-11 13:49:10 -08:00
Shendare f6c2c07a94 Augmentation Feature Patch Code Cleanup
Avoided an extraneous GetItem() call when performing an action that
doesn't return an augment to the player. Added additional error checking
and logging. Improved error messages and code comments.
2015-11-10 18:14:47 -08:00
Michael Cook (mackal) 78c75501f7 Reply to the request made on opening XTarget window
This allows the Extended Targets option in the EQ Menu to open the window
2015-11-10 03:27:30 -05:00
Shendare 9e5bfabf91 Augmentation Feature Patch
RoF+ clients now support the built-in adding, swapping, destroying, and
removing of augments in equipment, updating an equipped item's look in
case of ornamentation changes. All clients will now verify that the
proper distiller (or a perfected distiller for RoF+) is being sent for
consumption for safely removing augments. Hard-coded item IDs for
distillers have been replaced with checks on item types.
2015-11-09 22:43:25 -08:00
Akkadius 07f7b18b10 Merge pull request #468 from Shendare/master
Quick query logging addition
2015-11-09 12:19:47 -06:00
Shendare 992797f610 Fixed query logging addition
Resolved platform specific function use.
2015-11-08 22:41:39 -08:00
Shendare ad04b308c0 Quick query logging addition
Reports records affected by inserts, updates, and deletes as well as the
records returned by selects.
2015-11-08 22:18:51 -08:00
Akkadius 18c97ca637 Fix some indents, not sure how they got messed up [skip ci] 2015-11-07 13:23:15 -06:00
Akkadius d64205124f Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units
- Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone
- This can be quite the time saver
- This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise
2015-11-07 13:20:24 -06:00
Uleat 86f35e45d3 Fix for LoadBot() hp issue 2015-11-04 23:30:46 -05:00
Michael Cook (mackal) a6f6e18969 Implement cast restriction 700 (NPC only) 2015-11-03 18:43:47 -05:00
Cilraaz 9d01e832a8 Merge remote-tracking branch 'upstream/master' 2015-11-03 15:12:27 -05:00
Michael Cook (mackal) 8d80f39ead Fix copy paste error 2015-11-03 14:17:55 -05:00
Michael Cook (mackal) 63ae7ac315 Add Casting Restrictions to SE_CurrentHP (DoTs) buff processing 2015-11-03 14:16:36 -05:00
Michael Cook (mackal) e7184f402d Add Casting Restrictions to SE_CurrentHPOnce 2015-11-03 14:16:36 -05:00
Michael Cook (mackal) 835fbb81cb Expand Casting Restrictions
Mostly to nerf HT, not fully implemented
2015-11-03 14:16:36 -05:00
Akkadius 27c8a85f61 Change AI_scan_area_timer to have a little variability in renewing a new timer time versus deciding one on spawn and sticking with it 2015-11-02 23:23:04 -06:00
Akkadius 67c7254fd1 Copy paste fail [skip ci] 2015-11-02 22:48:17 -06:00
Akkadius 9304e09eca Adjust changelog.txt [skip ci] 2015-11-02 22:15:40 -06:00
Akkadius 63051dda9c Performance boost (exponential) - Adjusted default idle cast check timers in rules
- NPC:NPCToNPCAggroTimerMin	500 (Now 6000) 6 seconds
	- NPC:NPCToNPCAggroTimerMax	2000 (Now 60000) 60 seconds
	- Database version 9089 will take care of this update automatically only if you used the default values
	- The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when
		higher NPC count zones exist (Based off of process profiling)
			- Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless
				npc_spells dictates other values, which most of the time it does not
	- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
		to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them
	- These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max)
2015-11-02 22:12:41 -06:00
Akkadius f884d8d738 Fix an issue where during a depop cycle and NPC's are engaged by wiping hatelist before issuing NPC depop 2015-11-02 21:33:36 -06:00
Michael Cook (mackal) 21acd79acf Fix procs that have end cost from consuming end 2015-11-02 17:58:35 -05:00
Cilraaz 7b819c9edf Merge remote-tracking branch 'upstream/master' 2015-11-02 11:25:54 -05:00
Akkadius f4983f090d Once again another adjustment to npc to npc aggro check timer [skip cki] 2015-11-01 20:56:03 -06:00
Akkadius 0ee70a663c Small adjustments to my rushing [skip ci] 2015-11-01 20:31:01 -06:00
Akkadius e8d18cb014 Made many performance optimizing oriented code changes in the source
- Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds)
Added Perl Export Settings which should heavily reduce the Perl footprint
	- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
		this can make Perl very slow when events are triggered constantly
			- The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{})
			- qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal()
				methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered
	- A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png
	- After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result:
		http://i.imgur.com/Du5hth9.png
	- The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds
	- In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in
		EVENT_ITEM and EVENT_SAY a majority of the time if at all
	- In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates
		about 11-20 seconds of delay on its own (Depending on hardware of course)
	- I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded
		exports in sub routines that do not need them and used it to create the default table that will be installed in the database.
	- The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS
		- If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine

	+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
	| event_id | event_description                       | export_qglobals | export_mob | export_zone | export_item | export_event |
	+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
	|        0 | EVENT_SAY                               |               1 |          1 |           1 |           1 |            1 |
	|        1 | EVENT_ITEM                              |               1 |          1 |           1 |           0 |            1 |
	|        2 | EVENT_DEATH                             |               1 |          1 |           1 |           0 |            1 |
	|        3 | EVENT_SPAWN                             |               1 |          1 |           1 |           0 |            1 |
	|        4 | EVENT_ATTACK                            |               0 |          1 |           1 |           0 |            1 |
	|        5 | EVENT_COMBAT                            |               1 |          1 |           1 |           0 |            1 |
	+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+

	- If a change is made to this table while the server is live and running, you can hot reload all zone process settings via:
		#reloadperlexportsettings
	- For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as:
		(export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916
		(export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103
		(export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083
		(export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032
		(export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141
2015-11-01 20:29:51 -06:00
Akkadius 6de2bb720f Adjust AI_scan_area_timer to randomly start between 1-3 ticks (6-18 seconds) 2015-11-01 17:49:45 -06:00
Akkadius 66c7deb2ac Remove some debug junk 2015-11-01 17:46:00 -06:00
Akkadius ce0011ab18 Renaming of some timers 2015-11-01 17:12:14 -06:00
Akkadius 2a69ae42ee (Performance) Rate limit the rate in which signals are processed for NPC's 2015-11-01 17:02:52 -06:00
Akkadius e5ad5e13db Comment out Log.Out super hot path line 2015-11-01 16:11:25 -06:00
Akkadius 624c7341c5 Refactor cfp to currently_fleeing for readability 2015-11-01 16:02:41 -06:00
Akkadius 53c8d63981 Implement Perl Export Variable settings map (Huge performance boost) (Preliminary) 2015-11-01 15:59:24 -06:00
Akkadius 33917fe2a9 - Add Zone Process ID (OS PID) as information passed back to world, ultimately with the ability to display it in the telnet console under 'zonestatus'
- Refactored some zoneserver/worldserver code for readability
2015-10-31 20:19:57 -05:00
Akkadius ab3e31154c Adjust AI Aggro check timers for NPC's with npc_aggro flag set to be far less excessive (Performance increase) 2015-10-31 18:32:23 -05:00
Michael Cook (mackal) 1dd911b150 Correct charm invis breaking 2015-10-30 16:45:34 -04:00
Natedog2012 ec36a3787d Allow ModifyNPCStat to change npc spell effects lists 2015-10-21 01:24:51 -07:00
Natedog2012 376b04a37b Allow ModifyNPCStat to change an NPCs spell list 2015-10-19 10:05:50 -07:00
Uleat 861d057fe5 Merge branch 'master' of https://github.com/EQEmu/Server 2015-10-16 18:09:50 -04:00
Uleat 85adea631d Activated load/save of new bot data fields; added command '#bot clearfollowdistance' 2015-10-16 18:09:22 -04:00
KayenEQ d91e7731c3 Merge pull request #465 from KayenEQ/Development
Optional but recommended SQL to update spells_new table fields.
2015-10-15 18:24:06 -04:00
KayenEQ 190ebbbc6f Optional but recommended SQL to update spells_new table fields. 2015-10-15 18:22:56 -04:00
Cilraaz e2f1456624 Allow For Old Race/Class Experience Modifiers
Add new ruletypes 'Character:UseOldRaceExpPenalties' and 'Character:UseOldClassExpPenalties'

When set to true, adds in bonuses/penalties that existed in Classic

Class-based penalties were disabled during Velious, while race-based penalties were not removed until TSS

This method uses the original SOE method of increase exp needed to level, rather than decreasing exp gained
2015-10-14 22:57:17 -04:00
Michael Cook (mackal) efeb80cc8b Fix MGB not always turning off and make it work for discs 2015-10-14 16:36:38 -04:00
Uleat 98bc7f0ccd Activated load/save of new bot inventory fields (not use implementation) 2015-10-13 19:29:49 -04:00
Uleat 285bd3a627 Updated '2015_09_30_bots.sql' to alleviate import failures due to broken contraints 2015-10-13 14:00:51 -04:00
Uleat d3755cdb08 Temporarily disabled the bot script until a linux issue can be sorted out 2015-10-13 00:30:23 -04:00
Uleat 0a27ab372d Merge branch 'master' of https://github.com/EQEmu/Server 2015-10-12 21:17:07 -04:00
Uleat b85850052a Fix for creation_date mis-naming 2015-10-12 21:16:54 -04:00
KayenEQ d83cd0ce89 Merge pull request #464 from KayenEQ/Development
FD break from spells
2015-10-12 19:53:43 -04:00
KayenEQ e2e8d444e9 Feign death will now break when hit by casted spells, consisted with live.
Implemented suport for AA/spell effect which provides a chance to avoid FD breaking from spells.
2015-10-12 18:51:41 -04:00
Uleat 4a61558de8 Merge branch 'master' of https://github.com/EQEmu/Server into bots_updater 2015-10-12 18:27:54 -04:00
Uleat eeab7baef9 Final commit for bots database versioning 2015-10-12 18:27:26 -04:00
Uleat df88107697 Missed on final review... 2015-10-12 17:59:29 -04:00
Uleat 79eb2d3d4b Remote testing and some final updates 2015-10-12 17:17:07 -04:00
Michael Cook (mackal) 8ed255ad01 Fix expansionless AAs 2015-10-12 14:07:14 -04:00
Akkadius eb4e970c30 Unfix the fix [skip ci] 2015-10-11 21:59:16 -05:00
Akkadius 71d36af3ef eqemu_update.pl minor fix [skip ci] 2015-10-11 17:10:10 -05:00
KimLS f19648f615 Will prefer libmysql(dynamic) over mysqlclient(static) library for linking. Update travis.yml for new travis-ci container types. 2015-10-10 22:06:54 -07:00
Uleat c508b48b42 Merge branch 'master' of https://github.com/EQEmu/Server into bots_updater 2015-10-10 19:28:31 -04:00
Uleat e1a5853389 Updated bots load/drop scripts (thanks Shendare!) 2015-10-10 19:27:39 -04:00
KayenEQ b923c69f39 Merge pull request #463 from KayenEQ/Development
Invisible/Hide mechanics when cast on
2015-10-10 15:42:19 -04:00
KayenEQ 261b6a4623 Invisible/Hide mechanics when cast on
Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell.
Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE.
Hide skill now also follows the same rules as above.
Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break
when client is hit with an AOE spell.
2015-10-10 15:16:49 -04:00
Uleat 531cbf79f5 Merge branch 'master' of https://github.com/EQEmu/Server into bots_updater 2015-10-09 21:39:05 -04:00
Uleat ecd695ff9b Script and server code query updates for bots_updater 2015-10-09 21:34:31 -04:00
KayenEQ 817059a2e8 Merge pull request #462 from KayenEQ/Development
Updated a few AA effects to use database values instead of hard coded …
2015-10-09 14:42:10 -04:00
KayenEQ aae073f588 update 2015-10-09 14:29:15 -04:00
KayenEQ 79c9862131 Few more AA updates to use database instead of hard coded values. 2015-10-09 14:04:39 -04:00
KayenEQ 902a850c71 Merge pull request #461 from KayenEQ/Development
Updated a few AA effects to use database values instead of hard coded …
2015-10-09 13:58:04 -04:00
KayenEQ 2cf59ae2f2 Updated a few AA effects to use database values instead of hardcoded values. 2015-10-09 13:08:24 -04:00
KayenEQ 3bdd954ac0 Merge pull request #460 from KayenEQ/Development
Implemented SE_PC_Pet_Flurry_Chance
2015-10-08 19:58:32 -04:00
KayenEQ 43671fa749 Implemented SE_PC_Pet_Flurry_Chance 466 // Base1 % chance to do flurry from double attack hit. 2015-10-08 19:26:04 -04:00
KayenEQ 4835e87142 Merge pull request #459 from KayenEQ/Development
Implemented spells_new field 198 = no_detrimental_spell_aggro
2015-10-08 16:30:07 -04:00
KayenEQ 20bdbdd52d Implemented spells_new field 198 = no_detrimental_spell_aggro
Spells with this flag will not generate any aggro
Note: DOT portions of spells wilth this flag STILL generate aggro.
Example Harminous Arrow (Ranger AA) 16127
2015-10-08 16:05:14 -04:00
Michael Cook (mackal) 9bff5baa1c Nuked. 2015-10-08 13:36:04 -04:00
KayenEQ 5aa99aeef1 Merge pull request #458 from KayenEQ/Development
Update/Implementation of various fields in spells_new
2015-10-08 12:07:25 -04:00
KayenEQ c35eacbc99 Update/Implementation of various fields in spells_new
219 not_extendable - > not_focusable - No focus are applied to these spells
217 maxtargets -> no_heal_damage_item_mod - Not applied to these spells.
232 -> no_remove -> Can not click off these spells even if beneficial
209 powerful_flag -> no_resist -> Unresistable spell
2015-10-08 11:49:21 -04:00
Akkadius 893f752520 Fix for proper script exit eqemu_update.pl [skip ci] 2015-10-08 09:41:47 -05:00
Akkadius ffe1bede52 eqemu_update.pl additions for EQEmu Installer to come [skip ci] 2015-10-06 14:26:53 -05:00
Akkadius 2680fc1a83 Preliminary routines for modular installer efforts [skip ci] 2015-10-05 01:07:59 -05:00
Akkadius aaae583dab Fix hash order [skip ci] 2015-10-04 20:48:11 -05:00
Akkadius 8973059961 Fix menu links [skip ci] 2015-10-03 22:13:16 -05:00
Akkadius 658b6ba570 Adjustments to eqemu_update.pl menu (V11) 2015-10-03 20:23:39 -05:00
Akkadius bcf2a5c852 eqemu_update.pl minor adjustment, v10 [skip ci] 2015-10-03 16:03:53 -05:00
Uleat 9bf4f399da Temporarily disabled bot versioning until script methods are corrected 2015-10-03 13:42:00 -04:00
Akkadius 625df2ad9b Forgot one part [skip ci] 2015-10-02 20:31:24 -05:00
Akkadius 3e42cae123 Complete support for bots database versioning in eqemu_update.pl (Option 10), ready for Uleat to take it from here [skip ci]
- The one thing to note is that world bootup will not be interrupted with required bot updates, however full versioning is supported.
2015-10-02 20:30:30 -05:00
Uleat 3ac87c8e31 Merge branch 'master' of https://github.com/EQEmu/Server into bots_updater 2015-10-02 20:49:13 -04:00
Uleat 07ee9901b7 Name change for base bot schema sql files 2015-10-02 20:48:24 -04:00
Akkadius 1e3f7b14c8 Bots database versioning (prep) [skip ci] 2015-10-02 19:40:58 -05:00
Akkadius cbcfa2f2df Fix issue with an old SQL update and newer database engines [skip ci] 2015-10-02 19:35:02 -05:00
Uleat 75da37b7b4 Merge branch 'master' of https://github.com/EQEmu/Server into bots_updater 2015-10-02 19:11:59 -04:00
Uleat a5f805e1f7 Unversioned... 2015-10-02 18:59:56 -04:00
Uleat 0999278b75 Initial bots_updater commit 2015-10-02 18:57:51 -04:00
Michael Cook (mackal) 321fa9cd50 Merge pull request #457 from Cilraaz/master
Update to give client access to the proper AAs for the expansions all…
2015-09-30 13:30:44 -04:00
Cilraaz 8323f6af7b Update to give client access to the proper AAs for the expansions allowed
Bit shifting by expansion value minus 1, rather than expansion value
2015-09-30 12:58:05 -04:00
Uleat a1089fccd6 Implemented 'Inventory Snapshot' feature 2015-09-25 23:07:05 -04:00
KayenEQ 41d19c4e8a Merge pull request #456 from KayenEQ/Development
Implemented a few new stackable spell damage focus effects from live.
2015-09-25 05:19:56 -04:00
KayenEQ 370b5d7810 Implemented a few new stackable spell damage focus effects from live.
Implemented SE_ImprovedDamage2				461 // Increase spell damage by percent (SE_Fc_Damage_%2)
Implemented SE_FcDamageAmt2     		462 // Increase spell damage by flat amount (SE_Fc_Damage_Amt2)
2015-09-25 05:18:30 -04:00
KayenEQ eb1d43020e Merge pull request #455 from KayenEQ/Development
Implemented SE_PC_Pet_Rampage
2015-09-25 04:46:13 -04:00
KayenEQ a11816fddf Implemented SE_PC_Pet_Rampage 464 - Base1 % chance to do rampage for base2 % of damage each melee round 2015-09-25 04:44:17 -04:00
Michael Cook (mackal) 957aba7ae5 Fix Sinister Strikes calc 2015-09-24 19:39:36 -04:00
Michael Cook (mackal) d0f9a14217 Revert "Fix likely dev typo in sinister strikes calc"
This reverts commit 72aaf56c79.
2015-09-24 19:33:16 -04:00
KayenEQ 41dc7622f9 Merge pull request #454 from KayenEQ/Development
Implemented spells_new field 217 override_crit_chance
2015-09-22 03:03:11 -04:00
KayenEQ cc0d0cc126 Implemented spells_new field 217 override_crit_chance
Determines the maximum chance this spell has to critical hit.
Ie. If set to 15, the spell will never critical more then 15% of the time
regardless of your characters innate chance to critcal from AAs.
2015-09-22 03:02:24 -04:00
KayenEQ b3ded44a59 Merge pull request #453 from KayenEQ/Development
Added the latest spell effects to spdat.h for future implementation.
2015-09-21 20:30:08 -04:00
KayenEQ ccbaccd0c1 Added the latest spell effects to spdat.h for future implementation. 2015-09-21 20:28:48 -04:00
Akkadius bc525e33c5 Fixed an issue where tints and weapons weren't being refreshed on Mob::SendIllusion triggers from scripts 2015-09-21 15:28:29 -05:00
Akkadius 13ba997589 Update eqemu_update.pl (v8) to use new AA data post AA rework for fresh AA table downloads [skip ci] 2015-09-20 15:21:38 -05:00
Akkadius 4c0a9562ee Update db_dumper.pl (Database backup) script to only create backups with underscores as space delimiters (db 09-2-2015.sql) vs Now: (db_09_20_2015.sql) [skip ci] 2015-09-20 15:12:00 -05:00
Michael Cook (mackal) 72aaf56c79 Fix likely dev typo in sinister strikes calc 2015-09-20 03:58:21 -04:00
Michael Cook (mackal) 9408403a00 Fix damage bonus calculations
Based on dev quotes, nerfs Sinister Strikes
2015-09-18 19:50:48 -04:00
Michael Cook (mackal) 211462456c More hate fixes
Refix double spell casting subtlety
Fix double spell casting subtlety for beneficial spells
Move 100 initial bonus to AddToHateList so melee get it as well
Lower prox aggro since the 100 bonus is in AddToHateList now
2015-09-17 01:46:40 -04:00
Uleat b24f1914ab Minor fix for opcode_handlers.py (Underfoot to UF) 2015-09-16 19:45:28 -04:00
Michael Cook (mackal) 548701cba6 Fix int underflow error in disc reuse timers focus 2015-09-04 14:07:01 -04:00
Michael Cook (mackal) 0d3bd5988b Fix issue when RemoveXTarget was called with a mob not on our XTargets
This could be better, but works for now
2015-09-04 12:12:29 -04:00
Michael Cook (mackal) 5126104fd6 Some crash fixes noticed on EQMacEmu 2015-09-03 20:42:35 -04:00
Michael Cook (mackal) 64deca11b2 Woops, gotta initialize the new flag 2015-09-03 03:05:50 -04:00
Michael Cook (mackal) 4ae02e5efe XTargets will move auto entries up on removal like live
This also makes use of the bulk packet so not a crap ton of packets
generated.
2015-09-03 02:58:04 -04:00
Akkadius b7ee4634be Merge pull request #452 from KinglyKrab/master
Fixed #bot resist commands.
2015-08-31 15:46:12 -05:00
Kinglykrab b868cbbcfe Fixed #bot resist commands. 2015-08-31 14:41:58 -04:00
Michael Cook (mackal) 7002ee184a Merge pull request #451 from KinglyKrab/master
Fixed #npcedit rangedtype.
2015-08-28 15:19:38 -04:00
Kinglykrab 53292a99a2 Fixed #npcedit rangedtype. 2015-08-28 15:15:19 -04:00
Michael Cook (mackal) 43586a33cd Port PROX_AGGRO from EQMacEmu
If this ability is set, the NPCs will continuously add things to their
hate list while their engaged. If it's not set (default) they won't,
which is what the vast majority of NPCs do on live.
2015-08-26 16:20:56 -04:00
Michael Cook (mackal) 839b6e25d8 Fix "same spell line" optimization for same spell mana burns ... 2015-08-24 02:15:41 -04:00
Michael Cook (mackal) 39e35fa011 Temp solution for AE ramp crash 2015-08-21 03:09:27 -04:00
Michael Cook (mackal) 1d6a185f0f Break "same spell line" optimizations for mana burns 2015-08-19 22:21:17 -04:00
Michael Cook (mackal) 60c6583c54 Fix readability [skip ci] 2015-08-19 14:44:46 -04:00
Uleat bc9f85843e Fix for SoF character select screen issue 2015-08-17 23:23:24 -04:00
Alex ce2c1b585f Merge pull request #450 from noudess/master
Fix buffdurationpacket for seeinvis spells
2015-08-15 19:13:04 -07:00
Paul Coene a2c5f359d8 Fix buffdurationpacket for seeinvis spells 2015-08-15 20:14:15 -04:00
Michael Cook (mackal) a4d0db8e0a Implement the extra Wild Rampage/Rampage message (SoD+) 2015-08-15 00:34:10 -04:00
Michael Cook (mackal) fe0758c984 Add EVENT_TICK for NPCs
This event fires at the start of the tick processing so we can
script on the actual tick.
2015-08-13 22:30:49 -04:00
Michael Cook (mackal) 1fc23beb78 Clear auto XTargets on WipeHateList 2015-08-12 23:36:59 -04:00
Michael Cook (mackal) f46b88bbde Merge pull request #447 from noudess/master
Fix snow so it ends correctly.
2015-08-08 19:28:00 -04:00
Michael Cook (mackal) 4a3701f05a Merge pull request #449 from KinglyKrab/master
GetAccountAge() for Perl.
2015-08-08 19:26:30 -04:00
Kinglykrab ede969a614 Added GetAccountAge() functionality to Perl so people can grant veteran AAs based on account age. 2015-08-08 17:09:57 -04:00
Michael Cook (mackal) e0d65df4de Fix #myskills crash 2015-08-06 20:29:55 -04:00
Paul Coene 4e538d14c8 Fix snow so it ends correctly. Packet is different from the all zeros sent
to end rain.  End packets need to have the type that is ending.
2015-08-04 09:48:39 -04:00
Akkadius a04e78cfd1 Shendare: VS2013 query StringFormat glitches when "%f" is passed for the int GetRunSpeed().
Shendare: In CreateNewNPCCommand(), the npc_type_id and spawngroupid are created in the database, but never set in the spawn class, so later it can't delete them with #npcspawn remove or #npcspawn delete.
2015-08-02 02:24:26 -05:00
Akkadius 4106251497 Merge pull request #446 from KinglyKrab/master
Added $client->GetMoney(type, subtype) to Perl/Lua.
2015-08-01 21:28:35 -05:00
Kinglykrab 892fb58b18 Added $client->GetMoney(type, subtype) to Perl/Lua.
Types:
- 0: Copper
- 1: Silver
- 2: Gold
- 3: Platinum
Sub Types (if applicable):
- 0: On Character
- 1: In Bank
- 2: On Cursor
- 3: Shared Bank (only applies to Type 3/Platinum)
2015-08-01 01:28:50 -04:00
Michael Cook (mackal) 7fc8841a67 Fix AE Ramp iterator issue 2015-07-31 02:00:09 -04:00
Michael Cook (mackal) b98bc207fb Move AE Ramp back to 1 target until iterator invalidation issue is resolved 2015-07-31 01:46:16 -04:00
Michael Cook (mackal) f380519803 Fix error with previous commit 2015-07-30 21:42:55 -04:00
Michael Cook (mackal) 0513f1ad5d Default area rampage to unlimited targets 2015-07-30 21:26:51 -04:00
Uleat 4c9a3b7c29 Fix for crash potential in Client::Handle_OP_ShopPlayerBuy 2015-07-27 22:13:55 -04:00
Michael Cook (mackal) be459de555 Fix issue with adding spells via quest to an empty list 2015-07-27 01:20:21 -04:00
Drajor 4258e5cebc Fixes #445 (Integer wrap in Inventory::HasItem)
unit8 changed to uint32 will prevent wrapping, excepting maybe extreme
cases. Fixes #445
2015-07-25 17:13:18 +10:00
Drajor 22a157787e Fix for ClientTaskState::UpdateTasksOnDeliver
Fix for issue introduced in changes to allow stacked items to be handed
in. Calling GetCharges on an item that can not be stacked will return 0
so this mean't that task credit was not awarded for single items.
2015-07-25 16:14:33 +10:00
Alex 26e153727e Merge pull request #444 from KinglyKrab/master
Files changed: ruletypes.h, client.cpp
2015-07-22 19:39:32 -07:00
KimLS 97e47dcbfb Fix for localaddress overwriting address 2015-07-22 17:42:57 -07:00
Michael Cook (mackal) fb4cc70999 Correct some Aggro calcs
See updated post: http://www.eqemulator.org/forums/showthread.php?t=39819

Aggro:MaxStunProcAggro renamed to Aggro:MaxScalingProcAggro
2015-07-22 16:31:38 -04:00
Kinglykrab 918bdd73f4 Files changed: ruletypes.h, client.cpp
Files added: 2015_07_22_CommonTongue.sql

Adds new rules so you can change the start Common Tongue value for Iksars, Ogres, and Trolls.
2015-07-22 09:24:06 -04:00
Alex 234b7a3c57 Merge pull request #443 from EQEmu/TaskHandIn
Hand in stacked items
2015-07-22 01:30:39 -07:00
Alex 638c96f24a Merge pull request #442 from af4t/master
Compile fixes for Visual Studio 2015 Community
2015-07-21 22:58:42 -07:00
Drajor 8f78a3fd35 Hand in stacked items
Added support for handing in stacked items and getting task credit for
those items.
2015-07-22 15:50:19 +10:00
Kemmler 8a55106288 Visual Studio 2015 Community compiles bonuses.cpp correctly now. 2015-07-21 00:42:04 -04:00
Kemmler 76b29c04e5 Merge branch 'master' of https://github.com/af4t/Server 2015-07-20 10:53:52 -04:00
Kemmler a2f39e22d1 Merge branch 'master' of git://github.com/EQEmu/Server 2015-07-20 10:47:13 -04:00
Kemmler 5dc63a6d35 Merge branch 'master' of git://github.com/EQEmu/Server 2015-07-20 10:37:26 -04:00
Kemmler c2cbf7a2ab Merge branch 'master' of https://github.com/af4t/Server
Conflicts:
	zone/bonuses.cpp
2015-07-20 10:31:46 -04:00
Kemmler 5952610a7b Very preliminary work with Visual Studio 2015 Community RC/RTM, resolve some version-specific build errors:
1. Standard library functions snprintf & vsnprintf are available thusly named (without the prepended underscores).  Someone may want to check my conditionals against non-MSVC compilers, though.
2. zone/bonuses.cpp throws an internal compiler error with optimize enabled; #pragma disable optimization on VS2015 only on function Mob::NegateSpellBonuses works around it.
2015-07-20 10:27:51 -04:00
Natedog2012 87b4640ff0 Fix bots from loading AAs that are too high of a level for them. 2015-07-20 00:25:45 -07:00
Kemmler 663ff55271 Very preliminary work with Visual Studio 2015 Community RC/RTM, resolve some version-specific build errors:
1. Standard library functions snprintf & vsnprintf are available thusly named (without the prepended underscores).  Someone may want to check my conditionals against non-MSVC compilers, though.
2. zone/bonuses.cpp throws an internal compiler error with optimize enabled; #pragma disable optimization on VS2015 only. Doing further testing as to whether we have to disable optimization for the WHOLE file ...
2015-07-18 16:56:41 -04:00
Michael Cook (mackal) c91374444b Fix bard song hate 2015-07-18 01:01:27 -04:00
Michael Cook (mackal) be16e558ff Fix Spell Casting Subtlety for offensive spells 2015-07-18 00:58:02 -04:00
Michael Cook (mackal) 7cef9a05dd Bump witness fail chance to 50 2015-07-18 00:57:10 -04:00
Michael Cook (mackal) a245fceddd Merge pull request #439 from KinglyKrab/master
New commands.
2015-07-16 22:39:34 -04:00
Michael Cook (mackal) a52ab7ae48 Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819<F37> 2015-07-16 22:38:32 -04:00
Kinglykrab eb5e0ee72c New commands.
- #untraindisc [spellid] - Untrains specified discipline.
- #untraindiscs - Untrains all disciplines.
2015-07-16 21:25:24 -04:00
Akkadius 417b034273 Merge pull request #438 from hateborne/master
Add Optional Enforce Task Level Requirement on AssignTask
2015-07-16 18:12:06 -05:00
KimLS 4d68ddc82f More NAT fixes, please work 2015-07-16 15:07:59 -07:00
KimLS 87d42931aa Fix for not having address/localaddress set from not localhost 2015-07-16 14:35:20 -07:00
hateborne cb874ad4e2 Me being a fool.
Added missing closing paran
2015-07-16 14:56:08 -04:00
hateborne 1b8f613391 Amend these to last commit
Forgot to add changelog and adjustment to task.cpp getmin/getmax
2015-07-16 13:46:41 -04:00
hateborne d64f79cb2a Add Optional Enforce Task Level Requirement
Affected:
quest::assigntask
$client->AssignTask

This is to allow those task level requirements in DB to be used,
optionally. It defaults to do not enforce (translated: no change for
current servers), but can be set with an additional flag to both
commands (see below). The LUA bit was added thanks to help from demonstar55.

quest::assigntask(703); # works
quest::assigntask(703, 1); # denies user
$client->AssignTask(701, $npc->GetID()); # works
$client->AssignTask(701, $npc->GetID(), 1); # denies user
2015-07-16 13:41:46 -04:00
Alex c8f6b098c2 Merge pull request #437 from EQEmu/reload_sm
Reload sm
2015-07-16 02:18:37 -07:00
KimLS b7cd0b223f Added two other commands to let you do shared reloading on your own without the hotfix command. Also changed how world determines a zone's address 2015-07-16 01:51:10 -07:00
KimLS 9f1f36cca6 Merge from master 2015-07-15 23:15:25 -07:00
Michael Cook (mackal) 3cd474e960 Updated SpecialAbility lua constants 2015-07-12 23:37:43 -04:00
KimLS 8dd362a101 Fix for launcher not actually sending static ports when set in the db 2015-07-11 13:28:37 -07:00
Michael Cook (mackal) 7909270527 Make sure we actually have the AA they're trying to cast 2015-07-09 02:44:55 -04:00
Michael Cook (mackal) 3c1b499485 Fix Expendable AAs
Thanks to ASan
2015-07-09 02:37:43 -04:00
KimLS a69fbb9e0b Set -> Get Timer 2015-07-08 18:10:04 -07:00
KimLS 753f53be1b Some small tweaks to reduce the amount of SendPosUpdates() are actually getting sent out on the wire. 2015-07-08 17:10:55 -07:00
Michael Cook (mackal) 3455d70ca2 Make SPECATK_QUAD uncheesable
Live seems to have w kinds of "quads" one is an innate DW
but people found out you could cheese them so luclin+ you can't anymore

so INNATE_DW you can give the NPC a 2h and they will stop quadding
QUAD they will accept the 2h but still quad
2015-07-07 17:20:37 -04:00
Michael Cook (mackal) e70e11f86c Merge pull request #436 from KinglyKrab/master
Bot command changes.
2015-07-06 16:55:52 -04:00
Kinglykrab 2ca5a4ade6 Bot command changes.
- #bot ai mez is now #bot mez
- #bot bindme is now #bot bind
- #bot runeme is now #bot rune
- #bot augmentitem now has an alias of #bot ai
- #bot giveitem now has an alias of #bot gi
- Removed unused #bot groupmessages
- Removed useless additional parameters (c->GetName()/sep->arg[2])
- Formatted loops and conditionals.
2015-07-06 16:28:17 -04:00
Michael Cook (mackal) 1e75b4ba77 Implement Triple Attack as a skill
See change log for more details
Optional SQL will max toons triple attack skills
2015-07-06 16:11:00 -04:00
Alex 5a73d26d12 Merge pull request #435 from KinglyKrab/master
Fixed guild windows on bot-enabled servers.
2015-07-06 11:08:10 -07:00
Kinglykrab 61c9a07596 Fixed guild windows on bot-enabled servers. 2015-07-06 14:05:09 -04:00
Alex 88dfc4abd8 Merge pull request #434 from KinglyKrab/master
Bot saylinks and command aliases.
2015-07-06 10:30:34 -07:00
Kinglykrab e2ac647e03 Bot saylinks and command aliases. 2015-07-05 23:30:38 -04:00
Michael Cook (mackal) 1d29c873fb Rewrite NPC combat rounds logic
See changelog.txt
2015-07-05 16:36:12 -04:00
Michael Cook (mackal) 70577584ab Make SPECATK_QUAD == SPECATK_INNATE_DW when Combat:UseLiveCombatRounds is true 2015-07-05 03:33:16 -04:00
Michael Cook (mackal) dcd1a07553 Fix issue with two hander for NPCs dual wielding
Cleaned up some other 2hander logic as well
2015-07-05 03:11:25 -04:00
Michael Cook (mackal) d083262555 Fix clients offhand double attack check 2015-07-05 02:43:33 -04:00
Michael Cook (mackal) fe97af4d89 Fix some issues with Rampage/AE Ramp 2015-07-05 02:27:51 -04:00
Michael Cook (mackal) 22efe33f9b Correct the definition of "quading"
If you would like your NPCs to use the old rules, turn
Combat:UseLiveCombatRounds to false.
2015-07-05 02:05:50 -04:00
Michael Cook (mackal) 82fe15190b Add CheckDoubleAttack for mobs 2015-07-05 01:37:14 -04:00
Michael Cook (mackal) 7c89ab3fec Pull Mob mainhand/offhand attack rounds into their own functions 2015-07-05 01:15:46 -04:00
Michael Cook (mackal) 578bbf657a Make Client::AI_Process in line with uncharmed 2015-07-05 00:46:37 -04:00
Michael Cook (mackal) 99620f8535 Add Mob/Client CheckDualWield functions 2015-07-05 00:45:46 -04:00
Michael Cook (mackal) 8d3d3d2af2 Add Dual Wield/Double Attack NPC skill overrides
The vast majority of mobs on live follow this path. The exception
appears most commonly with PC pets though. Eventually these should
be changeable in the DB.
2015-07-05 00:42:06 -04:00
JJ 947145a642 Oops. [skip ci] 2015-07-04 12:12:18 -04:00
JJ fe98b3363d Filename consistency. [skip ci] 2015-07-04 12:10:58 -04:00
Michael Cook (mackal) 49e9c9ee34 Reworked activated avoidance skills based on dev quotes 2015-07-04 02:13:26 -04:00
Natedog2012 80c2d9d68d Set a deity for bots so they can LoadAA 2015-07-03 15:44:38 -07:00
Michael Cook (mackal) 0372651613 Fix Bot::LoadAA 2015-07-03 17:42:31 -04:00
Natedog2012 f2e0384cb8 Merge pull request #433 from KinglyKrab/master
Files changed: command.cpp, questmgr.cpp
2015-07-03 12:29:14 -07:00
Kinglykrab 59e40b3fbe Files changed: command.cpp, questmgr.cpp
- Added command aliases: #findzone -> #fz, #reloadquest -> #rq
- Added instance ID to $client->GoToSafeCoords() in quest::safemove();
2015-07-03 14:57:48 -04:00
Michael Cook (mackal) 927a88cf96 Really fix class AA check 2015-07-03 02:31:12 -04:00
Michael Cook (mackal) 803fa48c05 Fix AA class check 2015-07-03 02:17:14 -04:00
KimLS 81e827481b Final touch up on this, changelog + fix for sql classes default being left shifted 1. 2015-07-02 20:18:08 -07:00
KimLS 214873c139 Merge conflicts abound and now are fixed 2015-07-02 20:12:51 -07:00
KimLS 233b096c17 0 != 9 and i suck at manifests cause of that fact 2015-07-02 20:10:26 -07:00
KimLS cca7a7899a Merge branch 'aa' of github.com:EQEmu/Server into aa 2015-07-02 20:08:32 -07:00
KimLS 25c6ddd631 Scary final SQL stuff for aa branch 2015-07-02 20:07:09 -07:00
KimLS 35991b68a0 First sql, need to merge from master first before i finish. 2015-07-02 19:36:38 -07:00
Akkadius da1167671b changelog addition [skip ci] 2015-07-01 01:25:56 -05:00
Akkadius 2bf49be855 Fix an issue where emote messages would overflow the buffer of 256 by increasing the size and changing some of the initialization
Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates'
(Haynar) Fixed some runspeed issues with Perl and LUA scripts
(Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format.
(Haynar) Improved client movement while AI Controlled, such as feared and charmed.  Movement will be much smoother from clients perspective.
2015-07-01 01:23:00 -05:00
Akkadius b71e856c8c Increase emote buffer to 4096 2015-07-01 00:19:44 -05:00
Akkadius 88659b5f7e Runspeed changes added to database update manifest 2015-06-30 23:57:13 -05:00
Akkadius 895f27a6c1 Fix an issue with Guild messages sent via gmsay that are too long 2015-06-30 23:42:21 -05:00
Michael Cook (mackal) ea18238a12 Some servers apparently relied on the HP update spam 2015-06-30 20:35:28 -04:00
JJ 56b57d2ca6 Fix moving character to zone using character id and zone name. (bheam) 2015-06-30 20:05:35 -04:00
Akkadius fdfd602bd2 Merge pull request #432 from ngdeao/master
Updated additional support in code for new speed calculations.
2015-06-30 02:29:26 -05:00
ngdeao 850a908874 Fixed #modifynpcstat runspeed <value>, to work with new speed calculations.
Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format.
Improved client movement while AI Controlled, such as feared and charmed.  Movement will be much smoother from clients perspective.
2015-06-29 22:57:37 -06:00
Akkadius c61feffe26 Merge pull request #431 from ngdeao/master
Fixed some mob speed scaling.
2015-06-28 03:19:43 -05:00
ngdeao 74aec82d2a Optional SQL for adjusting mob speeds.
The base runspeeds for mobs were about 80% high.  This scales them to values appropriate for new speed calculations.
The RescaleRunspeeds regroups speeds into common seen speed bins.  Higher speeds it lowers them by 20%.  This should only be run once against a db.
The Set specific speeds is tailored to specific mob run speeds, based on data taken from eqlive.
2015-06-28 00:58:03 -06:00
ngdeao b11fea91a6 Fixed some mob speed scaling. 2015-06-28 00:35:55 -06:00
Michael Cook (mackal) 009918cbd1 Fix songcap implementation 2015-06-27 22:43:00 -04:00
Michael Cook (mackal) 5a6685d129 Fix issue with AA cast mana consumption
AAs will now cast from slot "0xFF" instead of the itemslot
to avoid special behavior of items.

Mana reduction also moved down to the same place consumption takes
place like live.
2015-06-27 18:39:13 -04:00
Michael Cook (mackal) 337ce2d74b Fix crash for Bard Furious Refrain
This does a frenzy, which bards don't have. Live this AA is broken.
2015-06-26 18:00:15 -04:00
Michael Cook (mackal) cee7e401dd Fix issue with initial cast of level override proc buffs 2015-06-26 02:19:13 -04:00
Michael Cook (mackal) cb525156ef Merge branch 'master' into aa 2015-06-26 02:04:48 -04:00
Michael Cook (mackal) 4b64e8c39c Ignore skills out of range for bonuses 2015-06-26 02:04:33 -04:00
Michael Cook (mackal) c3a805923c Up the bard level check to 255 again
1-254 actually has special bard logic and client expects it
2015-06-25 13:21:02 -04:00
KimLS 476ee10ca0 Fix for Berserkers not seeing AAs on SoD and below clients. 2015-06-24 20:02:11 -07:00
KimLS 31301e0a26 ResetAA should hopefully play better with granted AA points now 2015-06-24 01:25:49 -07:00
KimLS 3dd89b0daa Polishing shared memory hotfix code 2015-06-23 22:04:48 -07:00
KimLS 67143f1b8a Initial work on shared memory hotfixes 2015-06-23 17:39:06 -07:00
Michael Cook (mackal) 8f156b3c91 Add Client:GetAccountAge to Lua 2015-06-23 18:37:24 -04:00
KimLS a41570677f More work on Granting, incrementaa now uses grant internally which should make it work more consistently with its old behavior 2015-06-23 12:53:46 -07:00
KimLS ce5e185738 Reworked how grant aa works 2015-06-23 00:36:43 -07:00
Michael Cook (mackal) fd989cdbc8 Add back in the bard song focus check
But also allowed focusSpellDuration through for that AA
2015-06-22 00:08:21 -04:00
KimLS 51caa3c577 Merge branch 'aa' of github.com:EQEmu/Server into aa 2015-06-21 01:25:48 -07:00
KimLS 77f050b653 setaapts command will now let you have up to 5k AA points, from 200. Removed the need to specify a prev_id in alternate_abilities table it can deduce that by itself. 2015-06-21 01:25:34 -07:00
Michael Cook (mackal) c0ea82f9e1 SE_MeleeVulnerability really really is Max Mana limit
Also found the cause of bard song tick increase and removed
the uneeded code

Also removed the IsBardSong check from GetFocusEffect, it really
shouldn't be needed, but will need to keep an eye out. The focus
effects should most often limit out the bard songs anyways
2015-06-21 02:58:43 -04:00
Michael Cook (mackal) d34b4a786b Implement duration ramp and war cry with new AA system
Rampage also correctly does a full attack round for classes
other than monk and ranger
2015-06-21 02:01:48 -04:00
KimLS d5098a56e0 Timers and some more loading stuff 2015-06-20 19:44:00 -07:00
Michael Cook (mackal) 635ac692ea Fix merge ... 2015-06-19 21:48:34 -04:00
Michael Cook (mackal) 6621a125e6 Merge branch 'master' into aa 2015-06-19 21:44:58 -04:00
KimLS 94f47e7adf Merge branch 'aa' of github.com:EQEmu/Server into aa 2015-06-17 12:05:36 -07:00
KimLS 065363480f Added AA grant to quest system, fixed a bug here or there noticed incrementaa needs to be fixed or removed 2015-06-17 12:05:09 -07:00
Michael Cook (mackal) 0447321d92 Implement songcap needed for the AA revamp
Added rule Character:UseSpellFileSongCap defaulted to true since
most servers will probably be updating everything.
2015-06-17 02:47:05 -04:00
KimLS c445f63186 Okay timers now work right, for real this time 2015-06-16 23:41:46 -07:00
KimLS 33b6748c1b Merge branch 'aa' of github.com:EQEmu/Server into aa 2015-06-16 21:46:24 -07:00
KimLS 60f2e31240 Retooled how cooldowns work so they should be more consistent with how the client shows them 2015-06-16 21:43:51 -07:00
Michael Cook (mackal) f4c22d7111 Fix double riposte 2015-06-16 17:10:47 -04:00
KimLS d3280c9676 Removing old code, need to reimplement warcry and rampage still at least 2015-06-16 12:33:14 -07:00
KimLS 1b088b7157 AA bonus calc -> Mob from Client, Bots should now work with their aa stuff again (untested) 2015-06-16 11:34:43 -07:00
KimLS a984e9bd7c Some cleanup as well as fix for a certain type of aa proc 2015-06-15 15:09:06 -07:00
KimLS 34f0106437 Added reset aa command for rof2 (50 status req), fixed #resetaa command 2015-06-15 13:57:18 -07:00
Michael Cook (mackal) 335470d3db Port up AA sympathetic procs 2015-06-13 22:49:32 -04:00
Michael Cook (mackal) 121af489c4 Support for Eyes Wide Open
This probably needs testing on older clients ...
2015-06-13 17:53:21 -04:00
Michael Cook (mackal) 106e0c69ab Added todo list to ApplyAABonuses
Probably incomplete
2015-06-13 02:43:00 -04:00
Michael Cook (mackal) 4898bfd822 Fix focusReagenCost for pets
All focus seem to use 33 ...
2015-06-13 02:12:17 -04:00
Michael Cook (mackal) d68075a5dc Merge branch 'master' into aa 2015-06-12 22:50:05 -04:00
Michael Cook (mackal) ed11ee8bea AA effects and focus should work
Still need to verify all effects and implement currently unhandled
2015-06-12 22:41:18 -04:00
KimLS 65ac9683a3 Removed fluff code, added drakkin heritage and status can use modifiers to aa abilities 2015-06-12 13:39:20 -07:00
KimLS e5d1e98793 Added deity and race checking to AAs, doubled over the sanity check code and found a mistake, added code to make boats move smoother after loading into oot 50 times and seeing it skip every time. 2015-06-12 02:56:51 -07:00
KimLS afaa9ee6c9 Expendable aa work 2015-06-11 23:08:17 -07:00
KimLS dd345c01de Activating AAs now works, don't have expend charges working quite yet so they can just be cast over and over. 2015-06-11 21:33:39 -07:00
KimLS 63928caace Removing cruft, patches should *all* work now even titanium, incrementaa has been implemented (untested atm) 2015-06-11 18:38:46 -07:00
KimLS 985d969384 AA purchasing works 2015-06-11 17:04:59 -07:00
KimLS bad4a94b84 Apply RoF2 patch demon gave me for AAs 2015-06-11 01:45:55 -07:00
KimLS 416538764a Merge branch 'master' into aa 2015-06-10 22:47:45 -07:00
KimLS 1589169200 AAs should load from character data now, though will be fucked up if you already had stacked aas. 2015-06-10 22:46:57 -07:00
KimLS 8422ce6f25 Moved effects to a vector since we dont need the random access by slot 2015-06-09 22:46:53 -07:00
KimLS 963eb91669 Merge branch 'master' into aa 2015-06-09 22:13:03 -07:00
KimLS d5e697c061 More work, looks a lot better than before, tomorrow i hope to get actual client implementation done 2015-06-09 22:12:31 -07:00
KimLS 33c1c7c3e4 More packet figuring out... 2015-06-09 16:17:09 -07:00
KimLS dbbe6b5a91 Experimenting with packets 2015-06-09 12:39:39 -07:00
KimLS 250d0cc903 More aa work, it actually loads yay 2015-06-08 20:06:14 -07:00
KimLS 361c93b689 Merge branch 'master' into aa 2015-06-08 09:58:59 -07:00
KimLS 3ee1c43ac4 Remove old aa list send for experiment also want to merge from master... 2015-06-08 09:53:21 -07:00
KimLS 6515879c14 Merge branch 'master' into aa 2015-06-07 19:42:57 -07:00
KimLS 3d1dc6314d New style AA data loading, still rudimentary 2015-06-07 19:42:12 -07:00
325 changed files with 89034 additions and 21228 deletions
+10 -8
View File
@@ -1,16 +1,18 @@
language: cpp
compiler: gcc
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev
sudo: false
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON
- make
- make -j8
- ./bin/tests
branches:
only:
- master
- stable
notifications:
email: false
irc:
+6
View File
@@ -331,8 +331,14 @@ IF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(luabind)
ENDIF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/debug_utils/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour_tile_cache/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/recast/include")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(recast)
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
IF(EQEMU_BUILD_SERVER)
ADD_SUBDIRECTORY(shared_memory)
+251
View File
@@ -1,5 +1,256 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 01/13/2016 ==
Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog.
- Just target the person whose flag you want to refresh and type #flag.
Uleat: Added itemlink functionality to the #summonitem command. Current use is limited to extracting the item id from the link.
- Invoking by item link '#summonitem Arrow' produces the same result as by item id '#summonitem 8005'
== 01/12/2016 ==
Athrogate: Adding ClearCompassMark() to Lua.
- Lua didn't have ClearCompassMark(). Perl already had this.
== 01/12/2016 ==
Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player (thanks Natedog!)
== 12/29/2015 ==
Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true
- When a zone boots, it will spawn an invisible npc by the name of zone_controller
- Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua
- This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10
- Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC)
- EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables:
$spawned_entity_id
$spawned_npc_id
- EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables:
$killer_id
$killer_damage
$killer_spell
$killer_skill
$killed_npc_id
== 12/28/2015 ==
Kinglykrab: Added GetInstanceTimer() to Perl and Lua.
- Added GetInstanceTimerByID(instance_id) to Perl and Lua.
- Note: If you do not provide an instance id in the method it defaults to instance id 0 and returns 0 for time remaining.
- Added UpdateZoneHeader(type, value) to Perl and Lua.
- Note: UpdateZoneHeader allows you to manipulate fog color, fog density, and many other zone header settings on the fly in Perl and Lua.
== 12/21/2015 ==
Natedog: Updated item table fields and added a few missing fields for evolving items
-DO NOT implement Heirloom items till the inventory code is fixed to allow placing NO DROP
items in your shared bank. (but item field located on items table)
-NYI - SkillModMax: Max skill point modification from the percent mods. EX:
100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though)
Kinglykrab: Added GetMeleeMitigation() for NPCs and Clients in Perl and Lua.
- This allows you to check total item, spell, and AA melee mitigation contribution.
== 12/19/2015 ==
Kinglykrab: Added many methods to Perl and Lua, list below:
- SeeInvisible()
- SeeInvisibleUndead()
- SeeHide()
- SeeImprovedHide()
- GetNimbusEffect1() - returns first nimbus effect
- GetNimbusEffect2() - returns second nimbus effect
- GetNimbusEffect3() - returns third nimbus effect
- IsTargetable()
- HasShieldEquiped()
- HasTwoHandBluntEquiped()
- HasTwoHanderEquiped()
- GetHerosForgeModel() - returns int32 Hero's Forge model
- IsEliteMaterialItem() - returns uint32 Hero's Forge Model
- GetBaseSize() - returns Mob's base size
- HasOwner()
- IsPet()
- HasPet()
- IsSilenced()
- IsAmnesiad()
== 12/16/2015 ==
Noudess: Repaired issue with Bind Wounds on someone else. Message was not coming out on client (hold still) and a bind wounds on someone already binding their wounds would interrupt their bind and make them stand. Also removed some duplicate messaging.
== 12/14/2015 ==
Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua.
- Note: Both methods are Mob methods and may be used on NPCs or PCs.
Natedog: Added Discipline functions, UpdateInstanceTimer function, and UnmemSpellBySpellID to lua and perl
-Examples: http://wiki.eqemulator.org/i?M=Pastebin&Paste=BJ0ygmNM
== 12/07/2015 ==
Uleat: Command aliases are no longer handled through the command_add() function.
- To add a command alias, edit the database table `command_settings` - here, you will find three columns: `command`, `access` and `aliases`
- Adding command aliases require that the command contain an entry in `command_settings`.`command`
- Only 'real' commands go inside of the command_init() function in command.cpp .. if you wish to add aliases, you must enter them into the database
- 'Real' commands are loaded first .. then any access/alias data is loaded and applied afterwards
- Duplicate aliases will be ignored .. only the first encountered occurrence will be honored - if it does not conflict with an existing command name
- Aliases should not contain whitespace and should be '|' (pipe) delimited
- The restriction on the number of aliases has been removed .. though each alias will still be limited to the access level of the parent command
- If you need need more name space for aliases, simply edit the `command_settings` table and increase the size of the `aliases` column
- The old `commands` table has been renamed to `commands_old` for reference
- All of the current 'standard' commands have been added to the new `command_settings` table
- YOU WILL NEED TO VERIFY/IMPORT OLD ACCESS VALUES AS THIS CHANGE REVERTS ALL COMMAND ACCESS VALUES TO THEIR PEQDB DEFAULTS
== 11/30/2015 ==
Uleat: Changed criteria for a few bots scripts from count to null/not null in hopes of fixing special case failures
== 11/22/2015 ==
Uleat: Fix for loginserver project compile failure
== 11/7/2015 ==
Akkadius: Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units
- Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone
- This can be quite the time saver
- This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise
== 11/2/2015 ==
Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules
- Spells:AI_IdleNoSpellMinRecast 500 (Now 6000) 6 seconds
- Spells:AI_IdleNoSpellMaxRecast 2000 (Now 60000) 60 seconds
- Database version 9089 will take care of this update automatically only if you used the default values
- The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when higher NPC count zones exist (Based off of process profiling)
- Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless npc_spells dictates other values, which most of the time it does not
- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them
- These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max)
== 11/1/2015 ==
Akkadius: Made many performance optimizing oriented code changes in the source
- Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds)
Akkadius: Added Perl Export Settings which should heavily reduce the Perl footprint
- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
this can make Perl very slow when events are triggered constantly
- The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{})
- qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal()
methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered
- A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png
- After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result:
http://i.imgur.com/Du5hth9.png
- The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds
- In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in
EVENT_ITEM and EVENT_SAY a majority of the time if at all
- In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates
about 11-20 seconds of delay on its own (Depending on hardware of course)
- I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded
exports in sub routines that do not need them and used it to create the default table that will be installed in the database.
- The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS
- If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| event_id | event_description | export_qglobals | export_mob | export_zone | export_item | export_event |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| 0 | EVENT_SAY | 1 | 1 | 1 | 1 | 1 |
| 1 | EVENT_ITEM | 1 | 1 | 1 | 0 | 1 |
| 2 | EVENT_DEATH | 1 | 1 | 1 | 0 | 1 |
| 3 | EVENT_SPAWN | 1 | 1 | 1 | 0 | 1 |
| 4 | EVENT_ATTACK | 0 | 1 | 1 | 0 | 1 |
| 5 | EVENT_COMBAT | 1 | 1 | 1 | 0 | 1 |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
- If a change is made to this table while the server is live and running, you can hot reload all zone process settings via:
#reloadperlexportsettings
- For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as:
(export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916
(export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103
(export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083
(export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032
(export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141
== 10/16/2015 ==
Uleat: Added command '#bot clearfollowdistance [ <target> | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance
== 10/13/2015 ==
Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process
Note: Please visit the thread below if you encounter issues during the conversion process
== 10/12/2015 ==
Uleat: Implemented 'bots' database versioning
Note: See thread for more information: http://www.eqemulator.org/forums/showthread.php?t=40091
Kayen: Feign death will now break when hit by casted spells, consisted with live.
Implemented suport for AA/spell effect which provides a chance to avoid FD breaking from spells.
== 10/10/2015 ==
Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell.
Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE.
Hide skill now also follows the same rules as above.
Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break
when client is hit with an AOE spell.
== 09/25/2015 ==
Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals.
rules:
'Character:ActiveInvSnapshots' - active (true) or inactive (false - default)
'Character:InvSnapshotMinIntervalM' - minimum time between snapshots (in minutes)
'Character:InvSnapshotMinRetryM' - minimum time to attempt a retry after a failed snapshot (in minutes)
'Character:InvSnapshotHistoryD' - minimum time to keep snapshot entries (in days)
commands:
'#invsnapshot' - Takes a snapshot of target client's inventory (feature active or inactive)
'#clearinvsnapshots [use rule]' - Clears snapshot entries based on bool argument ([true] - honors the 'InvSnapshotHistoryD' rule, [false] - erases all)
== 08/02/2015 ==
Shendare: VS2013 query StringFormat glitches when "%f" is passed for the int GetRunSpeed().
Shendare: In CreateNewNPCCommand(), the npc_type_id and spawngroupid are created in the database, but never set in the spawn class, so later it can't delete them with #npcspawn remove or #npcspawn delete.
== 07/27/2015 ==
Uleat: Reworked the QS Audit code in Handle_OP_ShopPlayerBuy (\zone\client_packet.cpp) to help eliminate potential for exception errors
== 07/22/2015 ==
mackal: Corrected some hate value calcs based on updated http://www.eqemulator.org/forums/showthread.php?t=39819
Rule Aggro:MaxStunProcAggro to Aggro:MaxScalingProcAggro since the cap applies to more than stuns
== 07/16/2015 ==
mackal: Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819
== 07/15/2015 ==
Hateborne: Added optional ability to enforce task level requirements in perl and lua via an added, optional parameter to $client->AssignTask and quest::assigntask.
Use cases:
quest::assigntask(703); # this still assigns the task as normal, no functional change
quest::assigntask(703, 1); # this will assign the task, provided the character meets the db-stored level requirements
$client->AssignTask(703, $npc->GetID()); # still assigns the task as normal, no functional change
$client->AssignTask(703, $npc->GetID(), 1); # this will assign the task, provided the character meets the db-stored level requirements
== 07/06/2015 ==
mackal: Implement Triple Attack Skill
Parses showed about rand(1000) for the chance, may need more investigating
Corrected Double Attack chances as well
Running optional 2015_07_06_TripleAttack.sql will set current toons to their max skill
This is optional because the admins might want to go a different route.
== 07/05/2015 ==
mackal: Rewrite NPC combat attack round logic
An NPC "quading" is really just an NPC with innate dual wield that doubles on both hands
The old rules allowed NPCs to hit 6 times in one round
NPCs also seem to have their own skill progression for DW/DA
See: http://www.eqemulator.org/forums/showthread.php?t=38708
You can set Combat:UseLiveCombatRounds to false to use the old rules
PC Double Attack rates kind of follow the same thing but still needs to be implemented
Kinglykrab: WARNING: summonburriedplayercorpse is now summonburiedplayercorpse, getplayerburriedcorpsecount is now getplayerburiedcorpsecount, summon_burried_player_corpse is now summon_buried_player_corpse, and get_player_burried_corpse_count is now get_player_buried_corpse_count FIX THESE IN YOUR SCRIPTS OR THEY WILL NOT WORK!!!!
Added bot saylinks (thanks Uleat!)
Command aliases for #augmentitem (#aug), #findnpctype (#fn), #findspell (#fs)
Bot command changes: #bot sow -> #bot speed, #bot magepet -> #bot setpet, #bot resurrectme -> #bot resurrect
Changed all occurrences of burried to buried in the code.
client_packet.cpp was referencing old columns in character_corpses, not sure how we didn't already see this before.
== 7/4/2015 ==
mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on dev quotes
This also fixes the order things are checked (avoidance skills, THEN hit/miss)
Also riposte immunity from the increase riposte chance spell effect.
== 7/2/2015 ==
KLS/Demonstar55: AA system has been rewritten fixing a ton of bugs and extending functionality while making it easier to create new AA points.
KLS/Demonstar55: New tables are needed and so older data will need to be migrated to the new system.
KLS/Demonstar55: The SQL saves the old aa points spent/avail/character_alt_abilities data if any server ops want to do something different than PEQ did with it.
KLS/Demonstar55: Will try to get a wiki entry written up next week some time explaining the system but it's really not hard to follow the db tables in the meantime.
== 7/1/2015 ==
Akkadius: Fix an issue where emote messages would overflow the buffer of 256 by increasing the size and changing some of the initialization
Akkadius: Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates'
Example: https://www.youtube.com/watch?v=KUVdbPxLIn0
Akkadius: (Haynar) Fixed some runspeed issues with Perl and LUA scripts
Akkadius: (Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format.
Akkadius: (Haynar) Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective.
== 06/12/2015 ==
Uleat: Adjusted SessionStats to better reflect a sister implementation
+23 -20
View File
@@ -21,6 +21,12 @@ IF(MYSQL_ROOT)
NAMES mysql.h
PATHS ${MYSQL_ROOT}/include
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_PATH(MySQL_INCLUDE_DIR
NAMES mysql.h
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_PATH(MySQL_INCLUDE_DIR
@@ -30,49 +36,46 @@ ELSE(MYSQL_ROOT)
ENDIF(MYSQL_ROOT)
# Library
SET(MySQL_NAMES mysqlclient_r mysqlclient)
SET(MySQL_NAMES libmysql)
IF(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib/debug /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATHS ${MYSQL_ROOT}/lib
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
NAMES ${MySQL_NAMES}
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
NAMES ${MySQL_NAMES}
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ENDIF(MYSQL_ROOT)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
SET(MySQL_FOUND TRUE)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
SET(MySQL_FOUND FALSE)
SET( MySQL_LIBRARIES )
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
# handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY_DEBUG MySQL_LIBRARY_RELEASE MySQL_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR)
IF(MySQL_FOUND)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} )
SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} )
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} )
ELSE(MySQL_FOUND)
SET( MySQL_LIBRARIES )
ENDIF(MySQL_FOUND)
+3 -18
View File
@@ -30,16 +30,9 @@ SET(common_sources
faction.cpp
guild_base.cpp
guilds.cpp
inventory.cpp
inventory_db_data_model.cpp
ipc_mutex.cpp
item.cpp
item_container.cpp
item_container_default_serialization.cpp
item_container_personal_serialization.cpp
item_instance.cpp
md5.cpp
memory_buffer.cpp
memory_mapped_file.cpp
misc.cpp
misc_functions.cpp
@@ -71,6 +64,7 @@ SET(common_sources
unix.cpp
worldconn.cpp
xml_parser.cpp
pathfind.cpp
platform.cpp
patches/patches.cpp
patches/sod.cpp
@@ -142,25 +136,15 @@ SET(common_headers
global_define.h
guild_base.h
guilds.h
inventory.h
inventory_data_model.h
inventory_db_data_model.h
inventory_null_data_model.h
ipc_mutex.h
item.h
item_container.h
item_container_default_serialization.h
item_container_personal_serialization.h
item_container_serialization_strategy.h
item_data.h
item_fieldlist.h
item_instance.h
item_struct.h
languages.h
linked_list.h
loottable.h
mail_oplist.h
md5.h
memory_buffer.h
memory_mapped_file.h
misc.h
misc_functions.h
@@ -173,6 +157,7 @@ SET(common_headers
packet_dump.h
packet_dump_file.h
packet_functions.h
pathfind.h
platform.h
proc_launcher.h
profiler.h
+3 -1
View File
@@ -63,10 +63,12 @@ public:
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += (uint32)n; }
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }
uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; }
uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; }
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
+42 -13
View File
@@ -24,20 +24,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "types.h"
static const uint32 BIT_Client62 = 1;
static const uint32 BIT_Titanium = 2;
static const uint32 BIT_SoF = 4;
static const uint32 BIT_SoD = 8;
static const uint32 BIT_UF = 16;
static const uint32 BIT_RoF = 32;
static const uint32 BIT_RoF2 = 64;
static const uint32 BIT_Client62 = 0x00000001; // 1 (unsupported - placeholder for scripts)
static const uint32 BIT_Titanium = 0x00000002; // 2
static const uint32 BIT_SoF = 0x00000004; // 4
static const uint32 BIT_SoD = 0x00000008; // 8
static const uint32 BIT_UF = 0x00000010; // 16
static const uint32 BIT_RoF = 0x00000020; // 32
static const uint32 BIT_RoF2 = 0x00000040; // 64
static const uint32 BIT_TitaniumAndEarlier = 0x00000003; // 3
static const uint32 BIT_SoFAndEarlier = 0x00000007; // 7
static const uint32 BIT_SoDAndEarlier = 0x0000000F; // 15
static const uint32 BIT_UFAndEarlier = 0x0000001F; // 31
static const uint32 BIT_RoFAndEarlier = 0x0000003F; // 63
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; // 4294967292
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; // 4294967288
static const uint32 BIT_UFAndLater = 0xFFFFFFF0; // 4294967280
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; // 4294967264
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; // 4294967232
static const uint32 BIT_TitaniumAndEarlier = 0x00000003;
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC;
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8;
static const uint32 BIT_UFAndLater = 0xFFFFFFF0;
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
static const uint32 BIT_AllClients = 0xFFFFFFFF;
enum class ClientVersion
@@ -150,4 +157,26 @@ static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
}
}
static uint32 ExpansionFromClientVersion(ClientVersion clientVersion)
{
switch(clientVersion)
{
case ClientVersion::Unknown:
case ClientVersion::Client62:
case ClientVersion::Titanium:
return 0x000007FFU;
case ClientVersion::SoF:
return 0x00007FFFU;
case ClientVersion::SoD:
return 0x0000FFFFU;
case ClientVersion::UF:
return 0x0001FFFFU;
case ClientVersion::RoF:
case ClientVersion::RoF2:
return 0x000FFFFFU;
default:
return 0;
}
}
#endif /* CLIENTVERSIONS_H */
+11 -11
View File
@@ -23,23 +23,23 @@
namespace EQEmu
{
template <typename T, typename U, typename V>
T Clamp(const T& value, const U& lower, const V& upper) {
return std::max(static_cast<T>(lower), std::min(value, static_cast<T>(upper)));
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, typename U>
T ClampLower(const T& value, const U& lower) {
return std::max(static_cast<T>(lower), value);
template <typename T>
T ClampLower(const T& value, const T& lower) {
return std::max(lower, value);
}
template <typename T, typename U>
T ClampUpper(const T& value, const U& upper) {
return std::min(value, static_cast<T>(upper));
template <typename T>
T ClampUpper(const T& value, const T& upper) {
return std::min(value, upper);
}
template <typename T, typename U, typename V>
bool ValueWithin(const T& value, const U& lower, const V& upper) {
template <typename T>
bool ValueWithin(const T& value, const T& lower, const T& upper) {
return value >= lower && value <= upper;
}
+62 -19
View File
@@ -348,11 +348,11 @@ bool Database::DeleteCharacter(char *name) {
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid);
#else
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById()
#else
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid);
#endif
#endif
QueryDatabase(query);
return true;
@@ -677,7 +677,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
}
/* This only for new Character creation storing */
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv) {
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) {
uint32 charid = 0;
char zone[50];
float x, y, z;
@@ -1183,21 +1183,16 @@ bool Database::CheckNameFilter(const char* name, bool surname)
{
std::string str_name = name;
if(surname)
// the minimum 4 is enforced by the client too
if (!name || strlen(name) < 4)
{
// the minimum 4 is enforced by the client too
if(!name || strlen(name) < 3)
{
return false;
}
return false;
}
else
// Given name length is enforced by the client too
if (!surname && strlen(name) > 15)
{
// the minimum 4 is enforced by the client too
if(!name || strlen(name) < 4 || strlen(name) > 15)
{
return false;
}
return false;
}
for (size_t i = 0; i < str_name.size(); i++)
@@ -1384,7 +1379,7 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) {
}
bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) {
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID);
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", GetZoneID(iZonename), iCharID);
auto results = QueryDatabase(query);
if (!results.Success()) {
@@ -1564,7 +1559,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
char *escape_str = new char[lines.size()*2+1];
DoEscapeString(escape_str, lines.c_str(), lines.size());
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str);
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
QueryDatabase(query);
safe_delete_array(escape_str);
}
@@ -2173,3 +2168,51 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
}
}
}
void Database::ClearInvSnapshots(bool use_rule)
{
uint32 del_time = time(nullptr);
if (use_rule) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; }
std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time);
QueryDatabase(query);
}
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
{
TimeOfDay_Struct eqTime;
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0){
Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
eqTime.minute = 0;
eqTime.hour = 9;
eqTime.day = 1;
eqTime.month = 1;
eqTime.year = 3100;
realtime = time(0);
}
else{
auto row = results.begin();
eqTime.minute = atoi(row[0]);
eqTime.hour = atoi(row[1]);
eqTime.day = atoi(row[2]);
eqTime.month = atoi(row[3]);
eqTime.year = atoi(row[4]);
realtime = atoi(row[5]);
}
return eqTime;
}
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
{
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
auto results = QueryDatabase(query);
return results.Success();
}
+7 -4
View File
@@ -23,11 +23,11 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "types.h"
#include "dbcore.h"
#include "linked_list.h"
#include "eq_packet_structs.h"
#include "inventory.h"
#include <cmath>
#include <string>
@@ -37,7 +37,7 @@
//atoi is not uint32 or uint32 safe!!!!
#define atoul(str) strtoul(str, nullptr, 10)
class InventoryOld;
class Inventory;
class MySQLRequestResult;
class Client;
@@ -103,7 +103,7 @@ public:
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked);
bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone);
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv);
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
bool UpdateName(const char* oldname, const char* newname);
/* General Information Queries */
@@ -210,7 +210,6 @@ public:
/* Database Conversions 'database_conversions.cpp' */
bool CheckDatabaseConversions();
bool CheckDatabaseConvertBotsPostPPDeblob();
bool CheckDatabaseConvertCorpseDeblob();
bool CheckDatabaseConvertPPDeblob();
@@ -242,6 +241,8 @@ public:
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
void AddReport(std::string who, std::string against, std::string lines);
struct TimeOfDay_Struct LoadTime(time_t &realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 charid);
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
@@ -249,6 +250,8 @@ public:
void SetLFP(uint32 CharID, bool LFP);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
void ClearInvSnapshots(bool use_rule = true);
/* EQEmuLogSys */
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
+1 -159
View File
@@ -470,7 +470,6 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50)
bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertBotsPostPPDeblob();
CheckDatabaseConvertCorpseDeblob();
/* Fetch Automatic Upgrade Script */
@@ -494,7 +493,7 @@ bool Database::CheckDatabaseConversions() {
/* Check for a new version of this script, the arg passed
would have to be higher than the copy they have downloaded
locally and they will re fetch */
system("perl eqemu_update.pl V 7");
system("perl eqemu_update.pl V 14");
/* Run Automatic Database Upgrade Script */
system("perl eqemu_update.pl ran_from_world");
@@ -1491,163 +1490,6 @@ bool Database::CheckDatabaseConvertPPDeblob(){
return true;
}
bool Database::CheckDatabaseConvertBotsPostPPDeblob(){
#ifdef BOTS
int runbotsconvert = 0;
/* Check For Legacy Bot References */
std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`");
auto results = QueryDatabase(rquery);
if (results.RowCount() == 1){
auto row = results.begin();
std::string table_check = row[1];
if (table_check.find("character_data") == -1){
runbotsconvert = 1;
printf("\n\n::: Legacy Bot Views and Function Detected... \n");
printf("----------------------------------------------------------\n\n");
printf(" Database currently has bot view/function linkage to obselete \n");
printf(" table references and will now be converted...\n\n");
printf(" It is recommended that you backup your database \n");
printf(" before continuing the automatic conversion process...\n\n");
printf("----------------------------------------------------------\n\n");
std::cout << "Press ENTER to continue....." << std::endl << std::endl;
std::cin.ignore(1);
}
}
if (runbotsconvert == 1){
printf("Running bot views/function database conversion... \n");
/* Update view `vwbotcharactermobs` */
rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwBotCharacterMobs` AS\n"
"SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8'
"c.`id`,\n"
"c.`name`,\n"
"c.`class`,\n"
"c.`level`,\n"
"c.`last_login`,\n"
"c.`zone_id`\n"
"FROM `character_data` AS c\n"
"UNION ALL\n"
"SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8'
"b.`BotID` AS id,\n"
"b.`Name` AS name,\n"
"b.`Class` AS class,\n"
"b.`BotLevel` AS level,\n"
"0 AS timelaston,\n"
"0 AS zoneid\n"
"FROM bots AS b;"
);
results = QueryDatabase(rquery);
/* Update function `GetMobType` */
rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n"
"BEGIN\n"
" DECLARE Result CHAR(1);\n"
"\n"
" SET Result = NULL;\n"
"\n"
" IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n"
" SET Result = 'C';\n"
" ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n"
" SET Result = 'B';\n"
" END IF;\n "
"\n"
" RETURN Result;\n"
"END"
);
results = QueryDatabase(rquery);
/* Update view `vwgroups` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwGroups` AS\n"
"SELECT g.`groupid` AS groupid,\n"
"GetMobType(g.`name`) AS mobtype,\n"
"g.`name` AS name,\n"
"g.`charid` AS mobid,\n"
"IFNULL(c.`level`, b.`BotLevel`) AS level\n"
"FROM `group_id` AS g\n"
"LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n"
"LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;"
);
results = QueryDatabase(rquery);
/* Update view `vwbotgroups` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwBotGroups` AS\n"
"SELECT g.`BotGroupId`,\n"
"g.`BotGroupName`,\n"
"g.`BotGroupLeaderBotId`,\n"
"b.`Name` AS BotGroupLeaderName,\n"
"b.`BotOwnerCharacterId`,\n"
"c.`name` AS BotOwnerCharacterName\n"
"FROM `botgroup` AS g\n"
"JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n"
"JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n"
"ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;"
);
results = QueryDatabase(rquery);
/* Update view `vwguildmembers` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwGuildMembers` AS\n"
"SELECT 'C' AS mobtype,\n"
"cm.`char_id`,\n"
"cm.`guild_id`,\n"
"cm.`rank`,\n"
"cm.`tribute_enable`,\n"
"cm.`total_tribute`,\n"
"cm.`last_tribute`,\n"
"cm.`banker`,\n"
"cm.`public_note`,\n"
"cm.`alt`\n"
"FROM `guild_members` AS cm\n"
"UNION ALL\n"
"SELECT 'B' AS mobtype,\n"
"bm.`char_id`,\n"
"bm.`guild_id`,\n"
"bm.`rank`,\n"
"bm.`tribute_enable`,\n"
"bm.`total_tribute`,\n"
"bm.`last_tribute`,\n"
"bm.`banker`,\n"
"bm.`public_note`,\n"
"bm.`alt`\n"
"FROM `botguildmembers` AS bm;"
);
results = QueryDatabase(rquery);
}
if (runbotsconvert == 1){
printf("\n\nBot views/function conversion complete, continuing world bootup...\n");
}
#endif
return true;
}
bool Database::CheckDatabaseConvertCorpseDeblob(){
Convert::DBPlayerCorpse_Struct_temp* dbpc;
Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c;
+6 -1
View File
@@ -128,7 +128,12 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
{
if ((strncasecmp(query, "select", 6) == 0))
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
else
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
}
return requestResult;
}
+4
View File
@@ -215,6 +215,7 @@ N(OP_GroupUpdate),
N(OP_GroupUpdateB),
N(OP_GroupUpdateLeaderAA),
N(OP_GuildBank),
N(OP_GuildBankItemList),
N(OP_GuildCreate),
N(OP_GuildDelete),
N(OP_GuildDemote),
@@ -535,6 +536,8 @@ N(OP_WorldLogout),
N(OP_WorldObjectsSent),
N(OP_WorldUnknown001),
N(OP_XTargetAutoAddHaters),
N(OP_XTargetOpen),
N(OP_XTargetOpenResponse),
N(OP_XTargetRequest),
N(OP_XTargetResponse),
N(OP_YellForHelp),
@@ -548,4 +551,5 @@ N(OP_ZoneServerInfo),
N(OP_ZoneServerReady),
N(OP_ZoneSpawns),
N(OP_ZoneUnavail),
N(OP_ResetAA),
// mail and chat opcodes located in ../mail_oplist.h
+1 -1
View File
@@ -306,7 +306,7 @@ enum AugmentationRestrictionTypes : uint8 {
/*
** Container use types
**
** This correlates to world 'object.type' (object.h/Object.cpp) as well as ItemData.BagType
** This correlates to world 'object.type' (object.h/Object.cpp) as well as Item_Struct.BagType
**
** (ref: database, web forums and eqstr_us.txt)
*/
+75 -31
View File
@@ -25,7 +25,7 @@
#include <list>
#include <time.h>
#include "../common/version.h"
//#include "../common/item_data.h"
//#include "../common/item_struct.h"
static const uint32 BUFF_COUNT = 25;
static const uint32 MAX_MERC = 100;
@@ -126,14 +126,6 @@ struct LDoNTrapTemplate
// All clients translate the character select information to some degree
struct Inventory_Slot_Struct
{
int16 type;
int16 slot;
int16 bag;
int16 aug;
};
struct Color_Struct
{
union {
@@ -1330,7 +1322,7 @@ struct CombatDamage_Struct
/* 11 */ float force;
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */
/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
};
/*
@@ -1566,7 +1558,7 @@ struct DeleteItem_Struct {
/*0012*/
};
struct MoveItemOld_Struct
struct MoveItem_Struct
{
/*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot;
@@ -1574,19 +1566,6 @@ struct MoveItemOld_Struct
/*0012*/
};
struct MoveItem_Struct
{
int16 from_type;
int16 from_slot;
int16 from_bag_slot;
int16 from_aug_slot;
int16 to_type;
int16 to_slot;
int16 to_bag_slot;
int16 to_aug_slot;
uint32 number_in_stack;
};
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
// info at the moment..but, it is forwarded on to the server for handling/future use)
@@ -1978,11 +1957,13 @@ Unknowns:
struct Merchant_Sell_Struct {
uint32 npcid;
uint32 playerid;
uint32 itemslot;
int32 quantity;
uint32 price;
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown016[3];
/*020*/ uint32 price;
};
struct Merchant_Purchase_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
@@ -2118,7 +2099,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -4238,6 +4219,52 @@ struct UseAA_Struct {
uint32 end;
};
//new AA stuff
//reference only
struct AARankInfo_Struct
{
uint32 id;
int32 upper_hotkey_sid;
int32 lower_hotkey_sid;
int32 title_sid;
int32 desc_sid;
int32 level_req;
int32 cost;
uint32 seq;
uint32 current_level;
uint32 type;
int32 spell;
int32 spell_type;
int32 spell_refresh;
int32 classes;
int32 max_level;
int32 prev_id;
int32 next_id;
int32 total_cost;
int32 expansion;
int32 category;
uint32 charges;
uint8 grant_only;
uint32 total_effects;
uint32 total_prereqs;
};
struct AARankPrereq_Struct
{
int32 aa_id;
int32 points;
};
struct AARankEffect_Struct
{
int32 effect_id;
int32 base1;
int32 base2;
int32 slot;
};
//old AA stuff
struct AA_Ability {
/*00*/ uint32 skill_id;
/*04*/ uint32 base1;
@@ -4292,7 +4319,7 @@ struct SendAA_Struct {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};
@@ -4697,6 +4724,22 @@ struct GuildBankItemUpdate_Struct
/*226*/ uint16 Unknown226;
};
// newer clients (RoF+) send a list that contains 240 entries
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
struct GuildBankItemListEntry_Struct
{
uint8 vaild;
uint32 permissions;
char whofor[64];
char donator[64];
uint32 item_id;
uint32 item_icon;
uint32 quantity;
uint8 allow_merge; // 1 here for non-full stacks
uint8 usable;
char item_name[64];
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
@@ -4753,6 +4796,7 @@ struct BuffIcon_Struct
uint8 all_buffs;
uint16 count;
uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC
int32 tic_timer;
BuffIconEntry_Struct entries[0];
};
-8
View File
@@ -254,10 +254,6 @@ void EQEmuConfig::do_files(TiXmlElement *ele)
if (text) {
OpCodesFile = text;
}
text = ParseTextBlock(ele, "eqtime", true);
if (text) {
EQTimeFile = text;
}
}
void EQEmuConfig::do_directories(TiXmlElement *ele)
@@ -408,9 +404,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
if (var_name == "OpCodesFile") {
return (OpCodesFile);
}
if (var_name == "EQTimeFile") {
return (EQTimeFile);
}
if (var_name == "MapDir") {
return (MapDir);
}
@@ -475,7 +468,6 @@ void EQEmuConfig::Dump() const
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
std::cout << "SpellsFile = " << SpellsFile << std::endl;
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
std::cout << "EQTimeFile = " << EQTimeFile << std::endl;
std::cout << "MapDir = " << MapDir << std::endl;
std::cout << "QuestDir = " << QuestDir << std::endl;
std::cout << "PluginDir = " << PluginDir << std::endl;
-2
View File
@@ -79,7 +79,6 @@ class EQEmuConfig : public XMLParser
// From <files/>
std::string SpellsFile;
std::string OpCodesFile;
std::string EQTimeFile;
// From <directories/>
std::string MapDir;
@@ -154,7 +153,6 @@ class EQEmuConfig : public XMLParser
// Files
SpellsFile = "spells_us.txt";
OpCodesFile = "opcodes.conf";
EQTimeFile = "eqtime.cfg";
// Dirs
MapDir = "Maps";
QuestDir = "quests";
+28 -35
View File
@@ -102,6 +102,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::UCS_Server].log_to_console = Logs::General;
log_settings[Logs::Crash].log_to_console = Logs::General;
log_settings[Logs::MySQLError].log_to_console = Logs::General;
log_settings[Logs::Login_Server].log_to_console = Logs::General;
/* Declare process file names for log writing
If there is no process_file_name declared, no log file will be written, simply
@@ -116,32 +117,27 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
platform_file_name = "ucs";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
platform_file_name = "login";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch)
platform_file_name = "launcher";
}
std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message)
{
std::string category_string;
if (log_category > 0 && Logs::LogCategoryName[log_category])
category_string = StringFormat("[%s] ", Logs::LogCategoryName[log_category]);
return StringFormat("%s%s", category_string.c_str(), in_message.c_str());
std::string ret;
ret.push_back('[');
ret.append(Logs::LogCategoryName[log_category]);
ret.push_back(']');
ret.push_back(' ');
ret.append(in_message);
return ret;
}
void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message)
{
/* Check if category enabled for process */
if (log_settings[log_category].log_to_gmsay == 0)
return;
/* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */
if (log_category == Logs::LogCategory::Netcode)
return;
/* Make sure the message inbound is at a debug level we're set at */
if (log_settings[log_category].log_to_gmsay < debug_level)
return;
/* Check to see if the process that actually ran this is zone */
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone)
on_log_gmsay_hook(log_category, message);
@@ -159,14 +155,6 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const
crash_log.close();
}
/* Check if category enabled for process */
if (log_settings[log_category].log_to_file == 0)
return;
/* Make sure the message inbound is at a debug level we're set at */
if (log_settings[log_category].log_to_file < debug_level)
return;
char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
@@ -245,13 +233,6 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) {
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
{
/* Check if category enabled for process */
if (log_settings[log_category].log_to_console == 0)
return;
/* Make sure the message inbound is at a debug level we're set at */
if (log_settings[log_category].log_to_console < debug_level)
return;
#ifdef _WINDOWS
HANDLE console_handle;
@@ -272,20 +253,32 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
{
const bool log_to_console = log_settings[log_category].log_to_console > 0;
const bool log_to_file = log_settings[log_category].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false;
}
if (nothing_to_log) return;
bool log_to_file = true;
if (log_settings[log_category].log_to_file < debug_level) {
log_to_file = false;
}
bool log_to_gmsay = true;
if (log_settings[log_category].log_to_gmsay < debug_level) {
log_to_gmsay = false;
}
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log)
return;
va_list args;
va_start(args, message);
std::string output_message = vStringFormat(message.c_str(), args);
va_end(args);
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message);
if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
+2
View File
@@ -82,6 +82,7 @@ namespace Logs {
Client_Server_Packet_Unhandled,
Server_Client_Packet_With_Dump,
Client_Server_Packet_With_Dump,
Login_Server,
MaxCategoryID /* Don't Remove this*/
};
@@ -130,6 +131,7 @@ namespace Logs {
"Packet :: Client -> Server Unhandled",
"Packet :: Server -> Client (Dump)",
"Packet :: Client -> Server (Dump)",
"Login Server"
};
}
-66
View File
@@ -133,72 +133,6 @@ int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
return 1;
}
//saveFile and loadFile need to use long for the save datatype...
//For some reason, ifstream/ofstream have problems with EQEmu datatypes in files.
bool EQTime::saveFile(const char *filename)
{
std::ofstream of;
of.open(filename);
if (!of)
{
Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename);
return false;
}
//Enable for debugging
of << EQT_VERSION << std::endl;
of << (long)eqTime.start_eqtime.day << std::endl;
of << (long)eqTime.start_eqtime.hour << std::endl;
of << (long)eqTime.start_eqtime.minute << std::endl;
of << (long)eqTime.start_eqtime.month << std::endl;
of << eqTime.start_eqtime.year << std::endl;
of << eqTime.start_realtime << std::endl;
of.close();
return true;
}
bool EQTime::loadFile(const char *filename)
{
int version=0;
long in_data=0;
std::ifstream in;
in.open(filename);
if(!in)
{
Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename);
return false;
}
in >> version;
in.ignore(80, '\n');
if(version != EQT_VERSION)
{
Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION);
return false;
}
//in >> eqTime.start_eqtime.day;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.day = in_data;
//in >> eqTime.start_eqtime.hour;
in >> in_data;
eqTime.start_eqtime.hour = in_data;
in.ignore(80, '\n');
//in >> eqTime.start_eqtime.minute;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.minute = in_data;
//in >> eqTime.start_eqtime.month;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.month = in_data;
in >> eqTime.start_eqtime.year;
in.ignore(80, '\n');
in >> eqTime.start_realtime;
//Enable for debugging...
in.close();
return true;
}
bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) {
if (base->year > test->year)
return(true);
-6
View File
@@ -39,12 +39,6 @@ public:
static void ToString(TimeOfDay_Struct *t, std::string &str);
//Database functions
//bool loadDB(Database q);
//bool setDB(Database q);
bool loadFile(const char *filename);
bool saveFile(const char *filename);
private:
//This is our reference clock.
eqTimeOfDay eqTime;
+2
View File
@@ -54,6 +54,8 @@ struct ExtendedProfile_Struct {
uint32 mercTimerRemaining; /* Not Used */
uint8 mercGender; /* Not Used */
int32 mercState; /* Not Used */
uint32 last_invsnapshot_time; /* Used */
uint32 next_invsnapshot_time; /* Used */
};
#pragma pack()
+7 -1
View File
@@ -154,11 +154,12 @@ enum { //reuse times
enum { //timer settings, all in milliseconds
AImovement_duration = 100,
AIthink_duration = 150,
AIscanarea_delay = 500,
AIscanarea_delay = 6000,
AIfeignremember_delay = 500,
AItarget_check_duration = 500,
AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
ClientProximity_interval = 150,
CombatEventTimer_expire = 12000,
Tribute_duration = 600000,
@@ -232,6 +233,8 @@ enum { //some random constants
#define GROUP_EXP_PER_POINT 1000
#define RAID_EXP_PER_POINT 2000
#define ZONE_CONTROLLER_NPC_ID 10
//Some hard coded statuses from commands and other places:
enum {
minStatusToBeGM = 40,
@@ -270,6 +273,9 @@ enum {
#define NPC_DEFAULT_LOGGING_ENABLED false
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
#define SAYLINK_ITEM_ID 0xFFFFF
/*
+9 -9
View File
@@ -867,16 +867,16 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
//factored out so I dont have to copy this crap.
#ifdef BOTS
#define GuildMemberBaseQuery \
"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
" g.banker,g.public_note,g.alt" \
" FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype "
"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 `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
#else
#define GuildMemberBaseQuery \
"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_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id "
"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_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_`
@@ -969,7 +969,7 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
//load up the rank info for each guild.
std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mobtype = 'C'", char_id);
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id);
#endif
-782
View File
@@ -1,782 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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
*/
#include "inventory.h"
#include "inventory_null_data_model.h"
#include "item_container_personal_serialization.h"
#include "data_verification.h"
#include "string_util.h"
#include <map>
bool EQEmu::InventorySlot::IsValid() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotCursor)) {
return true;
}
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
return true;
}
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
return true;
}
if(type_ == InvTypeTribute && EQEmu::ValueWithin(slot_, 0, 4)) {
return true;
}
if(type_ == InvTypeTrade && EQEmu::ValueWithin(slot_, 0, 7)) {
return true;
}
if(type_ == InvTypeWorld && EQEmu::ValueWithin(slot_, 0, 255)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsDelete() const {
return type_ == -1 && slot_ == -1 && bag_index_ == -1 && aug_index_ == -1;
}
bool EQEmu::InventorySlot::IsBank() const {
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
return true;
}
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsCursor() const {
if(type_ == InvTypePersonal && slot_ == PersonalSlotCursor) {
return true;
}
if(type_ == InvTypeCursorBuffer) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsEquipment() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotAmmo)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsGeneral() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotGeneral1, PersonalSlotGeneral10)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsWeapon() const {
if(type_ == InvTypePersonal &&
(EQEmu::ValueWithin(slot_, PersonalSlotPrimary, PersonalSlotSecondary) || slot_ == PersonalSlotRange))
{
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsTrade() const {
if(type_ == InvTypeTrade) {
return true;
}
return false;
}
const std::string EQEmu::InventorySlot::ToString() const {
return StringFormat("(%i, %i, %i, %i)", type_, slot_, bag_index_, aug_index_);
}
struct EQEmu::Inventory::impl
{
std::map<int, ItemContainer> containers_;
int race_;
int class_;
int deity_;
std::unique_ptr<InventoryDataModel> data_model_;
};
EQEmu::Inventory::Inventory(int race, int class_, int deity) {
impl_ = new impl;
impl_->race_ = race;
impl_->class_ = class_;
impl_->deity_ = deity;
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(new InventoryNullDataModel());
}
EQEmu::Inventory::~Inventory() {
delete impl_;
}
void EQEmu::Inventory::SetRace(int race) {
impl_->race_ = race;
}
void EQEmu::Inventory::SetClass(int class_) {
impl_->class_ = class_;
}
void EQEmu::Inventory::SetDeity(int deity) {
impl_->deity_ = deity;
}
void EQEmu::Inventory::SetDataModel(InventoryDataModel *dm) {
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(dm);
}
EQEmu::ItemInstance::pointer EQEmu::Inventory::Get(const InventorySlot &slot) {
auto iter = impl_->containers_.find(slot.Type());
if(iter != impl_->containers_.end()) {
auto item = iter->second.Get(slot.Slot());
if(item) {
if(slot.BagIndex() > -1) {
auto sub_item = item->Get(slot.BagIndex());
if(sub_item) {
if(slot.AugIndex() > -1) {
return sub_item->Get(slot.AugIndex());
} else {
return sub_item;
}
}
} else {
return item;
}
}
}
return ItemInstance::pointer(nullptr);
}
bool EQEmu::Inventory::Put(const InventorySlot &slot, ItemInstance::pointer &inst) {
if(impl_->containers_.count(slot.Type()) == 0) {
if(slot.Type() == 0) {
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer(new ItemContainerPersonalSerialization())));
} else {
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer()));
}
}
//Verify item can be put into the slot requested
auto &container = impl_->containers_[slot.Type()];
if(slot.BagIndex() > -1) {
auto item = container.Get(slot.Slot());
if(!item)
return false;
if(slot.AugIndex() > -1) {
auto bag_item = item->Get(slot.BagIndex());
if(!bag_item) {
return false;
}
return bag_item->Put(slot.AugIndex(), inst);
} else {
return item->Put(slot.BagIndex(), inst);
}
} else {
if(slot.AugIndex() > -1) {
auto item = container.Get(slot.Slot());
if(!item)
return false;
return item->Put(slot.AugIndex(), inst);
}
return container.Put(slot.Slot(), inst);
}
return false;
}
bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest, int charges) {
if(src == dest) {
return true;
}
if(!src.IsValid()) {
return false;
}
if(src.Type() == InvTypeCursorBuffer || dest.Type() == InvTypeCursorBuffer) {
return true;
}
if(dest.IsDelete()) {
impl_->data_model_->Begin();
bool v = _destroy(src);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
if(!dest.IsValid()) {
return false;
}
auto i_src = Get(src);
auto i_dest = Get(dest);
if(!i_src) {
return false;
}
if(i_src->GetBaseItem()->ItemClass == ItemClassContainer && dest.BagIndex() > -1) {
if(i_src->GetContainer()->Size() > 0) {
return false;
}
}
if(dest.IsEquipment() && !CanEquip(i_src, dest)) {
return false;
}
//Check this -> trade no drop
if(dest.IsTrade() && i_src->IsNoDrop()) {
return false;
}
impl_->data_model_->Begin();
if(i_src->IsStackable()) {
//move # charges from src to dest
//0 means *all* the charges
if(charges == 0) {
charges = i_src->GetCharges();
}
//src needs to have that many charges
if(i_src->GetCharges() < charges) {
impl_->data_model_->Rollback();
return false;
}
//if dest exists it needs to not only be the same item id but also be able to hold enough charges to combine
//we can also swap if src id != dest id
if(i_dest) {
uint32 src_id = i_src->GetBaseItem()->ID;
uint32 dest_id = i_dest->GetBaseItem()->ID;
if(src_id != dest_id) {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges();
if(charges_avail < charges) {
impl_->data_model_->Rollback();
return false;
}
if(i_src->GetCharges() == charges) {
if(!_destroy(src)) {
impl_->data_model_->Rollback();
return false;
}
} else {
i_src->SetCharges(i_src->GetCharges() - charges);
impl_->data_model_->Insert(src, i_src);
}
i_dest->SetCharges(i_dest->GetCharges() + charges);
impl_->data_model_->Delete(dest);
impl_->data_model_->Insert(dest, i_dest);
impl_->data_model_->Commit();
return true;
} else {
//if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest
//if dest does not exist and src charges == # charges then we need to swap src to dest
if(i_src->GetCharges() > charges) {
auto split = i_src->Split(charges);
if(!split) {
impl_->data_model_->Rollback();
return false;
}
Put(dest, split);
impl_->data_model_->Delete(src);
impl_->data_model_->Delete(dest);
impl_->data_model_->Insert(src, i_src);
impl_->data_model_->Insert(dest, split);
impl_->data_model_->Commit();
return true;
} else {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
} else {
impl_->data_model_->Rollback();
}
return v;
}
}
} else {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
impl_->data_model_->Commit();
return true;
}
bool EQEmu::Inventory::Summon(const InventorySlot &slot, ItemInstance::pointer &inst) {
if(!inst)
return false;
if(CheckLoreConflict(inst->GetBaseItem())) {
return false;
}
auto cur = Get(slot);
if(cur) {
if(slot.IsCursor()) {
PushToCursorBuffer(inst);
}
return false;
}
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
} else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PushToCursorBuffer(ItemInstance::pointer &inst) {
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
impl_->containers_.insert(std::pair<int, ItemContainer>(InvTypeCursorBuffer, ItemContainer()));
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top + 1);
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PopFromCursorBuffer() {
InventorySlot cursor(InvTypePersonal, PersonalSlotCursor);
auto inst = Get(cursor);
if(inst) {
return false;
}
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
return false;
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top);
inst = Get(slot);
if(inst) {
impl_->data_model_->Begin();
bool v = _destroy(slot);
impl_->data_model_->Delete(slot);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
v = Put(cursor, inst);
impl_->data_model_->Insert(cursor, inst);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
impl_->data_model_->Commit();
return true;
}
return false;
}
EQEmu::InventorySlot EQEmu::Inventory::FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
bool for_bag = inst->GetItem()->ItemClass == ItemClassContainer;
int min_size = inst->GetItem()->Size;
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
//check upper level inventory
for(int i = slot_id_start; i <= slot_id_end; ++i) {
EQEmu::InventorySlot slot(container_id, i);
if(!Get(slot)) {
return slot;
}
}
//if not for a bag then check inside bags
if (!for_bag) {
for(int i = slot_id_start; i <= slot_id_end; ++i) {
EQEmu::InventorySlot slot(container_id, i);
auto inst = Get(slot);
if(inst && inst->GetBaseItem()->ItemClass == ItemClassContainer && inst->GetBaseItem()->BagSize >= min_size)
{
if(inst->GetBaseItem()->BagType == BagTypeQuiver && !is_arrow)
{
continue;
}
int slots = inst->GetBaseItem()->BagSlots;
for(int b_i = 0; b_i < slots; ++b_i) {
EQEmu::InventorySlot bag_slot(container_id, i, b_i);
if(!Get(bag_slot)) {
return bag_slot;
}
}
}
}
}
return EQEmu::InventorySlot();
}
int EQEmu::Inventory::FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
if(!inst->IsStackable()) {
return 0;
}
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
int item_id = inst->GetItem()->ID;
int charges_to_check = inst->GetCharges();
int charges = 0;
auto iter = impl_->containers_.find(container_id);
if(iter == impl_->containers_.end()) {
return 0;
}
auto &container = iter->second;
for(int i = slot_id_start; i <= slot_id_end; ++i) {
auto current = container.Get(i);
if(!current) {
continue;
}
if(current->GetItem()->ID == item_id) {
int free_charges = current->GetItem()->StackSize - current->GetCharges();
if(free_charges)
charges += free_charges;
if(charges >= charges_to_check) {
return charges_to_check;
}
} else if(current->GetItem()->ItemClass == ItemClassContainer) {
int sz = current->GetItem()->BagSlots;
for(int i = 0; i < sz; ++i) {
auto sub_item = current->Get(i);
if(!sub_item) {
continue;
}
if(sub_item->GetItem()->ID == item_id) {
int free_charges = sub_item->GetItem()->StackSize - sub_item->GetCharges();
if(free_charges)
charges += free_charges;
if(charges >= charges_to_check) {
return charges_to_check;
}
}
}
}
}
if(charges >= charges_to_check) {
return charges_to_check;
}
return charges;
}
void EQEmu::Inventory::UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst) {
impl_->data_model_->Begin();
impl_->data_model_->Delete(slot);
if(inst) {
impl_->data_model_->Insert(slot, inst);
}
impl_->data_model_->Commit();
}
int EQEmu::Inventory::CalcMaterialFromSlot(const InventorySlot &slot) {
if(slot.Type() != 0)
return _MaterialInvalid;
switch(slot.Slot()) {
case PersonalSlotHead:
return MaterialHead;
case PersonalSlotChest:
return MaterialChest;
case PersonalSlotArms:
return MaterialArms;
case PersonalSlotWrist1:
return MaterialWrist;
case PersonalSlotHands:
return MaterialHands;
case PersonalSlotLegs:
return MaterialLegs;
case PersonalSlotFeet:
return MaterialFeet;
case PersonalSlotPrimary:
return MaterialPrimary;
case PersonalSlotSecondary:
return MaterialSecondary;
default:
return _MaterialInvalid;
}
}
EQEmu::InventorySlot EQEmu::Inventory::CalcSlotFromMaterial(int material) {
switch(material)
{
case MaterialHead:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHead);
case MaterialChest:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotChest);
case MaterialArms:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotArms);
case MaterialWrist:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotWrist1);
case MaterialHands:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHands);
case MaterialLegs:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotLegs);
case MaterialFeet:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotFeet);
case MaterialPrimary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotPrimary);
case MaterialSecondary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotSecondary);
default:
return EQEmu::InventorySlot(-1, -1);
}
}
bool EQEmu::Inventory::CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot) {
if(!inst) {
return false;
}
if(slot.Type() != 0) {
return false;
}
if(!EQEmu::ValueWithin(slot.Slot(), EQEmu::PersonalSlotCharm, EQEmu::PersonalSlotAmmo)) {
return false;
}
auto item = inst->GetItem();
//check slot
int use_slot = -1;
if(slot.Slot() == EQEmu::PersonalSlotPowerSource) {
use_slot = EQEmu::PersonalSlotAmmo;
}
else if(slot.Slot() == EQEmu::PersonalSlotAmmo) {
use_slot = EQEmu::PersonalSlotPowerSource;
}
else {
use_slot = slot.Slot();
}
if(!(item->Slots & (1 << use_slot))) {
return false;
}
//todo: check deity
if(!item->IsEquipable(impl_->race_, impl_->class_)) {
return false;
}
//Checking augments
auto iter = inst->GetContainer()->Begin();
auto end = inst->GetContainer()->End();
while(iter != end) {
EQEmu::ItemInstance::pointer itm = iter->second;
if(!CanEquip(itm, InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first))) {
return false;
}
++iter;
}
return true;
}
bool EQEmu::Inventory::CheckLoreConflict(const ItemData *item) {
if(!item)
return false;
if(!item->LoreFlag)
return false;
if(item->LoreGroup == 0)
return false;
if(item->LoreGroup == 0xFFFFFFFF) {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItem(item->ID)) {
return true;
}
}
}
else {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItemByLoreGroup(item->LoreGroup)) {
return true;
}
}
}
return false;
}
bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
buf.SetWritePosition(0);
buf.SetReadPosition(0);
buf.Resize(0);
buf.Write<int32>(105);
bool value = false;
for(auto &iter : impl_->containers_) {
bool v = iter.second.Serialize(buf, iter.first);
if(v && !value) {
value = true;
}
}
return value;
}
void EQEmu::Inventory::Interrogate() {
printf("Inventory:\n");
printf("Class: %u, Race: %u, Deity: %u\n", impl_->class_, impl_->race_, impl_->deity_);
for(auto &iter : impl_->containers_) {
printf("Container: %u\n", iter.first);
iter.second.Interrogate(1);
}
printf("\n");
}
bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) {
auto src_i = Get(src);
auto dest_i = Get(dest);
if(src_i) {
if(!_destroy(src)) {
return false;
}
}
if(dest_i) {
if(!_destroy(dest)) {
return false;
}
impl_->data_model_->Insert(src, dest_i);
if(!Put(src, dest_i)) {
return false;
}
}
if(src_i) {
impl_->data_model_->Insert(dest, src_i);
if(!Put(dest, src_i)) {
return false;
}
}
return true;
}
bool EQEmu::Inventory::_destroy(const InventorySlot &slot) {
bool v = Put(slot, EQEmu::ItemInstance::pointer(nullptr));
impl_->data_model_->Delete(slot);
return v;
}
-165
View File
@@ -1,165 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_INVENTORY_H
#define COMMON_INVENTORY_H
#include "item_container.h"
#include <string>
namespace EQEmu
{
enum InventoryType : int
{
InvTypePersonal = 0,
InvTypeBank,
InvTypeSharedBank,
InvTypeTrade,
InvTypeWorld,
InvTypeCursorBuffer,
InvTypeTribute,
InvTypeTrophyTribute,
InvTypeGuildTribute,
InvTypeMerchant
};
enum PersonaInventorySlot : int
{
PersonalSlotCharm = 0,
PersonalSlotEar1,
PersonalSlotHead,
PersonalSlotFace,
PersonalSlotEar2,
PersonalSlotNeck,
PersonalSlotShoulders,
PersonalSlotArms,
PersonalSlotBack,
PersonalSlotWrist1,
PersonalSlotWrist2,
PersonalSlotRange,
PersonalSlotHands,
PersonalSlotPrimary,
PersonalSlotSecondary,
PersonalSlotFinger1,
PersonalSlotFinger2,
PersonalSlotChest,
PersonalSlotLegs,
PersonalSlotFeet,
PersonalSlotWaist,
PersonalSlotPowerSource,
PersonalSlotAmmo,
PersonalSlotGeneral1,
PersonalSlotGeneral2,
PersonalSlotGeneral3,
PersonalSlotGeneral4,
PersonalSlotGeneral5,
PersonalSlotGeneral6,
PersonalSlotGeneral7,
PersonalSlotGeneral8,
PersonalSlotGeneral9,
PersonalSlotGeneral10,
PersonalSlotCursor
};
class InventorySlot
{
public:
InventorySlot() : type_(-1), slot_(-1), bag_index_(-1), aug_index_(-1) { }
InventorySlot(int type, int slot)
: type_(type), slot_(slot), bag_index_(-1), aug_index_(-1) { }
InventorySlot(int type, int slot, int bag_index)
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(-1) { }
InventorySlot(int type, int slot, int bag_index, int aug_index)
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(aug_index) { }
bool IsValid() const;
bool IsDelete() const;
bool IsBank() const;
bool IsCursor() const;
bool IsEquipment() const;
bool IsGeneral() const;
bool IsWeapon() const;
bool IsTrade() const;
const std::string ToString() const;
inline int Type() { return type_; }
inline int Type() const { return type_; }
inline int Slot() { return slot_; }
inline int Slot() const { return slot_; }
inline int BagIndex() { return bag_index_; }
inline int BagIndex() const { return bag_index_; }
inline int AugIndex() { return aug_index_; }
inline int AugIndex() const { return aug_index_; }
private:
int type_;
int slot_;
int bag_index_;
int aug_index_;
};
inline bool operator==(const InventorySlot &lhs, const InventorySlot &rhs) {
return lhs.Type() == rhs.Type() &&
lhs.Slot() == rhs.Slot() &&
lhs.BagIndex() == rhs.BagIndex() &&
lhs.AugIndex() == rhs.AugIndex(); }
inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); }
class InventoryDataModel;
class Inventory
{
public:
Inventory(int race, int class_, int deity);
~Inventory();
void SetRace(int race);
void SetClass(int class_);
void SetDeity(int deity);
void SetDataModel(InventoryDataModel *dm);
ItemInstance::pointer Get(const InventorySlot &slot);
bool Put(const InventorySlot &slot, ItemInstance::pointer &inst);
bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges);
bool Summon(const InventorySlot &slot, ItemInstance::pointer &inst);
bool PushToCursorBuffer(ItemInstance::pointer &inst);
bool PopFromCursorBuffer();
InventorySlot FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
int FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
void UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst);
//utility
static int CalcMaterialFromSlot(const InventorySlot &slot);
static InventorySlot CalcSlotFromMaterial(int material);
bool CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot);
bool CheckLoreConflict(const ItemData *item);
bool Serialize(MemoryBuffer &buf);
//testing
void Interrogate();
private:
bool _swap(const InventorySlot &src, const InventorySlot &dest);
bool _destroy(const InventorySlot &slot);
struct impl;
impl *impl_;
};
} // EQEmu
#endif
-212
View File
@@ -1,212 +0,0 @@
#include "inventory_db_data_model.h"
#include "shareddb.h"
#include "string_util.h"
#include <list>
#include <string>
enum DataEventTypes
{
DB_Insert,
DB_Delete
};
struct DataEvent
{
DataEventTypes evt;
EQEmu::InventorySlot slot;
EQEmu::ItemInstance::pointer inst;
};
struct EQEmu::InventoryDatabaseDataModel::impl {
SharedDatabase *db_;
std::list<DataEvent> events_;
uint32 char_id_;
};
EQEmu::InventoryDatabaseDataModel::InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id) {
impl_ = new impl;
impl_->db_ = db;
impl_->char_id_ = char_id;
}
EQEmu::InventoryDatabaseDataModel::~InventoryDatabaseDataModel() {
delete impl_;
}
void EQEmu::InventoryDatabaseDataModel::Begin() {
impl_->db_->TransactionBegin();
impl_->events_.clear();
}
bool EQEmu::InventoryDatabaseDataModel::Commit() {
std::string base_insert = "INSERT INTO character_inventory(id, type, slot, bag_index, aug_index, "
"item_id, charges, color, attuned, custom_data, ornament_icon, ornament_idfile, ornament_hero_model"
", tracking_id) VALUES";
std::string current_insert = base_insert;
bool insert = false;
for(auto iter : impl_->events_) {
if(iter.evt == DB_Delete) {
if(insert) {
insert = false;
//commit the current_insert
auto res = impl_->db_->QueryDatabase(current_insert);
if(!res.Success()) {
Rollback();
return false;
}
current_insert = base_insert;
}
std::string current_delete;
if(iter.slot.BagIndex() > -1) {
if(iter.slot.AugIndex() > -1) {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u AND aug_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex(), iter.slot.AugIndex());
}
else {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex());
}
}
else if(iter.slot.AugIndex() > -1) {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND aug_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.AugIndex());
}
else {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot());
}
auto res = impl_->db_->QueryDatabase(current_delete);
if(!res.Success()) {
Rollback();
return false;
}
} else {
//insert
if(!insert) {
insert = true;
} else {
current_insert += ",";
}
current_insert += StringFormat("(%u, %i, %i, %i, %i, %u, %i, %u, %u, '%s', %u, %u, %u, %llu)",
impl_->char_id_,
iter.slot.Type(),
iter.slot.Slot(),
iter.slot.BagIndex(),
iter.slot.AugIndex(),
iter.inst->GetBaseItem()->ID,
iter.inst->GetCharges(),
iter.inst->GetColor(),
iter.inst->GetAttuned(),
EscapeString(iter.inst->GetCustomData()).c_str(),
iter.inst->GetOrnamentIcon(),
iter.inst->GetOrnamentIDFile(),
iter.inst->GetOrnamentHeroModel(),
iter.inst->GetTrackingID());
}
}
if(insert) {
insert = false;
//commit the current_insert
auto res = impl_->db_->QueryDatabase(current_insert);
if(!res.Success()) {
Rollback();
return false;
}
current_insert = base_insert;
}
impl_->db_->TransactionCommit();
impl_->events_.clear();
return true;
}
void EQEmu::InventoryDatabaseDataModel::Rollback() {
impl_->db_->TransactionRollback();
impl_->events_.clear();
}
void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, ItemInstance::pointer &inst) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = inst;
evt.slot = slot;
impl_->events_.push_back(evt);
//insert current item
if(slot.BagIndex() < 0 && slot.AugIndex() < 0) {
//if bag put all bag contents in
//if common put all augment contents in
if(inst->GetBaseItem()->ItemClass == ItemClassContainer) {
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, -1);
impl_->events_.push_back(evt);
//do augments here
if(evt.inst->GetBaseItem()->ItemClass == ItemClassCommon) {
auto inst_container = evt.inst->GetContainer();
auto inst_iter = inst_container->Begin();
while(inst_iter != inst_container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = inst_iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, inst_iter->first);
impl_->events_.push_back(evt);
++inst_iter;
}
}
++iter;
}
}
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
}
else if(slot.AugIndex() < 0 && inst->GetBaseItem()->ItemClass == ItemClassCommon) {
//bag item that can have augs
//if common put all augment contents in
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
}
void EQEmu::InventoryDatabaseDataModel::Delete(const InventorySlot &slot) {
DataEvent evt;
evt.evt = DB_Delete;
evt.slot = slot;
impl_->events_.push_back(evt);
}
+820 -102
View File
File diff suppressed because it is too large Load Diff
+68 -15
View File
@@ -27,8 +27,9 @@ class ItemParse; // Parses item packets
class EvolveInfo; // Stores information about an evolving item family
#include "../common/eq_constants.h"
#include "../common/item_data.h"
#include "../common/item_struct.h"
#include "../common/timer.h"
#include "../common/bodytypes.h"
#include <list>
#include <map>
@@ -104,9 +105,9 @@ protected:
};
// ########################################
// Class: InventoryOld
// Class: Inventory
// Character inventory
class InventoryOld
class Inventory
{
friend class ItemInst;
public:
@@ -114,8 +115,8 @@ public:
// Public Methods
///////////////////////////////
InventoryOld() { m_version = ClientVersion::Unknown; m_versionset = false; }
~InventoryOld();
Inventory() { m_version = ClientVersion::Unknown; m_versionset = false; }
~Inventory();
// Inventory v2 creep
bool SetInventoryVersion(ClientVersion version) {
@@ -168,7 +169,7 @@ public:
ItemInst* PopItem(int16 slot_id);
// Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
bool HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity);
// Check whether item exists in inventory
// where argument specifies OR'd list of invWhere constants to look
@@ -193,7 +194,7 @@ public:
static int16 CalcSlotFromMaterial(uint8 material);
static uint8 CalcMaterialFromSlot(int16 equipslot);
static bool CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container);
static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container);
// Test for valid inventory casting slot
bool SupportsClickCasting(int16 slot_id);
@@ -270,7 +271,7 @@ public:
/////////////////////////
// Constructors/Destructor
ItemInst(const ItemData* item = nullptr, int16 charges = 0);
ItemInst(const Item_Struct* item = nullptr, int16 charges = 0);
ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0);
@@ -331,7 +332,7 @@ public:
bool IsAugmented();
ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const;
bool UpdateOrnamentationInfo();
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false);
// Has attack/delay?
bool IsWeapon() const;
@@ -340,8 +341,8 @@ public:
// Accessors
const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); }
const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); }
const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const;
const Item_Struct* GetItem() const;
const Item_Struct* GetUnscaledItem() const;
int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; }
@@ -376,7 +377,7 @@ public:
// Allows treatment of this object as though it were a pointer to m_item
operator bool() const { return (m_item != nullptr); }
// Compare inner ItemData of two ItemInst objects
// Compare inner Item_Struct of two ItemInst objects
bool operator==(const ItemInst& right) const { return (this->m_item == right.m_item); }
bool operator!=(const ItemInst& right) const { return (this->m_item != right.m_item); }
@@ -418,6 +419,58 @@ public:
void StopTimer(std::string name);
void ClearTimers();
// Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
// and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance
// by default these do not recurse into augs
int GetItemArmorClass(bool augments = false) const;
int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const;
// These two differ in the fact that they're quick checks (they are checked BEFORE the one above
int GetItemElementalFlag(bool augments = false) const;
int GetItemElementalDamage(bool augments = false) const;
int GetItemRecommendedLevel(bool augments = false) const;
int GetItemRequiredLevel(bool augments = false) const;
int GetItemWeaponDamage(bool augments = false) const;
int GetItemBackstabDamage(bool augments = false) const;
// these two are just quick checks
int GetItemBaneDamageBody(bool augments = false) const;
int GetItemBaneDamageRace(bool augments = false) const;
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
int GetItemMagical(bool augments = false) const;
int GetItemHP(bool augments = false) const;
int GetItemMana(bool augments = false) const;
int GetItemEndur(bool augments = false) const;
int GetItemAttack(bool augments = false) const;
int GetItemStr(bool augments = false) const;
int GetItemSta(bool augments = false) const;
int GetItemDex(bool augments = false) const;
int GetItemAgi(bool augments = false) const;
int GetItemInt(bool augments = false) const;
int GetItemWis(bool augments = false) const;
int GetItemCha(bool augments = false) const;
int GetItemMR(bool augments = false) const;
int GetItemFR(bool augments = false) const;
int GetItemCR(bool augments = false) const;
int GetItemPR(bool augments = false) const;
int GetItemDR(bool augments = false) const;
int GetItemCorrup(bool augments = false) const;
int GetItemHeroicStr(bool augments = false) const;
int GetItemHeroicSta(bool augments = false) const;
int GetItemHeroicDex(bool augments = false) const;
int GetItemHeroicAgi(bool augments = false) const;
int GetItemHeroicInt(bool augments = false) const;
int GetItemHeroicWis(bool augments = false) const;
int GetItemHeroicCha(bool augments = false) const;
int GetItemHeroicMR(bool augments = false) const;
int GetItemHeroicFR(bool augments = false) const;
int GetItemHeroicCR(bool augments = false) const;
int GetItemHeroicPR(bool augments = false) const;
int GetItemHeroicDR(bool augments = false) const;
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
protected:
//////////////////////////
// Protected Members
@@ -425,13 +478,13 @@ protected:
std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
friend class InventoryOld;
friend class Inventory;
void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; }
ItemInstTypes m_use_type; // Usage type for item
const ItemData* m_item; // Ptr to item data
const Item_Struct* m_item; // Ptr to item data
int16 m_charges; // # of charges for chargeable items
uint32 m_price; // Bazaar /trader price
uint32 m_color;
@@ -443,7 +496,7 @@ protected:
uint32 m_exp;
int8 m_evolveLvl;
bool m_activated;
ItemData* m_scaledItem;
Item_Struct* m_scaledItem;
EvolveInfo* m_evolveInfo;
bool m_scaling;
uint32 m_ornamenticon;
-135
View File
@@ -1,135 +0,0 @@
#include "item_container.h"
#include "item_container_default_serialization.h"
#include <utility>
struct EQEmu::ItemContainer::impl
{
std::map<int, ItemInstance::pointer> items_;
ItemContainerSerializationStrategy *serialize_strat_;
};
EQEmu::ItemContainer::ItemContainer()
{
impl_ = new impl();
impl_->serialize_strat_ = new ItemContainerDefaultSerialization();
}
EQEmu::ItemContainer::ItemContainer(ItemContainerSerializationStrategy *strategy) {
impl_ = new impl();
impl_->serialize_strat_ = strategy;
}
EQEmu::ItemContainer::~ItemContainer()
{
if(impl_) {
delete impl_->serialize_strat_;
delete impl_;
}
}
EQEmu::ItemContainer::ItemContainer(ItemContainer &&other) {
impl_ = other.impl_;
other.impl_ = nullptr;
}
EQEmu::ItemContainer& EQEmu::ItemContainer::operator=(ItemContainer &&other) {
if(this == &other)
return *this;
impl_ = other.impl_;
other.impl_ = nullptr;
return *this;
}
EQEmu::ItemInstance::pointer EQEmu::ItemContainer::Get(const int slot_id) {
auto iter = impl_->items_.find(slot_id);
if(iter != impl_->items_.end()) {
return iter->second;
}
return EQEmu::ItemInstance::pointer(nullptr);
}
bool EQEmu::ItemContainer::Put(const int slot_id, ItemInstance::pointer &inst) {
if(!inst) {
impl_->items_.erase(slot_id);
return true;
} else {
auto iter = impl_->items_.find(slot_id);
if(iter == impl_->items_.end()) {
impl_->items_[slot_id] = inst;
return true;
}
}
return false;
}
bool EQEmu::ItemContainer::HasItem(uint32 item_id) {
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->ID == item_id) {
return true;
}
}
return false;
}
bool EQEmu::ItemContainer::HasItemByLoreGroup(uint32 loregroup) {
if(loregroup == 0xFFFFFFFF)
return false;
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->LoreGroup == loregroup) {
return true;
}
}
return false;
}
uint32 EQEmu::ItemContainer::Size() {
return (uint32)impl_->items_.size();
}
uint32 EQEmu::ItemContainer::Size() const {
return (uint32)impl_->items_.size();
}
bool EQEmu::ItemContainer::Delete(const int slot_id) {
auto iter = impl_->items_.find(slot_id);
if(iter == impl_->items_.end()) {
return false;
} else {
impl_->items_.erase(iter);
return true;
}
}
bool EQEmu::ItemContainer::Serialize(MemoryBuffer &buf, int container_number) {
if(impl_->serialize_strat_) {
return impl_->serialize_strat_->Serialize(buf, container_number, impl_->items_);
}
return false;
}
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::Begin() {
return impl_->items_.begin();
}
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() {
return impl_->items_.end();
}
void EQEmu::ItemContainer::Interrogate(int level) {
char buffer[16] = { 0 };
for(int i = 0; i < level; ++i) {
buffer[i] = '\t';
}
for(auto &iter : impl_->items_) {
printf("%s%u: (%u)%s (%u)\n", buffer, iter.first, iter.second->GetBaseItem()->ID, iter.second->GetBaseItem()->Name, iter.second->GetCharges());
iter.second->Interrogate(level + 1);
}
}
-70
View File
@@ -1,70 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_ITEM_CONTAINER_H
#define COMMON_ITEM_CONTAINER_H
#include "item_instance.h"
#include "item_container_serialization_strategy.h"
#include "memory_buffer.h"
#include <memory>
#include <map>
namespace EQEmu
{
class ItemContainerSerializationStrategy;
class ItemContainer
{
public:
typedef std::map<int, ItemInstance::pointer>::const_iterator ItemContainerIter;
ItemContainer();
ItemContainer(ItemContainerSerializationStrategy *strategy);
~ItemContainer();
ItemContainer(ItemContainer &&other);
ItemContainer& operator=(ItemContainer &&other);
ItemInstance::pointer Get(const int slot_id);
bool Put(const int slot_id, ItemInstance::pointer &inst);
bool Delete(const int slot_id);
//Utility
bool HasItem(uint32 item_id);
bool HasItemByLoreGroup(uint32 loregroup);
uint32 Size();
uint32 Size() const;
//Low level interface for encode/decode
bool Serialize(MemoryBuffer &buf, int container_number);
ItemContainerIter Begin();
ItemContainerIter End();
//testing
void Interrogate(int level);
protected:
struct impl;
impl *impl_;
private:
ItemContainer(const ItemContainer &other);
ItemContainer& operator=(const ItemContainer &other);
};
} // EQEmu
#endif
@@ -1,19 +0,0 @@
#include "item_container_default_serialization.h"
bool EQEmu::ItemContainerDefaultSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
if(items.size() == 0) {
return false;
}
bool ret = false;
for(auto &iter : items) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
return ret;
}
@@ -1,35 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
#define COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
#include "item_container_serialization_strategy.h"
namespace EQEmu
{
class ItemContainerDefaultSerialization : public ItemContainerSerializationStrategy
{
public:
ItemContainerDefaultSerialization() { }
virtual ~ItemContainerDefaultSerialization() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
};
} // EQEmu
#endif
@@ -1,21 +0,0 @@
#include "item_container_personal_serialization.h"
bool EQEmu::ItemContainerPersonalSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
if(items.size() == 0) {
return false;
}
bool ret = false;
for(auto &iter : items) {
if(iter.first < 33) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
}
return ret;
}
@@ -1,35 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
#define COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
#include "item_container_serialization_strategy.h"
namespace EQEmu
{
class ItemContainerPersonalSerialization : public ItemContainerSerializationStrategy
{
public:
ItemContainerPersonalSerialization() { }
virtual ~ItemContainerPersonalSerialization() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
};
} // EQEmu
#endif
@@ -1,37 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
#define COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
#include "item_container.h"
#include "memory_buffer.h"
#include <map>
namespace EQEmu
{
class ItemContainerSerializationStrategy
{
public:
ItemContainerSerializationStrategy() { }
virtual ~ItemContainerSerializationStrategy() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) = 0;
};
} // EQEmu
#endif
+4
View File
@@ -41,6 +41,7 @@ F(ac)
F(deity)
F(skillmodvalue)
F(UNK033)
F(skillmodmax)
F(skillmodtype)
F(banedmgrace)
F(banedmgamt)
@@ -172,7 +173,10 @@ F(bardlevel)
F(questitemflag)
F(svcorruption)
F(purity)
F(evoitem)
F(evoid)
F(evolvinglevel)
F(evomax)
F(backstabdmg)
F(dsmitigation)
F(heroic_str)
-389
View File
@@ -1,389 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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
*/
#include "item_instance.h"
#include "data_verification.h"
#include "item_container.h"
uint32 ItemInstanceSerial = 1;
uint32 EQEmu::GetNextItemInstanceSerial() {
ItemInstanceSerial++;
return ItemInstanceSerial;
}
struct EQEmu::ItemInstance::impl {
const ItemData *base_item_;
ItemData *modified_item_;
int16 charges_;
uint32 color_;
bool attuned_;
std::string custom_data_;
uint32 ornament_idfile_;
uint32 ornament_icon_;
uint32 ornament_hero_model_;
char tracking_id_[17];
uint32 serial_id_;
uint32 recast_timestamp_;
uint32 merchant_slot_;
uint32 merchant_count_;
uint32 price_;
ItemContainer contents_;
};
EQEmu::ItemInstance::ItemInstance(const ItemData* idata) {
impl_ = new impl;
impl_->base_item_ = idata;
impl_->modified_item_ = nullptr;
impl_->charges_ = -1;
impl_->color_ = 0;
impl_->attuned_ = false;
impl_->ornament_idfile_ = 0;
impl_->ornament_icon_ = 0;
impl_->ornament_hero_model_ = 0;
impl_->serial_id_ = 0;
impl_->recast_timestamp_ = 0;
impl_->merchant_slot_ = 0;
impl_->merchant_count_ = 0;
impl_->price_ = 0;
memset(impl_->tracking_id_, 0, 17);
}
EQEmu::ItemInstance::ItemInstance(const ItemData* idata, int16 charges) {
impl_ = new impl;
impl_->base_item_ = idata;
impl_->modified_item_ = nullptr;
impl_->charges_ = charges;
impl_->color_ = 0;
impl_->attuned_ = false;
impl_->ornament_idfile_ = 0;
impl_->ornament_icon_ = 0;
impl_->ornament_hero_model_ = 0;
impl_->recast_timestamp_ = 0;
impl_->serial_id_ = 0;
impl_->merchant_slot_ = 0;
impl_->merchant_count_ = 0;
impl_->price_ = 0;
memset(impl_->tracking_id_, 0, 17);
}
EQEmu::ItemInstance::~ItemInstance() {
delete impl_;
}
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Split(int charges) {
if(!IsStackable()) {
//Can't split non stackable items!
return pointer(nullptr);
}
if(charges >= GetCharges()) {
return pointer(nullptr);
}
if(impl_->contents_.Size() > 0) {
return pointer(nullptr);
}
pointer split = pointer(new EQEmu::ItemInstance(impl_->base_item_, charges));
split->SetSerialNumber(EQEmu::GetNextItemInstanceSerial());
//Set Tracking here
split->impl_->attuned_ = impl_->attuned_;
split->impl_->custom_data_ = impl_->custom_data_;
split->impl_->recast_timestamp_ = impl_->recast_timestamp_;
split->impl_->price_ = impl_->price_;
split->impl_->color_ = impl_->color_;
split->impl_->merchant_count_ = impl_->merchant_count_;
split->impl_->merchant_slot_ = impl_->merchant_slot_;
split->impl_->ornament_hero_model_ = impl_->ornament_hero_model_;
split->impl_->ornament_icon_ = impl_->ornament_icon_;
split->impl_->ornament_idfile_ = impl_->ornament_idfile_;
SetCharges(GetCharges() - charges);
return split;
}
const ItemData *EQEmu::ItemInstance::GetItem() {
return impl_->modified_item_ ? impl_->modified_item_ : impl_->base_item_;
}
const ItemData *EQEmu::ItemInstance::GetBaseItem() {
return impl_->base_item_;
}
const ItemData *EQEmu::ItemInstance::GetBaseItem() const {
return impl_->base_item_;
}
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Get(const int index) {
if(EQEmu::ValueWithin(index, 0, 255)) {
return impl_->contents_.Get(index);
}
return pointer(nullptr);
}
bool EQEmu::ItemInstance::Put(const int index, pointer &inst) {
if(!impl_->base_item_) {
return false;
}
auto item = impl_->base_item_;
if(item->ItemClass == ItemClassContainer) { // Bag
if(!EQEmu::ValueWithin(index, 0, item->BagSlots)) {
return false;
}
return impl_->contents_.Put(index, inst);
}
else if(item->ItemClass == ItemClassCommon) { // Augment
if(!EQEmu::ValueWithin(index, 0, EmuConstants::ITEM_COMMON_SIZE)) {
return false;
}
if(!item->AugSlotVisible[index]) {
return false;
}
if(inst) {
auto *aug_item = inst->GetItem();
int aug_type = aug_item->AugType;
if(aug_type == -1 || (1 << (item->AugSlotType[index] - 1)) & aug_type) {
return impl_->contents_.Put(index, inst);
}
} else {
return impl_->contents_.Put(index, inst);
}
return false;
}
return false;
}
int16 EQEmu::ItemInstance::GetCharges() {
return impl_->charges_;
}
int16 EQEmu::ItemInstance::GetCharges() const {
return impl_->charges_;
}
void EQEmu::ItemInstance::SetCharges(const int16 charges) {
impl_->charges_ = charges;
}
uint32 EQEmu::ItemInstance::GetColor() {
return impl_->color_;
}
uint32 EQEmu::ItemInstance::GetColor() const {
return impl_->color_;
}
void EQEmu::ItemInstance::SetColor(const uint32 color) {
impl_->color_ = color;
}
bool EQEmu::ItemInstance::GetAttuned() {
return impl_->attuned_;
}
bool EQEmu::ItemInstance::GetAttuned() const {
return impl_->attuned_;
}
void EQEmu::ItemInstance::SetAttuned(const bool attuned) {
impl_->attuned_ = attuned;
}
std::string EQEmu::ItemInstance::GetCustomData() {
return impl_->custom_data_;
}
std::string EQEmu::ItemInstance::GetCustomData() const {
return impl_->custom_data_;
}
void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) {
//We need to actually set the custom data stuff based on this string
impl_->custom_data_ = custom_data;
}
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() {
return impl_->ornament_idfile_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() const {
return impl_->ornament_idfile_;
}
void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) {
impl_->ornament_idfile_ = ornament_idfile;
}
uint32 EQEmu::ItemInstance::GetOrnamentIcon() {
return impl_->ornament_icon_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIcon() const {
return impl_->ornament_icon_;
}
void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) {
impl_->ornament_icon_ = ornament_icon;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() {
return impl_->ornament_hero_model_;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() const {
return impl_->ornament_hero_model_;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) const {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) {
impl_->ornament_hero_model_ = ornament_hero_model;
}
const char* EQEmu::ItemInstance::GetTrackingID() {
return impl_->tracking_id_;
}
const char* EQEmu::ItemInstance::GetTrackingID() const {
return impl_->tracking_id_;
}
void EQEmu::ItemInstance::SetTrackingID(const char *tracking_id) {
size_t len = strlen(tracking_id);
if(len > 16) {
return;
}
strncpy(impl_->tracking_id_, tracking_id, 16);
}
uint32 EQEmu::ItemInstance::GetRecastTimestamp() {
return impl_->recast_timestamp_;
}
uint32 EQEmu::ItemInstance::GetRecastTimestamp() const {
return impl_->recast_timestamp_;
}
void EQEmu::ItemInstance::SetRecastTimestamp(const uint32 recast_timestamp) {
impl_->recast_timestamp_ = recast_timestamp;
}
uint32 EQEmu::ItemInstance::GetMerchantSlot() {
return impl_->merchant_slot_;
}
uint32 EQEmu::ItemInstance::GetMerchantSlot() const {
return impl_->merchant_slot_;
}
void EQEmu::ItemInstance::SetMerchantSlot(uint32 slot) {
impl_->merchant_slot_ = slot;
}
uint32 EQEmu::ItemInstance::GetMerchantCount() {
return impl_->merchant_count_;
}
uint32 EQEmu::ItemInstance::GetMerchantCount() const {
return impl_->merchant_count_;
}
void EQEmu::ItemInstance::SetMerchantCount(const uint32 cnt) {
impl_->merchant_count_ = cnt;
}
uint32 EQEmu::ItemInstance::GetPrice() {
return impl_->price_;
}
uint32 EQEmu::ItemInstance::GetPrice() const {
return impl_->price_;
}
void EQEmu::ItemInstance::SetPrice(const uint32 p) {
impl_->price_ = p;
}
uint32 EQEmu::ItemInstance::GetSerialNumber() {
return impl_->serial_id_;
}
uint32 EQEmu::ItemInstance::GetSerialNumber() const {
return impl_->serial_id_;
}
void EQEmu::ItemInstance::SetSerialNumber(const uint32 sn) {
impl_->serial_id_ = sn;
}
bool EQEmu::ItemInstance::IsStackable() {
return impl_->base_item_->Stackable;
}
bool EQEmu::ItemInstance::IsStackable() const {
return impl_->base_item_->Stackable;
}
bool EQEmu::ItemInstance::IsNoDrop() {
return GetAttuned() || GetBaseItem()->NoDrop == 0;
}
bool EQEmu::ItemInstance::IsNoDrop() const {
return GetAttuned() || GetBaseItem()->NoDrop == 0;
}
EQEmu::ItemContainer *EQEmu::ItemInstance::GetContainer() {
return &(impl_->contents_);
}
void EQEmu::ItemInstance::Interrogate(int level) {
impl_->contents_.Interrogate(level);
}
-126
View File
@@ -1,126 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_ITEM_INSTANCE_H
#define COMMON_ITEM_INSTANCE_H
#include "item_data.h"
#include <memory>
namespace EQEmu
{
uint32 GetNextItemInstanceSerial();
class ItemContainer;
class ItemInstance
{
public:
typedef std::shared_ptr<ItemInstance> pointer;
ItemInstance(const ItemData* idata);
ItemInstance(const ItemData* idata, const int16 charges);
~ItemInstance();
const ItemData *GetItem();
const ItemData *GetBaseItem();
const ItemData *GetBaseItem() const;
pointer Split(int charges);
//Container
pointer Get(const int index);
bool Put(const int index, pointer &inst);
//Persistent State
int16 GetCharges();
int16 GetCharges() const;
void SetCharges(const int16 charges);
uint32 GetColor();
uint32 GetColor() const;
void SetColor(const uint32 color);
bool GetAttuned();
bool GetAttuned() const;
void SetAttuned(const bool attuned);
std::string GetCustomData();
std::string GetCustomData() const;
void SetCustomData(const std::string &custom_data);
uint32 GetOrnamentIDFile();
uint32 GetOrnamentIDFile() const;
void SetOrnamentIDFile(const uint32 ornament_idfile);
uint32 GetOrnamentIcon();
uint32 GetOrnamentIcon() const;
void SetOrnamentIcon(const uint32 ornament_icon);
uint32 GetOrnamentHeroModel();
uint32 GetOrnamentHeroModel() const;
uint32 GetOrnamentHeroModel(int material_slot);
uint32 GetOrnamentHeroModel(int material_slot) const;
void SetOrnamentHeroModel(const uint32 ornament_hero_model);
const char* GetTrackingID();
const char* GetTrackingID() const;
void SetTrackingID(const char *tracking_id);
uint32 GetRecastTimestamp();
uint32 GetRecastTimestamp() const;
void SetRecastTimestamp(const uint32 recast_timestamp);
//Merchant
uint32 GetMerchantSlot();
uint32 GetMerchantSlot() const;
void SetMerchantSlot(const uint32 slot);
uint32 GetMerchantCount();
uint32 GetMerchantCount() const;
void SetMerchantCount(const uint32 cnt);
uint32 GetPrice();
uint32 GetPrice() const;
void SetPrice(const uint32 p);
//Serial Number
uint32 GetSerialNumber();
uint32 GetSerialNumber() const;
void SetSerialNumber(uint32 sn);
//Basic Stats
bool IsStackable();
bool IsStackable() const;
bool IsNoDrop();
bool IsNoDrop() const;
void CheckStackRemaining(pointer &insert, int &charges);
//Internal state
//Used for low level operations such as encode/decode
ItemContainer *GetContainer();
void Interrogate(int level);
private:
struct impl;
impl *impl_;
};
} // EQEmu
#endif
+27 -20
View File
@@ -16,8 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#ifndef COMMON_ITEM_DATA_H
#define COMMON_ITEM_DATA_H
#ifndef ITEM_STRUCT_H
#define ITEM_STRUCT_H
/*
* Note: (Doodman)
@@ -35,7 +35,7 @@
*
* Note #3: (Doodman)
* Please take care when adding new found data fields to add them
* to the appropriate structure. ItemData has elements that are
* to the appropriate structure. Item_Struct has elements that are
* global to all types of items only.
*
* Note #4: (Doodman)
@@ -46,12 +46,12 @@
#include "eq_dictionary.h"
/*
** Child struct of ItemData:
** Child struct of Item_Struct:
** Effect data: Click, Proc, Focus, Worn, Scroll
**
*/
struct ItemEffect_Struct {
int16 Effect;
int32 Effect;
uint8 Type;
uint8 Level;
uint8 Level2;
@@ -69,18 +69,10 @@ struct InternalSerializedItem_Struct {
const void * inst;
};
struct SerializedItemInstance_Struct {
int32 container_id;
int32 slot_id;
int32 bag_id;
int32 aug_id;
void *inst;
};
// use EmuConstants::ITEM_COMMON_SIZE
//#define MAX_AUGMENT_SLOTS 5
struct ItemData {
struct Item_Struct {
bool IsEquipable(uint16 Race, uint16 Class) const;
// Non packet based fields
uint8 MinStatus;
@@ -107,10 +99,17 @@ struct ItemData {
uint32 Favor; // Individual favor
uint32 GuildFavor; // Guild favor
uint32 PointType;
//uint32 Unk117;
//uint32 Unk118;
//uint32 Unk121;
//uint32 Unk124;
uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
uint8 BagSlots; // Number of slots
uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
uint8 BagWR; // 0->100
bool BenefitFlag;
bool Tradeskills; // Is this a tradeskill item?
int8 CR; // Save vs Cold
@@ -129,7 +128,9 @@ struct ItemData {
int32 Mana; // Mana
int32 AC; // AC
uint32 Deity; // Bitmask of Deities that can equip this item
//uint32 Unk033
int32 SkillModValue; // % Mod to skill specified in SkillModType
int32 SkillModMax; // Max skill point modification
uint32 SkillModType; // Type of skill for SkillModValue to apply to
uint32 BaneDmgRace; // Bane Damage Race
int8 BaneDmgAmt; // Bane Damage Body Amount
@@ -150,11 +151,13 @@ struct ItemData {
uint32 Color; // RR GG BB 00 <-- as it appears in pc
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
uint32 Races; // Bitfield of races that can equip item (1 << race#)
//uint32 Unk054;
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
uint8 ItemType; // Item Type/Skill (itemClass* from above)
uint8 Material; // Item material type
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
float SellRate; // Sell rate
//uint32 Unk059;
union {
uint32 Fulfilment; // Food fulfilment (How long it lasts)
int16 CastTime; // Cast Time for clicky effects, in milliseconds
@@ -209,13 +212,17 @@ struct ItemData {
int16 StackSize;
uint8 PotionBeltSlots;
ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
uint8 Book; // 0=Not book, 1=Book
uint32 BookType;
char Filename[33]; // Filename for book data
// Begin SoF Fields
int32 SVCorruption;
uint32 Purity;
uint8 EvolvingItem;
uint32 EvolvingID;
uint8 EvolvingLevel;
uint8 EvolvingMax;
uint32 BackstabDmg;
uint32 DSMitigation;
int32 HeroicStr;
@@ -237,11 +244,11 @@ struct ItemData {
uint32 ScriptFileID;
uint16 ExpendableArrow;
uint32 Clairvoyance;
char ClickName[65];
char ProcName[65];
char WornName[65];
char FocusName[65];
char ScrollName[65];
char ClickName[65];
char ProcName[65];
char WornName[65];
char FocusName[65];
char ScrollName[65];
};
-212
View File
@@ -1,212 +0,0 @@
#include "memory_buffer.h"
EQEmu::MemoryBuffer::MemoryBuffer() {
buffer_ = nullptr;
size_ = 0;
capacity_ = 0;
read_pos_ = 0;
write_pos_ = 0;
}
EQEmu::MemoryBuffer::MemoryBuffer(size_t sz) {
buffer_ = nullptr;
size_ = 0;
capacity_ = 0;
read_pos_ = 0;
write_pos_ = 0;
Resize(sz);
}
EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) {
if(other.capacity_) {
buffer_ = new uchar[other.capacity_];
memcpy(buffer_, other.buffer_, other.capacity_);
} else {
buffer_ = nullptr;
}
size_ = other.size_;
capacity_ = other.capacity_;
write_pos_ = other.write_pos_;
read_pos_ = other.read_pos_;
}
EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) {
uchar *tbuf = other.buffer_;
size_t tsz = other.size_;
size_t tcapacity = other.capacity_;
size_t twrite_pos = other.write_pos_;
size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
other.read_pos_ = 0;
other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) {
if(this == &other) {
return *this;
}
if(buffer_) {
delete[] buffer_;
}
if(other.capacity_) {
buffer_ = new uchar[other.capacity_];
memcpy(buffer_, other.buffer_, other.capacity_);
}
else {
buffer_ = nullptr;
}
size_ = other.size_;
capacity_ = other.capacity_;
write_pos_ = other.write_pos_;
read_pos_ = other.read_pos_;
return *this;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) {
uchar *tbuf = other.buffer_;
size_t tsz = other.size_;
size_t tcapacity = other.capacity_;
size_t twrite_pos = other.write_pos_;
size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
other.read_pos_ = 0;
other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
return *this;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) {
if(!rhs.buffer_) {
return *this;
}
if(buffer_) {
size_t old_size = size_;
Resize(size_ + rhs.size_);
memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_);
} else {
buffer_ = new uchar[rhs.capacity_];
memcpy(buffer_, rhs.buffer_, rhs.capacity_);
size_ = rhs.size_;
capacity_ = rhs.capacity_;
}
return *this;
}
EQEmu::MemoryBuffer::~MemoryBuffer() { Clear(); }
uchar& EQEmu::MemoryBuffer::operator[](size_t pos) {
return buffer_[pos];
}
const uchar& EQEmu::MemoryBuffer::operator[](size_t pos) const {
return buffer_[pos];
}
bool EQEmu::MemoryBuffer::Empty() {
return size_ == 0;
}
bool EQEmu::MemoryBuffer::Empty() const {
return size_ == 0;
}
size_t EQEmu::MemoryBuffer::Size() {
return size_;
}
size_t EQEmu::MemoryBuffer::Size() const {
return size_;
}
size_t EQEmu::MemoryBuffer::Capacity() {
return capacity_;
}
size_t EQEmu::MemoryBuffer::Capacity() const {
return capacity_;
}
void EQEmu::MemoryBuffer::Resize(size_t sz) {
if(!buffer_) {
size_t new_size = sz + 64;
buffer_ = new uchar[new_size];
capacity_ = new_size;
size_ = sz;
memset(buffer_, 0, capacity_);
return;
}
if(sz > capacity_) {
size_t new_size = sz + 32;
uchar *temp = new uchar[new_size];
memcpy(temp, buffer_, capacity_);
delete[] buffer_;
buffer_ = temp;
capacity_ = new_size;
size_ = sz;
}
else {
size_ = sz;
}
}
void EQEmu::MemoryBuffer::Clear() {
if(buffer_) {
delete[] buffer_;
buffer_ = nullptr;
}
size_ = 0;
capacity_ = 0;
write_pos_ = 0;
read_pos_ = 0;
}
void EQEmu::MemoryBuffer::Zero() {
if(buffer_) {
memset(buffer_, 0, capacity_);
}
}
void EQEmu::MemoryBuffer::Write(const char *val, size_t len) {
size_t size_needed = write_pos_ + len;
Resize(size_needed);
memcpy(&buffer_[write_pos_], val, len);
write_pos_ += len;
}
void EQEmu::MemoryBuffer::Read(uchar *buf, size_t len) {
memcpy(buf, &buffer_[read_pos_], len);
read_pos_ += len;
}
void EQEmu::MemoryBuffer::Read(char *str) {
size_t len = strlen((const char*)&buffer_[read_pos_]);
memcpy(str, &buffer_[read_pos_], len);
read_pos_ += len;
}
-124
View File
@@ -1,124 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 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_MEMORY_BUFFER_H
#define COMMON_MEMORY_BUFFER_H
#include "types.h"
#include <type_traits>
#include <string.h>
#include <string>
namespace EQEmu
{
class MemoryBuffer
{
public:
MemoryBuffer();
MemoryBuffer(size_t sz);
MemoryBuffer(const MemoryBuffer &other);
MemoryBuffer(MemoryBuffer &&other);
MemoryBuffer& operator=(const MemoryBuffer &other);
MemoryBuffer& operator=(MemoryBuffer &&other);
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
~MemoryBuffer();
uchar& operator[](size_t pos);
const uchar& operator[](size_t pos) const;
template<typename T>
operator T*() {
return reinterpret_cast<T*>(buffer_);
}
template<typename T>
operator T*() const {
return reinterpret_cast<T*>(buffer_);
}
operator bool() { return buffer_ != nullptr; }
operator bool() const { return buffer_ != nullptr; }
bool Empty();
bool Empty() const;
size_t Size();
size_t Size() const;
size_t Capacity();
size_t Capacity() const;
void Resize(size_t sz);
void Clear();
void Zero();
template<typename T>
void Write(T val) {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T));
}
template<typename T>
T Read() {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp;
Read((uchar*)&temp, sizeof(T));
return temp;
}
void Write(const std::string &val) {
Write(val.c_str(), val.length());
Write((uint8)0);
}
void Write(const char *val) {
size_t len = strlen(val);
Write(val, len);
Write((uint8)0);
}
std::string ReadString() {
std::string ret;
size_t len = strlen((const char*)&buffer_[read_pos_]);
ret.resize(len);
memcpy(&ret[0], &buffer_[read_pos_], len);
read_pos_ += len + 1;
return ret;
}
void Write(const char *val, size_t len);
void Read(uchar *buf, size_t len);
void Read(char *str);
inline size_t GetWritePosition() { return write_pos_; }
inline void SetWritePosition(size_t wp) { write_pos_ = wp; }
inline void WriteSkipBytes(size_t skip) { write_pos_ += skip; }
inline size_t GetReadPosition() { return read_pos_; }
inline void SetReadPosition(size_t wp) { read_pos_ = wp; }
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
private:
uchar *buffer_;
size_t size_;
size_t capacity_;
size_t write_pos_;
size_t read_pos_;
};
} // EQEmu
#endif
+1
View File
@@ -146,6 +146,7 @@ INr(OP_GuildDelete); //?
IN(OP_GuildPublicNote, GuildUpdate_PublicNote);
INz(OP_GetGuildsList); //?
IN(OP_SetGuildMOTD, GuildMOTD_Struct);
IN(OP_SetRunMode, SetRunMode_Struct);
INz(OP_GuildPeace); //?
INz(OP_GuildWar); //?
IN(OP_GuildLeader, GuildMakeLeader);
+10 -10
View File
@@ -10,19 +10,19 @@
#include "rof2.h"
void RegisterAllPatches(EQStreamIdentifier &into) {
//Titanium::Register(into);
//SoF::Register(into);
//SoD::Register(into);
//UF::Register(into);
//RoF::Register(into);
Titanium::Register(into);
SoF::Register(into);
SoD::Register(into);
UF::Register(into);
RoF::Register(into);
RoF2::Register(into);
}
void ReloadAllPatches() {
//Titanium::Reload();
//SoF::Reload();
//SoD::Reload();
//UF::Reload();
//RoF::Reload();
Titanium::Reload();
SoF::Reload();
SoD::Reload();
UF::Reload();
RoF::Reload();
RoF2::Reload();
}
+313 -155
View File
@@ -435,7 +435,7 @@ namespace RoF
memset(__packet->pBuffer, 0, sz);
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(0); // PlayerID ?
__packet->WriteUInt32(emu->tic_timer);
__packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt16(emu->count);
@@ -532,72 +532,71 @@ namespace RoF
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
// in->pBuffer = new uchar[in->size];
//
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
//
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
//
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClickObjectAction)
@@ -659,9 +658,10 @@ namespace RoF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force)
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z)
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
}
@@ -1179,6 +1179,54 @@ namespace RoF
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildBank)
{
auto in = *p;
*p = nullptr;
auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger
// The first action in the enum was removed, everything 1 less
// Normally we cast them to their structs, but there are so many here! will only do when it's easier
switch (in->ReadUInt32()) {
case 10: // GuildBankAcknowledge
outapp->WriteUInt32(9);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
break;
case 5: // GuildBankDeposit (ack)
outapp->WriteUInt32(4);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
outapp->WriteUInt32(in->ReadUInt32());
break;
case 1: { // GuildBankItemUpdate
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
eq->Action = 0;
OUT(Unknown004);
eq->Unknown08 = 0;
OUT(SlotID);
OUT(Area);
OUT(Unknown012);
OUT(ItemID);
OUT(Icon);
OUT(Quantity);
OUT(Permissions);
OUT(AllowMerge);
OUT(Useable);
OUT_str(ItemName);
OUT_str(Donator);
OUT_str(WhoFor);
OUT(Unknown226);
break;
}
default:
break;
}
delete in;
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberList)
{
//consume the packet
@@ -1709,14 +1757,14 @@ namespace RoF
ENCODE(OP_MoveItem)
{
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToRoFSlot(emu->from_slot);
//eq->to_slot = ServerToRoFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -2344,13 +2392,14 @@ namespace RoF
outapp->WriteSInt32(234); // Endurance Total ?
outapp->WriteSInt32(345); // Mana Total ?
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
// these are needed to fix display bugs
outapp->WriteUInt32(0x19); // base CR
outapp->WriteUInt32(0x19); // base FR
outapp->WriteUInt32(0x19); // base MR
outapp->WriteUInt32(0xf); // base DR
outapp->WriteUInt32(0xf); // base PR
outapp->WriteUInt32(0xf); // base PhR?
outapp->WriteUInt32(0xf); // base Corrup
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
@@ -2811,7 +2860,7 @@ namespace RoF
eq->aa_spent = emu->aa_spent;
// These fields may need to be correctly populated at some point
eq->aapoints_assigned = emu->aa_spent + 1;
eq->aapoints_assigned = emu->aa_spent;
eq->aa_spent_general = 0;
eq->aa_spent_archetype = 0;
eq->aa_spent_class = 0;
@@ -2847,58 +2896,81 @@ namespace RoF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for Live
if (emu->clientver <= 7)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
eq->prereq_skill_count = 1; // min 1
OUT(prereq_skill);
eq->prereq_minpoints_count = 1; // min 1
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
eq->unknown057 = 1; // Introduced during HoT
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
std::vector<int32> skill;
std::vector<int32> points;
for(auto i = 0; i < emu->total_prereqs; ++i) {
skill.push_back(inapp->ReadUInt32());
points.push_back(inapp->ReadUInt32());
}
FINISH_ENCODE();
outapp->WriteUInt32(emu->id);
outapp->WriteUInt8(1);
outapp->WriteSInt32(emu->upper_hotkey_sid);
outapp->WriteSInt32(emu->lower_hotkey_sid);
outapp->WriteSInt32(emu->title_sid);
outapp->WriteSInt32(emu->desc_sid);
outapp->WriteSInt32(emu->level_req);
outapp->WriteSInt32(emu->cost);
outapp->WriteUInt32(emu->seq);
outapp->WriteUInt32(emu->current_level);
if(emu->total_prereqs) {
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : skill)
outapp->WriteSInt32(e);
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : points)
outapp->WriteSInt32(e);
}
else {
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
}
outapp->WriteSInt32(emu->type);
outapp->WriteSInt32(emu->spell);
outapp->WriteSInt32(1);
outapp->WriteSInt32(emu->spell_type);
outapp->WriteSInt32(emu->spell_refresh);
outapp->WriteSInt32(emu->classes);
outapp->WriteSInt32(emu->max_level);
outapp->WriteSInt32(emu->prev_id);
outapp->WriteSInt32(emu->next_id);
outapp->WriteSInt32(emu->total_cost);
outapp->WriteUInt8(0);
outapp->WriteUInt8(emu->grant_only);
outapp->WriteUInt8(0);
outapp->WriteUInt32(emu->charges);
outapp->WriteSInt32(emu->expansion);
outapp->WriteSInt32(emu->category);
outapp->WriteUInt8(0); // shroud
outapp->WriteUInt8(0); // unknown109
outapp->WriteUInt8(0); // loh
outapp->WriteUInt8(0); // unknown111
outapp->WriteUInt32(emu->total_effects);
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
for(auto i = 0; i < emu->total_effects; ++i) {
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@@ -3066,13 +3138,13 @@ namespace RoF
{
ENCODE_LENGTH_EXACT(Merchant_Sell_Struct);
SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
OUT(npcid);
OUT(playerid);
OUT(itemslot);
OUT(quantity);
OUT(price);
FINISH_ENCODE();
}
@@ -4567,6 +4639,92 @@ namespace RoF
DECODE_FORWARD(OP_GroupInvite);
}
DECODE(OP_GuildBank)
{
// all actions are 1 off due to the removal of one of enums
switch (__packet->ReadUInt32()) {
case 2: {// GuildBankPromote
DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct);
SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct);
emu->Action = 3;
IN(Unknown04);
IN(Slot);
IN(Slot2);
FINISH_DIRECT_DECODE();
return;
}
case 3: { // GuildBankViewItem
DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct);
SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct);
emu->Action = 4;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Unknown16);
FINISH_DIRECT_DECODE();
return;
}
case 4: { // GuildBankDeposit
__packet->WriteUInt32(5);
return;
}
case 5: { // GuildBankPermissions
DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct);
SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct);
emu->Action = 6;
IN(Unknown04);
IN(SlotID);
IN(Unknown10);
IN(ItemID);
IN(Permissions);
strn0cpy(emu->MemberName, eq->MemberName, 64);
FINISH_DIRECT_DECODE();
return;
}
case 6: { // GuildBankWithdraw
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 7;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 7: { // GuildBankSplitStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 8;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 8: { // GuildBankMergeStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 9;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
default:
Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
return;
}
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);
@@ -4704,16 +4862,16 @@ namespace RoF
DECODE(OP_MoveItem)
{
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
//Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
//emu->from_slot = RoFToServerSlot(eq->from_slot);
//emu->to_slot = RoFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -4841,13 +4999,13 @@ namespace RoF
{
DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct);
SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
IN(npcid);
IN(playerid);
IN(itemslot);
IN(quantity);
IN(price);
FINISH_DIRECT_DECODE();
}
@@ -5044,7 +5202,7 @@ namespace RoF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const ItemData *item = inst->GetUnscaledItem();
const Item_Struct *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
RoF::structs::ItemSerializationHeader hdr;
@@ -5074,19 +5232,19 @@ namespace RoF
hdr.unknown044 = 0;
hdr.unknown048 = 0;
hdr.unknown052 = 0;
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
hdr.isEvolving = item->EvolvingItem;
ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader));
if (item->EvolvingLevel > 0) {
if (item->EvolvingItem > 0) {
RoF::structs::EvolvingItem evotop;
evotop.unknown001 = 0;
evotop.unknown002 = 0;
evotop.unknown003 = 0;
evotop.unknown004 = 0;
evotop.evoLevel = item->EvolvingLevel;
evotop.progress = 95.512;
evotop.progress = 0;
evotop.Activated = 1;
evotop.evomaxlevel = 7;
evotop.evomaxlevel = item->EvolvingMax;
ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem));
}
//ORNAMENT IDFILE / ICON
@@ -5103,7 +5261,7 @@ namespace RoF
ss.write(tmp, strlen(tmp));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = inst->GetOrnamentationIcon();
heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in));
heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in));
}
else
{
@@ -5196,7 +5354,7 @@ namespace RoF
ibs.Races = item->Races;
ibs.Deity = item->Deity;
ibs.SkillModValue = item->SkillModValue;
ibs.SkillModMax = 0xffffffff;
ibs.SkillModMax = item->SkillModMax;
ibs.SkillModType = (int8)(item->SkillModType);
ibs.SkillModExtra = 0;
ibs.BaneDmgRace = item->BaneDmgRace;
@@ -5546,7 +5704,7 @@ namespace RoF
/*
// TEST CODE: <watch>
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+465 -239
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -57,6 +57,7 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@@ -152,6 +153,7 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
+115 -6
View File
@@ -1487,7 +1487,8 @@ struct CombatDamage_Struct
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25[5]; // was [9]
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 30 */
};
@@ -1858,6 +1859,114 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@@ -2310,7 +2419,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -4289,7 +4398,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
/*16*/
};
@@ -4406,7 +4515,7 @@ struct RoF2SlotStruct
struct ItemSerializationHeader
{
/*000*/ char tracking_id[17]; // New for HoT. Looks like a string.
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
@@ -4623,7 +4732,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4638,7 +4747,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
+2
View File
@@ -42,6 +42,7 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@@ -137,6 +138,7 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
+114 -5
View File
@@ -1517,7 +1517,8 @@ struct CombatDamage_Struct
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25[5]; // was [9]
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 30 */
};
@@ -1888,6 +1889,114 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@@ -2338,7 +2447,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -4288,7 +4397,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
/*16*/
};
@@ -4622,7 +4731,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4637,7 +4746,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
+136 -154
View File
@@ -336,72 +336,71 @@ namespace SoD
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
//
// in->pBuffer = new uchar[in->size];
//
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
//
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
//
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -447,9 +446,10 @@ namespace SoD
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force)
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z)
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
}
@@ -1267,14 +1267,14 @@ namespace SoD
ENCODE(OP_MoveItem)
{
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToSoDSlot(emu->from_slot);
//eq->to_slot = ServerToSoDSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToSoDSlot(emu->from_slot);
eq->to_slot = ServerToSoDSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1678,8 +1678,8 @@ namespace SoD
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 16383;
OUT(expansions);
//eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -1863,55 +1863,56 @@ namespace SoD
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for SoD
if (emu->clientver <= 5)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@@ -2206,25 +2207,6 @@ namespace SoD
ptr += sizeof(uint32);
ptr += 1;
}
/*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
uint8 write_var8 = 1;
ss.write((const char*)&emu->entity_id, sizeof(uint32));
ss.write((const char*)&emu->count, sizeof(uint16));
write_var8 = 0;
for(uint16 i = 0; i < emu->count; ++i)
{
ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32));
ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32));
ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32));
ss.write((const char*)&write_var8, sizeof(uint8));
}
__packet->size = ss.str().length();
__packet->pBuffer = new unsigned char[__packet->size];
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
*/
FINISH_ENCODE();
}
@@ -3265,16 +3247,16 @@ namespace SoD
DECODE(OP_MoveItem)
{
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = SoDToServerSlot(eq->from_slot);
//emu->to_slot = SoDToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = SoDToServerSlot(eq->from_slot);
emu->to_slot = SoDToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -3560,7 +3542,7 @@ namespace SoD
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const ItemData *item = inst->GetUnscaledItem();
const Item_Struct *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
SoD::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3958,7 +3940,7 @@ namespace SoD
/*
// TEST CODE: <watch>
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+7 -7
View File
@@ -1275,7 +1275,8 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23[5]; // was [9]
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 28 */
};
@@ -1973,7 +1974,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -3813,8 +3814,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3840,7 +3840,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};
@@ -4111,7 +4111,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4126,7 +4126,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
+132 -133
View File
@@ -318,70 +318,69 @@ namespace SoF
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
//*p = nullptr;
//
//if (in->size == 0) {
// in->size = 4;
// in->pBuffer = new uchar[in->size];
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
//
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
// uchar *OldBuffer = in->pBuffer;
//
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
//
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -427,9 +426,9 @@ namespace SoF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force)
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z)
OUT(meleepush_z);
FINISH_ENCODE();
}
@@ -932,14 +931,14 @@ namespace SoF
ENCODE(OP_MoveItem)
{
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToSoFSlot(emu->from_slot);
//eq->to_slot = ServerToSoFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToSoFSlot(emu->from_slot);
eq->to_slot = ServerToSoFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1336,8 +1335,8 @@ namespace SoF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 16383;
OUT(expansions);
//eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -1521,56 +1520,56 @@ namespace SoF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 4 is for SoF
if (emu->clientver <= 4)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@@ -2604,16 +2603,16 @@ namespace SoF
DECODE(OP_MoveItem)
{
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = SoFToServerSlot(eq->from_slot);
//emu->to_slot = SoFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = SoFToServerSlot(eq->from_slot);
emu->to_slot = SoFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -2885,7 +2884,7 @@ namespace SoF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const ItemData *item = inst->GetUnscaledItem();
const Item_Struct *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
SoF::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3281,7 +3280,7 @@ namespace SoF
/*
// TEST CODE: <watch>
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+6 -7
View File
@@ -1253,7 +1253,7 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23[5]; // was [9]
/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here?
/* 28 */
};
@@ -1948,7 +1948,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -3677,8 +3677,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3702,7 +3701,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};
@@ -3966,7 +3965,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -3981,7 +3980,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
+111 -94
View File
@@ -263,42 +263,57 @@ namespace Titanium
EQApplicationPacket *in = *p;
*p = nullptr;
delete in;
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
//if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
// delete in;
// return;
//}
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
////do the transform...
//int r;
//std::string serial_string;
//for (r = 0; r < itemcount; r++, eq++) {
// uint32 length;
// char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
// if (serialized) {
// serial_string.append(serialized, length + 1);
// safe_delete_array(serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//
//}
//
//in->size = serial_string.length();
//in->pBuffer = new unsigned char[in->size];
//memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
//
//delete[] __emu_buffer;
//
//dest->FastQueuePacket(&in, ack_req);
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//do the transform...
int r;
std::string serial_string;
for (r = 0; r < itemcount; r++, eq++) {
uint32 length;
char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
if (serialized) {
serial_string.append(serialized, length + 1);
safe_delete_array(serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
in->size = serial_string.length();
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_Damage)
{
ENCODE_LENGTH_EXACT(CombatDamage_Struct);
SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct);
OUT(target);
OUT(source);
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z);
FINISH_ENCODE();
}
ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); }
@@ -778,14 +793,14 @@ namespace Titanium
ENCODE(OP_MoveItem)
{
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
//eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1109,50 +1124,52 @@ namespace Titanium
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
// Check clientver field to verify this AA should be sent for Titanium
// clientver 1 is for all clients and 3 is for Titanium
if (emu->clientver <= 3)
{
OUT(id);
eq->unknown004 = 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->title_sid = emu->id - emu->current_level + 1;
eq->desc_sid = emu->id - emu->current_level + 1;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
OUT(type);
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
OUT(unknown80[0]);
OUT(unknown80[1]);
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@@ -1854,16 +1871,16 @@ namespace Titanium
DECODE(OP_MoveItem)
{
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = TitaniumToServerSlot(eq->from_slot);
//emu->to_slot = TitaniumToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = TitaniumToServerSlot(eq->from_slot);
emu->to_slot = TitaniumToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -2072,7 +2089,7 @@ namespace Titanium
int16 slot_id = ServerToTitaniumSlot(slot_id_in);
uint32 merchant_slot = inst->GetMerchantSlot();
int16 charges = inst->GetCharges();
const ItemData *item = inst->GetUnscaledItem();
const Item_Struct *item = inst->GetUnscaledItem();
int i;
uint32 sub_length;
+1
View File
@@ -6,6 +6,7 @@ E(OP_BazaarSearch)
E(OP_BecomeTrader)
E(OP_ChannelMessage)
E(OP_CharInventory)
E(OP_Damage)
E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DeleteSpawn)
+3 -4
View File
@@ -1700,7 +1700,7 @@ struct AdventureRequestResponse_Struct{
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -3157,8 +3157,7 @@ struct SendAA_Struct {
/*0052*/ uint32 spellid;
/*0056*/ uint32 spell_type;
/*0060*/ uint32 spell_refresh;
/*0064*/ uint16 classes;
/*0066*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0064*/ uint32 classes;
/*0068*/ uint32 max_level;
/*0072*/ uint32 last_id;
/*0076*/ uint32 next_id;
@@ -3175,7 +3174,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};
+164 -147
View File
@@ -365,7 +365,7 @@ namespace UF
memset(__packet->pBuffer, 0, sz);
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(0);
__packet->WriteUInt32(emu->tic_timer);
__packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff
__packet->WriteUInt16(emu->count);
@@ -474,69 +474,68 @@ namespace UF
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
// in->pBuffer = new uchar[in->size];
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -582,9 +581,10 @@ namespace UF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force)
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z)
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
}
@@ -1506,14 +1506,14 @@ namespace UF
ENCODE(OP_MoveItem)
{
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToUFSlot(emu->from_slot);
//eq->to_slot = ServerToUFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToUFSlot(emu->from_slot);
eq->to_slot = ServerToUFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1806,11 +1806,13 @@ namespace UF
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
OUT(aa_array[r].AA);
OUT(aa_array[r].value);
OUT(aa_array[r].charges);
eq->aa_array[r].AA = emu->aa_array[r].AA;
eq->aa_array[r].value = emu->aa_array[r].value;
eq->aa_array[r].charges = emu->aa_array[r].charges;
}
// OUT(unknown02220[4]);
OUT(mana);
OUT(cur_hp);
OUT(STR);
@@ -1940,8 +1942,8 @@ namespace UF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 0xffff;
OUT(expansions);
//eq->expansions = 0x1ffff;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -2129,7 +2131,7 @@ namespace UF
eq->aa_spent = emu->aa_spent;
eq->aa_assigned = emu->aa_spent;
eq->aa_spent3 = emu->aa_spent;
eq->aa_spent3 = 0;
eq->unknown012 = 0;
eq->unknown016 = 0;
eq->unknown020 = 0;
@@ -2146,55 +2148,56 @@ namespace UF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 6 is for Underfoot
if (emu->clientver <= 6)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@@ -3045,11 +3048,21 @@ namespace UF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
if (emu->equipment[MaterialPrimary].Material > 99999) {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
} else {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
if (emu->equipment[MaterialSecondary].Material > 99999) {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
} else {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
}
@@ -3059,7 +3072,11 @@ namespace UF
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) {
Equipment[k].Material = emu->equipment[k].Material;
if (emu->equipment[k].Material > 99999) {
Equipment[k].Material = 63;
} else {
Equipment[k].Material = emu->equipment[k].Material;
}
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
}
@@ -3587,16 +3604,16 @@ namespace UF
DECODE(OP_MoveItem)
{
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = UFToServerSlot(eq->from_slot);
//emu->to_slot = UFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = UFToServerSlot(eq->from_slot);
emu->to_slot = UFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -3812,7 +3829,7 @@ namespace UF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const ItemData *item = inst->GetUnscaledItem();
const Item_Struct *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
UF::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3832,25 +3849,25 @@ namespace UF
hdr.unknown044 = 0;
hdr.unknown048 = 0;
hdr.unknown052 = 0;
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
hdr.isEvolving = item->EvolvingItem;
ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader));
if (item->EvolvingLevel > 0) {
if (item->EvolvingItem > 0) {
UF::structs::EvolvingItem evotop;
evotop.unknown001 = 0;
evotop.unknown002 = 0;
evotop.unknown003 = 0;
evotop.unknown004 = 0;
evotop.evoLevel = item->EvolvingLevel;
evotop.progress = 95.512;
evotop.progress = 0;
evotop.Activated = 1;
evotop.evomaxlevel = 7;
evotop.evomaxlevel = item->EvolvingMax;
ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
}
//ORNAMENT IDFILE / ICON -
uint16 ornaIcon = 0;
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
const ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = aug_weap->Icon;
@@ -3944,7 +3961,7 @@ namespace UF
ibs.Races = item->Races;
ibs.Deity = item->Deity;
ibs.SkillModValue = item->SkillModValue;
ibs.unknown5 = 0;
ibs.SkillModMax = item->SkillModMax;
ibs.SkillModType = item->SkillModType;
ibs.BaneDmgRace = item->BaneDmgRace;
ibs.BaneDmgBody = item->BaneDmgBody;
@@ -4266,7 +4283,7 @@ namespace UF
/*
// TEST CODE: <watch>
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+8 -8
View File
@@ -1333,7 +1333,8 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23[5]; // was [9]
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 28 */
};
@@ -2032,7 +2033,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
ItemData item;
Item_Struct item;
uint8 iss_unknown001[6];
};*/
@@ -3886,8 +3887,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3913,7 +3913,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};
@@ -4103,7 +4103,7 @@ struct ItemBodyStruct
uint32 Races;
uint32 Deity;
int32 SkillModValue;
uint32 unknown5;
uint32 SkillModMax;
uint32 SkillModType;
uint32 BaneDmgRace;
uint32 BaneDmgBody;
@@ -4206,7 +4206,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4221,7 +4221,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
+363
View File
@@ -0,0 +1,363 @@
#include "pathfind.h"
#include "random.h"
#include <stdio.h>
#include <string.h>
#include <zlib.h>
namespace Pathfind
{
uint32_t InflateData(const char* buffer, uint32_t len, char* out_buffer, uint32_t out_len_max) {
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
zstream.avail_out = out_len_max;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2(&zstream, 15);
if (i != Z_OK) {
return 0;
}
zerror = inflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END) {
inflateEnd(&zstream);
return zstream.total_out;
}
else {
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd(&zstream);
return 0;
}
}
}
const uint32_t nav_mesh_file_version = 2;
const float max_dest_drift = 10.0f;
const float at_waypoint_eps = 1.0f;
EQEmu::Random path_rng;
float vec_dist(const glm::vec3 &a, const glm::vec3 &b) {
float dist_x = a.x - b.x;
float dist_y = a.y - b.y;
float dist_z = a.z - b.z;
return sqrt((dist_x * dist_x) + (dist_y * dist_y) + (dist_z * dist_z));
}
PathfindingManager::PathfindingManager()
{
m_nav_mesh = nullptr;
m_nav_query = nullptr;
m_filter.setIncludeFlags(NavigationPolyFlagAll);
m_filter.setAreaCost(NavigationAreaFlagNormal, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagWater, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagLava, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagPvP, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagSlime, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagIce, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagVWater, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagGeneralArea, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagPortal, 1.0f);
}
PathfindingManager::~PathfindingManager()
{
Clear();
}
void PathfindingManager::Load(const std::string &zone_name)
{
Clear();
std::string filename = MAP_DIR + std::string("/") + zone_name + ".nav";
FILE *f = fopen(filename.c_str(), "rb");
if (f) {
char magic[9] = { 0 };
if (fread(magic, 9, 1, f) != 1) {
fclose(f);
return;
}
if (strncmp(magic, "EQNAVMESH", 9) != 0)
{
fclose(f);
return;
}
uint32_t version = 0;
if (fread(&version, sizeof(uint32_t), 1, f) != 1) {
fclose(f);
return;
}
if (version != nav_mesh_file_version) {
fclose(f);
return;
}
uint32_t data_size;
if (fread(&data_size, sizeof(data_size), 1, f) != 1) {
fclose(f);
return;
}
uint32_t buffer_size;
if (fread(&buffer_size, sizeof(buffer_size), 1, f) != 1) {
fclose(f);
return;
}
std::vector<char> data;
data.resize(data_size);
if (fread(&data[0], data_size, 1, f) != 1) {
fclose(f);
return;
}
std::vector<char> buffer;
buffer.resize(buffer_size);
uint32_t v = Pathfind::InflateData(&data[0], data_size, &buffer[0], buffer_size);
fclose(f);
char *buf = &buffer[0];
m_nav_mesh = dtAllocNavMesh();
uint32_t number_of_tiles = *(uint32_t*)buf;
buf += sizeof(uint32_t);
dtNavMeshParams params = *(dtNavMeshParams*)buf;
buf += sizeof(dtNavMeshParams);
dtStatus status = m_nav_mesh->init(&params);
if (dtStatusFailed(status))
{
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
return;
}
for (unsigned int i = 0; i < number_of_tiles; ++i)
{
uint32_t tile_ref = *(uint32_t*)buf;
buf += sizeof(uint32_t);
int32_t data_size = *(uint32_t*)buf;
buf += sizeof(uint32_t);
if (!tile_ref || !data_size) {
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
return;
}
unsigned char* data = (unsigned char*)dtAlloc(data_size, DT_ALLOC_PERM);
memcpy(data, buf, data_size);
buf += data_size;
m_nav_mesh->addTile(data, data_size, DT_TILE_FREE_DATA, tile_ref, 0);
}
}
}
void PathfindingManager::Clear()
{
if (m_nav_mesh) {
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
}
if (m_nav_query) {
dtFreeNavMeshQuery(m_nav_query);
m_nav_query = nullptr;
}
}
PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const glm::vec3 &dest_loc)
{
glm::vec3 current_location(src_loc.x, src_loc.z, src_loc.y);
glm::vec3 dest_location(dest_loc.x, dest_loc.z, dest_loc.y);
PathfindingRoute ret;
ret.m_status = PathComplete;
ret.m_dest = dest_loc;
ret.m_current_node = 0;
ret.m_active = true;
if (!m_nav_mesh) {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
return ret;
}
if (!m_nav_query) {
m_nav_query = dtAllocNavMeshQuery();
m_nav_query->init(m_nav_mesh, 4092);
}
dtPolyRef start_ref;
dtPolyRef end_ref;
glm::vec3 ext(15.0f, 15.0f, 15.0f);
m_nav_query->findNearestPoly(&current_location[0], &ext[0], &m_filter, &start_ref, 0);
m_nav_query->findNearestPoly(&dest_location[0], &ext[0], &m_filter, &end_ref, 0);
if (!start_ref || !end_ref) {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
return ret;
}
int npoly = 0;
dtPolyRef path[256] = { 0 };
auto status = m_nav_query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &m_filter, path, &npoly, 256);
if (status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
ret.m_status = PathPartial;
}
else if (status & DT_PARTIAL_RESULT) {
ret.m_status = PathBroken;
}
if (npoly) {
glm::vec3 epos = dest_location;
if (path[npoly - 1] != end_ref)
m_nav_query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
float straight_path[512 * 3];
unsigned char straight_path_flags[512];
int n_straight_polys;
dtPolyRef straight_path_polys[512];
status = m_nav_query->findStraightPath(&current_location[0], &epos[0], path, npoly,
straight_path, straight_path_flags,
straight_path_polys, &n_straight_polys, 512, DT_STRAIGHTPATH_ALL_CROSSINGS);
if (ret.m_status == PathComplete && status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
ret.m_status = PathPartial;
}
else if (ret.m_status == PathComplete && status & DT_PARTIAL_RESULT) {
ret.m_status = PathBroken;
}
if (n_straight_polys) {
ret.m_nodes.reserve(n_straight_polys);
for (int i = 0; i < n_straight_polys; ++i)
{
PathfindingNode node;
node.position.x = straight_path[i * 3];
node.position.z = straight_path[i * 3 + 1];
node.position.y = straight_path[i * 3 + 2];
if (!dtStatusSucceed(m_nav_mesh->getPolyFlags(straight_path_polys[i], &node.flag))) {
node.flag = 0;
}
ret.m_nodes.push_back(node);
}
}
}
else {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
}
return ret;
}
bool PathfindingManager::GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos)
{
if(!m_nav_mesh)
return false;
if (!m_nav_query) {
m_nav_query = dtAllocNavMeshQuery();
m_nav_query->init(m_nav_mesh, 4092);
}
glm::vec3 ext(10.0f, 10.0f, 10.0f);
dtPolyRef start_ref;
m_nav_query->findNearestPoly(&start[0], &ext[0], &m_filter, &start_ref, 0);
if (!start_ref) {
return false;
}
dtPolyRef random_ref;
glm::vec3 pt;
dtStatus status = m_nav_query->findRandomPointAroundCircle(start_ref, &start[0], radius,
&m_filter, []() -> float { return (float)path_rng.Real(0.0, 1.0); }, &random_ref, &pt[0]);
if (dtStatusSucceed(status))
{
pos.x = pt.x;
pos.z = pt.y;
pos.y = pt.z;
return true;
}
return false;
}
PathfindingRoute::PathfindingRoute()
{
m_active = false;
}
PathfindingRoute::~PathfindingRoute()
{
}
bool PathfindingRoute::DestinationValid(const glm::vec3 &dest)
{
if (m_status == PathPartial && m_current_node + 1 == m_nodes.size()) {
return false;
}
auto dist = vec_dist(dest, m_dest);
if (dist <= max_dest_drift) {
return true;
}
return false;
}
void PathfindingRoute::CalcCurrentNode(const glm::vec3 &current_pos, bool &wp_changed)
{
wp_changed = false;
if (m_active) {
//if we're at last node then we dont need to do anything.
if (m_nodes.size() - 1 == m_current_node) {
return;
}
auto &current = GetCurrentNode();
auto dist = vec_dist(current.position, current_pos);
if (dist < at_waypoint_eps) {
m_current_node++;
wp_changed = true;
}
}
}
unsigned short PathfindingRoute::GetPreviousNodeFlag()
{
if(m_current_node == 0)
return 0;
return m_nodes[m_current_node - 1].flag;
}
+94
View File
@@ -0,0 +1,94 @@
#pragma once
#include <string>
#include <vector>
#include <DetourNavMesh.h>
#include <DetourNavMeshQuery.h>
#include <glm/vec3.hpp>
enum NavigationAreaFlags
{
NavigationAreaFlagNormal,
NavigationAreaFlagWater,
NavigationAreaFlagLava,
NavigationAreaFlagZoneLine,
NavigationAreaFlagPvP,
NavigationAreaFlagSlime,
NavigationAreaFlagIce,
NavigationAreaFlagVWater,
NavigationAreaFlagGeneralArea,
NavigationAreaFlagPortal,
NavigationAreaFlagDisabled,
};
enum NavigationPolyFlags
{
NavigationPolyFlagNormal = 1,
NavigationPolyFlagWater = 2,
NavigationPolyFlagLava = 4,
NavigationPolyFlagZoneLine = 8,
NavigationPolyFlagPvP = 16,
NavigationPolyFlagSlime = 32,
NavigationPolyFlagIce = 64,
NavigationPolyFlagVWater = 128,
NavigationPolyFlagGeneralArea = 256,
NavigationPolyFlagPortal = 512,
NavigationPolyFlagDisabled = 1024,
NavigationPolyFlagAll = 0xFFFF
};
struct PathfindingNode
{
glm::vec3 position;
unsigned short flag;
};
enum PathfindingRouteStatus
{
PathComplete,
PathPartial,
PathBroken
};
class PathfindingRoute
{
public:
PathfindingRoute();
~PathfindingRoute();
bool Active() const { return m_active; }
bool DestinationValid(const glm::vec3 &dest);
void CalcCurrentNode(const glm::vec3 &current_pos, bool &wp_changed);
const PathfindingNode& GetCurrentNode() { return m_nodes[m_current_node]; }
unsigned short GetPreviousNodeFlag();
const std::vector<PathfindingNode>& GetNodes() const { return m_nodes; }
std::vector<PathfindingNode>& GetNodesEdit() { return m_nodes; }
PathfindingRouteStatus GetStatus() { return m_status; }
private:
glm::vec3 m_dest;
std::vector<PathfindingNode> m_nodes;
int m_current_node;
bool m_active;
PathfindingRouteStatus m_status;
friend class PathfindingManager;
};
class PathfindingManager
{
public:
PathfindingManager();
~PathfindingManager();
void Load(const std::string &filename);
void Clear();
//Expects locations in EQEmu internal format eg what #loc returns not what /loc returns.
PathfindingRoute FindRoute(const glm::vec3 &current_location, const glm::vec3 &dest_location);
bool GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos);
bool Loaded() const { return m_nav_mesh != nullptr; }
private:
dtNavMesh *m_nav_mesh;
dtNavMeshQuery *m_nav_query;
dtQueryFilter m_filter;
};
-4
View File
@@ -139,8 +139,4 @@ protected:
std::map<pTimerType, PersistentTimer *> _list;
};
//code prettying macros
#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3))
#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5))))
#endif
+149 -172
View File
@@ -17,43 +17,14 @@
*/
#include "rulesys.h"
#include "database.h"
#include "string_util.h"
#include <cstdlib>
#include <cstring>
/*
FatherNitwit: Added new rules subsystem to allow game rules to be changed
at runtime. more about this will come as time goes on.
FatherNitwit: Added #rules command to manage rules data from in game.
FatherNitwit: Renamed old #rules to #serverrules
FatherNitwit: Moved max level into the rules system (Character:MaxLevel)
Requred SQL:
CREATE TABLE rule_sets (
ruleset_id TINYINT UNSIGNED NOT NULL auto_increment,
name VARCHAR(255) NOT NULL,
PRIMARY KEY(ruleset_id)
);
INSERT INTO rule_sets VALUES(0, "default");
UPDATE rule_sets SET ruleset_id=0;
CREATE TABLE rule_values (
ruleset_id TINYINT UNSIGNED NOT NULL,
rule_name VARCHAR(64) NOT NULL,
rule_value VARCHAR(10) NOT NULL,
INDEX(ruleset_id),
PRIMARY KEY(ruleset_id,rule_name)
);
Commands:
#rules:
Commands:
#rules:
current -> lists current set name
switch (set name) -> change set in the DB, but dont reload
load (set name) -> load set into this zone without changing the world
@@ -94,28 +65,28 @@ RuleManager::RuleManager()
}
RuleManager::CategoryType RuleManager::FindCategory(const char *catname) {
int r;
for(r = 0; r < _CatCount; r++) {
if(strcasecmp(catname, s_categoryNames[r]) == 0)
return((CategoryType) r);
int i;
for (i = 0; i < _CatCount; i++) {
if (strcasecmp(catname, s_categoryNames[i]) == 0)
return((CategoryType)i);
}
return(InvalidCategory);
}
bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into) {
CategoryType cat = InvalidCategory;
if(catname != nullptr) {
if (catname != nullptr) {
cat = FindCategory(catname);
if(cat == InvalidCategory) {
if (cat == InvalidCategory) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname);
return(false);
}
}
int r;
int rcount = CountRules();
for(r = 0; r < rcount; r++) {
const RuleInfo &rule = s_RuleInfo[r];
if(catname == nullptr || cat == rule.category) {
int i;
int rule_count = CountRules();
for (i = 0; i < rule_count; i++) {
const RuleInfo &rule = s_RuleInfo[i];
if (catname == nullptr || cat == rule.category) {
into.push_back(rule.name);
}
}
@@ -123,15 +94,14 @@ bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into
}
bool RuleManager::ListCategories(std::vector<const char *> &into) {
int r;
for(r = 0; r < _CatCount; r++) {
into.push_back(s_categoryNames[r]);
int i;
for (i = 0; i < _CatCount; i++) {
into.push_back(s_categoryNames[i]);
}
return(true);
}
bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) {
bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
RuleType type;
uint16 index;
if (!_FindRule(rule_name, type, index))
@@ -151,12 +121,12 @@ bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) {
break;
}
ret_val = tmp;
return_value = tmp;
return true;
}
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *db, bool db_save) {
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) {
if(rule_name == nullptr || rule_value == nullptr)
return(false);
@@ -166,25 +136,26 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
return(false);
switch(type) {
case IntRule:
m_RuleIntValues [index] = atoi(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
break;
case RealRule:
m_RuleRealValues[index] = atof(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
break;
case BoolRule:
uint32 val = 0;
if(!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
val = 1;
m_RuleBoolValues[index] = val;
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ?"true":"false");
break;
case IntRule:
m_RuleIntValues[index] = atoi(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
break;
case RealRule:
m_RuleRealValues[index] = atof(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
break;
case BoolRule:
uint32 val = 0;
if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
val = 1;
m_RuleBoolValues[index] = val;
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
break;
}
if(db_save)
_SaveRule(db, type, index);
_SaveRule(database, type, index);
return(true);
}
@@ -201,14 +172,14 @@ void RuleManager::ResetRules() {
}
bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) {
if(rule_name == nullptr)
if (rule_name == nullptr)
return(false);
int r;
int rcount = CountRules();
for(r = 0; r < rcount; r++) {
const RuleInfo &rule = s_RuleInfo[r];
if(strcmp(rule_name, rule.name) == 0) {
int i;
int rule_count = CountRules();
for (i = 0; i < rule_count; i++) {
const RuleInfo &rule = s_RuleInfo[i];
if (strcmp(rule_name, rule.name) == 0) {
type_into = rule.type;
index_into = rule.rule_index;
return(true);
@@ -220,191 +191,197 @@ bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &
//assumes index is valid!
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
switch(type) {
case IntRule:
return(s_RuleInfo[index].name);
case RealRule:
return(s_RuleInfo[index+_IntRuleCount].name);
case BoolRule:
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
switch (type) {
case IntRule:
return(s_RuleInfo[index].name);
case RealRule:
return(s_RuleInfo[index + _IntRuleCount].name);
case BoolRule:
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name);
}
//should never happen
return("InvalidRule??");
}
void RuleManager::SaveRules(Database *db, const char *ruleset) {
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
if(ruleset != nullptr) {
if (ruleset_name != nullptr) {
//saving to a specific name
if(m_activeName != ruleset) {
if (m_activeName != ruleset_name) {
//a new name...
m_activeRuleset = _FindOrCreateRuleset(db, ruleset);
if(m_activeRuleset == -1) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset);
m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name);
if (m_activeRuleset == -1) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name);
return;
}
m_activeName = ruleset;
m_activeName = ruleset_name;
}
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset, m_activeRuleset);
} else {
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset);
}
else {
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
}
int r;
for(r = 0; r < _IntRuleCount; r++) {
_SaveRule(db, IntRule, r);
int i;
for (i = 0; i < _IntRuleCount; i++) {
_SaveRule(database, IntRule, i);
}
for(r = 0; r < _RealRuleCount; r++) {
_SaveRule(db, RealRule, r);
for (i = 0; i < _RealRuleCount; i++) {
_SaveRule(database, RealRule, i);
}
for(r = 0; r < _BoolRuleCount; r++) {
_SaveRule(db, BoolRule, r);
for (i = 0; i < _BoolRuleCount; i++) {
_SaveRule(database, BoolRule, i);
}
}
bool RuleManager::LoadRules(Database *db, const char *ruleset) {
int rsid = GetRulesetID(db, ruleset);
if(rsid < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset);
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
int ruleset_id = GetRulesetID(database, ruleset_name);
if (ruleset_id < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
return(false);
}
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset, rsid);
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
m_activeRuleset = rsid;
m_activeName = ruleset;
m_activeRuleset = ruleset_id;
m_activeName = ruleset_name;
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", rsid);
auto results = db->QueryDatabase(query);
if (!results.Success())
{
return false;
/* Load default ruleset values first if we're loading something other than default */
if (strcasecmp(ruleset_name, "default") != 0){
std::string default_ruleset_name = "default";
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
if (default_ruleset_id < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str());
return(false);
}
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
}
for(auto row = results.begin(); row != results.end(); ++row)
if(!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
return true;
}
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
char vstr[100];
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
char value_string[100];
switch(type) {
case IntRule:
sprintf(vstr, "%d", m_RuleIntValues[index]);
break;
case RealRule:
sprintf(vstr, "%.13f", m_RuleRealValues[index]);
break;
case BoolRule:
sprintf(vstr, "%s", m_RuleBoolValues[index]?"true":"false");
break;
case IntRule:
sprintf(value_string, "%d", m_RuleIntValues[index]);
break;
case RealRule:
sprintf(value_string, "%.13f", m_RuleRealValues[index]);
break;
case BoolRule:
sprintf(value_string, "%s", m_RuleBoolValues[index]?"true":"false");
break;
}
std::string query = StringFormat("REPLACE INTO rule_values "
"(ruleset_id, rule_name, rule_value) "
" VALUES(%d, '%s', '%s')",
m_activeRuleset, _GetRuleName(type, index), vstr);
auto results = db->QueryDatabase(query);
m_activeRuleset, _GetRuleName(type, index), value_string);
auto results = database->QueryDatabase(query);
}
int RuleManager::GetRulesetID(Database *db, const char *rulesetname) {
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
uint32 len = strlen(rulesetname);
char* rst = new char[2*len+1];
db->DoEscapeString(rst, rulesetname, len);
uint32 len = strlen(ruleset_name);
char* rst = new char[2 * len + 1];
database->DoEscapeString(rst, ruleset_name, len);
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
safe_delete_array(rst);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return -1;
}
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
safe_delete_array(rst);
auto results = database->QueryDatabase(query);
if (!results.Success())
return -1;
if (results.RowCount() == 0)
return -1;
if (results.RowCount() == 0)
return -1;
auto row = results.begin();
auto row = results.begin();
return atoi(row[0]);
}
int RuleManager::_FindOrCreateRuleset(Database *db, const char *ruleset) {
int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) {
int res = GetRulesetID(db, ruleset);
if(res >= 0)
return res; //found and existing one...
int ruleset_id = GetRulesetID(database, in_ruleset_name);
if (ruleset_id >= 0)
return ruleset_id; //found and existing one...
uint32 len = strlen(ruleset);
char* rst = new char[2*len+1];
db->DoEscapeString(rst, ruleset, len);
uint32 len = strlen(in_ruleset_name);
char* ruleset_name = new char[2 * len + 1];
database->DoEscapeString(ruleset_name, in_ruleset_name, len);
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", rst);
safe_delete_array(rst);
auto results = db->QueryDatabase(query);
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name);
safe_delete_array(ruleset_name);
auto results = database->QueryDatabase(query);
if (!results.Success())
{
return -1;
}
return results.LastInsertedID();
return results.LastInsertedID();
}
std::string RuleManager::GetRulesetName(Database *db, int id) {
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", id);
auto results = db->QueryDatabase(query);
std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) {
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
{
return "";
}
return "";
if (results.RowCount() == 0)
return "";
return "";
auto row = results.begin();
auto row = results.begin();
return row[0];
}
bool RuleManager::ListRulesets(Database *db, std::map<int, std::string> &into) {
bool RuleManager::ListRulesets(Database *database, std::map<int, std::string> &into) {
//start out with the default set which is always present.
into[0] = "default";
std::string query = "SELECT ruleset_id, name FROM rule_sets";
auto results = db->QueryDatabase(query);
std::string query = "SELECT ruleset_id, name FROM rule_sets";
auto results = database->QueryDatabase(query);
if (results.Success())
{
return false;
}
for (auto row = results.begin(); row != results.end(); ++row)
into[ atoi(row[0]) ] = row[1];
into[atoi(row[0])] = row[1];
return true;
}
int32 RuleManager::GetIntRule(RuleManager::IntType t) const
{
int32 RuleManager::GetIntRule(RuleManager::IntType t) const{
return(m_RuleIntValues[t]);
}
float RuleManager::GetRealRule(RuleManager::RealType t) const
{
float RuleManager::GetRealRule(RuleManager::RealType t) const{
return(m_RuleRealValues[t]);
}
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
{
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const{
return (m_RuleBoolValues[t] == 1);
}
+58 -13
View File
@@ -85,6 +85,8 @@ RULE_INT(Character, MaxCharmDurationForPlayerCharacter, 15)
RULE_INT(Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values
RULE_BOOL(Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas
RULE_BOOL(Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses
RULE_BOOL(Character, UseOldRaceExpPenalties, false) // Setting this to true will enable racial exp penalties for Iksar, Troll, Ogre, and Barbarian, as well as the bonus for Halflings
RULE_BOOL(Character, UseOldClassExpPenalties, false) // Setting this to true will enable old class exp penalties for Paladin, SK, Ranger, Bard, Monk, Wizard, Enchanter, Magician, and Necromancer, as well as the bonus for Rogues and Warriors
RULE_BOOL(Character, RespawnFromHover, false) // Use Respawn window, or not.
RULE_INT(Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS
RULE_BOOL(Character, UseNewStatsWindow, true) // New stats window shows everything
@@ -99,6 +101,7 @@ RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Wind
RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap
RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update
RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well.
RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field
RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225.
RULE_INT(Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type
RULE_REAL(Character, EnvironmentDamageMulipliter, 1)
@@ -113,6 +116,16 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on!
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
RULE_INT(Character, TrollCommonTongue, 95) // 95 By default (live-like?)
RULE_BOOL(Character, ActiveInvSnapshots, false) // Takes a periodic snapshot of inventory contents from online players
RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) between inventory snapshots
RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure
RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries
RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -183,6 +196,7 @@ RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against Ant
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method.
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
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.
@@ -219,6 +233,7 @@ RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mod
RULE_INT(Zone, WeatherTimer, 600) // Weather timer when no duration is available
RULE_BOOL(Zone, EnableLoggedOffReplenishments, true)
RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours
RULE_BOOL(Zone, UseZoneController, true) // Enables the ability to use persistent quest based zone controllers (zone_controller.pl/lua)
RULE_CATEGORY_END()
RULE_CATEGORY(Map)
@@ -336,8 +351,8 @@ RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast
RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random)
RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell.
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_IdleNoSpellMinRecast, 6000) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 60000) // 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
@@ -435,7 +450,7 @@ RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's n
RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain.
RULE_INT(Combat, MonkACBonusWeight, 15)
RULE_INT(Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target
RULE_INT(Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers
RULE_INT(Combat, QuiverHasteCap, 1000) //Quiver haste cap 1000 on live for a while, currently 700 on live
RULE_BOOL(Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll
RULE_INT(Combat, ArcheryBonusChance, 50)
RULE_INT(Combat, BerserkerFrenzyStart, 35)
@@ -444,6 +459,10 @@ RULE_BOOL(Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per
RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.
RULE_BOOL(Combat, MeleePush, true) // enable melee push
RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad
RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs
RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist another NPC at once
RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space
RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF
RULE_CATEGORY_END()
RULE_CATEGORY(NPC)
@@ -463,6 +482,8 @@ RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPC
RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage
RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage
RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid)
RULE_INT(NPC, NPCToNPCAggroTimerMin, 500)
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000)
RULE_CATEGORY_END()
RULE_CATEGORY(Aggro)
@@ -475,8 +496,9 @@ RULE_INT(Aggro, SpellAggroMod, 100)
RULE_INT(Aggro, SongAggroMod, 33)
RULE_INT(Aggro, PetSpellAggroMod, 10)
RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob
RULE_INT(Aggro, MaxStunProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add.
RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that HP scaling SPA effect in a proc will add.
RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference.
RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live
RULE_CATEGORY_END()
RULE_CATEGORY(TaskSystem)
@@ -490,17 +512,19 @@ RULE_CATEGORY_END()
#ifdef BOTS
RULE_CATEGORY(Bots)
RULE_REAL(Bots, BotManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.
RULE_BOOL(Bots, BotFinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.
RULE_INT(Bots, CreateBotCount, 150) // Number of bots that each account can create
RULE_INT(Bots, SpawnBotCount, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid
RULE_BOOL(Bots, BotQuest, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl
RULE_BOOL(Bots, BotGroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.
RULE_BOOL(Bots, BotSpellQuest, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests.
RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion
RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion
RULE_INT(Bots, CreationLimit, 150) // Number of bots that each account can create
RULE_BOOL(Bots, FinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.
RULE_BOOL(Bots, GroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.
RULE_REAL(Bots, ManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.
RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl
RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests.
RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid
RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group.
RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs.
RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs (optional script)
RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior)
RULE_BOOL(Bots, BotCharacterLevelEnabled, false) // Enables required level to spawn bots
RULE_INT(Bots, BotCharacterLevel, 0) // 0 as default (if level > this value you can spawn bots if BotCharacterLevelEnabled is true)
RULE_CATEGORY_END()
#endif
@@ -584,6 +608,27 @@ RULE_CATEGORY_END()
RULE_CATEGORY(QueryServ)
RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat
RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades
RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins
RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills
RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes
RULE_BOOL(QueryServ, PlayerLogMoves, false) // Logs Player Moves
RULE_BOOL(QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions
RULE_BOOL(QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events
RULE_BOOL(QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item
RULE_BOOL(QueryServ, PlayerLogZone, false) // Logs Player Zone Events
RULE_BOOL(QueryServ, PlayerLogDeaths, false) // Logs Player Deaths
RULE_BOOL(QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State
RULE_BOOL(QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling
RULE_BOOL(QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates
RULE_BOOL(QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates
RULE_BOOL(QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates
RULE_BOOL(QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions
RULE_BOOL(QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases
RULE_BOOL(QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions
RULE_BOOL(QueryServ, PlayerLogIssuedCommandes, false) // Log Player Issued Commands
RULE_BOOL(QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits
RULE_BOOL(QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions
RULE_CATEGORY_END()
RULE_CATEGORY(Inventory)
+140 -2
View File
@@ -84,6 +84,7 @@
#define ServerOP_QGlobalDelete 0x0064
#define ServerOP_DepopPlayerCorpse 0x0065
#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues
#define ServerOP_ChangeSharedMem 0x0067
#define ServerOP_RaidAdd 0x0100 //in use
#define ServerOP_RaidRemove 0x0101 //in use
@@ -181,7 +182,15 @@
#define ServerOP_CZMessagePlayer 0x4008
#define ServerOP_ReloadWorld 0x4009
#define ServerOP_ReloadLogs 0x4010
#define ServerOP_QSSendQuery 0x5000
#define ServerOP_ReloadPerlExportSettings 0x4011
/* Query Server OP Codes */
#define ServerOP_QSPlayerLogTrades 0x5010
#define ServerOP_QSPlayerLogHandins 0x5011
#define ServerOP_QSPlayerLogNPCKills 0x5012
#define ServerOP_QSPlayerLogDeletes 0x5013
#define ServerOP_QSPlayerLogMoves 0x5014
#define ServerOP_QSPlayerLogMerchantTransactions 0x5015
#define ServerOP_QSSendQuery 0x5016
#define ServerOP_CZSignalNPC 0x5017
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
@@ -514,7 +523,7 @@ struct ServerLSPlayerZoneChange_Struct {
uint32 from; // 0 = world
uint32 to; // 0 = world
};
struct ServerLSClientAuth {
struct ClientAuth_Struct {
uint32 lsaccount_id; // ID# in login server's db
char name[30]; // username in login server's db
char key[30]; // the Key the client will present
@@ -538,7 +547,9 @@ struct ServerLSPeerConnect {
struct ServerConnectInfo {
char address[250];
char local_address[250];
uint16 port;
uint32 process_id;
};
struct ServerGMGoto_Struct {
@@ -753,6 +764,7 @@ typedef enum {
struct LauncherZoneRequest {
uint8 command;
char short_name[33];
uint16 port;
};
struct LauncherZoneStatus {
@@ -1106,6 +1118,132 @@ struct CZClientSignalByName_Struct {
uint32 data;
};
struct QSTradeItems_Struct {
uint32 from_id;
uint16 from_slot;
uint32 to_id;
uint16 to_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogTrade_Struct {
uint32 char1_id;
MoneyUpdate_Struct char1_money;
uint16 char1_count;
uint32 char2_id;
MoneyUpdate_Struct char2_money;
uint16 char2_count;
uint16 _detail_count;
QSTradeItems_Struct items[0];
};
struct QSHandinItems_Struct {
char action_type[7]; // handin, return or reward
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogHandin_Struct {
uint32 quest_id;
uint32 char_id;
MoneyUpdate_Struct char_money;
uint16 char_count;
uint32 npc_id;
MoneyUpdate_Struct npc_money;
uint16 npc_count;
uint16 _detail_count;
QSHandinItems_Struct items[0];
};
struct QSPlayerLogNPCKillSub_Struct{
uint32 NPCID;
uint32 ZoneID;
uint32 Type;
};
struct QSPlayerLogNPCKillsPlayers_Struct{
uint32 char_id;
};
struct QSPlayerLogNPCKill_Struct{
QSPlayerLogNPCKillSub_Struct s1;
QSPlayerLogNPCKillsPlayers_Struct Chars[0];
};
struct QSDeleteItems_Struct {
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogDelete_Struct {
uint32 char_id;
uint16 stack_size; // '0' indicates full stack or non-stackable item move
uint16 char_count;
QSDeleteItems_Struct items[0];
};
struct QSMoveItems_Struct {
uint16 from_slot;
uint16 to_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogMove_Struct {
uint32 char_id;
uint16 from_slot;
uint16 to_slot;
uint16 stack_size; // '0' indicates full stack or non-stackable item move
uint16 char_count;
bool postaction;
QSMoveItems_Struct items[0];
};
struct QSTransactionItems_Struct {
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSMerchantLogTransaction_Struct {
uint32 zone_id;
uint32 merchant_id;
MoneyUpdate_Struct merchant_money;
uint16 merchant_count;
uint32 char_id;
MoneyUpdate_Struct char_money;
uint16 char_count;
QSTransactionItems_Struct items[0];
};
struct QSGeneralQuery_Struct {
char QueryString[0];
};
+531 -480
View File
File diff suppressed because it is too large Load Diff
+35 -31
View File
@@ -9,19 +9,19 @@
#include "base_data.h"
#include "fixed_memory_hash_set.h"
#include "fixed_memory_variable_hash_set.h"
#include "inventory.h"
#include <list>
#include <map>
#include <memory>
class EvolveInfo;
class InventoryOld;
class Inventory;
class ItemInst;
struct BaseDataStruct;
struct InspectMessage_Struct;
struct PlayerProfile_Struct;
struct SPDat_Spell_Struct;
struct ItemData;
struct Item_Struct;
struct NPCFactionList;
struct LootTable_Struct;
struct LootDrop_Struct;
@@ -51,9 +51,7 @@ class SharedDatabase : public Database
int32 DeleteStalePlayerCorpses();
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);
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
/*
@@ -66,15 +64,15 @@ class SharedDatabase : public Database
bool UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
bool UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
bool VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst);
bool GetSharedBank(uint32 id, InventoryOld* inv, bool is_charid);
bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid);
int32 GetSharedPlatinum(uint32 account_id);
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
bool GetInventory(uint32 char_id, EQEmu::Inventory* inv);
bool GetInventory(uint32 account_id, char* name, InventoryOld* inv);
bool GetInventory(uint32 char_id, Inventory* inv);
bool GetInventory(uint32 account_id, char* name, Inventory* inv);
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type);
void ClearOldRecastTimestamps(uint32 char_id);
bool SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
bool SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
std::string GetBook(const char *txtfile);
@@ -82,10 +80,9 @@ class SharedDatabase : public Database
/*
Item Methods
*/
ItemInst* CreateItemOld(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateItemOld(const ItemData* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateBaseItemOld(const ItemData* item, int16 charges = 0);
EQEmu::ItemInstance::pointer CreateItem(uint32 item_id, int16 charges = 0, bool unique = true);
ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateItem(const Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges = 0);
/*
Shared Memory crap
@@ -94,52 +91,59 @@ class SharedDatabase : public Database
//items
void GetItemsCount(int32 &item_count, uint32 &max_id);
void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id);
bool LoadItems();
const ItemData* IterateItems(uint32* id);
const ItemData* GetItem(uint32 id);
bool LoadItems(const std::string &prefix);
const Item_Struct* IterateItems(uint32* id);
const Item_Struct* GetItem(uint32 id);
const EvolveInfo* GetEvolveInfo(uint32 loregroup);
//faction lists
void GetFactionListInfo(uint32 &list_count, uint32 &max_lists);
const NPCFactionList* GetNPCFactionEntry(uint32 id);
void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists);
bool LoadNPCFactionLists();
bool LoadNPCFactionLists(const std::string &prefix);
//loot
void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries);
void GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries);
void LoadLootTables(void *data, uint32 size);
void LoadLootDrops(void *data, uint32 size);
bool LoadLoot();
bool LoadLoot(const std::string &prefix);
const LootTable_Struct* GetLootTable(uint32 loottable_id);
const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id);
void LoadSkillCaps(void *data);
bool LoadSkillCaps();
bool LoadSkillCaps(const std::string &prefix);
uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level);
uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level);
int GetMaxSpellID();
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
void LoadSpells(void *data, int max_spells);
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
int GetMaxBaseDataLevel();
bool LoadBaseData();
bool LoadBaseData(const std::string &prefix);
void LoadBaseData(void *data, int max_level);
const BaseDataStruct* GetBaseData(int lvl, int cl);
#ifdef BOTS
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
#endif
protected:
EQEmu::MemoryMappedFile *skill_caps_mmf;
EQEmu::MemoryMappedFile *items_mmf;
EQEmu::FixedMemoryHashSet<ItemData> *items_hash;
EQEmu::MemoryMappedFile *faction_mmf;
EQEmu::FixedMemoryHashSet<NPCFactionList> *faction_hash;
EQEmu::MemoryMappedFile *loot_table_mmf;
EQEmu::FixedMemoryVariableHashSet<LootTable_Struct> *loot_table_hash;
EQEmu::MemoryMappedFile *loot_drop_mmf;
EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct> *loot_drop_hash;
EQEmu::MemoryMappedFile *base_data_mmf;
std::unique_ptr<EQEmu::MemoryMappedFile> skill_caps_mmf;
std::unique_ptr<EQEmu::MemoryMappedFile> items_mmf;
std::unique_ptr<EQEmu::FixedMemoryHashSet<Item_Struct>> items_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> faction_mmf;
std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>> faction_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> loot_table_mmf;
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>> loot_table_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> loot_drop_mmf;
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>> loot_drop_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> base_data_mmf;
std::unique_ptr<EQEmu::MemoryMappedFile> spells_mmf;
};
#endif /*SHAREDDB_H_*/
+5 -4
View File
@@ -108,16 +108,17 @@ enum SkillUseTypes
/*13869*/ SkillBerserking,
/*13902*/ SkillTaunt,
/*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
// SoF+ specific skills
// /*03670*/ SkillRemoveTraps,
// /*13049*/ SkillTripleAttack,
/*03670*/ SkillRemoveTraps,
/*13049*/ SkillTripleAttack,
// RoF2+ specific skills
// /*00789*/ Skill2HPiercing,
// /*01216*/ SkillNone, // This needs to move down as new skills are added
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
// Skill Counts
// /*-----*/ _SkillCount_62 = 75, // use for Ti and earlier max skill checks
// /*-----*/ _SkillCount_SoF = 77, // use for SoF thru RoF1 max skill checks
@@ -170,7 +171,7 @@ enum SkillUseTypes
};
// temporary until it can be sorted out...
#define HIGHEST_SKILL SkillFrenzy
#define HIGHEST_SKILL SkillTripleAttack
// Spell Effects use this value to determine if an effect applies to all skills.
#define ALL_SKILLS -1
+9 -1
View File
@@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id)
bool IsBardSong(uint16 spell_id)
{
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 127 && !spells[spell_id].IsDisciplineBuff)
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255 && !spells[spell_id].IsDisciplineBuff)
return true;
return false;
@@ -1092,6 +1092,14 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id)
return false;
}
bool NoDetrimentalSpellAggro(uint16 spell_id)
{
if (IsValidSpell(spell_id))
return spells[spell_id].no_detrimental_spell_aggro;
return false;
}
uint32 GetNimbusEffect(uint16 spell_id)
{
if (IsValidSpell(spell_id))
+49 -32
View File
@@ -381,47 +381,47 @@ typedef enum {
#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance.
#define SE_TwoHandBash 226 // *not implemented as bonus
#define SE_ReduceSkillTimer 227 // implemented
//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling
#define SE_PersistantCasting 229 // implemented
//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
//#define SE_FreePet 236 // not used
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
#define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr
#define SE_CharmBreakChance 243 // implemented - Total Domination
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
//#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
#define SE_SetBreathLevel 246 // *not implemented as bonus
#define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap.
//#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap.
#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes)
#define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther)
#define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100)
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
#define SE_Blank 254 // implemented
//#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
//#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs
//#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
#define SE_ShroudofStealth 256 // implemented
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
#define SE_CombatStability 259 // implemented[AA] - damage mitigation
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
#define SE_RaiseStatCap 262 // implemented
//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect
#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master.
#define SE_HastenedAASkill 264 // implemented
#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled
#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon.
#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast
//#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance
#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance
#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound.
#define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo)
#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods
@@ -434,14 +434,14 @@ typedef enum {
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
#define SE_Flurry 279 // implemented
#define SE_PetFlurry 280 // implemented[AA]
//#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
//#define SE_LoHSetHeal 284 // not used
//#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
#define SE_FcDamageAmt 286 // implemented - adds direct spell damage
#define SE_SpellDurationIncByTic 287 // implemented
#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch].
#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch)
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
#define SE_Purify 291 // implemented - Removes determental effects
@@ -478,7 +478,7 @@ typedef enum {
#define SE_GateToHomeCity 322 // implemented
#define SE_DefensiveProc 323 // implemented
#define SE_HPToMana 324 // implemented
//#define SE_ChanceInvsBreakToAoE 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability
#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have
#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die
@@ -486,7 +486,7 @@ typedef enum {
#define SE_CriticalDamageMob 330 // implemented
#define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine
//#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp)
#define SE_CastOnRuneFadeEffect 333 // implemented
#define SE_CastOnRuneFadeEffect 333 // implemented
#define SE_BardAEDot 334 // implemented
#define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494)
//#define SE_IllusionaryTarget 336 // not used
@@ -515,8 +515,8 @@ typedef enum {
//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing)
#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed
//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
#define SE_TripleAttackChance 364 // implemented
#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA
@@ -525,7 +525,7 @@ typedef enum {
#define SE_CorruptionCounter 369 // implemented
#define SE_ResistCorruption 370 // implemented
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
#define SE_ApplyEffect 374 // implemented
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
@@ -544,7 +544,7 @@ typedef enum {
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used]
#define SE_LimitManaMax 391 // implemented
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
@@ -579,7 +579,7 @@ typedef enum {
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
@@ -613,12 +613,25 @@ typedef enum {
#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent.
#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type
//#define SE_Ff_Override_NotFocusable 460 //
#define SE_ImprovedDamage2 461 // implemented - Increase spell damage by percent (SE_Fc_Damage_%2)
#define SE_FcDamageAmt2 462 // implemented - Increase spell damage by flat amount (SE_Fc_Damage_Amt2)
//#define SE_Shield_Target 463 //
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
//#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm.
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
//#define SE_DS_Mitigation_Amount 467 //
//#define SE_DS_Mitigation_Percentage 468 //
//#define SE_Chance_Best_in_Spell_Grp 469 //
//#define SE_Trigger_Best_in_Spell Grp 470 //
//#define SE_Double_Melee_Round 471 //
// LAST
#define DF_Permanent 50
#define DF_Aura 51
#define DF_Aura 51
// note this struct is historical, we don't actually need it to be
// aligned to anything, but for maintaining it it is kept in the order that
@@ -731,26 +744,28 @@ struct SPDat_Spell_Struct
/* 194 */ float directional_start; //Cone Start Angle:
/* 195 */ float directional_end; // Cone End Angle:
/* 196 */ bool sneak; // effect can only be used if sneaking (rogue 'Daggerfall' ect)
/* 197 */ bool not_extendable;
/* 198- 199 */
/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell
/* 198 */ bool no_detrimental_spell_aggro;
/* 199 */
/* 200 */ bool suspendable; // buff is suspended in suspended buff zones
/* 201 */ int viral_range;
/* 202 */
/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented)
/* 202 */ int songcap; // individual song cap
/* 203 */
/* 204 */
/* 205 */ bool no_block;
/* 206 */
/* 207 */ int spellgroup;
/* 208 */ int rank; //increments AA effects with same name
/* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though
/* 209 */ int no_resist; //makes spells unresistable, which makes charms unbreakable as well.
/* 210 */ // bool DurationFrozen; ???
/* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat
/* 212 */ bool AllowRest;
/* 213 */ bool InCombat; //Allow spell if target is in combat
/* 214 */ bool OutofCombat; //Allow spell if target is out of combat
/* 215 - 217 */
/* 215 - 216 */
/* 217 */ int override_crit_chance; //Places a cap on the max chance to critical
/* 218 */ int aemaxtargets; //Is used for various AE effects
/* 219 */ int maxtargets; //Is used for beam and ring spells for target # limits (not implemented)
/* 219 */ int no_heal_damage_item_mod;
/* 220 - 223 */
/* 224 */ bool persistdeath; // buff doesn't get stripped on death
/* 225 - 226 */
@@ -759,7 +774,8 @@ struct SPDat_Spell_Struct
/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance)
/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance)
/* 231 */ float min_range; //Min casting range
/* 232 - 236 */
/* 232 */ bool no_remove; //prevents buff from being removed by click
/* 233 - 236 */
uint8 DamageShieldType; // This field does not exist in spells_us.txt
};
@@ -865,6 +881,7 @@ uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
bool NoDetrimentalSpellAggro(uint16 spell_id);
int CalcPetHp(int levelb, int classb, int STA = 75);
const char *GetRandPetName();
+3 -1
View File
@@ -23,7 +23,9 @@
*/
#ifdef _WINDOWS
#define snprintf _snprintf
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
#define snprintf _snprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
+3 -1
View File
@@ -43,7 +43,9 @@ typedef unsigned char uchar;
typedef const char Const_char; //for perl XS
#ifdef _WINDOWS
#define snprintf _snprintf
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
#define snprintf _snprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
typedef void ThreadReturnType;
+6 -1
View File
@@ -30,7 +30,12 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9083
#define CURRENT_BINARY_DATABASE_VERSION 9095
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
#ifndef WIN32
-2
View File
@@ -102,8 +102,6 @@ int main(int argc, char *argv[]) {
Log.Out(Logs::Detail, Logs::Launcher, "Starting main loop...");
// zones["test"] = new ZoneLaunch(&world, "./zone", "dynamic_1");
ProcLauncher *launch = ProcLauncher::get();
RunLoops = true;
while(RunLoops) {
+1 -2
View File
@@ -86,14 +86,13 @@ void WorldServer::Process() {
}
const LauncherZoneRequest *lzr = (const LauncherZoneRequest *) pack->pBuffer;
switch(ZoneRequestCommands(lzr->command)) {
case ZR_Start: {
if(m_zones.find(lzr->short_name) != m_zones.end()) {
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s, but it is already running.", lzr->short_name);
} else {
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s.", lzr->short_name);
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, m_config);
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config);
m_zones[lzr->short_name] = l;
}
break;
+10 -5
View File
@@ -34,10 +34,11 @@ void ZoneLaunch::InitStartTimer() {
}
ZoneLaunch::ZoneLaunch(WorldServer *world, const char *launcher_name,
const char *zone_name, const EQEmuConfig *config)
const char *zone_name, uint16 port, const EQEmuConfig *config)
: m_state(StateStartPending),
m_world(world),
m_zone(zone_name),
m_port(port),
m_launcherName(launcher_name),
m_config(config),
m_timer(config->RestartWait),
@@ -61,10 +62,14 @@ void ZoneLaunch::SendStatus() const {
void ZoneLaunch::Start() {
ProcLauncher::Spec *spec = new ProcLauncher::Spec();
spec->program = m_config->ZoneExe;
// if(m_zone.substr(0,7) == "dynamic")
// spec->args.push_back(".");
// else
spec->args.push_back(m_zone);
if(m_port) {
std::string arg = m_zone + std::string(":") + std::to_string(m_port);
spec->args.push_back(arg);
} else {
spec->args.push_back(m_zone);
}
spec->args.push_back(m_launcherName);
spec->handler = this;
spec->logFile = m_config->LogPrefix + m_zone + m_config->LogSuffix;
+2 -1
View File
@@ -28,7 +28,7 @@ class EQEmuConfig;
class ZoneLaunch : protected ProcLauncher::EventHandler {
public:
ZoneLaunch(WorldServer *world, const char *launcher_name,
const char *zone_name, const EQEmuConfig *config);
const char *zone_name, uint16 port, const EQEmuConfig *config);
virtual ~ZoneLaunch();
void Stop(bool graceful = true);
@@ -63,6 +63,7 @@ protected:
const std::string m_zone;
const char *const m_launcherName;
const EQEmuConfig *const m_config;
const uint16 m_port;
Timer m_timer;
ProcLauncher::ProcRef m_ref;
+1 -3
View File
@@ -6,7 +6,6 @@ SET(eqlogin_sources
config.cpp
database_mysql.cpp
database_postgresql.cpp
error_log.cpp
main.cpp
server_manager.cpp
world_server.cpp
@@ -26,7 +25,6 @@ SET(eqlogin_headers
database_postgresql.h
encryption.h
eq_crypto_api.h
error_log.h
login_server.h
login_structures.h
options.h
@@ -43,7 +41,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers})
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
IF(MSVC)
SET_TARGET_PROPERTIES(loginserver PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
+107 -102
View File
@@ -16,12 +16,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client.h"
#include "error_log.h"
#include "login_server.h"
#include "login_structures.h"
#include "../common/misc_functions.h"
#include "../common/eqemu_logsys.h"
extern ErrorLog *server_log;
extern EQEmuLogSys Log;
extern LoginServer server;
Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
@@ -41,7 +41,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
server_log->Log(log_network, "Application packet received from client (size %u)", app->Size());
Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size());
}
if(server.options.IsDumpInPacketsOn())
@@ -55,7 +55,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
server_log->Log(log_network, "Session ready received from client.");
Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client.");
}
Handle_SessionReady((const char*)app->pBuffer, app->Size());
break;
@@ -64,13 +64,13 @@ bool Client::Process()
{
if(app->Size() < 20)
{
server_log->Log(log_network_error, "Login received but it is too small, discarding.");
Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding.");
break;
}
if(server.options.IsTraceOn())
{
server_log->Log(log_network, "Login received from client.");
Log.Out(Logs::General, Logs::Login_Server, "Login received from client.");
}
Handle_Login((const char*)app->pBuffer, app->Size());
@@ -80,7 +80,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
server_log->Log(log_network, "Server list request received from client.");
Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client.");
}
SendServerListPacket();
@@ -90,7 +90,7 @@ bool Client::Process()
{
if(app->Size() < sizeof(PlayEverquestRequest_Struct))
{
server_log->Log(log_network_error, "Play received but it is too small, discarding.");
Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding.");
break;
}
@@ -101,7 +101,7 @@ bool Client::Process()
{
char dump[64];
app->build_header_dump(dump);
server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump);
Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump);
}
}
@@ -116,20 +116,20 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
{
if(status != cs_not_sent_session_ready)
{
server_log->Log(log_network_error, "Session ready received again after already being received.");
Log.Out(Logs::General, Logs::Error, "Session ready received again after already being received.");
return;
}
if(size < sizeof(unsigned int))
{
server_log->Log(log_network_error, "Session ready was too small.");
Log.Out(Logs::General, Logs::Error, "Session ready was too small.");
return;
}
unsigned int mode = *((unsigned int*)data);
if(mode == (unsigned int)lm_from_world)
{
server_log->Log(log_network, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
Log.Out(Logs::General, Logs::Login_Server, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
connection->Close();
return;
}
@@ -175,138 +175,144 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
void Client::Handle_Login(const char* data, unsigned int size)
{
if(status != cs_waiting_for_login)
{
server_log->Log(log_network_error, "Login received after already having logged in.");
if(status != cs_waiting_for_login) {
Log.Out(Logs::General, Logs::Error, "Login received after already having logged in.");
return;
}
if((size - 12) % 8 != 0)
{
server_log->Log(log_network_error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
if((size - 12) % 8 != 0) {
Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
return;
}
status = cs_logged_in;
string e_user;
string e_hash;
char *e_buffer = nullptr;
unsigned int d_account_id = 0;
string d_pass_hash;
string entered_username;
string entered_password_hash_result;
char *login_packet_buffer = nullptr;
unsigned int db_account_id = 0;
string db_account_password_hash;
#ifdef WIN32
e_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
int buffer_len = strlen(e_buffer);
e_hash.assign(e_buffer, buffer_len);
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
int login_packet_buffer_length = strlen(login_packet_buffer);
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
if(server.options.IsTraceOn())
{
server_log->Log(log_client, "User: %s", e_user.c_str());
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
if(server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
}
server.eq_crypto->DeleteHeap(e_buffer);
server.eq_crypto->DeleteHeap(login_packet_buffer);
#else
e_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
login_packet_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
int buffer_len = strlen(e_buffer);
e_hash.assign(e_buffer, buffer_len);
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
int login_packet_buffer_length = strlen(login_packet_buffer);
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
if(server.options.IsTraceOn())
{
server_log->Log(log_client, "User: %s", e_user.c_str());
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
if(server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
}
_HeapDeleteCharBuffer(e_buffer);
_HeapDeleteCharBuffer(login_packet_buffer);
#endif
bool result;
if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false)
{
server_log->Log(log_client_error, "Error logging in, user %s does not exist in the database.", e_user.c_str());
result = false;
}
else
{
if(d_pass_hash.compare(e_hash) == 0)
{
if(server.db->GetLoginDataFromAccountName(entered_username, db_account_password_hash, db_account_id) == false) {
/* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/
if (
server.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0 &&
server.db->CreateLoginData(entered_username, entered_password_hash_result, db_account_id) == true
){
Log.Out(Logs::General, Logs::Error, "User %s does not exist in the database, so we created it...", entered_username.c_str());
result = true;
}
else
{
else{
Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", entered_username.c_str());
result = false;
}
}
else {
if(db_account_password_hash.compare(entered_password_hash_result) == 0) {
result = true;
}
else {
result = false;
}
}
if(result)
{
server.CM->RemoveExistingClient(d_account_id);
/* Login Accepted */
if(result) {
server.client_manager->RemoveExistingClient(db_account_id);
in_addr in;
in.s_addr = connection->GetRemoteIP();
server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in)));
server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in)));
GenerateKey();
account_id = d_account_id;
account_name = e_user;
account_id = db_account_id;
account_name = entered_username;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
LoginLoginAccepted_Struct* llas = (LoginLoginAccepted_Struct *)outapp->pBuffer;
llas->unknown1 = llrs->unknown1;
llas->unknown2 = llrs->unknown2;
llas->unknown3 = llrs->unknown3;
llas->unknown4 = llrs->unknown4;
llas->unknown5 = llrs->unknown5;
LoginAccepted_Struct* login_accepted = (LoginAccepted_Struct *)outapp->pBuffer;
login_accepted->unknown1 = llrs->unknown1;
login_accepted->unknown2 = llrs->unknown2;
login_accepted->unknown3 = llrs->unknown3;
login_accepted->unknown4 = llrs->unknown4;
login_accepted->unknown5 = llrs->unknown5;
Login_ReplyBlock_Struct * lrbs = new Login_ReplyBlock_Struct;
memset(lrbs, 0, sizeof(Login_ReplyBlock_Struct));
LoginFailedAttempts_Struct * login_failed_attempts = new LoginFailedAttempts_Struct;
memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct));
lrbs->failed_attempts = 0;
lrbs->message = 0x01;
lrbs->lsid = d_account_id;
lrbs->unknown3[3] = 0x03;
lrbs->unknown4[3] = 0x02;
lrbs->unknown5[0] = 0xe7;
lrbs->unknown5[1] = 0x03;
lrbs->unknown6[0] = 0xff;
lrbs->unknown6[1] = 0xff;
lrbs->unknown6[2] = 0xff;
lrbs->unknown6[3] = 0xff;
lrbs->unknown7[0] = 0xa0;
lrbs->unknown7[1] = 0x05;
lrbs->unknown8[3] = 0x02;
lrbs->unknown9[0] = 0xff;
lrbs->unknown9[1] = 0x03;
lrbs->unknown11[0] = 0x63;
lrbs->unknown12[0] = 0x01;
memcpy(lrbs->key, key.c_str(), key.size());
login_failed_attempts->failed_attempts = 0;
login_failed_attempts->message = 0x01;
login_failed_attempts->lsid = db_account_id;
login_failed_attempts->unknown3[3] = 0x03;
login_failed_attempts->unknown4[3] = 0x02;
login_failed_attempts->unknown5[0] = 0xe7;
login_failed_attempts->unknown5[1] = 0x03;
login_failed_attempts->unknown6[0] = 0xff;
login_failed_attempts->unknown6[1] = 0xff;
login_failed_attempts->unknown6[2] = 0xff;
login_failed_attempts->unknown6[3] = 0xff;
login_failed_attempts->unknown7[0] = 0xa0;
login_failed_attempts->unknown7[1] = 0x05;
login_failed_attempts->unknown8[3] = 0x02;
login_failed_attempts->unknown9[0] = 0xff;
login_failed_attempts->unknown9[1] = 0x03;
login_failed_attempts->unknown11[0] = 0x63;
login_failed_attempts->unknown12[0] = 0x01;
memcpy(login_failed_attempts->key, key.c_str(), key.size());
#ifdef WIN32
unsigned int e_size;
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)lrbs, 75, e_size);
memcpy(llas->encrypt, encrypted_buffer, 80);
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)login_failed_attempts, 75, e_size);
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
server.eq_crypto->DeleteHeap(encrypted_buffer);
#else
unsigned int e_size;
char *encrypted_buffer = Encrypt((const char*)lrbs, 75, e_size);
memcpy(llas->encrypt, encrypted_buffer, 80);
char *encrypted_buffer = Encrypt((const char*)login_failed_attempts, 75, e_size);
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
_HeapDeleteCharBuffer(encrypted_buffer);
#endif
if(server.options.IsDumpOutPacketsOn())
{
if(server.options.IsDumpOutPacketsOn()) {
DumpPacket(outapp);
}
connection->QueuePacket(outapp);
delete outapp;
}
else
{
else {
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct));
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
LoginLoginFailed_Struct* llas = (LoginLoginFailed_Struct *)outapp->pBuffer;
@@ -317,8 +323,7 @@ void Client::Handle_Login(const char* data, unsigned int size)
llas->unknown5 = llrs->unknown5;
memcpy(llas->unknown6, FailedLoginResponseData, sizeof(FailedLoginResponseData));
if(server.options.IsDumpOutPacketsOn())
{
if(server.options.IsDumpOutPacketsOn()) {
DumpPacket(outapp);
}
@@ -331,7 +336,7 @@ void Client::Handle_Play(const char* data)
{
if(status != cs_logged_in)
{
server_log->Log(log_client_error, "Client sent a play request when they either were not logged in, discarding.");
Log.Out(Logs::General, Logs::Error, "Client sent a play request when they either were not logged in, discarding.");
return;
}
@@ -341,18 +346,18 @@ void Client::Handle_Play(const char* data)
if(server.options.IsTraceOn())
{
server_log->Log(log_network, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
Log.Out(Logs::General, Logs::Login_Server, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
}
this->play_server_id = (unsigned int)play->ServerNumber;
play_sequence_id = sequence_in;
play_server_id = server_id_in;
server.SM->SendUserToWorldRequest(server_id_in, account_id);
server.server_manager->SendUserToWorldRequest(server_id_in, account_id);
}
void Client::SendServerListPacket()
{
EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this);
EQApplicationPacket *outapp = server.server_manager->CreateServerListPacket(this);
if(server.options.IsDumpOutPacketsOn())
{
@@ -367,8 +372,8 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp)
{
if(server.options.IsTraceOn())
{
server_log->Log(log_network_trace, "Sending play response for %s.", GetAccountName().c_str());
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
Log.Out(Logs::General, Logs::Netcode, "Sending play response for %s.", GetAccountName().c_str());
// server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
}
connection->QueuePacket(outapp);
status = cs_logged_in;
@@ -378,7 +383,7 @@ void Client::GenerateKey()
{
key.clear();
int count = 0;
while(count < 10)
while (count < 10)
{
static const char key_selection[] =
{
+15 -14
View File
@@ -16,13 +16,14 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client_manager.h"
#include "error_log.h"
#include "login_server.h"
extern ErrorLog *server_log;
extern LoginServer server;
extern bool run_server;
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
ClientManager::ClientManager()
{
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
@@ -30,18 +31,18 @@ ClientManager::ClientManager()
titanium_ops = new RegularOpcodeManager;
if(!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str()))
{
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
server.config->GetVariable("Titanium", "opcodes").c_str());
run_server = false;
}
if(titanium_stream->Open())
{
server_log->Log(log_network, "ClientManager listening on Titanium stream.");
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on Titanium stream.");
}
else
{
server_log->Log(log_error, "ClientManager fatal error: couldn't open Titanium stream.");
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open Titanium stream.");
run_server = false;
}
@@ -50,18 +51,18 @@ ClientManager::ClientManager()
sod_ops = new RegularOpcodeManager;
if(!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str()))
{
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
server.config->GetVariable("SoD", "opcodes").c_str());
run_server = false;
}
if(sod_stream->Open())
{
server_log->Log(log_network, "ClientManager listening on SoD stream.");
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on SoD stream.");
}
else
{
server_log->Log(log_error, "ClientManager fatal error: couldn't open SoD stream.");
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open SoD stream.");
run_server = false;
}
}
@@ -99,7 +100,7 @@ void ClientManager::Process()
{
struct in_addr in;
in.s_addr = cur->GetRemoteIP();
server_log->Log(log_network, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
Log.Out(Logs::General, Logs::Login_Server, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
cur->SetOpcodeManager(&titanium_ops);
Client *c = new Client(cur, cv_titanium);
@@ -112,7 +113,7 @@ void ClientManager::Process()
{
struct in_addr in;
in.s_addr = cur->GetRemoteIP();
server_log->Log(log_network, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
Log.Out(Logs::General, Logs::Login_Server, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
cur->SetOpcodeManager(&sod_ops);
Client *c = new Client(cur, cv_sod);
@@ -125,7 +126,7 @@ void ClientManager::Process()
{
if((*iter)->Process() == false)
{
server_log->Log(log_client, "Client had a fatal error and had to be removed from the login.");
Log.Out(Logs::General, Logs::Debug, "Client had a fatal error and had to be removed from the login.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -144,7 +145,7 @@ void ClientManager::ProcessDisconnect()
std::shared_ptr<EQStream> c = (*iter)->GetConnection();
if(c->CheckClosed())
{
server_log->Log(log_network, "Client disconnected from the server, removing client.");
Log.Out(Logs::General, Logs::Login_Server, "Client disconnected from the server, removing client.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -172,7 +173,7 @@ void ClientManager::RemoveExistingClient(unsigned int account_id)
{
if((*iter)->GetAccountID() == account_id)
{
server_log->Log(log_network, "Client attempting to log in and existing client already logged in, removing existing client.");
Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -200,7 +201,7 @@ Client *ClientManager::GetClient(unsigned int account_id)
if(count > 1)
{
server_log->Log(log_client_error, "More than one client with a given account_id existed in the client list.");
Log.Out(Logs::General, Logs::Error, "More than one client with a given account_id existed in the client list.");
}
return cur;
}
+6 -6
View File
@@ -16,10 +16,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "config.h"
#include "error_log.h"
extern ErrorLog *server_log;
extern EQEmuLogSys Log;
/**
* Retrieves the variable we want from our title or theme
* First gets the map from the title
@@ -48,7 +48,7 @@ void Config::Parse(const char *file_name)
{
if(file_name == nullptr)
{
server_log->Log(log_error, "Config::Parse(), file_name passed was null.");
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file_name passed was null.");
return;
}
@@ -71,7 +71,7 @@ void Config::Parse(const char *file_name)
++iter;
if(iter == tokens.end())
{
server_log->Log(log_error, "Config::Parse(), EOF before title done parsing.");
Log.Out(Logs::General, Logs::Error, "Config::Parse(), EOF before title done parsing.");
fclose(input);
vars.clear();
return;
@@ -104,7 +104,7 @@ void Config::Parse(const char *file_name)
mode++;
if((*iter).compare("=") != 0)
{
server_log->Log(log_error, "Config::Parse(), invalid parse token where = should be.");
Log.Out(Logs::General, Logs::Error, "Config::Parse(), invalid parse token where = should be.");
fclose(input);
vars.clear();
return;
@@ -133,7 +133,7 @@ void Config::Parse(const char *file_name)
}
else
{
server_log->Log(log_error, "Config::Parse(), file was unable to be opened for parsing.");
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file was unable to be opened for parsing.");
}
}
+2
View File
@@ -44,6 +44,8 @@ public:
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; }
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id) { return false; }
/**
* Retrieves the world registration from the long and short names provided.
* Needed for world login procedure.
+86 -61
View File
@@ -20,14 +20,12 @@
#ifdef EQEMU_MYSQL_ENABLED
#include "database_mysql.h"
#include "error_log.h"
#include "login_server.h"
#include "../common/eqemu_logsys.h"
extern ErrorLog *server_log;
extern EQEmuLogSys Log;
extern LoginServer server;
#pragma comment(lib, "mysqlclient.lib")
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name)
{
this->user = user;
@@ -35,35 +33,35 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port,
this->host = host;
this->name = name;
db = mysql_init(nullptr);
if(db)
database = mysql_init(nullptr);
if(database)
{
my_bool r = 1;
mysql_options(db, MYSQL_OPT_RECONNECT, &r);
if(!mysql_real_connect(db, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
mysql_options(database, MYSQL_OPT_RECONNECT, &r);
if(!mysql_real_connect(database, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
{
mysql_close(db);
server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(db));
mysql_close(database);
Log.Out(Logs::General, Logs::Error, "Failed to connect to MySQL database. Error: %s", mysql_error(database));
exit(1);
}
}
else
{
server_log->Log(log_database, "Failed to create db object in MySQL database.");
Log.Out(Logs::General, Logs::Error, "Failed to create db object in MySQL database.");
}
}
DatabaseMySQL::~DatabaseMySQL()
{
if(db)
if(database)
{
mysql_close(db);
mysql_close(database);
}
}
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
{
if(!db)
if (!database)
{
return false;
}
@@ -75,17 +73,17 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
query << name;
query << "'";
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(db);
res = mysql_use_result(database);
if(res)
if (res)
{
while((row = mysql_fetch_row(res)) != nullptr)
while ((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]);
password = row[1];
@@ -94,14 +92,41 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
}
}
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id)
{
if (!database) {
return false;
}
MYSQL_RES *result;
MYSQL_ROW row;
stringstream query(stringstream::in | stringstream::out);
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
if (mysql_query(database, query.str().c_str()) != 0) {
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
else{
id = mysql_insert_id(database);
return true;
}
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password)
unsigned int &trusted, string &list_desc, string &account, string &password)
{
if(!db)
if (!database)
{
return false;
}
@@ -110,8 +135,8 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
MYSQL_ROW row;
char escaped_short_name[101];
unsigned long length;
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length+1] = 0;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
@@ -120,16 +145,16 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
query << escaped_short_name;
query << "'";
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(db);
if(res)
res = mysql_use_result(database);
if (res)
{
if((row = mysql_fetch_row(res)) != nullptr)
if ((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]);
desc = row[1];
@@ -139,22 +164,22 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
int db_account_id = atoi(row[5]);
mysql_free_result(res);
if(db_account_id > 0)
if (db_account_id > 0)
{
stringstream query(stringstream::in | stringstream::out);
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
query << " WHERE ServerAdminID = " << db_account_id;
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(db);
if(res)
res = mysql_use_result(database);
if (res)
{
if((row = mysql_fetch_row(res)) != nullptr)
if ((row = mysql_fetch_row(res)) != nullptr)
{
account = row[0];
password = row[1];
@@ -163,20 +188,20 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
}
}
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
return true;
}
}
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
{
if(!db)
if (!database)
{
return;
}
@@ -187,15 +212,15 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
query << "', LastLoginDate = now() where LoginServerID = ";
query << id;
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
}
}
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email)
{
if(!db)
if (!database)
{
return;
}
@@ -206,23 +231,23 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
query << "', LastIPAddress = '0.0.0.0', LastLoginDate = now()";
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
}
}
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
{
if(!db)
if (!database)
{
return;
}
char escaped_long_name[101];
unsigned long length;
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length+1] = 0;
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
query << ip_address;
@@ -231,15 +256,15 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
query << "' WHERE ServerID = ";
query << id;
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
}
}
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id)
{
if(!db)
if (!database)
{
return false;
}
@@ -249,23 +274,23 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
char escaped_long_name[201];
char escaped_short_name[101];
unsigned long length;
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length+1] = 0;
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length+1] = 0;
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length + 1] = 0;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(db);
if(res)
res = mysql_use_result(database);
if (res)
{
if((row = mysql_fetch_row(res)) != nullptr)
if ((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]) + 1;
mysql_free_result(res);
@@ -275,15 +300,15 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";
if(mysql_query(db, query.str().c_str()) != 0)
if (mysql_query(database, query.str().c_str()) != 0)
{
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
return true;
}
}
server_log->Log(log_database, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
Log.Out(Logs::General, Logs::Error, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
return false;
}
+5 -3
View File
@@ -35,7 +35,7 @@ public:
/**
* Constructor, sets our database to null.
*/
DatabaseMySQL() { db = nullptr; }
DatabaseMySQL() { database = nullptr; }
/**
* Constructor, tries to set our database to connect to the supplied options.
@@ -50,7 +50,7 @@ public:
/**
* @return Returns true if the database successfully connected.
*/
virtual bool IsConnected() { return (db != nullptr); }
virtual bool IsConnected() { return (database != nullptr); }
/**
* Retrieves the login data (password hash and account id) from the account name provided
@@ -59,6 +59,8 @@ public:
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id);
/**
* Retrieves the world registration from the long and short names provided.
* Needed for world login procedure.
@@ -88,7 +90,7 @@ public:
virtual bool CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id);
protected:
std::string user, pass, host, port, name;
MYSQL *db;
MYSQL *database;
};
#endif
+7 -7
View File
@@ -23,7 +23,7 @@
#include "error_log.h"
#include "login_server.h"
extern ErrorLog *server_log;
extern LoginServer server;
#pragma comment(lib, "libpq.lib")
@@ -34,12 +34,12 @@ DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, st
db = PQsetdbLogin(host.c_str(), port.c_str(), nullptr, nullptr, name.c_str(), user.c_str(), pass.c_str());
if(!db)
{
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
}
if(PQstatus(db) != CONNECTION_OK)
{
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
PQfinish(db);
db = nullptr;
}
@@ -83,7 +83,7 @@ bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &passwo
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
PQclear(res);
return false;
}
@@ -135,7 +135,7 @@ bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_nam
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
PQclear(res);
return false;
}
@@ -188,7 +188,7 @@ void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address)
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
}
PQclear(res);
}
@@ -225,7 +225,7 @@ void DatabasePostgreSQL::UpdateWorldRegistration(unsigned int id, string long_na
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
}
PQclear(res);
}
+6 -6
View File
@@ -17,16 +17,16 @@
*/
#include "../common/global_define.h"
#include "encryption.h"
#include "error_log.h"
#include <string>
extern ErrorLog *server_log;
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
bool Encryption::LoadCrypto(std::string name)
{
if(!Load(name.c_str()))
{
server_log->Log(log_error, "Failed to load %s from the operating system.", name.c_str());
Log.Out(Logs::General, Logs::Error, "Failed to load %s from the operating system.", name.c_str());
return false;
}
else
@@ -34,21 +34,21 @@ bool Encryption::LoadCrypto(std::string name)
encrypt_func = (DLLFUNC_Encrypt)GetSym("Encrypt");
if(encrypt_func == NULL)
{
server_log->Log(log_error, "Failed to attach Encrypt.");
Log.Out(Logs::General, Logs::Error, "Failed to attach Encrypt.");
Unload();
return false;
}
decrypt_func = (DLLFUNC_DecryptUsernamePassword)GetSym("DecryptUsernamePassword");
if(decrypt_func == NULL)
{
server_log->Log(log_error, "Failed to attach DecryptUsernamePassword.");
Log.Out(Logs::General, Logs::Error, "Failed to attach DecryptUsernamePassword.");
Unload();
return false;
}
delete_func = (DLLFUNC_HeapDelete)GetSym("_HeapDeleteCharBuffer");
if(delete_func == NULL)
{
server_log->Log(log_error, "Failed to attach _HeapDeleteCharBuffer.");
Log.Out(Logs::General, Logs::Error, "Failed to attach _HeapDeleteCharBuffer.");
Unload();
return false;
}
-210
View File
@@ -1,210 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2010 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
*/
#include <string.h>
#include "error_log.h"
const char *eqLogTypes[_log_largest_type] =
{
"Debug",
"Error",
"Database",
"Network",
"Network Trace",
"Network Error",
"World",
"World Error",
"Client",
"Client Error"
};
ErrorLog::ErrorLog(const char* file_name)
{
log_mutex = new Mutex();
error_log = fopen(file_name, "w");
}
ErrorLog::~ErrorLog()
{
log_mutex->lock();
if(error_log)
{
fclose(error_log);
}
log_mutex->unlock();
delete log_mutex;
}
void ErrorLog::Log(eqLogType type, const char *message, ...)
{
if(type >= _log_largest_type)
{
return;
}
va_list argptr;
char *buffer = new char[4096];
va_start(argptr, message);
vsnprintf(buffer, 4096, message, argptr);
va_end(argptr);
time_t m_clock;
struct tm *m_time;
time(&m_clock);
m_time = localtime(&m_clock);
log_mutex->lock();
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
buffer);
if(error_log)
{
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
buffer);
fflush(error_log);
}
log_mutex->unlock();
delete[] buffer;
}
void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size)
{
if(type >= _log_largest_type)
{
return;
}
log_mutex->lock();
time_t m_clock;
struct tm *m_time;
time(&m_clock);
m_time = localtime(&m_clock);
log_mutex->lock();
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u:\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
(unsigned int)size);
if(error_log)
{
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
(unsigned int)size);
}
char ascii[17]; //16 columns + 1 null term
memset(ascii, 0, 17);
size_t j = 0;
size_t i = 0;
for(; i < size; ++i)
{
if(i % 16 == 0)
{
if(i != 0)
{
printf(" | %s\n", ascii);
if(error_log)
{
fprintf(error_log, " | %s\n", ascii);
}
}
printf("%.4u: ", (unsigned int)i);
memset(ascii, 0, 17);
j = 0;
}
else if(i % 8 == 0)
{
printf("- ");
if(error_log)
{
fprintf(error_log, "- ");
}
}
printf("%02X ", (unsigned int)data[i]);
if(error_log)
{
fprintf(error_log, "%02X ", (unsigned int)data[i]);
}
if(data[i] >= 32 && data[i] < 127)
{
ascii[j++] = data[i];
}
else
{
ascii[j++] = '.';
}
}
size_t k = (i - 1) % 16;
if(k < 8)
{
printf(" ");
if(error_log)
{
fprintf(error_log, " ");
}
}
for(size_t h = k + 1; h < 16; ++h)
{
printf(" ");
if(error_log)
{
fprintf(error_log, " ");
}
}
printf(" | %s\n", ascii);
if(error_log)
{
fprintf(error_log, " | %s\n", ascii);
fflush(error_log);
}
log_mutex->unlock();
}
-79
View File
@@ -1,79 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2010 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_ERROR_LOG_H
#define EQEMU_ERROR_LOG_H
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string>
#include "../common/mutex.h"
/**
* Dictates the log type specified in ErrorLog for Log(...)
*/
enum eqLogType
{
log_debug,
log_error,
log_database,
log_network,
log_network_trace,
log_network_error,
log_world,
log_world_error,
log_client,
log_client_error,
_log_largest_type
};
/**
* Basic error logging class.
* Thread safe logging class that records time and date to both a file and to console(if exists).
*/
class ErrorLog
{
public:
/**
* Constructor: opens the log file for writing and creates our mutex for writing to the log.
*/
ErrorLog(const char* file_name);
/**
* Closes the file and destroys the mutex.
*/
~ErrorLog();
/**
* Writes to the log system a variable message.
*/
void Log(eqLogType type, const char *message, ...);
/**
* Writes to the log system a packet.
*/
void LogPacket(eqLogType type, const char *data, size_t size);
protected:
Mutex *log_mutex;
FILE* error_log;
};
#endif
+3 -4
View File
@@ -18,7 +18,6 @@
#ifndef EQEMU_LOGINSERVER_H
#define EQEMU_LOGINSERVER_H
#include "error_log.h"
#include "config.h"
#include "database.h"
#include "database_mysql.h"
@@ -40,7 +39,7 @@ public:
* but it's the most trivial way to do this.
*/
#ifdef WIN32
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), SM(nullptr) { }
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), server_manager(nullptr) { }
#else
LoginServer() : config(nullptr), db(nullptr) { }
#endif
@@ -48,8 +47,8 @@ public:
Config *config;
Database *db;
Options options;
ServerManager *SM;
ClientManager *CM;
ServerManager *server_manager;
ClientManager *client_manager;
#ifdef WIN32
Encryption *eq_crypto;
+2 -2
View File
@@ -38,7 +38,7 @@ struct LoginLoginRequest_Struct {
char unknown6[16];
};
struct LoginLoginAccepted_Struct {
struct LoginAccepted_Struct {
short unknown1;
short unknown2;
short unknown3;
@@ -47,7 +47,7 @@ struct LoginLoginAccepted_Struct {
char encrypt[80];
};
struct Login_ReplyBlock_Struct
struct LoginFailedAttempts_Struct
{
char message; //0x01
char unknown2[7]; //0x00
+79 -133
View File
@@ -32,7 +32,6 @@
TimeoutManager timeout_manager;
LoginServer server;
EQEmuLogSys Log;
ErrorLog *server_log;
bool run_server = true;
void CatchSignal(int sig_num)
@@ -43,106 +42,63 @@ int main()
{
RegisterExecutablePlatform(ExePlatformLogin);
set_exception_handler();
Log.LoadLogSettingsDefaults();
//Create our error log, is of format login_<number>.log
time_t current_time = time(nullptr);
std::stringstream log_name(std::stringstream::in | std::stringstream::out);
#ifdef WIN32
log_name << ".\\logs\\login_" << (unsigned int)current_time << ".log";
#else
log_name << "./logs/login_" << (unsigned int)current_time << ".log";
#endif
server_log = new ErrorLog(log_name.str().c_str());
server_log->Log(log_debug, "Logging System Init.");
Log.log_settings[Logs::Error].log_to_console = Logs::General;
//Create our subsystem and parse the ini file.
Log.Out(Logs::General, Logs::Login_Server, "Logging System Init.");
/* Parse out login.ini */
server.config = new Config();
server_log->Log(log_debug, "Config System Init.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Init.");
server.config->Parse("login.ini");
//Parse unregistered allowed option.
if(server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
{
if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
server.options.AllowUnregistered(false);
}
//Parse trace option.
if(server.config->GetVariable("options", "trace").compare("TRUE") == 0)
{
if (server.config->GetVariable("options", "trace").compare("TRUE") == 0)
server.options.Trace(true);
}
//Parse trace option.
if(server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
{
if (server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
server.options.WorldTrace(true);
}
//Parse packet inc dump option.
if(server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
{
if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
server.options.DumpInPackets(true);
}
//Parse packet out dump option.
if(server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
{
if (server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
server.options.DumpOutPackets(true);
}
//Parse encryption mode option.
std::string mode = server.config->GetVariable("security", "mode");
if(mode.size() > 0)
{
if (mode.size() > 0)
server.options.EncryptionMode(atoi(mode.c_str()));
}
//Parse local network option.
std::string ln = server.config->GetVariable("options", "local_network");
if(ln.size() > 0)
{
server.options.LocalNetwork(ln);
}
std::string local_network = server.config->GetVariable("options", "local_network");
if (local_network.size() > 0)
server.options.LocalNetwork(local_network);
//Parse reject duplicate servers option.
if(server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
{
if (server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
server.options.RejectDuplicateServers(true);
}
//Parse account table option.
ln = server.config->GetVariable("schema", "account_table");
if(ln.size() > 0)
{
server.options.AccountTable(ln);
}
local_network = server.config->GetVariable("schema", "account_table");
if (local_network.size() > 0)
server.options.AccountTable(local_network);
//Parse world account table option.
ln = server.config->GetVariable("schema", "world_registration_table");
if(ln.size() > 0)
{
server.options.WorldRegistrationTable(ln);
}
local_network = server.config->GetVariable("schema", "world_registration_table");
if (local_network.size() > 0)
server.options.WorldRegistrationTable(local_network);
//Parse admin world account table option.
ln = server.config->GetVariable("schema", "world_admin_registration_table");
if(ln.size() > 0)
{
server.options.WorldAdminRegistrationTable(ln);
}
local_network = server.config->GetVariable("schema", "world_admin_registration_table");
if (local_network.size() > 0)
server.options.WorldAdminRegistrationTable(local_network);
//Parse world type table option.
ln = server.config->GetVariable("schema", "world_server_type_table");
if(ln.size() > 0)
{
server.options.WorldServerTypeTable(ln);
}
local_network = server.config->GetVariable("schema", "world_server_type_table");
if (local_network.size() > 0)
server.options.WorldServerTypeTable(local_network);
//Create our DB from options.
if(server.config->GetVariable("database", "subsystem").compare("MySQL") == 0)
{
/* Create database connection */
if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) {
#ifdef EQEMU_MYSQL_ENABLED
server_log->Log(log_debug, "MySQL Database Init.");
Log.Out(Logs::General, Logs::Login_Server, "MySQL Database Init.");
server.db = (Database*)new DatabaseMySQL(
server.config->GetVariable("database", "user"),
server.config->GetVariable("database", "password"),
@@ -151,10 +107,9 @@ int main()
server.config->GetVariable("database", "db"));
#endif
}
else if(server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0)
{
else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) {
#ifdef EQEMU_POSTGRESQL_ENABLED
server_log->Log(log_debug, "PostgreSQL Database Init.");
Log.Out(Logs::General, Logs::Login_Server, "PostgreSQL Database Init.");
server.db = (Database*)new DatabasePostgreSQL(
server.config->GetVariable("database", "user"),
server.config->GetVariable("database", "password"),
@@ -164,78 +119,70 @@ int main()
#endif
}
//Make sure our database got created okay, otherwise cleanup and exit.
if(!server.db)
{
server_log->Log(log_error, "Database Initialization Failure.");
server_log->Log(log_debug, "Config System Shutdown.");
/* Make sure our database got created okay, otherwise cleanup and exit. */
if (!server.db) {
Log.Out(Logs::General, Logs::Error, "Database Initialization Failure.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown.");
return 1;
}
#if WIN32
//initialize our encryption.
server_log->Log(log_debug, "Encryption Initialize.");
Log.Out(Logs::General, Logs::Login_Server, "Encryption Initialize.");
server.eq_crypto = new Encryption();
if(server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin")))
{
server_log->Log(log_debug, "Encryption Loaded Successfully.");
if (server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) {
Log.Out(Logs::General, Logs::Login_Server, "Encryption Loaded Successfully.");
}
else
{
else {
//We can't run without encryption, cleanup and exit.
server_log->Log(log_error, "Encryption Failed to Load.");
server_log->Log(log_debug, "Database System Shutdown.");
Log.Out(Logs::General, Logs::Error, "Encryption Failed to Load.");
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db;
server_log->Log(log_debug, "Config System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
#endif
//create our server manager.
server_log->Log(log_debug, "Server Manager Initialize.");
server.SM = new ServerManager();
if(!server.SM)
{
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Initialize.");
server.server_manager = new ServerManager();
if (!server.server_manager) {
//We can't run without a server manager, cleanup and exit.
server_log->Log(log_error, "Server Manager Failed to Start.");
Log.Out(Logs::General, Logs::Error, "Server Manager Failed to Start.");
#ifdef WIN32
server_log->Log(log_debug, "Encryption System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
server_log->Log(log_debug, "Database System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db;
server_log->Log(log_debug, "Config System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
//create our client manager.
server_log->Log(log_debug, "Client Manager Initialize.");
server.CM = new ClientManager();
if(!server.CM)
{
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Initialize.");
server.client_manager = new ClientManager();
if (!server.client_manager) {
//We can't run without a client manager, cleanup and exit.
server_log->Log(log_error, "Client Manager Failed to Start.");
server_log->Log(log_debug, "Server Manager Shutdown.");
delete server.SM;
Log.Out(Logs::General, Logs::Error, "Client Manager Failed to Start.");
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
delete server.server_manager;
#ifdef WIN32
server_log->Log(log_debug, "Encryption System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
server_log->Log(log_debug, "Database System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db;
server_log->Log(log_debug, "Config System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
@@ -247,30 +194,29 @@ int main()
#endif
#endif
server_log->Log(log_debug, "Server Started.");
while(run_server)
{
Log.Out(Logs::General, Logs::Login_Server, "Server Started.");
while (run_server) {
Timer::SetCurrentTime();
server.CM->Process();
server.SM->Process();
server.client_manager->Process();
server.server_manager->Process();
Sleep(100);
}
server_log->Log(log_debug, "Server Shutdown.");
server_log->Log(log_debug, "Client Manager Shutdown.");
delete server.CM;
server_log->Log(log_debug, "Server Manager Shutdown.");
delete server.SM;
Log.Out(Logs::General, Logs::Login_Server, "Server Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Shutdown.");
delete server.client_manager;
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
delete server.server_manager;
#ifdef WIN32
server_log->Log(log_debug, "Encryption System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
server_log->Log(log_debug, "Database System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db;
server_log->Log(log_debug, "Config System Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 0;
}
+99 -140
View File
@@ -17,11 +17,12 @@
*/
#include "server_manager.h"
#include "login_server.h"
#include "error_log.h"
#include "login_structures.h"
#include <stdlib.h>
extern ErrorLog *server_log;
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern LoginServer server;
extern bool run_server;
@@ -31,21 +32,18 @@ ServerManager::ServerManager()
int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str());
tcps = new EmuTCPServer(listen_port, true);
if(tcps->Open(listen_port, error_buffer))
{
server_log->Log(log_network, "ServerManager listening on port %u", listen_port);
if(tcps->Open(listen_port, error_buffer)) {
Log.Out(Logs::General, Logs::Login_Server, "ServerManager listening on port %u", listen_port);
}
else
{
server_log->Log(log_error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
else {
Log.Out(Logs::General, Logs::Error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
run_server = false;
}
}
ServerManager::~ServerManager()
{
if(tcps)
{
if (tcps) {
tcps->Close();
delete tcps;
}
@@ -55,38 +53,32 @@ void ServerManager::Process()
{
ProcessDisconnect();
EmuTCPConnection *tcp_c = nullptr;
while(tcp_c = tcps->NewQueuePop())
{
while (tcp_c = tcps->NewQueuePop()) {
in_addr tmp;
tmp.s_addr = tcp_c->GetrIP();
server_log->Log(log_network, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
Log.Out(Logs::General, Logs::Login_Server, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
WorldServer *cur = GetServerByAddress(tcp_c->GetrIP());
if(cur)
{
server_log->Log(log_network, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
cur->GetConnection()->Free();
cur->SetConnection(tcp_c);
cur->Reset();
WorldServer *server_entity = GetServerByAddress(tcp_c->GetrIP());
if (server_entity) {
Log.Out(Logs::General, Logs::Login_Server, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
server_entity->GetConnection()->Free();
server_entity->SetConnection(tcp_c);
server_entity->Reset();
}
else
{
else {
WorldServer *w = new WorldServer(tcp_c);
world_servers.push_back(w);
}
}
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter)->Process() == false)
{
server_log->Log(log_world, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
while (iter != world_servers.end()) {
if ((*iter)->Process() == false) {
Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
delete (*iter);
iter = world_servers.erase(iter);
}
else
{
else {
++iter;
}
}
@@ -95,20 +87,17 @@ void ServerManager::Process()
void ServerManager::ProcessDisconnect()
{
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
EmuTCPConnection *c = (*iter)->GetConnection();
if(!c->Connected())
{
while (iter != world_servers.end()) {
EmuTCPConnection *connection = (*iter)->GetConnection();
if (!connection->Connected()) {
in_addr tmp;
tmp.s_addr = c->GetrIP();
server_log->Log(log_network, "World server disconnected from the server, removing server and freeing connection.");
c->Free();
tmp.s_addr = connection->GetrIP();
Log.Out(Logs::General, Logs::Login_Server, "World server disconnected from the server, removing server and freeing connection.");
connection->Free();
delete (*iter);
iter = world_servers.erase(iter);
}
else
{
else {
++iter;
}
}
@@ -117,10 +106,8 @@ void ServerManager::ProcessDisconnect()
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter)->GetConnection()->GetrIP() == address)
{
while (iter != world_servers.end()) {
if ((*iter)->GetConnection()->GetrIP() == address) {
return (*iter);
}
++iter;
@@ -138,10 +125,8 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
string client_ip = inet_ntoa(in);
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter)->IsAuthorized() == false)
{
while (iter != world_servers.end()) {
if ((*iter)->IsAuthorized() == false) {
++iter;
continue;
}
@@ -149,16 +134,13 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
in.s_addr = (*iter)->GetConnection()->GetrIP();
string world_ip = inet_ntoa(in);
if(world_ip.compare(client_ip) == 0)
{
if (world_ip.compare(client_ip) == 0) {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
}
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
{
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
}
else
{
else {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetRemoteIP().size() + 24;
}
@@ -167,98 +149,87 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ServerListResponse, packet_size);
ServerListHeader_Struct *sl = (ServerListHeader_Struct*)outapp->pBuffer;
sl->Unknown1 = 0x00000004;
sl->Unknown2 = 0x00000000;
sl->Unknown3 = 0x01650000;
/**
* Not sure what this is but it should be noted setting it to
* 0xFFFFFFFF crashes the client so: don't do that.
*/
sl->Unknown4 = 0x00000000;
sl->NumberOfServers = server_count;
ServerListHeader_Struct *server_list = (ServerListHeader_Struct*)outapp->pBuffer;
server_list->Unknown1 = 0x00000004;
server_list->Unknown2 = 0x00000000;
server_list->Unknown3 = 0x01650000;
unsigned char *data_ptr = outapp->pBuffer;
data_ptr += sizeof(ServerListHeader_Struct);
/**
* Not sure what this is but it should be noted setting it to
* 0xFFFFFFFF crashes the client so: don't do that.
*/
server_list->Unknown4 = 0x00000000;
server_list->NumberOfServers = server_count;
unsigned char *data_pointer = outapp->pBuffer;
data_pointer += sizeof(ServerListHeader_Struct);
iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter)->IsAuthorized() == false)
{
while (iter != world_servers.end()) {
if ((*iter)->IsAuthorized() == false) {
++iter;
continue;
}
in.s_addr = (*iter)->GetConnection()->GetrIP();
string world_ip = inet_ntoa(in);
if(world_ip.compare(client_ip) == 0)
{
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_ptr += ((*iter)->GetLocalIP().size() + 1);
if (world_ip.compare(client_ip) == 0) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
}
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
{
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_ptr += ((*iter)->GetLocalIP().size() + 1);
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
}
else
{
memcpy(data_ptr, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
data_ptr += ((*iter)->GetRemoteIP().size() + 1);
else {
memcpy(data_pointer, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
data_pointer += ((*iter)->GetRemoteIP().size() + 1);
}
switch((*iter)->GetServerListID())
{
case 1:
{
*(unsigned int*)data_ptr = 0x00000030;
switch ((*iter)->GetServerListID()) {
case 1: {
*(unsigned int*)data_pointer = 0x00000030;
break;
}
case 2:
{
*(unsigned int*)data_ptr = 0x00000009;
case 2: {
*(unsigned int*)data_pointer = 0x00000009;
break;
}
default:
{
*(unsigned int*)data_ptr = 0x00000001;
default: {
*(unsigned int*)data_pointer = 0x00000001;
}
}
data_ptr += 4;
*(unsigned int*)data_ptr = (*iter)->GetRuntimeID();
data_ptr += 4;
data_pointer += 4;
memcpy(data_ptr, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
data_ptr += ((*iter)->GetLongName().size() + 1);
*(unsigned int*)data_pointer = (*iter)->GetRuntimeID();
data_pointer += 4;
memcpy(data_ptr, "EN", 2);
data_ptr += 3;
memcpy(data_pointer, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
data_pointer += ((*iter)->GetLongName().size() + 1);
memcpy(data_ptr, "US", 2);
data_ptr += 3;
memcpy(data_pointer, "EN", 2);
data_pointer += 3;
memcpy(data_pointer, "US", 2);
data_pointer += 3;
// 0 = Up, 1 = Down, 2 = Up, 3 = down, 4 = locked, 5 = locked(down)
if((*iter)->GetStatus() < 0)
{
if((*iter)->GetZonesBooted() == 0)
{
*(uint32*)data_ptr = 0x01;
if ((*iter)->GetStatus() < 0) {
if ((*iter)->GetZonesBooted() == 0) {
*(uint32*)data_pointer = 0x01;
}
else
{
*(uint32*)data_ptr = 0x04;
else {
*(uint32*)data_pointer = 0x04;
}
}
else
{
*(uint32*)data_ptr = 0x02;
else {
*(uint32*)data_pointer = 0x02;
}
data_ptr += 4;
data_pointer += 4;
*(uint32*)data_ptr = (*iter)->GetPlayersOnline();
data_ptr += 4;
*(uint32*)data_pointer = (*iter)->GetPlayersOnline();
data_pointer += 4;
++iter;
}
@@ -270,10 +241,8 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
{
list<WorldServer*>::iterator iter = world_servers.begin();
bool found = false;
while(iter != world_servers.end())
{
if((*iter)->GetRuntimeID() == server_id)
{
while (iter != world_servers.end()) {
if ((*iter)->GetRuntimeID() == server_id) {
ServerPacket *outapp = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp->pBuffer;
utwr->worldid = server_id;
@@ -281,8 +250,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
(*iter)->GetConnection()->SendPacket(outapp);
found = true;
if(server.options.IsDumpInPacketsOn())
{
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(outapp);
}
delete outapp;
@@ -290,25 +258,21 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
++iter;
}
if(!found && server.options.IsTraceOn())
{
server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
if (!found && server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
}
}
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter) == ignore)
{
while (iter != world_servers.end()) {
if ((*iter) == ignore) {
++iter;
continue;
}
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
{
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
return true;
}
@@ -320,18 +284,14 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while(iter != world_servers.end())
{
if((*iter) == ignore)
{
while (iter != world_servers.end()) {
if ((*iter) == ignore) {
++iter;
}
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
{
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
EmuTCPConnection *c = (*iter)->GetConnection();
if(c->Connected())
{
if (c->Connected()) {
c->Disconnect();
}
c->Free();
@@ -341,5 +301,4 @@ void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServe
++iter;
}
}
}
+128 -129
View File
@@ -16,11 +16,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "world_server.h"
#include "error_log.h"
#include "login_server.h"
#include "login_structures.h"
#include "config.h"
extern ErrorLog *server_log;
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern LoginServer server;
WorldServer::WorldServer(EmuTCPConnection *c)
@@ -28,19 +30,18 @@ WorldServer::WorldServer(EmuTCPConnection *c)
connection = c;
zones_booted = 0;
players_online = 0;
status = 0;
server_status = 0;
runtime_id = 0;
server_list_id = 0;
server_type = 0;
authorized = false;
trusted = false;
logged_in = false;
is_server_authorized = false;
is_server_trusted = false;
is_server_logged_in = false;
}
WorldServer::~WorldServer()
{
if(connection)
{
if(connection) {
connection->Free();
}
}
@@ -49,12 +50,12 @@ void WorldServer::Reset()
{
zones_booted = 0;
players_online = 0;
status = 0;
server_status = 0;
runtime_id;
server_list_id = 0;
server_type = 0;
authorized = false;
logged_in = false;
is_server_authorized = false;
is_server_logged_in = false;
}
bool WorldServer::Process()
@@ -64,7 +65,7 @@ bool WorldServer::Process()
{
if(server.options.IsWorldTraceOn())
{
server_log->Log(log_network_trace, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
}
if(server.options.IsDumpInPacketsOn())
@@ -78,14 +79,14 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerNewLSInfo_Struct))
{
server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
server_log->Log(log_network_trace, "New Login Info Recieved.");
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
}
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)app->pBuffer;
@@ -96,14 +97,14 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerLSStatus_Struct))
{
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
server_log->Log(log_network_trace, "World Server Status Recieved.");
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)app->pBuffer;
@@ -127,7 +128,7 @@ bool WorldServer::Process()
{
if(app->size < sizeof(UsertoWorldResponse_Struct))
{
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
@@ -137,21 +138,22 @@ bool WorldServer::Process()
//While keeping world server spam with multiple servers connected almost impossible.
if(server.options.IsTraceOn())
{
server_log->Log(log_network_trace, "User-To-World Response received.");
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer;
server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.CM->GetClient(utwr->lsaccountid);
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if(c)
{
server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
server_log->Log(log_client, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if(utwr->response > 0)
{
@@ -180,9 +182,9 @@ bool WorldServer::Process()
if(server.options.IsTraceOn())
{
server_log->Log(log_network_trace, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
}
if(server.options.IsDumpOutPacketsOn())
@@ -195,7 +197,7 @@ bool WorldServer::Process()
}
else
{
server_log->Log(log_client_error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
break;
}
@@ -203,16 +205,16 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerLSAccountUpdate_Struct))
{
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer;
if(trusted)
if(is_server_trusted)
{
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
string name;
string password;
string email;
@@ -225,7 +227,7 @@ bool WorldServer::Process()
}
default:
{
server_log->Log(log_network_error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
}
}
@@ -237,9 +239,9 @@ bool WorldServer::Process()
void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(logged_in)
if(is_server_logged_in)
{
server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
Log.Out(Logs::General, Logs::Error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
return;
}
@@ -249,7 +251,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, account name was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account name was too long.");
return;
}
@@ -259,7 +261,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, account password was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account password was too long.");
return;
}
@@ -269,7 +271,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, long name was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, long name was too long.");
return;
}
@@ -279,7 +281,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, short name was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, short name was too long.");
return;
}
@@ -287,7 +289,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(strlen(i->local_address) == 0)
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
local_ip = "127.0.0.1";
}
else
@@ -297,7 +299,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was too long.");
return;
}
@@ -308,7 +310,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in_addr in;
in.s_addr = GetConnection()->GetrIP();
remote_ip = inet_ntoa(in);
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
}
else
{
@@ -320,7 +322,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in_addr in;
in.s_addr = GetConnection()->GetrIP();
remote_ip = inet_ntoa(in);
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
}
if(strlen(i->serverversion) <= 64)
@@ -329,7 +331,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, server version was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, server version was too long.");
return;
}
@@ -339,27 +341,27 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
server_log->Log(log_network_error, "Handle_NewLSInfo error, protocol version was too long.");
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, protocol version was too long.");
return;
}
server_type = i->servertype;
logged_in = true;
is_server_logged_in = true;
if(server.options.IsRejectingDuplicateServers())
{
if(server.SM->ServerExists(long_name, short_name, this))
if(server.server_manager->ServerExists(long_name, short_name, this))
{
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
return;
}
}
else
{
if(server.SM->ServerExists(long_name, short_name, this))
if(server.server_manager->ServerExists(long_name, short_name, this))
{
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
server.SM->DestroyServerByName(long_name, short_name, this);
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
server.server_manager->DestroyServerByName(long_name, short_name, this);
}
}
@@ -378,112 +380,112 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
{
server_log->Log(log_world, "Server %s(%s) successfully logged into account that had no user/password requirement.",
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged into account that had no user/password requirement.",
long_name.c_str(), short_name.c_str());
authorized = true;
is_server_authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
}
else if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
{
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
long_name.c_str(), short_name.c_str());
authorized = true;
is_server_authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
if(s_trusted)
{
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
trusted = true;
if(s_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
}
}
else
{
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
" registered servers are allowed.", long_name.c_str(), short_name.c_str());
return;
}
}
else
{
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
long_name.c_str(), short_name.c_str());
return;
}
}
else
{
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
long_name.c_str(), short_name.c_str());
return;
}
}
else
{
unsigned int s_id = 0;
unsigned int s_list_type = 0;
unsigned int s_trusted = 0;
string s_desc;
string s_list_desc;
string s_acct_name;
string s_acct_pass;
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
else {
unsigned int server_id = 0;
unsigned int server_list_type = 0;
unsigned int is_server_trusted = 0;
string server_description;
string server_list_description;
string server_account_name;
string server_account_password;
if(server.db->GetWorldRegistration(
long_name,
short_name,
server_id,
server_description,
server_list_type,
is_server_trusted,
server_list_description,
server_account_name,
server_account_password))
{
if(account_name.size() > 0 && account_password.size() > 0)
{
if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
{
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
if(account_name.size() > 0 && account_password.size() > 0) {
if(server_account_name.compare(account_name) == 0 && server_account_password.compare(account_password) == 0) {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
long_name.c_str(), short_name.c_str());
authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
if(s_trusted)
{
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
trusted = true;
is_server_authorized = true;
SetRuntimeID(server_id);
server_list_id = server_list_type;
desc = server_description;
if(is_server_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
}
}
else
{
else {
// this is the first of two cases where we should deny access even if unregistered is allowed
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
long_name.c_str(), short_name.c_str());
}
}
else
{
if(s_acct_name.size() > 0 || s_acct_pass.size() > 0)
{
else {
if(server_account_name.size() > 0 || server_account_password.size() > 0) {
// this is the second of two cases where we should deny access even if unregistered is allowed
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but this server requires a password.",
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but this server requires a password.",
long_name.c_str(), short_name.c_str());
}
else
{
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
long_name.c_str(), short_name.c_str());
authorized = true;
SetRuntimeID(s_id);
is_server_authorized = true;
SetRuntimeID(server_id);
server_list_id = 3;
}
}
}
else
{
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
long_name.c_str(), short_name.c_str());
if(server.db->CreateWorldRegistration(long_name, short_name, s_id))
{
authorized = true;
SetRuntimeID(s_id);
if(server.db->CreateWorldRegistration(long_name, short_name, server_id)) {
is_server_authorized = true;
SetRuntimeID(server_id);
server_list_id = 3;
}
}
@@ -493,9 +495,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in.s_addr = connection->GetrIP();
server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, string(inet_ntoa(in)));
if(authorized)
if(is_server_authorized)
{
server.CM->UpdateServerList();
server.client_manager->UpdateServerList();
}
}
@@ -503,43 +505,40 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
{
players_online = s->num_players;
zones_booted = s->num_zones;
status = s->status;
server_status = s->status;
}
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id)
{
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth));
ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer;
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
slsca->lsaccount_id = account_id;
strncpy(slsca->name, account.c_str(), account.size() > 30 ? 30 : account.size());
strncpy(slsca->key, key.c_str(), 10);
slsca->lsadmin = 0;
slsca->worldadmin = 0;
slsca->ip = ip;
client_auth->lsaccount_id = account_id;
strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size());
strncpy(client_auth->key, key.c_str(), 10);
client_auth->lsadmin = 0;
client_auth->worldadmin = 0;
client_auth->ip = ip;
in_addr in;
in.s_addr = ip;connection->GetrIP();
in.s_addr = ip; connection->GetrIP();
string client_address(inet_ntoa(in));
in.s_addr = connection->GetrIP();
string world_address(inet_ntoa(in));
if(client_address.compare(world_address) == 0)
{
slsca->local = 1;
if (client_address.compare(world_address) == 0) {
client_auth->local = 1;
}
else if(client_address.find(server.options.GetLocalNetwork()) != string::npos)
{
slsca->local = 1;
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) {
client_auth->local = 1;
}
else
{
slsca->local = 0;
else {
client_auth->local = 0;
}
connection->SendPacket(outapp);
if(server.options.IsDumpInPacketsOn())
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(outapp);
}
+6 -6
View File
@@ -86,7 +86,7 @@ public:
/**
* Gets whether the server is authorized to show up on the server list or not.
*/
bool IsAuthorized() const { return authorized; }
bool IsAuthorized() const { return is_server_authorized; }
/**
* Gets the local ip of the server.
@@ -106,7 +106,7 @@ public:
/**
* Gets the status of the server.
*/
int GetStatus() const { return status; }
int GetStatus() const { return server_status; }
/**
* Gets the number of zones online on the server.
@@ -138,7 +138,7 @@ private:
EmuTCPConnection *connection;
unsigned int zones_booted;
unsigned int players_online;
int status;
int server_status;
unsigned int runtime_id;
unsigned int server_list_id;
unsigned int server_type;
@@ -151,9 +151,9 @@ private:
std::string local_ip;
std::string protocol;
std::string version;
bool authorized;
bool logged_in;
bool trusted;
bool is_server_authorized;
bool is_server_logged_in;
bool is_server_trusted;
};
#endif
+223
View File
@@ -123,6 +123,229 @@ void Database::AddSpeech(const char* from, const char* to, const char* message,
}
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
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.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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_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.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
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.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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_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.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
/* These are item moves */
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.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%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.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
/* Merchant transactions are from the perspective of the merchant, not the player */
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.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
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.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::GeneralQueryReceive(ServerPacket *pack) {
/*
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
+6
View File
@@ -44,6 +44,12 @@ public:
~Database();
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount);
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount);
void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members);
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items);
void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items);
void GeneralQueryReceive(ServerPacket *pack);
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
+35
View File
@@ -81,6 +81,41 @@ void WorldServer::Process()
database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type);
break;
}
case ServerOP_QSPlayerLogTrades: {
QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)pack->pBuffer;
database.LogPlayerTrade(QS, QS->_detail_count);
break;
}
case ServerOP_QSPlayerLogHandins: {
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)pack->pBuffer;
database.LogPlayerHandin(QS, QS->_detail_count);
break;
}
case ServerOP_QSPlayerLogNPCKills: {
QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
uint32 Members = pack->size - sizeof(QSPlayerLogNPCKill_Struct);
if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct);
database.LogPlayerNPCKill(QS, Members);
break;
}
case ServerOP_QSPlayerLogDeletes: {
QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)pack->pBuffer;
uint32 Items = QS->char_count;
database.LogPlayerDelete(QS, Items);
break;
}
case ServerOP_QSPlayerLogMoves: {
QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)pack->pBuffer;
uint32 Items = QS->char_count;
database.LogPlayerMove(QS, Items);
break;
}
case ServerOP_QSPlayerLogMerchantTransactions: {
QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)pack->pBuffer;
uint32 Items = QS->char_count + QS->merchant_count;
database.LogMerchantTransaction(QS, Items);
break;
}
case ServerOP_QueryServGeneric: {
/*
The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets
+103
View File
@@ -0,0 +1,103 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(recast_navigation_sources
debug_utils/src/DebugDraw.cpp
debug_utils/src/DetourDebugDraw.cpp
debug_utils/src/RecastDebugDraw.cpp
debug_utils/src/RecastDump.cpp
detour/src/DetourAlloc.cpp
detour/src/DetourCommon.cpp
detour/src/DetourNavMesh.cpp
detour/src/DetourNavMeshBuilder.cpp
detour/src/DetourNavMeshQuery.cpp
detour/src/DetourNode.cpp
detour_tile_cache/src/DetourTileCache.cpp
detour_tile_cache/src/DetourTileCacheBuilder.cpp
recast/src/Recast.cpp
recast/src/RecastAlloc.cpp
recast/src/RecastArea.cpp
recast/src/RecastContour.cpp
recast/src/RecastFilter.cpp
recast/src/RecastLayers.cpp
recast/src/RecastMesh.cpp
recast/src/RecastMeshDetail.cpp
recast/src/RecastRasterization.cpp
recast/src/RecastRegion.cpp
)
SET(recast_navigation_headers
debug_utils/include/DebugDraw.h
debug_utils/include/DetourDebugDraw.h
debug_utils/include/RecastDebugDraw.h
debug_utils/include/RecastDump.h
detour/include/DetourAlloc.h
detour/include/DetourAssert.h
detour/include/DetourCommon.h
detour/include/DetourMath.h
detour/include/DetourNavMesh.h
detour/include/DetourNavMeshBuilder.h
detour/include/DetourNavMeshQuery.h
detour/include/DetourNode.h
detour/include/DetourStatus.h
detour_tile_cache/include/DetourTileCache.h
detour_tile_cache/include/DetourTileCacheBuilder.h
recast/include/Recast.h
recast/include/RecastAlloc.h
recast/include/RecastAssert.h
)
SOURCE_GROUP(DebugUtils FILES
debug_utils/src/DebugDraw.cpp
debug_utils/src/DetourDebugDraw.cpp
debug_utils/src/RecastDebugDraw.cpp
debug_utils/src/RecastDump.cpp
debug_utils/include/DebugDraw.h
debug_utils/include/DetourDebugDraw.h
debug_utils/include/RecastDebugDraw.h
debug_utils/include/RecastDump.h
)
SOURCE_GROUP(Detour FILES
detour/src/DetourAlloc.cpp
detour/src/DetourCommon.cpp
detour/src/DetourNavMesh.cpp
detour/src/DetourNavMeshBuilder.cpp
detour/src/DetourNavMeshQuery.cpp
detour/src/DetourNode.cpp
detour/include/DetourAlloc.h
detour/include/DetourAssert.h
detour/include/DetourCommon.h
detour/include/DetourMath.h
detour/include/DetourNavMesh.h
detour/include/DetourNavMeshBuilder.h
detour/include/DetourNavMeshQuery.h
detour/include/DetourNode.h
detour/include/DetourStatus.h
)
SOURCE_GROUP(DetourTileCache FILES
detour_tile_cache/src/DetourTileCache.cpp
detour_tile_cache/src/DetourTileCacheBuilder.cpp
detour_tile_cache/include/DetourTileCache.h
detour_tile_cache/include/DetourTileCacheBuilder.h
)
SOURCE_GROUP(Recast FILES
recast/src/Recast.cpp
recast/src/RecastAlloc.cpp
recast/src/RecastArea.cpp
recast/src/RecastContour.cpp
recast/src/RecastFilter.cpp
recast/src/RecastLayers.cpp
recast/src/RecastMesh.cpp
recast/src/RecastMeshDetail.cpp
recast/src/RecastRasterization.cpp
recast/src/RecastRegion.cpp
recast/include/Recast.h
recast/include/RecastAlloc.h
recast/include/RecastAssert.h
)
ADD_LIBRARY(recast_navigation ${recast_navigation_sources} ${recast_navigation_headers})
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
+220
View File
@@ -0,0 +1,220 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DEBUGDRAW_H
#define DEBUGDRAW_H
// Some math headers don't have PI defined.
static const float DU_PI = 3.14159265f;
enum duDebugDrawPrimitives
{
DU_DRAW_POINTS,
DU_DRAW_LINES,
DU_DRAW_TRIS,
DU_DRAW_QUADS,
};
/// Abstract debug draw interface.
struct duDebugDraw
{
virtual ~duDebugDraw() = 0;
virtual void depthMask(bool state) = 0;
virtual void texture(bool state) = 0;
/// Begin drawing primitives.
/// @param prim [in] primitive type to draw, one of rcDebugDrawPrimitives.
/// @param size [in] size of a primitive, applies to point size and line width only.
virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f) = 0;
/// Submit a vertex
/// @param pos [in] position of the verts.
/// @param color [in] color of the verts.
virtual void vertex(const float* pos, unsigned int color) = 0;
/// Submit a vertex
/// @param x,y,z [in] position of the verts.
/// @param color [in] color of the verts.
virtual void vertex(const float x, const float y, const float z, unsigned int color) = 0;
/// Submit a vertex
/// @param pos [in] position of the verts.
/// @param color [in] color of the verts.
virtual void vertex(const float* pos, unsigned int color, const float* uv) = 0;
/// Submit a vertex
/// @param x,y,z [in] position of the verts.
/// @param color [in] color of the verts.
virtual void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v) = 0;
/// End drawing primitives.
virtual void end() = 0;
};
inline unsigned int duRGBA(int r, int g, int b, int a)
{
return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);
}
inline unsigned int duRGBAf(float fr, float fg, float fb, float fa)
{
unsigned char r = (unsigned char)(fr*255.0f);
unsigned char g = (unsigned char)(fg*255.0f);
unsigned char b = (unsigned char)(fb*255.0f);
unsigned char a = (unsigned char)(fa*255.0f);
return duRGBA(r,g,b,a);
}
unsigned int duIntToCol(int i, int a);
void duIntToCol(int i, float* col);
inline unsigned int duMultCol(const unsigned int col, const unsigned int d)
{
const unsigned int r = col & 0xff;
const unsigned int g = (col >> 8) & 0xff;
const unsigned int b = (col >> 16) & 0xff;
const unsigned int a = (col >> 24) & 0xff;
return duRGBA((r*d) >> 8, (g*d) >> 8, (b*d) >> 8, a);
}
inline unsigned int duDarkenCol(unsigned int col)
{
return ((col >> 1) & 0x007f7f7f) | (col & 0xff000000);
}
inline unsigned int duLerpCol(unsigned int ca, unsigned int cb, unsigned int u)
{
const unsigned int ra = ca & 0xff;
const unsigned int ga = (ca >> 8) & 0xff;
const unsigned int ba = (ca >> 16) & 0xff;
const unsigned int aa = (ca >> 24) & 0xff;
const unsigned int rb = cb & 0xff;
const unsigned int gb = (cb >> 8) & 0xff;
const unsigned int bb = (cb >> 16) & 0xff;
const unsigned int ab = (cb >> 24) & 0xff;
unsigned int r = (ra*(255-u) + rb*u)/255;
unsigned int g = (ga*(255-u) + gb*u)/255;
unsigned int b = (ba*(255-u) + bb*u)/255;
unsigned int a = (aa*(255-u) + ab*u)/255;
return duRGBA(r,g,b,a);
}
inline unsigned int duTransCol(unsigned int c, unsigned int a)
{
return (a<<24) | (c & 0x00ffffff);
}
void duCalcBoxColors(unsigned int* colors, unsigned int colTop, unsigned int colSide);
void duDebugDrawCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col, const float lineWidth);
void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col, const float lineWidth);
void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col, const float lineWidth);
void duDebugDrawArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1,
const float as0, const float as1, unsigned int col, const float lineWidth);
void duDebugDrawCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
const float r, unsigned int col, const float lineWidth);
void duDebugDrawCross(struct duDebugDraw* dd, const float x, const float y, const float z,
const float size, unsigned int col, const float lineWidth);
void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, const unsigned int* fcol);
void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz,
const int w, const int h, const float size,
const unsigned int col, const float lineWidth);
// Versions without begin/end, can be used to draw multiple primitives.
void duAppendCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
void duAppendBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
void duAppendBoxPoints(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col);
void duAppendArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1,
const float as0, const float as1, unsigned int col);
void duAppendCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
const float r, unsigned int col);
void duAppendCross(struct duDebugDraw* dd, const float x, const float y, const float z,
const float size, unsigned int col);
void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, const unsigned int* fcol);
void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
class duDisplayList : public duDebugDraw
{
float* m_pos;
unsigned int* m_color;
int m_size;
int m_cap;
bool m_depthMask;
duDebugDrawPrimitives m_prim;
float m_primSize;
void resize(int cap);
public:
duDisplayList(int cap = 512);
~duDisplayList();
virtual void depthMask(bool state);
virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f);
virtual void vertex(const float x, const float y, const float z, unsigned int color);
virtual void vertex(const float* pos, unsigned int color);
virtual void end();
void clear();
void draw(struct duDebugDraw* dd);
private:
// Explicitly disabled copy constructor and copy assignment operator.
duDisplayList(const duDisplayList&);
duDisplayList& operator=(const duDisplayList&);
};
#endif // DEBUGDRAW_H
@@ -0,0 +1,48 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURDEBUGDRAW_H
#define DETOURDEBUGDRAW_H
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
#include "DetourTileCacheBuilder.h"
enum DrawNavMeshFlags
{
DU_DRAWNAVMESH_OFFMESHCONS = 0x01,
DU_DRAWNAVMESH_CLOSEDLIST = 0x02,
DU_DRAWNAVMESH_COLOR_TILES = 0x04,
};
void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh& mesh, unsigned char flags);
void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, unsigned char flags);
void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query);
void duDebugDrawNavMeshBVTree(struct duDebugDraw* dd, const dtNavMesh& mesh);
void duDebugDrawNavMeshPortals(struct duDebugDraw* dd, const dtNavMesh& mesh);
void duDebugDrawNavMeshPolysWithFlags(struct duDebugDraw* dd, const dtNavMesh& mesh, const unsigned short polyFlags, const unsigned int col);
void duDebugDrawNavMeshPoly(struct duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef ref, const unsigned int col);
void duDebugDrawTileCacheLayerAreas(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch);
void duDebugDrawTileCacheLayerRegions(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch);
void duDebugDrawTileCacheContours(duDebugDraw* dd, const struct dtTileCacheContourSet& lcset,
const float* orig, const float cs, const float ch);
void duDebugDrawTileCachePolyMesh(duDebugDraw* dd, const struct dtTileCachePolyMesh& lmesh,
const float* orig, const float cs, const float ch);
#endif // DETOURDEBUGDRAW_H

Some files were not shown because too many files have changed in this diff Show More