mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-30 07:35:45 +00:00
Compare commits
196 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75391d96f4 | |||
| 81b07a5aa0 | |||
| 774aa99b29 | |||
| 756e835144 | |||
| c5c575b028 | |||
| 152e99444c | |||
| 795df5c597 | |||
| 18eff726d0 | |||
| f06a37a009 | |||
| ae53efc52c | |||
| 548eb65e1d | |||
| fede8760d4 | |||
| 6faa202b57 | |||
| c406710623 | |||
| 662c4012db | |||
| 849e7b910d | |||
| 8e33755f02 | |||
| dfaa929778 | |||
| 306b06745f | |||
| 108fc82ee0 | |||
| 577f61b082 | |||
| a01cf0718d | |||
| 90412ba61b | |||
| 5cbc380c62 | |||
| 6c289a7c71 | |||
| 57335b188f | |||
| 056e429100 | |||
| f548aeddb2 | |||
| 4ff9faa4e6 | |||
| 17fc350d46 | |||
| b18bc66b42 | |||
| 324bfd448e | |||
| 75560ee830 | |||
| 50db7637aa | |||
| 67fdc75df3 | |||
| 9993022418 | |||
| bd95ed44fd | |||
| 65fd323eab | |||
| 290c58741e | |||
| 39d0772a01 | |||
| 622fe50479 | |||
| f41a219309 | |||
| 23bc3c7fd6 | |||
| 3144ac1a28 | |||
| a5106420e8 | |||
| 5a42c4f667 | |||
| a3107cc54d | |||
| f0152cef66 | |||
| 21755a9f9e | |||
| b329515a07 | |||
| ff4b117cfa | |||
| e305ba852b | |||
| b8c91cf4f9 | |||
| cd82bd8472 | |||
| 20bed20f47 | |||
| c93054421f | |||
| b7a1fc6644 | |||
| 6bfb8fca2e | |||
| 9d6a7ad743 | |||
| 076b88be9a | |||
| 84a779c4df | |||
| 3fb479e612 | |||
| c1f4ee0e65 | |||
| 32f7dc3d1b | |||
| fa55fd1664 | |||
| c44c0d4efa | |||
| 50c63b95db | |||
| 612029de6e | |||
| dbc6346fe8 | |||
| 93a4153a4b | |||
| 434f270f68 | |||
| 5ba33b88bd | |||
| ce1de9997b | |||
| 8814ab26cd | |||
| 8c23eee42a | |||
| 5475615448 | |||
| 4a5559022f | |||
| 5be2041085 | |||
| 9f4d60ec36 | |||
| c64a2aec94 | |||
| 0e582eda82 | |||
| 7eff6ada87 | |||
| 291997d35b | |||
| ac4572bf79 | |||
| f0a9578b6a | |||
| baa824d8fb | |||
| b19d3ac8a2 | |||
| 6a393bf0c3 | |||
| 09a5551de1 | |||
| 6e2e035d66 | |||
| ac5922bb32 | |||
| ecf2a369cc | |||
| 95b306599f | |||
| 497d20512a | |||
| db916e946e | |||
| 958549b407 | |||
| 71ebf1b2d4 | |||
| e19b8d3056 | |||
| 8b1d64a043 | |||
| 576f99f292 | |||
| e3761cf2a3 | |||
| ad1764b464 | |||
| 1c9ea57a4e | |||
| 03c158b674 | |||
| 39b5374e92 | |||
| 2d3ddcb574 | |||
| ed09281f66 | |||
| 8e51bf8b19 | |||
| 844efa7e20 | |||
| fa3a5c7a72 | |||
| 93db35658a | |||
| d45a57056a | |||
| ff40dbc710 | |||
| 7523c972fa | |||
| 4320c1429e | |||
| dc8bfddd7a | |||
| a8cdfb07e6 | |||
| 011de2692e | |||
| 0cc76ab489 | |||
| c5c9985e0d | |||
| a7e95d7818 | |||
| 933d856b5b | |||
| 285cc3af29 | |||
| de8ae7afa6 | |||
| 1b272cba50 | |||
| e35e38b039 | |||
| 9215ba7a8a | |||
| 3f4334985b | |||
| 21002c2e8a | |||
| 445f967ed6 | |||
| 57a15d473f | |||
| df92c578d2 | |||
| 3af43a8e8d | |||
| 647bcce30b | |||
| 25b527156c | |||
| b3ab7deb80 | |||
| 4a9cb07132 | |||
| 8f1b62d166 | |||
| 7e9994b5d4 | |||
| f2f8fae58b | |||
| 3a1e88f9ed | |||
| 4e101aa6d6 | |||
| ef411ee154 | |||
| 93b3f97f24 | |||
| c1d4cb90b9 | |||
| e939c82717 | |||
| 7d03479f41 | |||
| ff440e16b6 | |||
| c6bb0f6495 | |||
| d142bc552a | |||
| 7dc57c3b05 | |||
| ea9b09cf1f | |||
| 968278d8f8 | |||
| aa910864c8 | |||
| 1499f3338e | |||
| fef2f9fc61 | |||
| 8afbc585da | |||
| 457ce85746 | |||
| 49c093dc62 | |||
| beccd557a8 | |||
| e11610b9fa | |||
| 3e652b98bc | |||
| d43af28de4 | |||
| f5106b6af6 | |||
| 3386d13d2d | |||
| d1b7c675f9 | |||
| a40e1cf893 | |||
| c81ab00764 | |||
| 025ef5e1d6 | |||
| 1f29a40e6d | |||
| 66cadd599b | |||
| aa0345c1f1 | |||
| 73b11c5036 | |||
| efbeb2dbb7 | |||
| 8c97c20727 | |||
| f2d07e5c69 | |||
| 64d5b54e65 | |||
| 89b3a04eb3 | |||
| 1bafe0b6b3 | |||
| 82762c3f5a | |||
| 2742eca119 | |||
| 8fc7f3a732 | |||
| 39ce0178f9 | |||
| 3d2f560436 | |||
| a0768d2d28 | |||
| 9009a7aa23 | |||
| 67b03b4e31 | |||
| b08975aefb | |||
| ea3a7cae0b | |||
| 81314a3315 | |||
| d33cfad567 | |||
| c1698a5bdd | |||
| 2a094e8792 | |||
| 4a0725e278 | |||
| 218ffbb2c5 | |||
| 3e30e78158 |
+302
@@ -1,3 +1,305 @@
|
||||
## [22.13.1] - 06/13/2023
|
||||
|
||||
### Targeting
|
||||
|
||||
* Revert #3383 ([#3405](https://github.com/EQEmu/Server/pull/3405)) @noudess 2023-06-13
|
||||
|
||||
## [22.13.0] - 06/12/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Add GMFind_Struct to packet structures ([#3402](https://github.com/EQEmu/Server/pull/3402)) @Kinglykrab 2023-06-12
|
||||
* Remove CHECK_LOS_STEP from zone/common.h ([#3398](https://github.com/EQEmu/Server/pull/3398)) @Kinglykrab 2023-06-12
|
||||
* Remove CheckCoordLosNoZLeaps() from zone/entity.cpp and zone/entity.h ([#3384](https://github.com/EQEmu/Server/pull/3384)) @Kinglykrab 2023-06-12
|
||||
* Remove CountTempPets() from zone/entity.cpp and zone/entity.h ([#3390](https://github.com/EQEmu/Server/pull/3390)) @Kinglykrab 2023-06-12
|
||||
* Remove Evade() from zone/entity.cpp and zone/entity.h ([#3394](https://github.com/EQEmu/Server/pull/3394)) @Kinglykrab 2023-06-12
|
||||
* Remove GateAllClients() from zone/entity.cpp and zone/entity.h ([#3391](https://github.com/EQEmu/Server/pull/3391)) @Kinglykrab 2023-06-12
|
||||
* Remove GetClient(ip, port) from zone/entity.h ([#3386](https://github.com/EQEmu/Server/pull/3386)) @Kinglykrab 2023-06-12
|
||||
* Remove GetClientCount() from zone/entity.cpp and zone/entity.h ([#3392](https://github.com/EQEmu/Server/pull/3392)) @Kinglykrab 2023-06-12
|
||||
* Remove GetGroupByBot(), GetRaidByMob(), and GetRaidByLeaderName() from zone/entity.cpp and zone/entity.h ([#3387](https://github.com/EQEmu/Server/pull/3387)) @Kinglykrab 2023-06-12
|
||||
* Remove InteractiveChat() and TakenAction() from zone/npc.h ([#3382](https://github.com/EQEmu/Server/pull/3382)) @Kinglykrab 2023-06-12
|
||||
* Remove LimitCheckBoth() from zone/entity.cpp and zone/entity.h ([#3393](https://github.com/EQEmu/Server/pull/3393)) @Kinglykrab 2023-06-12
|
||||
* Remove NPC::AddCash() from npc.cpp/npc.h ([#3380](https://github.com/EQEmu/Server/pull/3380)) @Kinglykrab 2023-06-09
|
||||
* Remove RemoveMob() and RemoveRaid() from zone/entity.cpp and zone/entity.h ([#3389](https://github.com/EQEmu/Server/pull/3389)) @Kinglykrab 2023-06-12
|
||||
* Remove SPECIALIZE_MANA_REDUCE from zone/common.h ([#3400](https://github.com/EQEmu/Server/pull/3400)) @Kinglykrab 2023-06-12
|
||||
* Remove SendAATimer() from zone/entity.h ([#3388](https://github.com/EQEmu/Server/pull/3388)) @Kinglykrab 2023-06-12
|
||||
* Remove WriteEntityIDs() from zone/entity.cpp and zone/entity.h ([#3395](https://github.com/EQEmu/Server/pull/3395)) @Kinglykrab 2023-06-12
|
||||
* Remove _BECOMENPCPET() and _NPCPET() from zone/common.h ([#3399](https://github.com/EQEmu/Server/pull/3399)) @Kinglykrab 2023-06-12
|
||||
* Remove pDBAsyncWorkID from zone/entity.h ([#3385](https://github.com/EQEmu/Server/pull/3385)) @Kinglykrab 2023-06-12
|
||||
* Remove struct DynamicZoneSafeReturn from zone/entity.h ([#3396](https://github.com/EQEmu/Server/pull/3396)) @Kinglykrab 2023-06-12
|
||||
* Remove struct TradeEntity from zone/common.h ([#3397](https://github.com/EQEmu/Server/pull/3397)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Commands
|
||||
|
||||
* Assign #opcode to a #reload alias ([#3401](https://github.com/EQEmu/Server/pull/3401)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Illusions
|
||||
|
||||
* RandomizeFeatures and SetGender were killing db texture ([#3376](https://github.com/EQEmu/Server/pull/3376)) @noudess 2023-06-06
|
||||
|
||||
### Logging
|
||||
|
||||
* Fixed statements that logged incorrect data ([#3381](https://github.com/EQEmu/Server/pull/3381)) @noudess 2023-06-07
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetEXPForLevel() to Perl/Lua ([#3403](https://github.com/EQEmu/Server/pull/3403)) @Kinglykrab 2023-06-12
|
||||
* Add SendChannelMessage() to Perl/Lua ([#3378](https://github.com/EQEmu/Server/pull/3378)) @Kinglykrab 2023-06-04
|
||||
* Add several spell methods to Perl/Lua ([#3379](https://github.com/EQEmu/Server/pull/3379)) @Kinglykrab 2023-06-12
|
||||
|
||||
### Targeting
|
||||
|
||||
* /tar <bad target> should not untarget existing target ([#3383](https://github.com/EQEmu/Server/pull/3383)) @noudess 2023-06-12
|
||||
|
||||
## [22.12.0] - 05/29/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Cleanup #setskill and #setskillall Commands ([#3367](https://github.com/EQEmu/Server/pull/3367)) @Kinglykrab 2023-05-25
|
||||
* Delete message.h ([#3348](https://github.com/EQEmu/Server/pull/3348)) @Kinglykrab 2023-05-17
|
||||
* Fix #spawn command NPCs having 0 health ([#3371](https://github.com/EQEmu/Server/pull/3371)) @Kinglykrab 2023-05-21
|
||||
* Remove CalcPetHp from spdat.h ([#3364](https://github.com/EQEmu/Server/pull/3364)) @Kinglykrab 2023-05-25
|
||||
* Remove CountNPC() and QueueManaged() from entity.cpp/entity.h ([#3346](https://github.com/EQEmu/Server/pull/3346)) @Kinglykrab 2023-05-17
|
||||
* Remove DumpMerchantList() from zone.cpp/zone.h ([#3343](https://github.com/EQEmu/Server/pull/3343)) @Kinglykrab 2023-05-17
|
||||
* Remove GetDamageReceived() and GetHealReceived() from combat_record.cpp/combat_record.h ([#3358](https://github.com/EQEmu/Server/pull/3358)) @Kinglykrab 2023-05-17
|
||||
* Remove GetEscapingEntOnHateList() from hate_list.cpp/hate_list.h ([#3353](https://github.com/EQEmu/Server/pull/3353)) @Kinglykrab 2023-05-17
|
||||
* Remove GetMaxRank() from aa_ability.cpp/aa_ability.h ([#3347](https://github.com/EQEmu/Server/pull/3347)) @Kinglykrab 2023-05-25
|
||||
* Remove IsEntityInFrenzyMode() from hate_list.cpp/hate_list.h ([#3352](https://github.com/EQEmu/Server/pull/3352)) @Kinglykrab 2023-05-17
|
||||
* Remove IsRaid() from raids.h ([#3361](https://github.com/EQEmu/Server/pull/3361)) @Kinglykrab 2023-05-25
|
||||
* Remove LoadSpawn2() and PopulateZoneSpawnListClose() from spawn2.cpp/zonedb.h ([#3344](https://github.com/EQEmu/Server/pull/3344)) @Kinglykrab 2023-05-25
|
||||
* Remove SetGraveyard() from zone.cpp/zone.h ([#3354](https://github.com/EQEmu/Server/pull/3354)) @Kinglykrab 2023-05-17
|
||||
* Remove SetTradeCash() from trading.cpp/common.h ([#3356](https://github.com/EQEmu/Server/pull/3356)) @Kinglykrab 2023-05-17
|
||||
* Remove TraderUpdate() from trading.cpp/client.h ([#3357](https://github.com/EQEmu/Server/pull/3357)) @Kinglykrab 2023-05-17
|
||||
* Remove TypeToSkill() from tradeskills.cpp/object.h ([#3355](https://github.com/EQEmu/Server/pull/3355)) @Kinglykrab 2023-05-17
|
||||
* Remove Z_AGGRO from spdat.h ([#3365](https://github.com/EQEmu/Server/pull/3365)) @Kinglykrab 2023-05-25
|
||||
* Remove numMembers from raids.h ([#3362](https://github.com/EQEmu/Server/pull/3362)) @Kinglykrab 2023-05-25
|
||||
* Set GetAugmentType() to int again ([#3335](https://github.com/EQEmu/Server/pull/3335)) @Kinglykrab 2023-05-08
|
||||
|
||||
### Commands
|
||||
|
||||
* Add #findcurrency Command ([#3368](https://github.com/EQEmu/Server/pull/3368)) @Kinglykrab 2023-05-25
|
||||
* Add entity variable command ([#3345](https://github.com/EQEmu/Server/pull/3345)) @Kinglykrab 2023-05-25
|
||||
* Cleanup #setanim ([#3350](https://github.com/EQEmu/Server/pull/3350)) @Kinglykrab 2023-05-25
|
||||
|
||||
### Feature
|
||||
|
||||
* Intoxication setter/getter for source, getter for Perl/Lua ([#3330](https://github.com/EQEmu/Server/pull/3330)) @JasXSL 2023-05-03
|
||||
|
||||
### Fixes
|
||||
|
||||
* #augmentitem bypasses augment restrictions ([#3332](https://github.com/EQEmu/Server/pull/3332)) @Kinglykrab 2023-05-07
|
||||
* Fix Heroic INT/WIS Bonuses ([#3341](https://github.com/EQEmu/Server/pull/3341)) @RekkasGit 2023-05-15
|
||||
* Fix duplicate messages in #npcedit ([#3372](https://github.com/EQEmu/Server/pull/3372)) @Kinglykrab 2023-05-21
|
||||
* Fix issue with Group Pointers/Member roles ([#3374](https://github.com/EQEmu/Server/pull/3374)) @Aeadoin 2023-05-25
|
||||
* Fix mob item bonus calc ([#3334](https://github.com/EQEmu/Server/pull/3334)) @Akkadius 2023-05-07
|
||||
* Fix typos in #zheader ([#3370](https://github.com/EQEmu/Server/pull/3370)) @Kinglykrab 2023-05-21
|
||||
* Mob scaling issue with min dmg set to zero while max dmg is not ([#3351](https://github.com/EQEmu/Server/pull/3351)) @RekkasGit 2023-05-20
|
||||
* NPC Armor Upgrade to a slot not handled correctly ([#3366](https://github.com/EQEmu/Server/pull/3366)) @noudess 2023-05-20
|
||||
* ReloadQuests() on Zone::Init() to avoid cached global quests/plugins ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Kinglykrab 2023-05-07
|
||||
* Revert " ReloadQuests() on Zone::Init() to avoid cached global quests/plugins " ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Akkadius 2023-05-08
|
||||
|
||||
### Memory Leak
|
||||
|
||||
* Fix large memory leak introduced in CalcItemBonuses ([#3331](https://github.com/EQEmu/Server/pull/3331)) @Akkadius 2023-05-07
|
||||
|
||||
### Messages
|
||||
|
||||
* Remove duplicate heal message for healing yourself ([#3329](https://github.com/EQEmu/Server/pull/3329)) @noudess 2023-05-03
|
||||
|
||||
### Performance
|
||||
|
||||
* Character bind is now bulk saved ([#3338](https://github.com/EQEmu/Server/pull/3338)) @Akkadius 2023-05-09
|
||||
* Character buffs now save in bulk ([#3336](https://github.com/EQEmu/Server/pull/3336)) @Akkadius 2023-05-09
|
||||
* Character pet bulk saving ([#3337](https://github.com/EQEmu/Server/pull/3337)) @Akkadius 2023-05-09
|
||||
* Character tribute is now bulk saved ([#3340](https://github.com/EQEmu/Server/pull/3340)) @Kinglykrab 2023-05-25
|
||||
* Mail key is now cached during player load ([#3339](https://github.com/EQEmu/Server/pull/3339)) @Akkadius 2023-05-09
|
||||
|
||||
### Pets
|
||||
|
||||
* Fix saving inconsistencies with pets ([#3375](https://github.com/EQEmu/Server/pull/3375)) @Akkadius 2023-05-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetHateListClosest(), GetHateListClosestBot(), GetHateListClosestClient(), and GetHateListClosestNPC() methods/overloads to Perl/Lua ([#3359](https://github.com/EQEmu/Server/pull/3359)) @RekkasGit 2023-05-16
|
||||
* Add GetPet() to Perl ([#3309](https://github.com/EQEmu/Server/pull/3309)) @Kinglykrab 2023-05-08
|
||||
* Add Memorize and Scribe Spell Events to Perl/Lua ([#3363](https://github.com/EQEmu/Server/pull/3363)) @Kinglykrab 2023-05-25
|
||||
* Add zone data methods to Perl/Lua ([#3342](https://github.com/EQEmu/Server/pull/3342)) @Kinglykrab 2023-05-24
|
||||
* Cleanup The Darkened Sea Quest Methods Names ([#3369](https://github.com/EQEmu/Server/pull/3369)) @Kinglykrab 2023-05-21
|
||||
|
||||
### Rules
|
||||
|
||||
* Add World:MaximumQuestErrors Rule ([#3349](https://github.com/EQEmu/Server/pull/3349)) @Kinglykrab 2023-05-21
|
||||
* ResurrectionEffectBlock to prevent/allow/move buffs. ([#3288](https://github.com/EQEmu/Server/pull/3288)) @nytmyr 2023-05-08
|
||||
|
||||
## [22.11.0] - 04/29/2023
|
||||
|
||||
### Code
|
||||
|
||||
* Add check for owner in quest::pausetimer() ([#3304](https://github.com/EQEmu/Server/pull/3304)) @Kinglykrab 2023-04-23
|
||||
* Add check for owner in quest::resumetimer() ([#3305](https://github.com/EQEmu/Server/pull/3305)) @Kinglykrab 2023-04-23
|
||||
* Add initiator/owner checks to various methods in questmgr.cpp ([#3306](https://github.com/EQEmu/Server/pull/3306)) @Kinglykrab 2023-04-23
|
||||
* Fix possible nullptr in quest::addloot() ([#3303](https://github.com/EQEmu/Server/pull/3303)) @Kinglykrab 2023-04-23
|
||||
* Remove GetClassHPFactor() from zone/client_mods.cpp and zone/client.h ([#3313](https://github.com/EQEmu/Server/pull/3313)) @Kinglykrab 2023-04-30
|
||||
* Remove GetClassHPFactor() from zone/merc.h ([#3314](https://github.com/EQEmu/Server/pull/3314)) @Kinglykrab 2023-04-30
|
||||
* Remove pDontCastBefore_casting_spell from zone/npc.h ([#3311](https://github.com/EQEmu/Server/pull/3311)) @Kinglykrab 2023-04-30
|
||||
* Remove unused code in zone/pets.cpp ([#3310](https://github.com/EQEmu/Server/pull/3310)) @Kinglykrab 2023-04-30
|
||||
* Remove unused methods in zone/bot.cpp and zone/bot.h ([#3315](https://github.com/EQEmu/Server/pull/3315)) @Kinglykrab 2023-04-30
|
||||
* Remove unused methods in zone/client.cpp and zone/client.h ([#3312](https://github.com/EQEmu/Server/pull/3312)) @Kinglykrab 2023-04-30
|
||||
* Remove unused variable in common/crash.cpp ([#3308](https://github.com/EQEmu/Server/pull/3308)) @Kinglykrab 2023-04-30
|
||||
* Use default ctor/dtor in oriented_bounding_box.h ([#3307](https://github.com/EQEmu/Server/pull/3307)) @Kinglykrab 2023-04-30
|
||||
* quest::createBot() unnecessary check against nullptr ([#3302](https://github.com/EQEmu/Server/pull/3302)) @Kinglykrab 2023-04-23
|
||||
* quest::setallskill() had always true condition. ([#3301](https://github.com/EQEmu/Server/pull/3301)) @Kinglykrab 2023-04-30
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix UCS crash that occurs during log reloading ([#3324](https://github.com/EQEmu/Server/pull/3324)) @Akkadius 2023-04-30
|
||||
* Fix possible dereference of nullptr in Client::CalcHPRegen ([#3316](https://github.com/EQEmu/Server/pull/3316)) @Aeadoin 2023-04-23
|
||||
* Fix possible nullptr in Client::GetCharMaxLevelFromQGlobal() ([#3317](https://github.com/EQEmu/Server/pull/3317)) @Kinglykrab 2023-04-23
|
||||
|
||||
### Discord
|
||||
|
||||
* Add Discord webhook callback processing to world ([#3322](https://github.com/EQEmu/Server/pull/3322)) @Akkadius 2023-04-30
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix issue with NPCs no longer using some armor. ([#3318](https://github.com/EQEmu/Server/pull/3318)) @noudess 2023-04-24
|
||||
* Fix issue with spawning Mercs ([#3327](https://github.com/EQEmu/Server/pull/3327)) @Aeadoin 2023-04-29
|
||||
* Possible issues with SummonItem in Client::QuestReward() methods ([#3325](https://github.com/EQEmu/Server/pull/3325)) @Kinglykrab 2023-04-27
|
||||
|
||||
### Maps
|
||||
|
||||
* Update download with faster releases link ([#3321](https://github.com/EQEmu/Server/pull/3321)) @Akkadius 2023-04-30
|
||||
|
||||
### Messages
|
||||
|
||||
* Remove duplicate you have lost a level message ([#3323](https://github.com/EQEmu/Server/pull/3323)) @noudess 2023-04-25
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetDefaultRaceSize() overloads to Perl/Lua ([#3320](https://github.com/EQEmu/Server/pull/3320)) @Kinglykrab 2023-04-30
|
||||
* Add HasSpellEffect() to Perl/Lua ([#3319](https://github.com/EQEmu/Server/pull/3319)) @Kinglykrab 2023-04-30
|
||||
|
||||
## [22.10.0] - 04/22/2023
|
||||
|
||||
### Backups
|
||||
|
||||
* Fix database dump error reporting ([#3175](https://github.com/EQEmu/Server/pull/3175)) @Akkadius 2023-04-04
|
||||
|
||||
### Bots
|
||||
|
||||
* Cleanup GetBotTables() ([#3270](https://github.com/EQEmu/Server/pull/3270)) @Aeadoin 2023-04-06
|
||||
|
||||
### Cleanuo
|
||||
|
||||
* Only define row if we have results in Database::GetCharacterID() ([#3199](https://github.com/EQEmu/Server/pull/3199)) @Kinglykrab 2023-04-05
|
||||
|
||||
### Code
|
||||
|
||||
* Add missing breaks and returns in bonuses.cpp ([#3231](https://github.com/EQEmu/Server/pull/3231)) @Kinglykrab 2023-04-05
|
||||
* Breaks in wrong spot in cases in spell_effects.cpp ([#3297](https://github.com/EQEmu/Server/pull/3297)) @Kinglykrab 2023-04-22
|
||||
* Cleanup always true/false statements in shareddb.cpp ([#3189](https://github.com/EQEmu/Server/pull/3189)) @Kinglykrab 2023-04-05
|
||||
* Cleanup cheap-to-copy reference to use value instead in eq_stream_ident.cpp/eq_stream_ident.h ([#3209](https://github.com/EQEmu/Server/pull/3209)) @Kinglykrab 2023-04-05
|
||||
* Cleanup discord.cpp and discord_manager.cpp ([#3205](https://github.com/EQEmu/Server/pull/3205)) @Kinglykrab 2023-04-05
|
||||
* Cleanup duplicate conditions in negate bonuses in bonuses.cpp ([#3226](https://github.com/EQEmu/Server/pull/3226)) @Kinglykrab 2023-04-05
|
||||
* Cleanup item_instance.cpp always true statements and reassigning of same values ([#3187](https://github.com/EQEmu/Server/pull/3187)) @Kinglykrab 2023-04-05
|
||||
* Cleanup macros in features.h ([#3185](https://github.com/EQEmu/Server/pull/3185)) @Kinglykrab 2023-04-05
|
||||
* Cleanup string -> char* -> string conversions in bot_command.cpp ([#3252](https://github.com/EQEmu/Server/pull/3252)) @Kinglykrab 2023-04-05
|
||||
* Cleanup unnecessary condition in Client::SendAlternateCurrencyValue() ([#3266](https://github.com/EQEmu/Server/pull/3266)) @Kinglykrab 2023-04-05
|
||||
* Cleanup zone/zoning.cpp ([#3289](https://github.com/EQEmu/Server/pull/3289)) @Kinglykrab 2023-04-14
|
||||
* Combine similar cases in Client::InitInnates() ([#3260](https://github.com/EQEmu/Server/pull/3260)) @Kinglykrab 2023-04-05
|
||||
* Convert equipable_slot_list to std::vector from std::list in bot_command.cpp ([#3253](https://github.com/EQEmu/Server/pull/3253)) @Kinglykrab 2023-04-05
|
||||
* Delete embxs.cpp/embxs.h ([#3284](https://github.com/EQEmu/Server/pull/3284)) @Kinglykrab 2023-04-14
|
||||
* Delete unused strings in bot_command.cpp ([#3251](https://github.com/EQEmu/Server/pull/3251)) @Kinglykrab 2023-04-05
|
||||
* Fix GetLastName() length check in Client::SendWindow() ([#3263](https://github.com/EQEmu/Server/pull/3263)) @Kinglykrab 2023-04-05
|
||||
* Fix always false conditions in Client::IncStats() ([#3256](https://github.com/EQEmu/Server/pull/3256)) @Kinglykrab 2023-04-05
|
||||
* Fix check for !this in Client::SendHPUpdateMarquee() ([#3257](https://github.com/EQEmu/Server/pull/3257)) @Kinglykrab 2023-04-05
|
||||
* Fix filter condition in attack.cpp ([#3218](https://github.com/EQEmu/Server/pull/3218)) @Kinglykrab 2023-04-05
|
||||
* Fix ornamentation augment icons in inspect requests ([#3264](https://github.com/EQEmu/Server/pull/3264)) @Kinglykrab 2023-04-05
|
||||
* Fix possible nullptr inst in GetSharedBank() ([#3190](https://github.com/EQEmu/Server/pull/3190)) @Kinglykrab 2023-04-08
|
||||
* Fix possible overflows in Client::AddPlatinum() and Client::TakePlatinum() ([#3255](https://github.com/EQEmu/Server/pull/3255)) @Kinglykrab 2023-04-05
|
||||
* Fix shared_tasks.cpp/shared_tasks.cpp variable named same as class member ([#3192](https://github.com/EQEmu/Server/pull/3192)) @Kinglykrab 2023-04-05
|
||||
* Fix skill_used being used as boolean in Mob::CommonDamage() ([#3220](https://github.com/EQEmu/Server/pull/3220)) @Kinglykrab 2023-04-05
|
||||
* Identical conditions right beside each other in aa.cpp ([#3213](https://github.com/EQEmu/Server/pull/3213)) @Kinglykrab 2023-04-05
|
||||
* Move unreachable code in ApplySpellsBonuses() ([#3229](https://github.com/EQEmu/Server/pull/3229)) @Kinglykrab 2023-04-05
|
||||
* Move variable definition to more relevant scope in DatabaseDumpService::Dump() ([#3200](https://github.com/EQEmu/Server/pull/3200)) @Kinglykrab 2023-04-05
|
||||
* Multiple cases with same outcome in GetDiscordPayloadFromEvent() ([#3184](https://github.com/EQEmu/Server/pull/3184)) @Kinglykrab 2023-04-05
|
||||
* Remove ExportVarComplex() from embparser.cpp/embparser.h ([#3282](https://github.com/EQEmu/Server/pull/3282)) @Kinglykrab 2023-04-14
|
||||
* Remove GetQGlobal() from qglobals.cpp/qglobals.h ([#3285](https://github.com/EQEmu/Server/pull/3285)) @Kinglykrab 2023-04-14
|
||||
* Remove IsFullHP from mob.cpp/mob.h ([#3277](https://github.com/EQEmu/Server/pull/3277)) @Kinglykrab 2023-04-14
|
||||
* Remove IsMeleeDmg() from skills.cpp/skills.h ([#3279](https://github.com/EQEmu/Server/pull/3279)) @Kinglykrab 2023-04-14
|
||||
* Remove _GetMovementSpeed() from mob.h ([#3276](https://github.com/EQEmu/Server/pull/3276)) @Kinglykrab 2023-04-14
|
||||
* Remove always true condition in Strings::Commify() ([#3193](https://github.com/EQEmu/Server/pull/3193)) @Kinglykrab 2023-04-05
|
||||
* Remove always true conditions and unreachable code in Client::SendMercPersonalInfo() ([#3258](https://github.com/EQEmu/Server/pull/3258)) @Kinglykrab 2023-04-05
|
||||
* Remove always true statement in say_link.cpp ([#3188](https://github.com/EQEmu/Server/pull/3188)) @Kinglykrab 2023-04-05
|
||||
* Remove always true statements in task_client_state.cpp ([#3292](https://github.com/EQEmu/Server/pull/3292)) @Kinglykrab 2023-04-14
|
||||
* Remove always true/false conditions from bot.cpp ([#3237](https://github.com/EQEmu/Server/pull/3237)) @Kinglykrab 2023-04-05
|
||||
* Remove bool return from GetSharedPlatinum() ([#3191](https://github.com/EQEmu/Server/pull/3191)) @Kinglykrab 2023-04-05
|
||||
* Remove extra assignment of current_endurance in Client ctor ([#3261](https://github.com/EQEmu/Server/pull/3261)) @Kinglykrab 2023-04-05
|
||||
* Remove extraneous check for NegateAttacks in SE_NegateAttacks ([#3228](https://github.com/EQEmu/Server/pull/3228)) @Kinglykrab 2023-04-05
|
||||
* Remove extraneous parentheses around math in Mob::ApplySpellsBonuses() ([#3227](https://github.com/EQEmu/Server/pull/3227)) @Kinglykrab 2023-04-05
|
||||
* Remove getd(), geti(), InUse(), lasterr(), my_get_sv(), and VarExists() in embperl.cpp/embperl.h ([#3283](https://github.com/EQEmu/Server/pull/3283)) @Kinglykrab 2023-04-15
|
||||
* Remove item_timers from questmgr.cpp/questmgr.h ([#3286](https://github.com/EQEmu/Server/pull/3286)) @Kinglykrab 2023-04-14
|
||||
* Remove pendinggroup from mob.h ([#3278](https://github.com/EQEmu/Server/pull/3278)) @Kinglykrab 2023-04-14
|
||||
* Remove position_same_update_count from client.cpp/client.h ([#3280](https://github.com/EQEmu/Server/pull/3280)) @Kinglykrab 2023-04-14
|
||||
* Remove unnecessary break in while loop in Mob::AddToHateList() ([#3219](https://github.com/EQEmu/Server/pull/3219)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary check for IsStackable() in DeleteItem() ([#3186](https://github.com/EQEmu/Server/pull/3186)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary condition and cleanup variable name in tasks.cpp ([#3293](https://github.com/EQEmu/Server/pull/3293)) @Kinglykrab 2023-04-14
|
||||
* Remove unnecessary conditions in Client::Consume() ([#3265](https://github.com/EQEmu/Server/pull/3265)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary conditions in Client::FilteredMessageCheck() ([#3262](https://github.com/EQEmu/Server/pull/3262)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary conditions in Client::SendFactionMessage() ([#3267](https://github.com/EQEmu/Server/pull/3267)) @Kinglykrab 2023-04-05
|
||||
* Remove unnecessary setting of reuse variable in Bot::DoClassAttacks() ([#3233](https://github.com/EQEmu/Server/pull/3233)) @Kinglykrab 2023-04-05
|
||||
* Remove unused SetConfigFile in common/eqemu_config.h ([#3208](https://github.com/EQEmu/Server/pull/3208)) @Kinglykrab 2023-04-05
|
||||
* Remove unused code in eq_packet.cpp/eq_packet.h ([#3183](https://github.com/EQEmu/Server/pull/3183)) @Kinglykrab 2023-04-05
|
||||
* Remove unused ctor and use default dtor in xtargetautohaters.h ([#3290](https://github.com/EQEmu/Server/pull/3290)) @Kinglykrab 2023-04-14
|
||||
* Remove unused macros in common/types.h ([#3194](https://github.com/EQEmu/Server/pull/3194)) @Kinglykrab 2023-04-05
|
||||
* Remove unused variable in Database::CopyCharacter() ([#3197](https://github.com/EQEmu/Server/pull/3197)) @Kinglykrab 2023-04-05
|
||||
* Remove unused variables and use reference in task_manager.cpp ([#3291](https://github.com/EQEmu/Server/pull/3291)) @Kinglykrab 2023-04-14
|
||||
* SE_AttackSpeed3 effect_value is always less than 0 ([#3222](https://github.com/EQEmu/Server/pull/3222)) @Kinglykrab 2023-04-05
|
||||
* SE_StrikeThrough and SE_StrikeThrough2 are the same in bonuses.cpp ([#3223](https://github.com/EQEmu/Server/pull/3223)) @Kinglykrab 2023-04-05
|
||||
* Set bonuses to use spell ID instead of boolean ([#3230](https://github.com/EQEmu/Server/pull/3230)) @Kinglykrab 2023-04-05
|
||||
* Use .clear() and .empty() instead of comparing to empty string or setting to empty string in CheckDatabaseConvertPPBlob() ([#3201](https://github.com/EQEmu/Server/pull/3201)) @Kinglykrab 2023-04-05
|
||||
* Use .clear() instead of setting string to empty in eqemu_command_handler.cpp ([#3195](https://github.com/EQEmu/Server/pull/3195)) @Kinglykrab 2023-04-05
|
||||
* Use .empty() in Client::ScribeSpells() and Client::LearnDisciplines() ([#3259](https://github.com/EQEmu/Server/pull/3259)) @Kinglykrab 2023-04-05
|
||||
* Use constant reference and check for empty string properly in dbcore.cpp ([#3203](https://github.com/EQEmu/Server/pull/3203)) @Kinglykrab 2023-04-05
|
||||
* Use default ctor instead of an empty ctor. ([#3206](https://github.com/EQEmu/Server/pull/3206)) @Kinglykrab 2023-04-05
|
||||
* Use default dtor instead of empty dtor for EQTime in eqtime.cpp/eqtime.h ([#3210](https://github.com/EQEmu/Server/pull/3210)) @Kinglykrab 2023-04-05
|
||||
* Use variable for c->GetTarget() instead of calling multiple times in bot_command.cpp ([#3254](https://github.com/EQEmu/Server/pull/3254)) @Kinglykrab 2023-04-05
|
||||
* Use variable for character instead of a loop ([#3268](https://github.com/EQEmu/Server/pull/3268)) @Kinglykrab 2023-04-05
|
||||
* Utilize .empty() instead of checking for an empty string in Database::ReserveName() ([#3198](https://github.com/EQEmu/Server/pull/3198)) @Kinglykrab 2023-04-05
|
||||
* Utilize IsTaunting(), SetPetPower(), SetPetType(), and SetTaunting() ([#3275](https://github.com/EQEmu/Server/pull/3275)) @Kinglykrab 2023-04-15
|
||||
* Validate for nullptrs in bot.cpp ([#3232](https://github.com/EQEmu/Server/pull/3232)) @Kinglykrab 2023-04-05
|
||||
* other is always defined in these cases in attack.cpp ([#3217](https://github.com/EQEmu/Server/pull/3217)) @Kinglykrab 2023-04-05
|
||||
* results variable is assigned but never used in SaveCharacterCreate() ([#3180](https://github.com/EQEmu/Server/pull/3180)) @Kinglykrab 2023-04-05
|
||||
|
||||
### Crash
|
||||
|
||||
* Add additional raid integrity checks on Bot Spawn. ([#3295](https://github.com/EQEmu/Server/pull/3295)) @Aeadoin 2023-04-16
|
||||
* Fix crash with uninitialized item instance, and Bot timeout ([#3296](https://github.com/EQEmu/Server/pull/3296)) @Aeadoin 2023-04-15
|
||||
* Resolve crash due to uninitialized pointer. ([#3271](https://github.com/EQEmu/Server/pull/3271)) @Aeadoin 2023-04-08
|
||||
|
||||
### Feature
|
||||
|
||||
* Make ornamentations work with any augment type ([#3281](https://github.com/EQEmu/Server/pull/3281)) @Kinglykrab 2023-04-16
|
||||
|
||||
### Fixes
|
||||
|
||||
* Camping was causing player to leave raid, causing unexpected behavior ([#3299](https://github.com/EQEmu/Server/pull/3299)) @Aeadoin 2023-04-22
|
||||
* Resolve loading of inventory ([#3272](https://github.com/EQEmu/Server/pull/3272)) @Aeadoin 2023-04-08
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add ApplySpellRaid() and SetSpellDurationRaid() to Bots in Perl/Lua ([#3274](https://github.com/EQEmu/Server/pull/3274)) @Kinglykrab 2023-04-09
|
||||
* Add GetBuffSpellIDs() to Perl/Lua ([#3273](https://github.com/EQEmu/Server/pull/3273)) @Kinglykrab 2023-04-09
|
||||
* Fix LDoN Methods in Perl/Lua ([#3287](https://github.com/EQEmu/Server/pull/3287)) @Kinglykrab 2023-04-10
|
||||
|
||||
### Rules
|
||||
|
||||
* Optional summoning when already in melee range ([#3204](https://github.com/EQEmu/Server/pull/3204)) @trentdm 2023-04-08
|
||||
|
||||
### Telnet
|
||||
|
||||
* Telnet encoding fix ([#3269](https://github.com/EQEmu/Server/pull/3269)) @Akkadius 2023-04-05
|
||||
|
||||
## [22.9.1] - 04/03/2023
|
||||
|
||||
### Code
|
||||
|
||||
@@ -630,6 +630,20 @@ bool IsINTCasterClass(uint8 class_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsHeroicINTCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
case SHADOWKNIGHT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsWISCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
@@ -642,6 +656,21 @@ bool IsWISCasterClass(uint8 class_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsHeroicWISCasterClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case PALADIN:
|
||||
case BEASTLORD:
|
||||
case RANGER:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPlateClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
|
||||
+2
-1
@@ -140,7 +140,8 @@ bool IsHybridClass(uint8 class_id);
|
||||
bool IsCasterClass(uint8 class_id);
|
||||
bool IsINTCasterClass(uint8 class_id);
|
||||
bool IsWISCasterClass(uint8 class_id);
|
||||
|
||||
bool IsHeroicINTCasterClass(uint8 class_id);
|
||||
bool IsHeroicWISCasterClass(uint8 class_id);
|
||||
bool IsPlateClass(uint8 class_id);
|
||||
bool IsChainClass(uint8 class_id);
|
||||
bool IsLeatherClass(uint8 class_id);
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace EQEmuCommand {
|
||||
*/
|
||||
std::string command_section;
|
||||
for (auto &it: in_function_map) {
|
||||
description = "";
|
||||
description.clear();
|
||||
|
||||
(it.second)(argc, argv, cmd, description);
|
||||
|
||||
|
||||
@@ -41,9 +41,6 @@ void SendCrashReport(const std::string &crash_report)
|
||||
r.set_connection_timeout(1, 0);
|
||||
r.set_read_timeout(1, 0);
|
||||
r.set_write_timeout(1, 0);
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
// os info
|
||||
auto os = EQ::GetOS();
|
||||
|
||||
+138
-121
@@ -353,7 +353,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
||||
|
||||
query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success() || results.ErrorMessage() != ""){ return false; }
|
||||
if (!results.Success() || !results.ErrorMessage().empty()){ return false; }
|
||||
|
||||
// Put character into the default guild if rule is being used.
|
||||
int guild_id = RuleI(Character, DefaultGuild);
|
||||
@@ -363,7 +363,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
|
||||
if (character_id > -1) {
|
||||
query = StringFormat("INSERT INTO `guild_members` SET `char_id` = %i, `guild_id` = '%i'", character_id, guild_id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success() || results.ErrorMessage() != ""){
|
||||
if (!results.Success() || !results.ErrorMessage().empty()){
|
||||
LogInfo("Could not put character [{}] into default Guild", name);
|
||||
}
|
||||
}
|
||||
@@ -449,7 +449,8 @@ bool Database::DeleteCharacter(char *character_name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){
|
||||
bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `character_data` ("
|
||||
"id,"
|
||||
@@ -634,101 +635,102 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
"%u," // guild_auto_consent
|
||||
"%u" // RestTimer
|
||||
")",
|
||||
character_id, // " id, "
|
||||
account_id, // " account_id, "
|
||||
Strings::Escape(pp->name).c_str(), // " `name`, "
|
||||
character_id, // " id, "
|
||||
account_id, // " account_id, "
|
||||
Strings::Escape(pp->name).c_str(), // " `name`, "
|
||||
Strings::Escape(pp->last_name).c_str(), // " last_name, "
|
||||
pp->gender, // " gender, "
|
||||
pp->race, // " race, "
|
||||
pp->class_, // " class, "
|
||||
pp->level, // " `level`, "
|
||||
pp->deity, // " deity, "
|
||||
pp->birthday, // " birthday, "
|
||||
pp->lastlogin, // " last_login, "
|
||||
pp->timePlayedMin, // " time_played, "
|
||||
pp->pvp, // " pvp_status, "
|
||||
pp->level2, // " level2, "
|
||||
pp->anon, // " anon, "
|
||||
pp->gm, // " gm, "
|
||||
pp->intoxication, // " intoxication, "
|
||||
pp->haircolor, // " hair_color, "
|
||||
pp->beardcolor, // " beard_color, "
|
||||
pp->eyecolor1, // " eye_color_1, "
|
||||
pp->eyecolor2, // " eye_color_2, "
|
||||
pp->hairstyle, // " hair_style, "
|
||||
pp->beard, // " beard, "
|
||||
pp->ability_time_seconds, // " ability_time_seconds, "
|
||||
pp->ability_number, // " ability_number, "
|
||||
pp->ability_time_minutes, // " ability_time_minutes, "
|
||||
pp->ability_time_hours, // " ability_time_hours, "
|
||||
pp->gender, // " gender, "
|
||||
pp->race, // " race, "
|
||||
pp->class_, // " class, "
|
||||
pp->level, // " `level`, "
|
||||
pp->deity, // " deity, "
|
||||
pp->birthday, // " birthday, "
|
||||
pp->lastlogin, // " last_login, "
|
||||
pp->timePlayedMin, // " time_played, "
|
||||
pp->pvp, // " pvp_status, "
|
||||
pp->level2, // " level2, "
|
||||
pp->anon, // " anon, "
|
||||
pp->gm, // " gm, "
|
||||
pp->intoxication, // " intoxication, "
|
||||
pp->haircolor, // " hair_color, "
|
||||
pp->beardcolor, // " beard_color, "
|
||||
pp->eyecolor1, // " eye_color_1, "
|
||||
pp->eyecolor2, // " eye_color_2, "
|
||||
pp->hairstyle, // " hair_style, "
|
||||
pp->beard, // " beard, "
|
||||
pp->ability_time_seconds, // " ability_time_seconds, "
|
||||
pp->ability_number, // " ability_number, "
|
||||
pp->ability_time_minutes, // " ability_time_minutes, "
|
||||
pp->ability_time_hours, // " ability_time_hours, "
|
||||
Strings::Escape(pp->title).c_str(), // " title, "
|
||||
Strings::Escape(pp->suffix).c_str(), // " suffix, "
|
||||
pp->exp, // " exp, "
|
||||
pp->points, // " points, "
|
||||
pp->mana, // " mana, "
|
||||
pp->cur_hp, // " cur_hp, "
|
||||
pp->STR, // " str, "
|
||||
pp->STA, // " sta, "
|
||||
pp->CHA, // " cha, "
|
||||
pp->DEX, // " dex, "
|
||||
pp->INT, // " `int`, "
|
||||
pp->AGI, // " agi, "
|
||||
pp->WIS, // " wis, "
|
||||
pp->face, // " face, "
|
||||
pp->y, // " y, "
|
||||
pp->x, // " x, "
|
||||
pp->z, // " z, "
|
||||
pp->heading, // " heading, "
|
||||
pp->pvp2, // " pvp2, "
|
||||
pp->pvptype, // " pvp_type, "
|
||||
pp->autosplit, // " autosplit_enabled, "
|
||||
pp->zone_change_count, // " zone_change_count, "
|
||||
pp->drakkin_heritage, // " drakkin_heritage, "
|
||||
pp->drakkin_tattoo, // " drakkin_tattoo, "
|
||||
pp->drakkin_details, // " drakkin_details, "
|
||||
pp->toxicity, // " toxicity, "
|
||||
pp->hunger_level, // " hunger_level, "
|
||||
pp->thirst_level, // " thirst_level, "
|
||||
pp->ability_up, // " ability_up, "
|
||||
pp->zone_id, // " zone_id, "
|
||||
pp->zoneInstance, // " zone_instance, "
|
||||
pp->leadAAActive, // " leadership_exp_on, "
|
||||
pp->ldon_points_guk, // " ldon_points_guk, "
|
||||
pp->ldon_points_mir, // " ldon_points_mir, "
|
||||
pp->ldon_points_mmc, // " ldon_points_mmc, "
|
||||
pp->ldon_points_ruj, // " ldon_points_ruj, "
|
||||
pp->ldon_points_tak, // " ldon_points_tak, "
|
||||
pp->ldon_points_available, // " ldon_points_available, "
|
||||
pp->tribute_time_remaining, // " tribute_time_remaining, "
|
||||
pp->showhelm, // " show_helm, "
|
||||
pp->career_tribute_points, // " career_tribute_points, "
|
||||
pp->tribute_points, // " tribute_points, "
|
||||
pp->tribute_active, // " tribute_active, "
|
||||
pp->endurance, // " endurance, "
|
||||
pp->group_leadership_exp, // " group_leadership_exp, "
|
||||
pp->raid_leadership_exp, // " raid_leadership_exp, "
|
||||
pp->group_leadership_points, // " group_leadership_points, "
|
||||
pp->raid_leadership_points, // " raid_leadership_points, "
|
||||
pp->air_remaining, // " air_remaining, "
|
||||
pp->PVPKills, // " pvp_kills, "
|
||||
pp->PVPDeaths, // " pvp_deaths, "
|
||||
pp->PVPCurrentPoints, // " pvp_current_points, "
|
||||
pp->PVPCareerPoints, // " pvp_career_points, "
|
||||
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
|
||||
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
|
||||
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
|
||||
pp->aapoints_spent, // " aa_points_spent, "
|
||||
pp->expAA, // " aa_exp, "
|
||||
pp->aapoints, // " aa_points, "
|
||||
pp->groupAutoconsent, // " group_auto_consent, "
|
||||
pp->raidAutoconsent, // " raid_auto_consent, "
|
||||
pp->guildAutoconsent, // " guild_auto_consent, "
|
||||
pp->RestTimer // " RestTimer) "
|
||||
pp->exp, // " exp, "
|
||||
pp->points, // " points, "
|
||||
pp->mana, // " mana, "
|
||||
pp->cur_hp, // " cur_hp, "
|
||||
pp->STR, // " str, "
|
||||
pp->STA, // " sta, "
|
||||
pp->CHA, // " cha, "
|
||||
pp->DEX, // " dex, "
|
||||
pp->INT, // " `int`, "
|
||||
pp->AGI, // " agi, "
|
||||
pp->WIS, // " wis, "
|
||||
pp->face, // " face, "
|
||||
pp->y, // " y, "
|
||||
pp->x, // " x, "
|
||||
pp->z, // " z, "
|
||||
pp->heading, // " heading, "
|
||||
pp->pvp2, // " pvp2, "
|
||||
pp->pvptype, // " pvp_type, "
|
||||
pp->autosplit, // " autosplit_enabled, "
|
||||
pp->zone_change_count, // " zone_change_count, "
|
||||
pp->drakkin_heritage, // " drakkin_heritage, "
|
||||
pp->drakkin_tattoo, // " drakkin_tattoo, "
|
||||
pp->drakkin_details, // " drakkin_details, "
|
||||
pp->toxicity, // " toxicity, "
|
||||
pp->hunger_level, // " hunger_level, "
|
||||
pp->thirst_level, // " thirst_level, "
|
||||
pp->ability_up, // " ability_up, "
|
||||
pp->zone_id, // " zone_id, "
|
||||
pp->zoneInstance, // " zone_instance, "
|
||||
pp->leadAAActive, // " leadership_exp_on, "
|
||||
pp->ldon_points_guk, // " ldon_points_guk, "
|
||||
pp->ldon_points_mir, // " ldon_points_mir, "
|
||||
pp->ldon_points_mmc, // " ldon_points_mmc, "
|
||||
pp->ldon_points_ruj, // " ldon_points_ruj, "
|
||||
pp->ldon_points_tak, // " ldon_points_tak, "
|
||||
pp->ldon_points_available, // " ldon_points_available, "
|
||||
pp->tribute_time_remaining, // " tribute_time_remaining, "
|
||||
pp->showhelm, // " show_helm, "
|
||||
pp->career_tribute_points, // " career_tribute_points, "
|
||||
pp->tribute_points, // " tribute_points, "
|
||||
pp->tribute_active, // " tribute_active, "
|
||||
pp->endurance, // " endurance, "
|
||||
pp->group_leadership_exp, // " group_leadership_exp, "
|
||||
pp->raid_leadership_exp, // " raid_leadership_exp, "
|
||||
pp->group_leadership_points, // " group_leadership_points, "
|
||||
pp->raid_leadership_points, // " raid_leadership_points, "
|
||||
pp->air_remaining, // " air_remaining, "
|
||||
pp->PVPKills, // " pvp_kills, "
|
||||
pp->PVPDeaths, // " pvp_deaths, "
|
||||
pp->PVPCurrentPoints, // " pvp_current_points, "
|
||||
pp->PVPCareerPoints, // " pvp_career_points, "
|
||||
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
|
||||
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
|
||||
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
|
||||
pp->aapoints_spent, // " aa_points_spent, "
|
||||
pp->expAA, // " aa_exp, "
|
||||
pp->aapoints, // " aa_points, "
|
||||
pp->groupAutoconsent, // " group_auto_consent, "
|
||||
pp->raidAutoconsent, // " raid_auto_consent, "
|
||||
pp->guildAutoconsent, // " guild_auto_consent, "
|
||||
pp->RestTimer // " RestTimer) "
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* Save Bind Points */
|
||||
query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
"(%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
"(%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||
@@ -739,57 +741,73 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
character_id, pp->binds[2].zone_id, 0, pp->binds[2].x, pp->binds[2].y, pp->binds[2].z, pp->binds[2].heading, 2,
|
||||
character_id, pp->binds[3].zone_id, 0, pp->binds[3].x, pp->binds[3].y, pp->binds[3].z, pp->binds[3].heading, 3,
|
||||
character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4
|
||||
); results = QueryDatabase(query);
|
||||
);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* HoTT Ability */
|
||||
if(RuleB(Character, GrantHoTTOnCreate))
|
||||
{
|
||||
query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", character_id, 14, 1);
|
||||
results = QueryDatabase(query);
|
||||
}
|
||||
/* HoTT Ability */
|
||||
if (RuleB(Character, GrantHoTTOnCreate)) {
|
||||
query = StringFormat(
|
||||
"INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)",
|
||||
character_id,
|
||||
14,
|
||||
1
|
||||
);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
/* Save Skills */
|
||||
int firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_SKILL; i++){
|
||||
if (pp->skills[i] > 0){
|
||||
if (firstquery != 1){
|
||||
int firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_SKILL; i++) {
|
||||
if (pp->skills[i] > 0) {
|
||||
if (firstquery != 1) {
|
||||
firstquery = 1;
|
||||
query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]);
|
||||
}
|
||||
else{
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)",
|
||||
character_id,
|
||||
i,
|
||||
pp->skills[i]
|
||||
);
|
||||
} else {
|
||||
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
/* Save Language */
|
||||
firstquery = 0;
|
||||
for (int i = 0; i < MAX_PP_LANGUAGE; i++){
|
||||
if (pp->languages[i] > 0){
|
||||
if (firstquery != 1){
|
||||
for (int i = 0; i < MAX_PP_LANGUAGE; i++) {
|
||||
if (pp->languages[i] > 0) {
|
||||
if (firstquery != 1) {
|
||||
firstquery = 1;
|
||||
query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]);
|
||||
}
|
||||
else{
|
||||
query = StringFormat(
|
||||
"REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)",
|
||||
character_id,
|
||||
i,
|
||||
pp->languages[i]
|
||||
);
|
||||
} else {
|
||||
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
results = QueryDatabase(query);
|
||||
QueryDatabase(query);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 Database::GetCharacterID(const char *name) {
|
||||
std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name);
|
||||
const auto query = fmt::format(
|
||||
"SELECT `id` FROM `character_data` WHERE `name` = '{}'",
|
||||
Strings::Escape(name)
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1)
|
||||
{
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2274,7 +2292,6 @@ bool Database::CopyCharacter(
|
||||
new_rows.emplace_back(new_values);
|
||||
}
|
||||
|
||||
std::string insert_values;
|
||||
std::vector<std::string> insert_rows;
|
||||
|
||||
for (auto &r: new_rows) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../database_schema.h"
|
||||
#include "../file.h"
|
||||
#include "../process/process.h"
|
||||
#include "../termcolor/rang.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@@ -36,6 +37,7 @@
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <thread>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -145,7 +147,7 @@ std::string DatabaseDumpService::GetQueryServTables()
|
||||
|
||||
std::string DatabaseDumpService::GetSystemTablesList()
|
||||
{
|
||||
auto system_tables = DatabaseSchema::GetServerTables();
|
||||
auto system_tables = DatabaseSchema::GetServerTables();
|
||||
auto version_tables = DatabaseSchema::GetVersionTables();
|
||||
|
||||
system_tables.insert(
|
||||
@@ -199,7 +201,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath()
|
||||
return GetSetDumpPath() + GetDumpFileName();
|
||||
}
|
||||
|
||||
void DatabaseDumpService::Dump()
|
||||
void DatabaseDumpService::DatabaseDump()
|
||||
{
|
||||
if (!IsMySQLInstalled()) {
|
||||
LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation");
|
||||
@@ -293,14 +295,6 @@ void DatabaseDumpService::Dump()
|
||||
pipe_file = fmt::format(" > {}.sql", GetDumpFileNameWithPath());
|
||||
}
|
||||
|
||||
std::string execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) {
|
||||
File::Makedir(GetSetDumpPath());
|
||||
}
|
||||
@@ -308,7 +302,7 @@ void DatabaseDumpService::Dump()
|
||||
if (IsDumpDropTableSyntaxOnly()) {
|
||||
std::vector<std::string> tables = Strings::Split(tables_to_dump, ' ');
|
||||
|
||||
for (auto &table : tables) {
|
||||
for (auto &table: tables) {
|
||||
std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl;
|
||||
}
|
||||
|
||||
@@ -317,12 +311,40 @@ void DatabaseDumpService::Dump()
|
||||
}
|
||||
}
|
||||
else {
|
||||
const auto execute_command = fmt::format(
|
||||
"{} {} {} {}",
|
||||
GetBaseMySQLDumpCommand(),
|
||||
options,
|
||||
tables_to_dump,
|
||||
pipe_file
|
||||
);
|
||||
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
std::cout << execution_result;
|
||||
}
|
||||
}
|
||||
|
||||
LogSys.EnableConsoleLogging();
|
||||
|
||||
if (!pipe_file.empty()) {
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
auto r = File::GetContents(file);
|
||||
if (!r.error.empty()) {
|
||||
LogError("{}", r.error);
|
||||
}
|
||||
|
||||
for (auto &line: Strings::Split(r.contents, "\n")) {
|
||||
if (Strings::Contains(line, "mysqldump:")) {
|
||||
LogError("{}", line);
|
||||
LogError("Database dump failed. Correct the error before continuing or trying again");
|
||||
LogError("This is to prevent data loss on behalf of the server operator");
|
||||
RemoveSqlBackup();
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tables_to_dump.empty()) {
|
||||
LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump));
|
||||
}
|
||||
@@ -343,6 +365,7 @@ void DatabaseDumpService::Dump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else if (Is7ZipAvailable()) {
|
||||
Process::execute(
|
||||
@@ -353,6 +376,7 @@ void DatabaseDumpService::Dump()
|
||||
)
|
||||
);
|
||||
LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath());
|
||||
RemoveSqlBackup();
|
||||
}
|
||||
else {
|
||||
LogInfo("Compression requested, but no available compression binary was found");
|
||||
@@ -535,3 +559,11 @@ void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables)
|
||||
{
|
||||
DatabaseDumpService::dump_merc_tables = dump_merc_tables;
|
||||
}
|
||||
|
||||
void DatabaseDumpService::RemoveSqlBackup()
|
||||
{
|
||||
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
|
||||
if (File::Exists(file)) {
|
||||
std::filesystem::remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
class DatabaseDumpService {
|
||||
public:
|
||||
void Dump();
|
||||
void DatabaseDump();
|
||||
bool IsDumpAllTables() const;
|
||||
void SetDumpAllTables(bool dump_all_tables);
|
||||
bool IsDumpWithNoData() const;
|
||||
@@ -92,6 +92,7 @@ private:
|
||||
std::string GetDumpFileNameWithPath();
|
||||
std::string GetSetDumpPath();
|
||||
std::string GetQueryServTables();
|
||||
void RemoveSqlBackup();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -967,7 +967,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
loadbar(char_iter_count, number_of_characters, 50);
|
||||
|
||||
/* Run inspect message convert */
|
||||
if (inspectmessage != ""){
|
||||
if (!inspectmessage.empty()){
|
||||
std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)"
|
||||
"VALUES (%u, '%s')",
|
||||
character_id,
|
||||
@@ -1314,7 +1314,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
The speed difference is dramatic
|
||||
*/
|
||||
/* Run AA Convert */
|
||||
int first_entry = 0; rquery = "";
|
||||
int first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < MAX_PP_AA_ARRAY; i++){
|
||||
if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){
|
||||
if (first_entry != 1){
|
||||
@@ -1327,14 +1327,14 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
|
||||
/* Run Bind Home Convert */
|
||||
if (pp->binds[4].zone_id < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) {
|
||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 1)",
|
||||
character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading);
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
}
|
||||
|
||||
/* Run Bind Convert */
|
||||
@@ -1342,10 +1342,10 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 0)",
|
||||
character_id, pp->binds[0].zone_id, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading);
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
}
|
||||
/* Run Language Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < MAX_PP_LANGUAGE; i++){
|
||||
if (pp->languages[i] > 0){
|
||||
if (first_entry != 1){
|
||||
@@ -1355,9 +1355,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Skill Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < MAX_PP_SKILL; i++){
|
||||
if (pp->skills[i] > 0){
|
||||
if (first_entry != 1){
|
||||
@@ -1367,9 +1367,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Spell Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < 480; i++){
|
||||
if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){
|
||||
if (first_entry != 1){
|
||||
@@ -1379,9 +1379,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Max Memmed Spell Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < 9; i++){
|
||||
if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){
|
||||
if (first_entry != 1){
|
||||
@@ -1391,9 +1391,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Discipline Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < MAX_PP_DISCIPLINES; i++){
|
||||
if (pp->disciplines.values[i] > 0 && pp->disciplines.values[i] < 60000){
|
||||
if (first_entry != 1){
|
||||
@@ -1403,9 +1403,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Material Color Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = EQ::textures::textureBegin; i < EQ::textures::materialCount; i++){
|
||||
if (pp->item_tint[i].color > 0){
|
||||
if (first_entry != 1){
|
||||
@@ -1415,9 +1415,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Tribute Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < 5; i++){
|
||||
if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){
|
||||
if (first_entry != 1){
|
||||
@@ -1427,9 +1427,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Bandolier Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < Convert::BANDOLIERS_SIZE; i++){
|
||||
if (strlen(pp->bandoliers[i].Name) < 32) {
|
||||
for (int si = 0; si < Convert::BANDOLIER_ITEM_COUNT; si++){
|
||||
@@ -1443,9 +1443,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Potion Belt Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < Convert::POTION_BELT_ITEM_COUNT; i++){
|
||||
if (pp->potionbelt.Items[i].ID > 0){
|
||||
if (first_entry != 1){
|
||||
@@ -1456,9 +1456,9 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
/* Run Leadership AA Convert */
|
||||
first_entry = 0; rquery = "";
|
||||
first_entry = 0; rquery.clear();
|
||||
for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){
|
||||
if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){
|
||||
if (first_entry != 1){
|
||||
@@ -1468,7 +1468,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
||||
rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]);
|
||||
}
|
||||
}
|
||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||
if (!rquery.empty()){ results = QueryDatabase(rquery); }
|
||||
}
|
||||
}
|
||||
if (runconvert == 1){
|
||||
@@ -1672,10 +1672,10 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
|
||||
dbpc->item_tint[8].color,
|
||||
Strings::ToUnsignedInt(row2[0])
|
||||
);
|
||||
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
|
||||
if (!scquery.empty()){ auto sc_results = QueryDatabase(scquery); }
|
||||
|
||||
first_entry = 0;
|
||||
scquery = "";
|
||||
scquery.clear();
|
||||
/* Print Items */
|
||||
for (unsigned int i = 0; i < dbpc->itemcount; i++) {
|
||||
if (first_entry != 1){
|
||||
@@ -1712,7 +1712,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
|
||||
);
|
||||
}
|
||||
}
|
||||
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
|
||||
if (!scquery.empty()){ auto sc_results = QueryDatabase(scquery); }
|
||||
}
|
||||
else{
|
||||
/* Classic Converter */
|
||||
@@ -1780,10 +1780,10 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
|
||||
dbpc_c->item_tint[8].color,
|
||||
Strings::ToUnsignedInt(row2[0])
|
||||
);
|
||||
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
|
||||
if (!scquery.empty()){ auto sc_results = QueryDatabase(scquery); }
|
||||
|
||||
first_entry = 0;
|
||||
scquery = "";
|
||||
scquery.clear();
|
||||
|
||||
/* Print Items */
|
||||
for (unsigned int i = 0; i < dbpc_c->itemcount; i++) {
|
||||
@@ -1821,7 +1821,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){
|
||||
);
|
||||
}
|
||||
}
|
||||
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); }
|
||||
if (!scquery.empty()){ auto sc_results = QueryDatabase(scquery); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace DatabaseSchema {
|
||||
{"character_spells", "id"},
|
||||
{"character_task_timers", "character_id"},
|
||||
{"character_tasks", "charid"},
|
||||
{"character_tribute", "id"},
|
||||
{"character_tribute", "character_id"},
|
||||
{"completed_tasks", "charid"},
|
||||
{"data_buckets", "id"},
|
||||
{"faction_values", "char_id"},
|
||||
@@ -392,9 +392,6 @@ namespace DatabaseSchema {
|
||||
"bot_command_settings",
|
||||
"bot_create_combinations",
|
||||
"bot_data",
|
||||
"bot_group_members",
|
||||
"bot_groups",
|
||||
"bot_guild_members",
|
||||
"bot_heal_rotation_members",
|
||||
"bot_heal_rotation_targets",
|
||||
"bot_heal_rotations",
|
||||
|
||||
+2
-2
@@ -80,7 +80,7 @@ MySQLRequestResult DBcore::QueryDatabase(const std::string& query, bool retryOnF
|
||||
return r;
|
||||
}
|
||||
|
||||
bool DBcore::DoesTableExist(std::string table_name)
|
||||
bool DBcore::DoesTableExist(const std::string& table_name)
|
||||
{
|
||||
auto results = QueryDatabase(fmt::format("SHOW TABLES LIKE '{}'", table_name));
|
||||
|
||||
@@ -136,7 +136,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
||||
/**
|
||||
* Error logging
|
||||
*/
|
||||
if (mysql_errno(mysql) > 0 && strlen(query) > 0) {
|
||||
if (mysql_errno(mysql) > 0 && query[0] != '\0') {
|
||||
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public:
|
||||
const std::string &GetOriginHost() const;
|
||||
void SetOriginHost(const std::string &origin_host);
|
||||
|
||||
bool DoesTableExist(std::string table_name);
|
||||
bool DoesTableExist(const std::string& table_name);
|
||||
|
||||
void SetMySQL(const DBcore &o)
|
||||
{
|
||||
|
||||
@@ -27,9 +27,6 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string &
|
||||
cli.set_connection_timeout(0, 15000000); // 15 sec
|
||||
cli.set_read_timeout(15, 0); // 15 seconds
|
||||
cli.set_write_timeout(15, 0); // 15 seconds
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
// payload
|
||||
Json::Value p;
|
||||
@@ -96,9 +93,6 @@ void Discord::SendPlayerEventMessage(
|
||||
cli.set_connection_timeout(0, 15000000); // 15 sec
|
||||
cli.set_read_timeout(15, 0); // 15 seconds
|
||||
cli.set_write_timeout(15, 0); // 15 seconds
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"}
|
||||
};
|
||||
|
||||
std::string payload = PlayerEventLogs::GetDiscordPayloadFromEvent(e);
|
||||
if (payload.empty()) {
|
||||
|
||||
@@ -37,7 +37,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
message,
|
||||
webhook.webhook_url
|
||||
);
|
||||
message = "";
|
||||
message.clear();
|
||||
}
|
||||
|
||||
message += m;
|
||||
@@ -51,7 +51,7 @@ void DiscordManager::ProcessMessageQueue()
|
||||
webhook.webhook_url
|
||||
);
|
||||
}
|
||||
message = "";
|
||||
message.clear();
|
||||
}
|
||||
}
|
||||
// final flush
|
||||
|
||||
@@ -1045,4 +1045,11 @@ enum ResurrectionActions
|
||||
Accept
|
||||
};
|
||||
|
||||
enum ScribeSpellActions
|
||||
{
|
||||
Scribe,
|
||||
Memorize,
|
||||
Unmemorize
|
||||
};
|
||||
|
||||
#endif /*COMMON_EQ_CONSTANTS_H*/
|
||||
|
||||
+1
-138
@@ -236,26 +236,6 @@ uint32 EQApplicationPacket::serialize(uint16 opcode, unsigned char *dest) const
|
||||
return size+OpCodeBytes;
|
||||
}
|
||||
|
||||
/*EQProtocolPacket::EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len)
|
||||
: BasePacket(buf, len),
|
||||
opcode(op)
|
||||
{
|
||||
|
||||
uint32 offset;
|
||||
opcode=ntohs(*(const uint16 *)buf);
|
||||
offset=2;
|
||||
|
||||
if (len-offset) {
|
||||
pBuffer= new unsigned char[len-offset];
|
||||
memcpy(pBuffer,buf+offset,len-offset);
|
||||
size=len-offset;
|
||||
} else {
|
||||
pBuffer=nullptr;
|
||||
size=0;
|
||||
}
|
||||
OpMgr=&RawOpcodeManager;
|
||||
}*/
|
||||
|
||||
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
|
||||
{
|
||||
bool result=false;
|
||||
@@ -287,74 +267,6 @@ bool result=false;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
this is the code to do app-layer combining, instead of protocol layer.
|
||||
this was taken out due to complex interactions with the opcode manager,
|
||||
and will require a bit more thinking (likely moving into EQStream) to
|
||||
get running again... but might be a good thing some day.
|
||||
|
||||
bool EQApplicationPacket::combine(const EQApplicationPacket *rhs)
|
||||
{
|
||||
uint32 newsize=0, offset=0;
|
||||
unsigned char *tmpbuffer=nullptr;
|
||||
|
||||
if (opcode!=OP_AppCombined) {
|
||||
newsize=app_opcode_size+size+(size>254?3:1)+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||
tmpbuffer=new unsigned char [newsize];
|
||||
offset=0;
|
||||
if (size>254) {
|
||||
tmpbuffer[offset++]=0xff;
|
||||
*(uint16 *)(tmpbuffer+offset)=htons(size);
|
||||
offset+=1;
|
||||
} else {
|
||||
tmpbuffer[offset++]=size;
|
||||
}
|
||||
offset+=serialize(tmpbuffer+offset);
|
||||
} else {
|
||||
newsize=size+app_opcode_size+rhs->size+(rhs->size>254?3:1);
|
||||
tmpbuffer=new unsigned char [newsize];
|
||||
memcpy(tmpbuffer,pBuffer,size);
|
||||
offset=size;
|
||||
}
|
||||
|
||||
if (rhs->size>254) {
|
||||
tmpbuffer[offset++]=0xff;
|
||||
*(uint16 *)(tmpbuffer+offset)=htons(rhs->size);
|
||||
offset+=1;
|
||||
} else {
|
||||
tmpbuffer[offset++]=rhs->size;
|
||||
}
|
||||
offset+=rhs->serialize(tmpbuffer+offset);
|
||||
|
||||
size=offset;
|
||||
opcode=OP_AppCombined;
|
||||
|
||||
delete[] pBuffer;
|
||||
pBuffer=tmpbuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool EQProtocolPacket::ValidateCRC(const unsigned char *buffer, int length, uint32 Key)
|
||||
{
|
||||
bool valid=false;
|
||||
// OP_SessionRequest, OP_SessionResponse, OP_OutOfSession are not CRC'd
|
||||
if (buffer[0]==0x00 && (buffer[1]==OP_SessionRequest || buffer[1]==OP_SessionResponse || buffer[1]==OP_OutOfSession)) {
|
||||
valid=true;
|
||||
} else {
|
||||
uint16 comp_crc=CRC16(buffer,length-2,Key);
|
||||
uint16 packet_crc=ntohs(*(const uint16 *)(buffer+length-2));
|
||||
#ifdef EQN_DEBUG
|
||||
if (packet_crc && comp_crc != packet_crc) {
|
||||
std::cout << "CRC mismatch: comp=" << std::hex << comp_crc << ", packet=" << packet_crc << std::dec << std::endl;
|
||||
}
|
||||
#endif
|
||||
valid = (!packet_crc || comp_crc == packet_crc);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
|
||||
{
|
||||
uint32 newlen=0;
|
||||
@@ -403,55 +315,6 @@ uint32 flag_offset=1,newlength;
|
||||
return newlength;
|
||||
}
|
||||
|
||||
void EQProtocolPacket::ChatDecode(unsigned char *buffer, int size, int DecodeKey)
|
||||
{
|
||||
if ((size >= 2) && buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||
int Key=DecodeKey;
|
||||
unsigned char *test=(unsigned char *)malloc(size);
|
||||
buffer+=2;
|
||||
size-=2;
|
||||
|
||||
int i;
|
||||
for (i = 0 ; i+4 <= size ; i+=4)
|
||||
{
|
||||
int pt = (*(int*)&buffer[i])^(Key);
|
||||
Key = (*(int*)&buffer[i]);
|
||||
*(int*)&test[i]=pt;
|
||||
}
|
||||
unsigned char KC=Key&0xFF;
|
||||
for ( ; i < size ; i++)
|
||||
{
|
||||
test[i]=buffer[i]^KC;
|
||||
}
|
||||
memcpy(buffer,test,size);
|
||||
free(test);
|
||||
}
|
||||
}
|
||||
|
||||
void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey)
|
||||
{
|
||||
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
|
||||
int Key=EncodeKey;
|
||||
char *test=(char*)malloc(size);
|
||||
int i;
|
||||
buffer+=2;
|
||||
size-=2;
|
||||
for ( i = 0 ; i+4 <= size ; i+=4)
|
||||
{
|
||||
int pt = (*(int*)&buffer[i])^(Key);
|
||||
Key = pt;
|
||||
*(int*)&test[i]=pt;
|
||||
}
|
||||
unsigned char KC=Key&0xFF;
|
||||
for ( ; i < size ; i++)
|
||||
{
|
||||
test[i]=buffer[i]^KC;
|
||||
}
|
||||
memcpy(buffer,test,size);
|
||||
free(test);
|
||||
}
|
||||
}
|
||||
|
||||
EQApplicationPacket *EQApplicationPacket::Copy() const {
|
||||
return(new EQApplicationPacket(*this));
|
||||
}
|
||||
@@ -515,4 +378,4 @@ std::string DumpPacketToString(const EQApplicationPacket* app){
|
||||
std::ostringstream out;
|
||||
out << DumpPacketHexToString(app->pBuffer, app->size);
|
||||
return out.str();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +80,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
static bool ValidateCRC(const unsigned char *buffer, int length, uint32 Key);
|
||||
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
|
||||
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
|
||||
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
|
||||
|
||||
uint16 GetRawOpcode() const { return(opcode); }
|
||||
|
||||
|
||||
@@ -1793,6 +1793,17 @@ struct GMSummon_Struct {
|
||||
/*104*/ uint32 unknown2; // E0 E0 56 00
|
||||
};
|
||||
|
||||
struct GMFind_Struct {
|
||||
char charname[64];
|
||||
char gmname[64];
|
||||
uint32 success;
|
||||
uint32 zoneID;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32 unknown2;
|
||||
};
|
||||
|
||||
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
|
||||
/* 0*/ char charname[64];
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ EQStreamIdentifier::~EQStreamIdentifier() {
|
||||
}
|
||||
}
|
||||
|
||||
void EQStreamIdentifier::RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
||||
void EQStreamIdentifier::RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) {
|
||||
auto p = new Patch;
|
||||
p->signature = sig;
|
||||
p->name = name;
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
~EQStreamIdentifier();
|
||||
|
||||
//registration interface.
|
||||
void RegisterPatch(const EQStreamInterface::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
||||
void RegisterPatch(EQStreamInterface::Signature sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs);
|
||||
|
||||
//main processing interface
|
||||
void Process();
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
|
||||
EQDB EQDB::s_EQDB;
|
||||
|
||||
EQDB::EQDB() {
|
||||
}
|
||||
|
||||
unsigned int EQDB::field_count() {
|
||||
return mysql_field_count(mysql_ref);
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
|
||||
//this is the main object exported to perl.
|
||||
class EQDB {
|
||||
EQDB();
|
||||
EQDB() = default;
|
||||
public:
|
||||
static EQDB *Singleton() { return(&s_EQDB); }
|
||||
|
||||
|
||||
@@ -147,12 +147,6 @@ class EQEmuConfig
|
||||
return (_config);
|
||||
}
|
||||
|
||||
// Allow the use to set the conf file to be used.
|
||||
static void SetConfigFile(std::string file)
|
||||
{
|
||||
EQEmuConfig::ConfigFile = file;
|
||||
}
|
||||
|
||||
// Load the config
|
||||
static bool LoadConfig(const std::string& path = "")
|
||||
{
|
||||
|
||||
+1
-5
@@ -58,10 +58,6 @@ EQTime::EQTime()
|
||||
SetCurrentEQTimeOfDay(start, time(0));
|
||||
}
|
||||
|
||||
EQTime::~EQTime()
|
||||
{
|
||||
}
|
||||
|
||||
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
|
||||
//This function was written by the ShowEQ Project.
|
||||
//Input: Current Time (as a time_t), a pointer to the TimeOfDay_Struct that will be written to.
|
||||
@@ -203,4 +199,4 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
|
||||
t->month, t->day, t->year, t->hour, t->minute);
|
||||
buf[127] = '\0';
|
||||
str = buf;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ public:
|
||||
//Constructor/destructor
|
||||
EQTime(TimeOfDay_Struct start_eq, time_t start_real);
|
||||
EQTime();
|
||||
~EQTime();
|
||||
~EQTime() = default;
|
||||
|
||||
//Get functions
|
||||
int GetCurrentEQTimeOfDay( TimeOfDay_Struct *eqTimeOfDay ) { return(GetCurrentEQTimeOfDay(time(nullptr), eqTimeOfDay)); }
|
||||
|
||||
@@ -333,7 +333,10 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatDroppedItemEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FISH_FAILURE: {
|
||||
case PlayerEvent::FISH_FAILURE:
|
||||
case PlayerEvent::FORAGE_FAILURE:
|
||||
case PlayerEvent::WENT_ONLINE:
|
||||
case PlayerEvent::WENT_OFFLINE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
@@ -348,10 +351,6 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatFishSuccessEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FORAGE_FAILURE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::FORAGE_SUCCESS: {
|
||||
PlayerEvent::ForageSuccessEvent n{};
|
||||
std::stringstream ss;
|
||||
@@ -550,11 +549,6 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
payload = PlayerEventDiscordFormatter::FormatResurrectAcceptEvent(e, n);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::WENT_ONLINE:
|
||||
case PlayerEvent::WENT_OFFLINE: {
|
||||
payload = PlayerEventDiscordFormatter::FormatWithNodata(e);
|
||||
break;
|
||||
}
|
||||
case PlayerEvent::MERCHANT_PURCHASE: {
|
||||
PlayerEvent::MerchantPurchaseEvent n{};
|
||||
std::stringstream ss;
|
||||
|
||||
+3
-3
@@ -218,14 +218,14 @@ enum { //some random constants
|
||||
#define HARD_LEVEL_CAP 127
|
||||
|
||||
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
||||
#define USE_NPC_RANGE2 200*200 //arbitrary right now
|
||||
#define USE_NPC_RANGE2 40000 //arbitrary right now
|
||||
|
||||
// Squared range for rampage 75.0 * 75.0 for now
|
||||
#define NPC_RAMPAGE_RANGE2 5625.0f
|
||||
|
||||
//the formula for experience for killing a mob.
|
||||
//level is the only valid variable to use
|
||||
#define EXP_FORMULA level*level*75*35/10
|
||||
#define EXP_FORMULA (level * level * 75 * 35 / 10)
|
||||
|
||||
#define HIGHEST_AA_VALUE 35
|
||||
|
||||
@@ -295,7 +295,7 @@ Developer configuration
|
||||
|
||||
#define COMMON_PROFILE
|
||||
|
||||
#define PROFILE_DUMP_TIME 3*60
|
||||
#define PROFILE_DUMP_TIME 180
|
||||
#endif //EQPROFILE
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -80,3 +81,26 @@ std::string File::GetCwd()
|
||||
{
|
||||
return fs::current_path().string();
|
||||
}
|
||||
|
||||
FileContentsResult File::GetContents(const std::string &file_name)
|
||||
{
|
||||
std::string error;
|
||||
std::ifstream f;
|
||||
f.open(file_name);
|
||||
std::string line;
|
||||
std::string lines;
|
||||
if (f.is_open()) {
|
||||
while (f) {
|
||||
std::getline(f, line);
|
||||
lines += line + "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = fmt::format("Couldn't open file [{}]", file_name);
|
||||
}
|
||||
|
||||
return FileContentsResult{
|
||||
.contents = lines,
|
||||
.error = error,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,10 +25,16 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct FileContentsResult {
|
||||
std::string contents;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
class File {
|
||||
public:
|
||||
static bool Exists(const std::string &name);
|
||||
static void Makedir(const std::string& directory_name);
|
||||
static FileContentsResult GetContents(const std::string &file_name);
|
||||
static std::string FindEqemuConfigPath();
|
||||
static std::string GetCwd();
|
||||
};
|
||||
|
||||
@@ -412,11 +412,12 @@ bool EQ::InventoryProfile::DeleteItem(int16 slot_id, int16 quantity) {
|
||||
// If there are no charges left on the item,
|
||||
if (item_to_delete->GetCharges() <= 0) {
|
||||
// If the item is stackable (e.g arrows), or
|
||||
// the item is not stackable, and is not a charged item, or is expendable, delete it
|
||||
if (item_to_delete->IsStackable() ||
|
||||
(!item_to_delete->IsStackable() &&
|
||||
((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable()))
|
||||
) {
|
||||
// the item is not a charged item, or is expendable, delete it
|
||||
if (
|
||||
item_to_delete->IsStackable() ||
|
||||
item_to_delete->GetItem()->MaxCharges == 0 ||
|
||||
item_to_delete->IsExpendable()
|
||||
) {
|
||||
// Item can now be destroyed
|
||||
InventoryProfile::MarkDirty(item_to_delete);
|
||||
return true;
|
||||
|
||||
+164
-159
@@ -355,181 +355,186 @@ namespace EQ
|
||||
|
||||
struct ItemData {
|
||||
// Non packet based fields
|
||||
uint8 MinStatus;
|
||||
uint8 MinStatus {};
|
||||
|
||||
// Packet based fields
|
||||
uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64]; // Name
|
||||
char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30]; // Visible model
|
||||
uint32 ID; // Unique ID (also PK for DB)
|
||||
int32 Weight; // Item weight * 10
|
||||
uint8 NoRent; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop
|
||||
uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
||||
uint32 Slots; // Bitfield for which slots this item can be used in
|
||||
uint32 Price; // Item cost (?)
|
||||
uint32 Icon; // Icon Number
|
||||
int32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag;
|
||||
bool ArtifactFlag;
|
||||
bool SummonedFlag;
|
||||
uint8 FVNoDrop; // Firiona Vie nodrop flag
|
||||
uint32 Favor; // Individual favor
|
||||
uint32 GuildFavor; // Guild favor
|
||||
uint32 PointType;
|
||||
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
|
||||
char Name[64] {}; // Name
|
||||
char Lore[80] {}; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore
|
||||
char IDFile[30] {}; // Visible model
|
||||
uint32 ID {}; // Unique ID (also PK for DB)
|
||||
int32 Weight {}; // Item weight * 10
|
||||
uint8 NoRent{} ; // No Rent: 0=norent, 255=not norent
|
||||
uint8 NoDrop {}; // No Drop: 0=nodrop, 255=not nodrop
|
||||
uint8 Size {}; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant
|
||||
uint32 Slots {}; // Bitfield for which slots this item can be used in
|
||||
uint32 Price {}; // Item cost (?)
|
||||
uint32 Icon {}; // Icon Number
|
||||
int32 LoreGroup {}; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295)
|
||||
bool LoreFlag {}; // This will be true if LoreGroup is non-zero
|
||||
bool PendingLoreFlag {};
|
||||
bool ArtifactFlag {};
|
||||
bool SummonedFlag {};
|
||||
uint8 FVNoDrop {}; // Firiona Vie nodrop flag
|
||||
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: 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
|
||||
uint8 BagType {}; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
|
||||
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
|
||||
int8 DR; // Save vs Disease
|
||||
int8 PR; // Save vs Poison
|
||||
int8 MR; // Save vs Magic
|
||||
int8 FR; // Save vs Fire
|
||||
int8 AStr; // Strength
|
||||
int8 ASta; // Stamina
|
||||
int8 AAgi; // Agility
|
||||
int8 ADex; // Dexterity
|
||||
int8 ACha; // Charisma
|
||||
int8 AInt; // Intelligence
|
||||
int8 AWis; // Wisdom
|
||||
int32 HP; // HP
|
||||
int32 Mana; // Mana
|
||||
int32 AC; // AC
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
bool BenefitFlag {};
|
||||
bool Tradeskills {}; // Is this a tradeskill item?
|
||||
int8 CR {}; // Save vs Cold
|
||||
int8 DR {}; // Save vs Disease
|
||||
int8 PR {}; // Save vs Poison
|
||||
int8 MR {}; // Save vs Magic
|
||||
int8 FR {}; // Save vs Fire
|
||||
int8 AStr {}; // Strength
|
||||
int8 ASta {}; // Stamina
|
||||
int8 AAgi {}; // Agility
|
||||
int8 ADex {}; // Dexterity
|
||||
int8 ACha {}; // Charisma
|
||||
int8 AInt {}; // Intelligence
|
||||
int8 AWis {}; // Wisdom
|
||||
int32 HP {}; // HP
|
||||
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
|
||||
int32 BaneDmgAmt; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody; // Bane Damage Body
|
||||
bool Magic; // True=Magic Item, False=not
|
||||
int32 CastTime_;
|
||||
uint8 ReqLevel; // Required Level to use item
|
||||
uint32 BardType; // Bard Skill Type
|
||||
int32 BardValue; // Bard Skill Amount
|
||||
int8 Light; // Light
|
||||
uint8 Delay; // Delay * 10
|
||||
uint8 RecLevel; // Recommended level to use item
|
||||
uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt; // Elemental Damage
|
||||
uint8 Range; // Range of item
|
||||
uint32 Damage; // Delay between item usage (in 0.1 sec increments)
|
||||
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)
|
||||
int32 SubType; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
||||
uint8 Material; // Item material type
|
||||
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
|
||||
float SellRate; // Sell rate
|
||||
//uint32 Unk059;
|
||||
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
|
||||
int32 BaneDmgAmt {}; // Bane Damage Body Amount
|
||||
uint32 BaneDmgBody {}; // Bane Damage Body
|
||||
bool Magic {}; // True=Magic Item, False=not
|
||||
int32 CastTime_ {};
|
||||
uint8 ReqLevel {}; // Required Level to use item
|
||||
uint32 BardType {}; // Bard Skill Type
|
||||
int32 BardValue {}; // Bard Skill Amount
|
||||
int8 Light {}; // Light
|
||||
uint8 Delay {}; // Delay * 10
|
||||
uint8 RecLevel {}; // Recommended level to use item
|
||||
uint8 RecSkill {}; // Recommended skill to use item (refers to primary skill of item)
|
||||
uint8 ElemDmgType {}; // Elemental Damage Type (1=magic, 2=fire)
|
||||
uint8 ElemDmgAmt {}; // Elemental Damage
|
||||
uint8 Range {}; // Range of item
|
||||
uint32 Damage {}; // Delay between item usage (in 0.1 sec increments)
|
||||
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)
|
||||
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
|
||||
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)
|
||||
uint32 CastTime; // Cast Time for clicky effects, in milliseconds
|
||||
};
|
||||
uint32 EliteMaterial;
|
||||
int32 ProcRate;
|
||||
int8 CombatEffects; // PoP: Combat Effects +
|
||||
int8 Shielding; // PoP: Shielding %
|
||||
int8 StunResist; // PoP: Stun Resist %
|
||||
int8 StrikeThrough; // PoP: Strike Through %
|
||||
int32 ExtraDmgSkill;
|
||||
int32 ExtraDmgAmt;
|
||||
int8 SpellShield; // PoP: Spell Shield %
|
||||
int8 Avoidance; // PoP: Avoidance +
|
||||
int8 Accuracy; // PoP: Accuracy +
|
||||
uint32 CharmFileID;
|
||||
int32 FactionMod1; // Faction Mod 1
|
||||
int32 FactionMod2; // Faction Mod 2
|
||||
int32 FactionMod3; // Faction Mod 3
|
||||
int32 FactionMod4; // Faction Mod 4
|
||||
int32 FactionAmt1; // Faction Amt 1
|
||||
int32 FactionAmt2; // Faction Amt 2
|
||||
int32 FactionAmt3; // Faction Amt 3
|
||||
int32 FactionAmt4; // Faction Amt 4
|
||||
char CharmFile[32]; // ?
|
||||
uint32 AugType;
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[invaug::SOCKET_COUNT]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme;
|
||||
uint32 LDoNPrice;
|
||||
uint32 LDoNSold;
|
||||
uint32 BaneDmgRaceAmt;
|
||||
uint32 AugRestrict;
|
||||
int32 Endur;
|
||||
int32 DotShielding;
|
||||
int32 Attack;
|
||||
int32 Regen;
|
||||
int32 ManaRegen;
|
||||
int32 EnduranceRegen;
|
||||
int32 Haste;
|
||||
int32 DamageShield;
|
||||
uint32 RecastDelay;
|
||||
int RecastType;
|
||||
uint32 AugDistiller;
|
||||
bool Attuneable;
|
||||
bool NoPet;
|
||||
bool PotionBelt;
|
||||
bool Stackable;
|
||||
bool NoTransfer;
|
||||
bool QuestItemFlag;
|
||||
int16 StackSize;
|
||||
uint8 PotionBeltSlots;
|
||||
item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
|
||||
uint32 EliteMaterial {};
|
||||
int32 ProcRate {};
|
||||
int8 CombatEffects {}; // PoP: Combat Effects +
|
||||
int8 Shielding {}; // PoP: Shielding %
|
||||
int8 StunResist {}; // PoP: Stun Resist %
|
||||
int8 StrikeThrough {}; // PoP: Strike Through %
|
||||
int32 ExtraDmgSkill {};
|
||||
int32 ExtraDmgAmt {};
|
||||
int8 SpellShield {}; // PoP: Spell Shield %
|
||||
int8 Avoidance {}; // PoP: Avoidance +
|
||||
int8 Accuracy {}; // PoP: Accuracy +
|
||||
uint32 CharmFileID {};
|
||||
int32 FactionMod1 {}; // Faction Mod 1
|
||||
int32 FactionMod2 {}; // Faction Mod 2
|
||||
int32 FactionMod3 {}; // Faction Mod 3
|
||||
int32 FactionMod4 {}; // Faction Mod 4
|
||||
int32 FactionAmt1 {}; // Faction Amt 1
|
||||
int32 FactionAmt2 {}; // Faction Amt 2
|
||||
int32 FactionAmt3 {}; // Faction Amt 3
|
||||
int32 FactionAmt4 {}; // Faction Amt 4
|
||||
char CharmFile[32] {}; // ?
|
||||
uint32 AugType {};
|
||||
uint8 AugSlotType[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Type
|
||||
uint8 AugSlotVisible[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Visible
|
||||
uint8 AugSlotUnk2[invaug::SOCKET_COUNT] {}; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related
|
||||
uint32 LDoNTheme {};
|
||||
uint32 LDoNPrice {};
|
||||
uint32 LDoNSold {};
|
||||
uint32 BaneDmgRaceAmt {};
|
||||
uint32 AugRestrict {};
|
||||
int32 Endur {};
|
||||
int32 DotShielding {};
|
||||
int32 Attack {};
|
||||
int32 Regen {};
|
||||
int32 ManaRegen {};
|
||||
int32 EnduranceRegen {};
|
||||
int32 Haste {};
|
||||
int32 DamageShield {};
|
||||
uint32 RecastDelay {};
|
||||
int RecastType {};
|
||||
uint32 AugDistiller {};
|
||||
bool Attuneable {};
|
||||
bool NoPet {};
|
||||
bool PotionBelt {};
|
||||
bool Stackable {};
|
||||
bool NoTransfer {};
|
||||
bool QuestItemFlag {};
|
||||
int16 StackSize {};
|
||||
uint8 PotionBeltSlots {};
|
||||
item::ItemEffect_Struct Click {};
|
||||
item::ItemEffect_Struct Proc {};
|
||||
item::ItemEffect_Struct Worn {};
|
||||
item::ItemEffect_Struct Focus {};
|
||||
item::ItemEffect_Struct Scroll {};
|
||||
item::ItemEffect_Struct Bard {};
|
||||
|
||||
uint8 Book; // 0=Not book, 1=Book
|
||||
uint32 BookType;
|
||||
char Filename[33]; // Filename for book data
|
||||
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;
|
||||
int32 HeroicInt;
|
||||
int32 HeroicWis;
|
||||
int32 HeroicAgi;
|
||||
int32 HeroicDex;
|
||||
int32 HeroicSta;
|
||||
int32 HeroicCha;
|
||||
int32 HeroicMR;
|
||||
int32 HeroicFR;
|
||||
int32 HeroicCR;
|
||||
int32 HeroicDR;
|
||||
int32 HeroicPR;
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
uint32 LDoNSellBackRate;
|
||||
uint32 ScriptFileID;
|
||||
uint16 ExpendableArrow;
|
||||
uint32 Clairvoyance;
|
||||
char ClickName[65];
|
||||
char ProcName[65];
|
||||
char WornName[65];
|
||||
char FocusName[65];
|
||||
char ScrollName[65];
|
||||
int32 SVCorruption {};
|
||||
uint32 Purity {};
|
||||
uint8 EvolvingItem {};
|
||||
uint32 EvolvingID {};
|
||||
uint8 EvolvingLevel {};
|
||||
uint8 EvolvingMax {};
|
||||
uint32 BackstabDmg {};
|
||||
uint32 DSMitigation {};
|
||||
int32 HeroicStr {};
|
||||
int32 HeroicInt {};
|
||||
int32 HeroicWis {};
|
||||
int32 HeroicAgi {};
|
||||
int32 HeroicDex {};
|
||||
int32 HeroicSta {};
|
||||
int32 HeroicCha {};
|
||||
int32 HeroicMR {};
|
||||
int32 HeroicFR {};
|
||||
int32 HeroicCR {};
|
||||
int32 HeroicDR {};
|
||||
int32 HeroicPR {};
|
||||
int32 HeroicSVCorrup {};
|
||||
int32 HealAmt {};
|
||||
int32 SpellDmg {};
|
||||
uint32 LDoNSellBackRate {};
|
||||
uint32 ScriptFileID {};
|
||||
uint16 ExpendableArrow {};
|
||||
uint32 Clairvoyance {};
|
||||
char ClickName[65] {};
|
||||
char ProcName[65] {};
|
||||
char WornName[65] {};
|
||||
char FocusName[65] {};
|
||||
char ScrollName[65] {};
|
||||
//BardName
|
||||
|
||||
bool IsEquipable(uint16 Race, uint16 Class) const;
|
||||
|
||||
+159
-164
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "inventory_profile.h"
|
||||
#include "../common/data_verification.h"
|
||||
//#include "classes.h"
|
||||
//#include "global_define.h"
|
||||
//#include "item_instance.h"
|
||||
@@ -57,108 +58,62 @@ static inline int32 GetNextItemInstSerialNumber() {
|
||||
// class EQ::ItemInstance
|
||||
//
|
||||
EQ::ItemInstance::ItemInstance(const ItemData* item, int16 charges) {
|
||||
m_use_type = ItemInstNormal;
|
||||
if(item) {
|
||||
m_item = new ItemData(*item);
|
||||
} else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
m_charges = charges;
|
||||
m_price = 0;
|
||||
m_attuned = false;
|
||||
m_merchantslot = 0;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
m_color = m_item->Color;
|
||||
else
|
||||
m_color = 0;
|
||||
m_merchantcount = 1;
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
if (item) {
|
||||
m_item = new ItemData(*item);
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_color = m_item->Color;
|
||||
}
|
||||
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
}
|
||||
|
||||
EQ::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) {
|
||||
m_use_type = ItemInstNormal;
|
||||
m_item = db->GetItem(item_id);
|
||||
if(m_item) {
|
||||
|
||||
m_item = db->GetItem(item_id);
|
||||
|
||||
if (m_item) {
|
||||
m_item = new ItemData(*m_item);
|
||||
}
|
||||
else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = charges;
|
||||
m_price = 0;
|
||||
m_merchantslot = 0;
|
||||
m_attuned=false;
|
||||
if (m_item && m_item->IsClassCommon())
|
||||
m_color = m_item->Color;
|
||||
else
|
||||
m_color = 0;
|
||||
m_merchantcount = 1;
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
if (m_item && m_item->IsClassCommon()) {
|
||||
m_color = m_item->Color;
|
||||
} else {
|
||||
m_color = 0;
|
||||
}
|
||||
|
||||
m_SerialNumber = GetNextItemInstSerialNumber();
|
||||
}
|
||||
|
||||
EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) {
|
||||
m_use_type = use_type;
|
||||
m_item = nullptr;
|
||||
m_charges = 0;
|
||||
m_price = 0;
|
||||
m_attuned = false;
|
||||
m_merchantslot = 0;
|
||||
m_color = 0;
|
||||
|
||||
m_exp = 0;
|
||||
m_evolveLvl = 0;
|
||||
m_activated = false;
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
m_ornament_hero_model = 0;
|
||||
m_recast_timestamp = 0;
|
||||
m_new_id_file = 0;
|
||||
m_use_type = use_type;
|
||||
}
|
||||
|
||||
// Make a copy of an EQ::ItemInstance object
|
||||
EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
{
|
||||
m_use_type=copy.m_use_type;
|
||||
if(copy.m_item)
|
||||
m_item = new ItemData(*copy.m_item);
|
||||
else
|
||||
m_item = nullptr;
|
||||
m_use_type = copy.m_use_type;
|
||||
|
||||
if (copy.m_item) {
|
||||
m_item = new ItemData(*copy.m_item);
|
||||
} else {
|
||||
m_item = nullptr;
|
||||
}
|
||||
|
||||
m_charges = copy.m_charges;
|
||||
m_price = copy.m_price;
|
||||
m_color = copy.m_color;
|
||||
m_merchantslot = copy.m_merchantslot;
|
||||
m_currentslot = copy.m_currentslot;
|
||||
m_attuned = copy.m_attuned;
|
||||
m_merchantcount = copy.m_merchantcount;
|
||||
|
||||
m_charges=copy.m_charges;
|
||||
m_price=copy.m_price;
|
||||
m_color=copy.m_color;
|
||||
m_merchantslot=copy.m_merchantslot;
|
||||
m_currentslot=copy.m_currentslot;
|
||||
m_attuned=copy.m_attuned;
|
||||
m_merchantcount=copy.m_merchantcount;
|
||||
// Copy container contents
|
||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||
ItemInstance* inst_old = it->second;
|
||||
@@ -168,37 +123,42 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
|
||||
inst_new = inst_old->Clone();
|
||||
}
|
||||
|
||||
if (inst_new != nullptr) {
|
||||
if (inst_new) {
|
||||
m_contents[it->first] = inst_new;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
for (iter = copy.m_custom_data.begin(); iter != copy.m_custom_data.end(); ++iter) {
|
||||
m_custom_data[iter->first] = iter->second;
|
||||
}
|
||||
m_SerialNumber = copy.m_SerialNumber;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
|
||||
m_exp = copy.m_exp;
|
||||
m_SerialNumber = copy.m_SerialNumber;
|
||||
m_custom_data = copy.m_custom_data;
|
||||
m_timers = copy.m_timers;
|
||||
|
||||
m_exp = copy.m_exp;
|
||||
m_evolveLvl = copy.m_evolveLvl;
|
||||
m_activated = copy.m_activated;
|
||||
if (copy.m_scaledItem)
|
||||
|
||||
if (copy.m_scaledItem) {
|
||||
m_scaledItem = new ItemData(*copy.m_scaledItem);
|
||||
else
|
||||
} else {
|
||||
m_scaledItem = nullptr;
|
||||
}
|
||||
|
||||
if(copy.m_evolveInfo)
|
||||
if (copy.m_evolveInfo) {
|
||||
m_evolveInfo = new EvolveInfo(*copy.m_evolveInfo);
|
||||
else
|
||||
} else {
|
||||
m_evolveInfo = nullptr;
|
||||
}
|
||||
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
m_ornament_hero_model = copy.m_ornament_hero_model;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
m_recast_timestamp = copy.m_recast_timestamp;
|
||||
m_new_id_file = copy.m_new_id_file;
|
||||
}
|
||||
|
||||
// Clean up container contents
|
||||
@@ -216,11 +176,13 @@ bool EQ::ItemInstance::IsType(item::ItemClass item_class) const
|
||||
// IsType(<ItemClassTypes>) does not protect against 'm_item = nullptr'
|
||||
|
||||
// Check usage type
|
||||
if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag))
|
||||
if (m_use_type == ItemInstWorldContainer && item_class == item::ItemClassBag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_item->ItemClass == item_class);
|
||||
}
|
||||
@@ -243,21 +205,20 @@ bool EQ::ItemInstance::IsClassBook() const
|
||||
// Is item stackable?
|
||||
bool EQ::ItemInstance::IsStackable() const
|
||||
{
|
||||
if (!m_item)
|
||||
return false;
|
||||
|
||||
return m_item->Stackable;
|
||||
return (m_item && m_item->Stackable);
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::IsCharged() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_item->MaxCharges > 1)
|
||||
if (m_item->MaxCharges > 1) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Can item be equipped?
|
||||
@@ -306,26 +267,30 @@ bool EQ::ItemInstance::IsEquipable(int16 slot_id) const
|
||||
|
||||
bool EQ::ItemInstance::IsAugmentable() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = invaug::SOCKET_BEGIN; index <= invaug::SOCKET_END; ++index) {
|
||||
if (m_item->AugSlotType[index] != 0)
|
||||
if (m_item->AugSlotType[index] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = invslot::EQUIPMENT_BEGIN;
|
||||
for (; index <= invslot::EQUIPMENT_END; ++index) {
|
||||
if (m_item->Slots & (1 << index)) {
|
||||
if (aug_wear_slots & (1 << index))
|
||||
if (aug_wear_slots & (1 << index)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,9 +359,10 @@ EQ::ItemInstance* EQ::ItemInstance::GetItem(uint8 index) const
|
||||
|
||||
uint32 EQ::ItemInstance::GetItemID(uint8 slot) const
|
||||
{
|
||||
ItemInstance *item = GetItem(slot);
|
||||
if (item)
|
||||
const auto item = GetItem(slot);
|
||||
if (item) {
|
||||
return item->GetID();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -520,14 +486,21 @@ uint8 EQ::ItemInstance::FirstOpenSlot() const
|
||||
|
||||
uint8 EQ::ItemInstance::GetTotalItemCount() const
|
||||
{
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 item_count = 1;
|
||||
|
||||
if (m_item && !m_item->IsClassBag()) { return item_count; }
|
||||
if (!m_item->IsClassBag()) {
|
||||
return item_count;
|
||||
}
|
||||
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } }
|
||||
for (int index = invbag::SLOT_BEGIN; index < m_item->BagSlots; ++index) {
|
||||
if (GetItem(index)) {
|
||||
++item_count;
|
||||
}
|
||||
}
|
||||
|
||||
return item_count;
|
||||
}
|
||||
@@ -555,78 +528,99 @@ EQ::ItemInstance* EQ::ItemInstance::GetAugment(uint8 augment_index) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAug(int32 ornamentationAugtype) const
|
||||
bool EQ::ItemInstance::IsOrnamentationAugment(EQ::ItemInstance* augment) const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) { return nullptr; }
|
||||
if (ornamentationAugtype == 0) { return nullptr; }
|
||||
if (!m_item || !m_item->IsClassCommon() || !augment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++)
|
||||
{
|
||||
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype)
|
||||
{
|
||||
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
|
||||
if (
|
||||
(strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0
|
||||
|| strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
|
||||
&& GetAugment(i)->GetItem()->HerosForgeModel == 0
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return GetAugment(i);
|
||||
const auto augment_item = augment->GetItem();
|
||||
if (!augment_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& idfile = augment_item->IDFile;
|
||||
|
||||
if (
|
||||
EQ::ValueWithin(
|
||||
augment->GetAugmentType(),
|
||||
OrnamentationAugmentTypes::StandardOrnamentation,
|
||||
OrnamentationAugmentTypes::SpecialOrnamentation
|
||||
) ||
|
||||
(
|
||||
idfile != "IT63" &&
|
||||
idfile != "IT64"
|
||||
) ||
|
||||
augment_item->HerosForgeModel
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; i++) {
|
||||
const auto augment = GetAugment(i);
|
||||
if (augment && IsOrnamentationAugment(augment)) {
|
||||
return augment;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const {
|
||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
||||
{
|
||||
// Not a Hero Forge item.
|
||||
if (m_ornament_hero_model == 0 || material_slot < 0)
|
||||
if (m_ornament_hero_model == 0 || material_slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Item is using an explicit Hero Forge ID
|
||||
if (m_ornament_hero_model >= 1000)
|
||||
if (m_ornament_hero_model >= 1000) {
|
||||
return m_ornament_hero_model;
|
||||
}
|
||||
|
||||
// Item is using a shorthand ID
|
||||
return (m_ornament_hero_model * 100) + material_slot;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo() {
|
||||
if (!m_item || !m_item->IsClassCommon())
|
||||
bool EQ::ItemInstance::UpdateOrnamentationInfo()
|
||||
{
|
||||
if (!m_item || !m_item->IsClassCommon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ornamentSet = false;
|
||||
const auto augment = GetOrnamentationAugment();
|
||||
|
||||
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
if (GetOrnamentationAug(ornamentationAugtype))
|
||||
{
|
||||
const ItemData* ornamentItem;
|
||||
ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
if (ornamentItem != nullptr)
|
||||
{
|
||||
SetOrnamentIcon(ornamentItem->Icon);
|
||||
SetOrnamentHeroModel(ornamentItem->HerosForgeModel);
|
||||
if (strlen(ornamentItem->IDFile) > 2)
|
||||
{
|
||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&ornamentItem->IDFile[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (augment) {
|
||||
const auto augment_item = GetOrnamentationAugment()->GetItem();
|
||||
|
||||
if (augment_item) {
|
||||
SetOrnamentIcon(augment_item->Icon);
|
||||
SetOrnamentHeroModel(augment_item->HerosForgeModel);
|
||||
|
||||
if (strlen(augment_item->IDFile) > 2) {
|
||||
SetOrnamentationIDFile(Strings::ToUnsignedInt(&augment_item->IDFile[2]));
|
||||
} else {
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
ornamentSet = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
}
|
||||
|
||||
return ornamentSet;
|
||||
SetOrnamentIcon(0);
|
||||
SetOrnamentHeroModel(0);
|
||||
SetOrnamentationIDFile(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EQ::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) {
|
||||
@@ -940,8 +934,9 @@ bool EQ::ItemInstance::IsDroppable(bool recurse) const
|
||||
|
||||
void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
// if there's no actual item, don't do anything
|
||||
if (!m_item)
|
||||
if (!m_item) {
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize scaling items
|
||||
if (m_item->CharmFileID != 0) {
|
||||
@@ -950,7 +945,7 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
// initialize evolving items
|
||||
else if ((db) && m_item->LoreGroup >= 1000 && m_item->LoreGroup != -1) {
|
||||
else if (db && m_item->LoreGroup >= 1000) {
|
||||
// not complete yet
|
||||
}
|
||||
}
|
||||
|
||||
+35
-29
@@ -51,6 +51,11 @@ typedef enum {
|
||||
byFlagNotSet //apply action if the flag is NOT set
|
||||
} byFlagSetting;
|
||||
|
||||
enum OrnamentationAugmentTypes {
|
||||
StandardOrnamentation = 20,
|
||||
SpecialOrnamentation = 21
|
||||
};
|
||||
|
||||
class SharedDatabase;
|
||||
|
||||
// ########################################
|
||||
@@ -103,7 +108,8 @@ namespace EQ
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augment_type) const;
|
||||
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
|
||||
inline int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
|
||||
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 0; }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
|
||||
|
||||
@@ -136,7 +142,8 @@ namespace EQ
|
||||
bool IsAugmented();
|
||||
bool ContainsAugmentByID(uint32 item_id);
|
||||
int CountAugmentByID(uint32 item_id);
|
||||
ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const;
|
||||
bool IsOrnamentationAugment(EQ::ItemInstance* augment) const;
|
||||
ItemInstance* GetOrnamentationAugment() const;
|
||||
bool UpdateOrnamentationInfo();
|
||||
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
|
||||
|
||||
@@ -304,34 +311,33 @@ namespace EQ
|
||||
|
||||
void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; }
|
||||
|
||||
ItemInstTypes m_use_type; // Usage type for item
|
||||
const ItemData* m_item; // Ptr to item data
|
||||
int16 m_charges; // # of charges for chargeable items
|
||||
uint32 m_price; // Bazaar /trader price
|
||||
uint32 m_color;
|
||||
uint32 m_merchantslot;
|
||||
int16 m_currentslot;
|
||||
bool m_attuned;
|
||||
int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp;
|
||||
int8 m_evolveLvl;
|
||||
bool m_activated;
|
||||
ItemData* m_scaledItem;
|
||||
::EvolveInfo* m_evolveInfo;
|
||||
bool m_scaling;
|
||||
uint32 m_ornamenticon;
|
||||
uint32 m_ornamentidfile;
|
||||
uint32 m_new_id_file;
|
||||
uint32 m_ornament_hero_model;
|
||||
uint32 m_recast_timestamp;
|
||||
int m_task_delivered_count = 0;
|
||||
ItemInstTypes m_use_type {ItemInstNormal}; // Usage type for item
|
||||
const ItemData* m_item {nullptr}; // Ptr to item data
|
||||
int16 m_charges {0}; // # of charges for chargeable items
|
||||
uint32 m_price {0}; // Bazaar /trader price
|
||||
uint32 m_color {0};
|
||||
uint32 m_merchantslot {0};
|
||||
int16 m_currentslot {0};
|
||||
bool m_attuned {false};
|
||||
int32 m_merchantcount {1}; //number avaliable on the merchant, -1=unlimited
|
||||
int32 m_SerialNumber {0}; // Unique identifier for this instance of an item. Needed for Bazaar.
|
||||
uint32 m_exp {0};
|
||||
int8 m_evolveLvl {0};
|
||||
bool m_activated {false};
|
||||
ItemData* m_scaledItem {nullptr};
|
||||
::EvolveInfo* m_evolveInfo {nullptr};
|
||||
bool m_scaling {false};
|
||||
uint32 m_ornamenticon {0};
|
||||
uint32 m_ornamentidfile {0};
|
||||
uint32 m_new_id_file {0};
|
||||
uint32 m_ornament_hero_model {0};
|
||||
uint32 m_recast_timestamp {0};
|
||||
int m_task_delivered_count {0};
|
||||
|
||||
//
|
||||
// Items inside of this item (augs or contents);
|
||||
std::map<uint8, ItemInstance*> m_contents; // Zero-based index: min=0, max=9
|
||||
std::map<std::string, std::string> m_custom_data;
|
||||
std::map<std::string, ::Timer> m_timers;
|
||||
// Items inside of this item (augs or contents) {};
|
||||
std::map<uint8, ItemInstance*> m_contents {}; // Zero-based index: min=0, max=9
|
||||
std::map<std::string, std::string> m_custom_data {};
|
||||
std::map<std::string, ::Timer> m_timers {};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ void EQ::Net::TCPConnection::Write(const char *data, size_t count)
|
||||
|
||||
WriteBaton *baton = new WriteBaton;
|
||||
baton->connection = this;
|
||||
baton->buffer = new char[count];;
|
||||
baton->buffer = new char[count];
|
||||
|
||||
uv_write_t *write_req = new uv_write_t;
|
||||
memset(write_req, 0, sizeof(uv_write_t));
|
||||
|
||||
@@ -5218,7 +5218,6 @@ namespace RoF
|
||||
/**
|
||||
* Ornamentation
|
||||
*/
|
||||
int ornamentation_augment_type = RuleI(Character, OrnamentationAugmentType);
|
||||
uint32 ornamentation_icon = (inst->GetOrnamentationIcon() ? inst->GetOrnamentationIcon() : 0);
|
||||
uint32 hero_model = 0;
|
||||
|
||||
|
||||
@@ -5477,7 +5477,6 @@ namespace RoF2
|
||||
/**
|
||||
* Ornamentation
|
||||
*/
|
||||
int ornamentation_augment_type = RuleI(Character, OrnamentationAugmentType);
|
||||
uint32 ornamentation_icon = (inst->GetOrnamentationIcon() ? inst->GetOrnamentationIcon() : 0);
|
||||
uint32 hero_model = 0;
|
||||
|
||||
|
||||
@@ -3851,17 +3851,17 @@ namespace UF
|
||||
ob.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
|
||||
}
|
||||
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
uint16 ornaIcon = 0;
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
const EQ::ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
ornaIcon = aug_weap->Icon;
|
||||
uint16 ornament_icon = 0;
|
||||
const auto augment = inst->GetOrnamentationAugment();
|
||||
|
||||
ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
if (augment) {
|
||||
const auto augment_item = augment->GetItem();
|
||||
ornament_icon = augment_item->Icon;
|
||||
|
||||
ob.write(augment_item->IDFile, strlen(augment_item->IDFile));
|
||||
}
|
||||
else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
ornament_icon = inst->GetOrnamentationIcon();
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
|
||||
ob.write(tmp, strlen(tmp));
|
||||
@@ -3870,7 +3870,7 @@ namespace UF
|
||||
|
||||
UF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.ornamentIcon = ornament_icon;
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown061 = 0; //possibly ornament / special ornament
|
||||
hdrf.isCopied = 0; //Flag for item to be 'Copied'
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
std::string Process::execute(const std::string &cmd)
|
||||
{
|
||||
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
std::string command = fmt::format("{} 2>&1", cmd);
|
||||
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
|
||||
if (!pipe) { return "ERROR"; }
|
||||
char buffer[128];
|
||||
std::string result;
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
#define EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseCharacterTributeRepository {
|
||||
public:
|
||||
struct CharacterTribute {
|
||||
int32_t id;
|
||||
uint32_t character_id;
|
||||
uint8_t tier;
|
||||
uint32_t tribute;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"character_id",
|
||||
"tier",
|
||||
"tribute",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"character_id",
|
||||
"tier",
|
||||
"tribute",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("character_tribute");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static CharacterTribute NewEntity()
|
||||
{
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = 0;
|
||||
e.character_id = 0;
|
||||
e.tier = 0;
|
||||
e.tribute = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static CharacterTribute GetCharacterTribute(
|
||||
const std::vector<CharacterTribute> &character_tributes,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
for (auto &character_tribute : character_tributes) {
|
||||
if (character_tribute.id == character_tribute_id) {
|
||||
return character_tribute;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static CharacterTribute FindOne(
|
||||
Database& db,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
character_tribute_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int character_tribute_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
character_tribute_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const CharacterTribute &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.character_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.tier));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.tribute));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static CharacterTribute InsertOne(
|
||||
Database& db,
|
||||
CharacterTribute e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.tier));
|
||||
v.push_back(std::to_string(e.tribute));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<CharacterTribute> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.character_id));
|
||||
v.push_back(std::to_string(e.tier));
|
||||
v.push_back(std::to_string(e.tribute));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<CharacterTribute> All(Database& db)
|
||||
{
|
||||
std::vector<CharacterTribute> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<CharacterTribute> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<CharacterTribute> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharacterTribute e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
|
||||
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
#define EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_character_tribute_repository.h"
|
||||
|
||||
class CharacterTributeRepository: public BaseCharacterTributeRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* CharacterTributeRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* CharacterTributeRepository::GetWhereNeverExpires()
|
||||
* CharacterTributeRepository::GetWhereXAndY()
|
||||
* CharacterTributeRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
|
||||
+3
-2
@@ -136,7 +136,6 @@ RULE_BOOL(Character, EnableFoodRequirement, true, "If disabled, food is no longe
|
||||
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, "Multiplier for environmental damage like fall damage.")
|
||||
RULE_BOOL(Character, UnmemSpellsOnDeath, true, "Setting whether at death all memorized Spells are forgotten")
|
||||
RULE_REAL(Character, TradeskillUpAlchemy, 2.0, "Alchemy skillup rate adjustment. Lower is faster")
|
||||
@@ -298,6 +297,7 @@ RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone alw
|
||||
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login")
|
||||
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
|
||||
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
|
||||
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
@@ -445,7 +445,7 @@ RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist be
|
||||
RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.")
|
||||
RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type")
|
||||
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
|
||||
RULE_BOOL(Spells, ResurrectionEffectsBlock, true, "If enabled, resurrection effects cannot be overwritten.")
|
||||
RULE_INT(Spells, ResurrectionEffectBlock, 2, "0 = allow overwrites/rule disabled. If set to 1 = Block all buffs that would overwrite Resurrection Effects. If set to 2 = Will not overwrite Resurrection Effects, instead moves new buff to an empty slot if available. Default is 2.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
@@ -518,6 +518,7 @@ RULE_BOOL(Combat, HeadshotOnlyHumanoids, true, "Enable or disable Headshot only
|
||||
RULE_BOOL(Combat, EnableWarriorShielding, true, "Enable or disable Warrior Shielding Ability (/shield), true by default.")
|
||||
RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental weapon damage affecting backstab damage, false by default.")
|
||||
RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.")
|
||||
RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a player when already in melee range of the summoner.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(NPC)
|
||||
|
||||
+7
-9
@@ -403,16 +403,14 @@ SaylinkRepository::Saylink EQ::SayLinkEngine::GetOrSaveSaylink(std::string sayli
|
||||
}
|
||||
|
||||
// if not found in database - save
|
||||
if (saylinks.empty()) {
|
||||
auto new_saylink = SaylinkRepository::NewEntity();
|
||||
new_saylink.phrase = saylink_text;
|
||||
auto new_saylink = SaylinkRepository::NewEntity();
|
||||
new_saylink.phrase = saylink_text;
|
||||
|
||||
// persist to database
|
||||
auto link = SaylinkRepository::InsertOne(database, new_saylink);
|
||||
if (link.id > 0) {
|
||||
g_cached_saylinks.emplace_back(link);
|
||||
return link;
|
||||
}
|
||||
// persist to database
|
||||
auto link = SaylinkRepository::InsertOne(database, new_saylink);
|
||||
if (link.id > 0) {
|
||||
g_cached_saylinks.emplace_back(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
+13
-12
@@ -235,18 +235,19 @@
|
||||
#define ServerOP_ReloadMerchants 0x4109
|
||||
#define ServerOP_ReloadNPCEmotes 0x4110
|
||||
#define ServerOP_ReloadObjects 0x4111
|
||||
#define ServerOP_ReloadPerlExportSettings 0x4112
|
||||
#define ServerOP_ReloadRules 0x4113
|
||||
#define ServerOP_ReloadStaticZoneData 0x4114
|
||||
#define ServerOP_ReloadTasks 0x4115
|
||||
#define ServerOP_ReloadTitles 0x4116
|
||||
#define ServerOP_ReloadTraps 0x4117
|
||||
#define ServerOP_ReloadVariables 0x4118
|
||||
#define ServerOP_ReloadVeteranRewards 0x4119
|
||||
#define ServerOP_ReloadWorld 0x4120
|
||||
#define ServerOP_ReloadZonePoints 0x4121
|
||||
#define ServerOP_ReloadDzTemplates 0x4122
|
||||
#define ServerOP_ReloadZoneData 0x4123
|
||||
#define ServerOP_ReloadOpcodes 0x4112
|
||||
#define ServerOP_ReloadPerlExportSettings 0x4113
|
||||
#define ServerOP_ReloadRules 0x4114
|
||||
#define ServerOP_ReloadStaticZoneData 0x4115
|
||||
#define ServerOP_ReloadTasks 0x4116
|
||||
#define ServerOP_ReloadTitles 0x4117
|
||||
#define ServerOP_ReloadTraps 0x4118
|
||||
#define ServerOP_ReloadVariables 0x4119
|
||||
#define ServerOP_ReloadVeteranRewards 0x4120
|
||||
#define ServerOP_ReloadWorld 0x4121
|
||||
#define ServerOP_ReloadZonePoints 0x4122
|
||||
#define ServerOP_ReloadDzTemplates 0x4123
|
||||
#define ServerOP_ReloadZoneData 0x4124
|
||||
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
|
||||
@@ -47,9 +47,9 @@ const SharedTasksRepository::SharedTasks &SharedTask::GetDbSharedTask() const
|
||||
return m_db_shared_task;
|
||||
}
|
||||
|
||||
void SharedTask::SetDbSharedTask(const SharedTasksRepository::SharedTasks &m_db_shared_task)
|
||||
void SharedTask::SetDbSharedTask(const SharedTasksRepository::SharedTasks &t)
|
||||
{
|
||||
SharedTask::m_db_shared_task = m_db_shared_task;
|
||||
SharedTask::m_db_shared_task = t;
|
||||
}
|
||||
|
||||
SharedTaskRequest SharedTask::GetRequestCharacters(Database &db, uint32_t requested_character_id)
|
||||
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
|
||||
// active record of database shared task
|
||||
const SharedTasksRepository::SharedTasks &GetDbSharedTask() const;
|
||||
void SetDbSharedTask(const SharedTasksRepository::SharedTasks &m_db_shared_task);
|
||||
void SetDbSharedTask(const SharedTasksRepository::SharedTasks &t);
|
||||
|
||||
std::vector<SharedTaskActivityStateEntry> m_shared_task_activity_state;
|
||||
std::vector<SharedTaskMember> m_members;
|
||||
|
||||
+92
-69
@@ -133,55 +133,54 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
||||
|
||||
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||
{
|
||||
char MailKeyString[17];
|
||||
char mail_key[17];
|
||||
|
||||
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
|
||||
else
|
||||
sprintf(MailKeyString, "%08X", MailKey);
|
||||
if (RuleB(Chat, EnableMailKeyIPVerification) == true) {
|
||||
sprintf(mail_key, "%08X%08X", IPAddress, MailKey);
|
||||
}
|
||||
else {
|
||||
sprintf(mail_key, "%08X", MailKey);
|
||||
}
|
||||
|
||||
const std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||
MailKeyString, CharID);
|
||||
const auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, MailKeyString, results.ErrorMessage().c_str());
|
||||
const std::string query = StringFormat(
|
||||
"UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||
mail_key, CharID
|
||||
);
|
||||
|
||||
const auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string SharedDatabase::GetMailKey(int CharID, bool key_only)
|
||||
SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
|
||||
{
|
||||
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
|
||||
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str());
|
||||
return std::string();
|
||||
return MailKeys{};
|
||||
}
|
||||
|
||||
if (!results.RowCount()) {
|
||||
|
||||
Log(Logs::General, Logs::ClientLogin, "Error: Mailkey for character id [%i] does not exist or could not be found", CharID);
|
||||
return std::string();
|
||||
Log(Logs::General,
|
||||
Logs::ClientLogin,
|
||||
"Error: Mailkey for character id [%i] does not exist or could not be found",
|
||||
character_id
|
||||
);
|
||||
return MailKeys{};
|
||||
}
|
||||
|
||||
auto& row = results.begin();
|
||||
auto &row = results.begin();
|
||||
if (row != results.end()) {
|
||||
|
||||
std::string mail_key = row[0];
|
||||
|
||||
if (mail_key.length() > 8 && key_only) {
|
||||
return mail_key.substr(8);
|
||||
}
|
||||
else {
|
||||
return mail_key;
|
||||
}
|
||||
return MailKeys{
|
||||
.mail_key = mail_key.substr(8),
|
||||
.mail_key_full = mail_key
|
||||
};
|
||||
}
|
||||
else {
|
||||
|
||||
Log(Logs::General, Logs::MySQLError, "Internal MySQL error in SharedDatabase::GetMailKey(int, bool)");
|
||||
return std::string();
|
||||
}
|
||||
return MailKeys{};
|
||||
}
|
||||
|
||||
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQ::ItemInstance*>::const_iterator &start, std::list<EQ::ItemInstance*>::const_iterator &end)
|
||||
@@ -425,17 +424,13 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) {
|
||||
|
||||
int32 SharedDatabase::GetSharedPlatinum(uint32 account_id)
|
||||
{
|
||||
const std::string query = StringFormat("SELECT sharedplat FROM account WHERE id = '%i'", account_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto& row = results.begin();
|
||||
const auto query = fmt::format("SELECT sharedplat FROM account WHERE id = {}", account_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
return Strings::ToInt(row[0]);
|
||||
}
|
||||
|
||||
@@ -499,25 +494,32 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is
|
||||
{
|
||||
std::string query;
|
||||
|
||||
if (is_charid)
|
||||
query = StringFormat("SELECT sb.slotid, sb.itemid, sb.charges, "
|
||||
"sb.augslot1, sb.augslot2, sb.augslot3, "
|
||||
"sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data "
|
||||
"FROM sharedbank sb INNER JOIN character_data ch "
|
||||
"ON ch.account_id=sb.acctid WHERE ch.id = %i ORDER BY sb.slotid",
|
||||
id);
|
||||
else
|
||||
query = StringFormat("SELECT slotid, itemid, charges, "
|
||||
"augslot1, augslot2, augslot3, "
|
||||
"augslot4, augslot5, augslot6, custom_data "
|
||||
"FROM sharedbank WHERE acctid=%i ORDER BY slotid",
|
||||
id);
|
||||
if (is_charid) {
|
||||
query = fmt::format(
|
||||
"SELECT sb.slotid, sb.itemid, sb.charges, "
|
||||
"sb.augslot1, sb.augslot2, sb.augslot3, "
|
||||
"sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data "
|
||||
"FROM sharedbank sb INNER JOIN character_data ch "
|
||||
"ON ch.account_id = sb.acctid WHERE ch.id = {} ORDER BY sb.slotid",
|
||||
id
|
||||
);
|
||||
} else {
|
||||
query = fmt::format(
|
||||
"SELECT slotid, itemid, charges, "
|
||||
"augslot1, augslot2, augslot3, "
|
||||
"augslot4, augslot5, augslot6, custom_data "
|
||||
"FROM sharedbank WHERE acctid = {} ORDER BY slotid",
|
||||
id
|
||||
);
|
||||
}
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
// If we have no results we still need to return true
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
for (auto row : results) {
|
||||
int16 slot_id = static_cast<int16>(Strings::ToInt(row[0]));
|
||||
uint32 item_id = Strings::ToUnsignedInt(row[1]);
|
||||
const int16 charges = static_cast<int16>(Strings::ToInt(row[2]));
|
||||
@@ -533,16 +535,26 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is
|
||||
const EQ::ItemData *item = GetItem(item_id);
|
||||
|
||||
if (!item) {
|
||||
LogError("Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]",
|
||||
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
||||
LogError(
|
||||
"Warning: [{}] [{}] has an invalid item_id [{}] in inventory slot [{}]",
|
||||
is_charid ? "charid" : "acctid",
|
||||
id,
|
||||
item_id,
|
||||
slot_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto inst = CreateBaseItem(item, charges);
|
||||
if (!inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EQ::ItemInstance *inst = CreateBaseItem(item, charges);
|
||||
if (inst && item->IsClassCommon()) {
|
||||
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
|
||||
if (aug[i])
|
||||
if (aug[i]) {
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,14 +568,21 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is
|
||||
safe_delete(inst);
|
||||
|
||||
// Save ptr to item in inventory
|
||||
if (put_slot_id != INVALID_INDEX)
|
||||
if (put_slot_id != INVALID_INDEX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LogError("Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]",
|
||||
((is_charid == true) ? "charid" : "acctid"), id, item_id, slot_id);
|
||||
LogError(
|
||||
"Warning: Invalid slot_id for item in shared bank inventory: [{}]=[{}], item_id=[{}], slot_id=[{}]",
|
||||
is_charid ? "charid" : "acctid",
|
||||
id,
|
||||
item_id,
|
||||
slot_id
|
||||
);
|
||||
|
||||
if (is_charid)
|
||||
if (is_charid) {
|
||||
SaveInventory(id, nullptr, slot_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -619,7 +638,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
||||
}
|
||||
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { // Titanium check
|
||||
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||
if (parent_index < EQ::invslot::SLOT_BEGIN || parent_index >= bank_size) {
|
||||
if (parent_index >= bank_size) {
|
||||
cv_conflict = true;
|
||||
continue;
|
||||
}
|
||||
@@ -1564,24 +1583,28 @@ EQ::ItemInstance* SharedDatabase::CreateBaseItem(const EQ::ItemData* item, int16
|
||||
if (item) {
|
||||
// if maxcharges is -1 that means it is an unlimited use item.
|
||||
// set it to 1 charge so that it is usable on creation
|
||||
if (charges == 0 && item->MaxCharges == -1)
|
||||
if (charges == 0 && item->MaxCharges == -1) {
|
||||
charges = 1;
|
||||
}
|
||||
|
||||
// Stackable items need a minimum charge of 1 to remain moveable.
|
||||
if(charges <= 0 && item->Stackable)
|
||||
if (charges <= 0 && item->Stackable) {
|
||||
charges = 1;
|
||||
}
|
||||
|
||||
inst = new EQ::ItemInstance(item, charges);
|
||||
|
||||
if (inst == nullptr) {
|
||||
if (!inst) {
|
||||
LogError("Error: valid item data returned a null reference for EQ::ItemInstance creation in SharedDatabase::CreateBaseItem()");
|
||||
LogError("Item Data = ID: {}, Name: {}, Charges: {}", item->ID, item->Name, charges);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(item->CharmFileID != 0 || (item->LoreGroup >= 1000 && item->LoreGroup != -1)) {
|
||||
if (item->CharmFileID != 0 || item->LoreGroup >= 1000) {
|
||||
inst->Initialize(this);
|
||||
}
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -81,7 +81,11 @@ public:
|
||||
bool SetGMInvul(uint32 account_id, bool gminvul);
|
||||
bool SetGMFlymode(uint32 account_id, uint8 flymode);
|
||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||
std::string GetMailKey(int CharID, bool key_only = false);
|
||||
struct MailKeys {
|
||||
std::string mail_key;
|
||||
std::string mail_key_full;
|
||||
};
|
||||
MailKeys GetMailKey(int character_id);
|
||||
bool SaveCursor(
|
||||
uint32 char_id,
|
||||
std::list<EQ::ItemInstance *>::const_iterator &start,
|
||||
|
||||
@@ -148,33 +148,6 @@ int32 EQ::skills::GetBaseDamage(SkillType skill)
|
||||
}
|
||||
}
|
||||
|
||||
bool EQ::skills::IsMeleeDmg(SkillType skill)
|
||||
{
|
||||
switch (skill) {
|
||||
case Skill1HBlunt:
|
||||
case Skill1HSlashing:
|
||||
case Skill2HBlunt:
|
||||
case Skill2HSlashing:
|
||||
case SkillBackstab:
|
||||
case SkillBash:
|
||||
case SkillDragonPunch:
|
||||
case SkillEagleStrike:
|
||||
case SkillFlyingKick:
|
||||
case SkillHandtoHand:
|
||||
case SkillKick:
|
||||
case Skill1HPiercing:
|
||||
case SkillRiposte:
|
||||
case SkillRoundKick:
|
||||
case SkillThrowing:
|
||||
case SkillTigerClaw:
|
||||
case SkillFrenzy:
|
||||
case Skill2HPiercing:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<EQ::skills::SkillType, std::string>& EQ::skills::GetSkillTypeMap()
|
||||
{
|
||||
static const std::map<SkillType, std::string> skill_type_map = {
|
||||
|
||||
@@ -168,7 +168,6 @@ namespace EQ
|
||||
bool IsBardInstrumentSkill(SkillType skill);
|
||||
bool IsCastingSkill(SkillType skill);
|
||||
int32 GetBaseDamage(SkillType skill);
|
||||
bool IsMeleeDmg(SkillType skill);
|
||||
|
||||
extern const std::map<SkillType, std::string>& GetSkillTypeMap();
|
||||
extern const std::vector<SkillType>& GetExtraDamageSkills();
|
||||
|
||||
+1177
-700
File diff suppressed because it is too large
Load Diff
+101
-60
@@ -171,6 +171,37 @@
|
||||
#define SPELL_ILLUSION_MALE 1732
|
||||
#define SPELL_UNSUMMON_SELF 892
|
||||
#define SPELL_ANCIENT_LIFEBANE 2115
|
||||
#define SPELL_GMHP25K 6817
|
||||
#define SPELL_GMHP50K 6818
|
||||
#define SPELL_GMHP100K 6819
|
||||
#define SPELL_GMHP225K 6820
|
||||
#define SPELL_GMHP475K 6821
|
||||
#define SPELL_GMHP925K 6822
|
||||
#define SPELL_GMHP2M 6823
|
||||
#define SPELL_GMHP3M 6824
|
||||
#define SPELL_GMHP5M 39851
|
||||
#define SPELL_GUIDE_ACTING_ONE 778
|
||||
#define SPELL_GUIDE_ALLIANCE_ONE 810
|
||||
#define SPELL_GUIDE_CANCEL_MAGIC_ONE 811
|
||||
#define SPELL_GUIDE_JOURNEY_ONE 813
|
||||
#define SPELL_GUIDE_VISION_ONE 814
|
||||
#define SPELL_GUIDE_HEALTH_ONE 815
|
||||
#define SPELL_GUIDE_INVULNERABILITY_ONE 816
|
||||
#define SPELL_GUIDE_BOLT_ONE 817
|
||||
#define SPELL_GUIDE_MEMORY_BLUR_ONE 818
|
||||
#define SPELL_GUIDE_ACTING_TWO 1209
|
||||
#define SPELL_GUIDE_CANCEL_MAGIC_TWO 1211
|
||||
#define SPELL_GUIDE_JOURNEY_TWO 1212
|
||||
#define SPELL_GUIDE_VISION_TWO 1213
|
||||
#define SPELL_GUIDE_HEALTH_TWO 1214
|
||||
#define SPELL_GUIDE_INVULNERABILITY_TWO 1215
|
||||
#define SPELL_GUIDE_BOLT_TWO 1216
|
||||
#define SPELL_GUIDE_MEMORY_BLUR_TWO 1217
|
||||
#define SPELL_GUIDE_ALLIANCE_TWO 1219
|
||||
#define SPELL_GUIDE_EVACUATION 3921
|
||||
#define SPELL_GUIDE_LEVITATION 39852
|
||||
#define SPELL_GUIDE_SPELL_HASTE 39853
|
||||
#define SPELL_GUIDE_HASTE 39854
|
||||
|
||||
//spellgroup ids
|
||||
#define SPELLGROUP_FRENZIED_BURNOUT 2754
|
||||
@@ -201,8 +232,22 @@
|
||||
#define INSTRUMENT_LUTE 13011
|
||||
#define INSTRUMENT_HORN 13012
|
||||
|
||||
//option types for the rule Spells:ResurrectionEffectBlock
|
||||
#define RES_EFFECTS_CANNOT_STACK -1
|
||||
#define NO_RES_EFFECTS_BLOCK 0
|
||||
#define RES_EFFECTS_BLOCK 1
|
||||
#define RES_EFFECTS_BLOCK_WITH_BUFFS 2
|
||||
#define MOVE_NEW_SLOT 2
|
||||
|
||||
const int Z_AGGRO=10;
|
||||
#define PARTIAL_DEATH_SAVE 1
|
||||
#define FULL_DEATH_SAVE 2
|
||||
|
||||
#define MAX_FAST_HEAL_CASTING_TIME 2000
|
||||
#define MAX_VERY_FAST_HEAL_CASTING_TIME 1000
|
||||
|
||||
#define DETRIMENTAL_EFFECT 0
|
||||
#define BENEFICIAL_EFFECT 1
|
||||
#define BENEFICIAL_EFFECT_GROUP_ONLY 2
|
||||
|
||||
const uint32 MobAISpellRange=100; // max range of buffs
|
||||
|
||||
@@ -1160,7 +1205,7 @@ typedef enum {
|
||||
#define SE_LimitUseMin 422 // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt
|
||||
#define SE_LimitUseType 423 // implemented, @Ff Focus will only affect if has this numhits type, base: numhit 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_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_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt)
|
||||
#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none
|
||||
@@ -1443,7 +1488,7 @@ extern int32 SPDAT_RECORDS;
|
||||
bool IsTargetableAESpell(uint16 spell_id);
|
||||
bool IsSacrificeSpell(uint16 spell_id);
|
||||
bool IsLifetapSpell(uint16 spell_id);
|
||||
bool IsMezSpell(uint16 spell_id);
|
||||
bool IsMesmerizeSpell(uint16 spell_id);
|
||||
bool IsStunSpell(uint16 spell_id);
|
||||
bool IsSlowSpell(uint16 spell_id);
|
||||
bool IsHasteSpell(uint16 spell_id);
|
||||
@@ -1452,22 +1497,23 @@ bool IsPercentalHealSpell(uint16 spell_id);
|
||||
bool IsGroupOnlySpell(uint16 spell_id);
|
||||
bool IsBeneficialSpell(uint16 spell_id);
|
||||
bool IsDetrimentalSpell(uint16 spell_id);
|
||||
bool IsInvisSpell(uint16 spell_id);
|
||||
bool IsInvisibleSpell(uint16 spell_id);
|
||||
bool IsInvulnerabilitySpell(uint16 spell_id);
|
||||
bool IsCHDurationSpell(uint16 spell_id);
|
||||
bool IsCompleteHealDurationSpell(uint16 spell_id);
|
||||
bool IsPoisonCounterSpell(uint16 spell_id);
|
||||
bool IsDiseaseCounterSpell(uint16 spell_id);
|
||||
bool IsSummonItemSpell(uint16 spell_id);
|
||||
bool IsSummonSkeletonSpell(uint16 spell_id);
|
||||
bool IsSummonPetSpell(uint16 spell_id);
|
||||
bool IsSummonPCSpell(uint16 spell_id);
|
||||
bool IsPetSpell(uint16 spell_id);
|
||||
bool IsCharmSpell(uint16 spell_id);
|
||||
bool IsBlindSpell(uint16 spell_id);
|
||||
bool IsEffectHitpointsSpell(uint16 spell_id);
|
||||
bool IsReduceCastTimeSpell(uint16 spell_id);
|
||||
bool IsHealthSpell(uint16 spell_id);
|
||||
bool IsCastTimeReductionSpell(uint16 spell_id);
|
||||
bool IsIncreaseDurationSpell(uint16 spell_id);
|
||||
bool IsReduceManaSpell(uint16 spell_id);
|
||||
bool IsExtRangeSpell(uint16 spell_id);
|
||||
bool IsManaCostReductionSpell(uint16 spell_id);
|
||||
bool IsIncreaseRangeSpell(uint16 spell_id);
|
||||
bool IsImprovedHealingSpell(uint16 spell_id);
|
||||
bool IsImprovedDamageSpell(uint16 spell_id);
|
||||
bool IsAEDurationSpell(uint16 spell_id);
|
||||
@@ -1475,26 +1521,22 @@ bool IsPureNukeSpell(uint16 spell_id);
|
||||
bool IsAENukeSpell(uint16 spell_id);
|
||||
bool IsPBAENukeSpell(uint16 spell_id);
|
||||
bool IsAERainNukeSpell(uint16 spell_id);
|
||||
bool IsPartialCapableSpell(uint16 spell_id);
|
||||
bool IsPartialResistableSpell(uint16 spell_id);
|
||||
bool IsResistableSpell(uint16 spell_id);
|
||||
bool IsGroupSpell(uint16 spell_id);
|
||||
bool IsTGBCompatibleSpell(uint16 spell_id);
|
||||
bool IsBardSong(uint16 spell_id);
|
||||
bool IsEffectInSpell(uint16 spellid, int effect);
|
||||
uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect);
|
||||
bool IsBlankSpellEffect(uint16 spellid, int effect_index);
|
||||
bool IsValidSpell(uint32 spellid);
|
||||
bool IsSummonSpell(uint16 spellid);
|
||||
bool IsEvacSpell(uint16 spellid);
|
||||
bool IsDamageSpell(uint16 spellid);
|
||||
bool IsFearSpell(uint16 spellid);
|
||||
bool IsCureSpell(uint16 spellid);
|
||||
bool BeneficialSpell(uint16 spell_id);
|
||||
bool GroupOnlySpell(uint16 spell_id);
|
||||
int GetSpellEffectIndex(uint16 spell_id, int effect);
|
||||
int CanUseSpell(uint16 spellid, int classa, int level);
|
||||
int GetMinLevel(uint16 spell_id);
|
||||
int GetSpellLevel(uint16 spell_id, int classa);
|
||||
bool IsEffectInSpell(uint16 spell_id, int effect_id);
|
||||
uint16 GetSpellTriggerSpellID(uint16 spell_id, int effect_id);
|
||||
bool IsBlankSpellEffect(uint16 spell_id, int effect_index);
|
||||
bool IsValidSpell(uint32 spell_id);
|
||||
bool IsSummonSpell(uint16 spell_id);
|
||||
bool IsDamageSpell(uint16 spell_id);
|
||||
bool IsFearSpell(uint16 spell_id);
|
||||
bool IsCureSpell(uint16 spell_id);
|
||||
int GetSpellEffectIndex(uint16 spell_id, int effect_id);
|
||||
uint8 GetSpellMinimumLevel(uint16 spell_id);
|
||||
uint8 GetSpellLevel(uint16 spell_id, uint8 class_id);
|
||||
int CalcBuffDuration_formula(int level, int formula, int duration);
|
||||
int32 CalculatePoisonCounters(uint16 spell_id);
|
||||
int32 CalculateDiseaseCounters(uint16 spell_id);
|
||||
@@ -1505,10 +1547,11 @@ bool IsDisciplineBuff(uint16 spell_id);
|
||||
bool IsDiscipline(uint16 spell_id);
|
||||
bool IsCombatSkill(uint16 spell_id);
|
||||
bool IsResurrectionEffects(uint16 spell_id);
|
||||
int8 GetSpellResurrectionSicknessCheck(uint16 spell_id_one, uint16 spell_id_two);
|
||||
bool IsRuneSpell(uint16 spell_id);
|
||||
bool IsMagicRuneSpell(uint16 spell_id);
|
||||
bool IsManaTapSpell(uint16 spell_id);
|
||||
bool IsAllianceSpellLine(uint16 spell_id);
|
||||
bool IsAllianceSpell(uint16 spell_id);
|
||||
bool IsDeathSaveSpell(uint16 spell_id);
|
||||
bool IsFullDeathSaveSpell(uint16 spell_id);
|
||||
bool IsPartialDeathSaveSpell(uint16 spell_id);
|
||||
@@ -1517,10 +1560,10 @@ bool IsSuccorSpell(uint16 spell_id);
|
||||
bool IsTeleportSpell(uint16 spell_id);
|
||||
bool IsTranslocateSpell(uint16 spell_id);
|
||||
bool IsGateSpell(uint16 spell_id);
|
||||
bool IsPlayerIllusionSpell(uint16 spell_id); // seveian 2008-09-23
|
||||
bool IsIllusionSpell(uint16 spell_id);
|
||||
bool IsLDoNObjectSpell(uint16 spell_id);
|
||||
int32 GetSpellResistType(uint16 spell_id);
|
||||
int32 GetSpellTargetType(uint16 spell_id);
|
||||
int GetSpellResistType(uint16 spell_id);
|
||||
int GetSpellTargetType(uint16 spell_id);
|
||||
bool IsHealOverTimeSpell(uint16 spell_id);
|
||||
bool IsCompleteHealSpell(uint16 spell_id);
|
||||
bool IsFastHealSpell(uint16 spell_id);
|
||||
@@ -1535,38 +1578,36 @@ bool IsSelfConversionSpell(uint16 spell_id);
|
||||
bool IsBuffSpell(uint16 spell_id);
|
||||
bool IsPersistDeathSpell(uint16 spell_id);
|
||||
bool IsSuspendableSpell(uint16 spell_id);
|
||||
uint32 GetMorphTrigger(uint32 spell_id);
|
||||
bool IsCastonFadeDurationSpell(uint16 spell_id);
|
||||
bool IsPowerDistModSpell(uint16 spell_id);
|
||||
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);
|
||||
bool IsStackableDot(uint16 spell_id);
|
||||
bool IsBardOnlyStackEffect(int effect);
|
||||
bool IsCastWhileInvis(uint16 spell_id);
|
||||
bool IsEffectIgnoredInStacking(int spa);
|
||||
bool IsFocusLimit(int spa);
|
||||
bool SpellRequiresTarget(int target_type);
|
||||
bool IsVirusSpell(int32 spell_id);
|
||||
int GetViralMinSpreadTime(int32 spell_id);
|
||||
int GetViralMaxSpreadTime(int32 spell_id);
|
||||
int GetViralSpreadRange(int32 spell_id);
|
||||
bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect);
|
||||
bool IsPulsingBardSong(int32 spell_id);
|
||||
uint32 GetProcLimitTimer(int32 spell_id, int proc_type);
|
||||
bool IgnoreCastingRestriction(int32 spell_id);
|
||||
int CalcPetHp(int levelb, int classb, int STA = 75);
|
||||
int GetSpellEffectDescNum(uint16 spell_id);
|
||||
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0);
|
||||
bool DetrimentalSpellAllowsRest(uint16 spell_id);
|
||||
uint32 GetNimbusEffect(uint16 spell_id);
|
||||
int32 GetFuriousBash(uint16 spell_id);
|
||||
bool IsCastOnFadeDurationSpell(uint16 spell_id);
|
||||
bool IsDistanceModifierSpell(uint16 spell_id);
|
||||
int GetSpellPartialMeleeRuneReduction(uint16 spell_id);
|
||||
int GetSpellPartialMagicRuneReduction(uint16 spell_id);
|
||||
int GetSpellPartialMeleeRuneAmount(uint16 spell_id);
|
||||
int GetSpellPartialMagicRuneAmount(uint16 spell_id);
|
||||
bool IsNoDetrimentalSpellAggroSpell(uint16 spell_id);
|
||||
bool IsStackableDOT(uint16 spell_id);
|
||||
bool IsBardOnlyStackEffect(int effect_id);
|
||||
bool IsCastWhileInvisibleSpell(uint16 spell_id);
|
||||
bool IsEffectIgnoredInStacking(int effect_id);
|
||||
bool IsFocusLimit(int effect_id);
|
||||
bool IsTargetRequiredForSpell(uint16 spell_id);
|
||||
bool IsVirusSpell(uint16 spell_id);
|
||||
int GetSpellViralMinimumSpreadTime(uint16 spell_id);
|
||||
int GetSpellViralMaximumSpreadTime(uint16 spell_id);
|
||||
int GetSpellViralSpreadRange(uint16 spell_id);
|
||||
bool IsInstrumentModifierAppliedToSpellEffect(uint16 spell_id, int effect_id);
|
||||
bool IsPulsingBardSong(uint16 spell_id);
|
||||
int GetSpellProcLimitTimer(uint16 spell_id, int proc_type);
|
||||
bool IsCastNotStandingSpell(uint16 spell_id);
|
||||
int GetSpellEffectDescriptionNumber(uint16 spell_id);
|
||||
DmgShieldType GetDamageShieldType(uint16 spell_id, int damage_shield_type = 0);
|
||||
bool IsRestAllowedSpell(uint16 spell_id);
|
||||
int GetSpellNimbusEffect(uint16 spell_id);
|
||||
int GetSpellFuriousBash(uint16 spell_id);
|
||||
bool IsShortDurationBuff(uint16 spell_id);
|
||||
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
|
||||
bool IsSpellUsableInThisZoneType(uint16 spell_id, uint8 zone_type);
|
||||
const char *GetSpellName(uint16 spell_id);
|
||||
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0);
|
||||
bool CastRestrictedSpell(int spellid);
|
||||
int GetSpellStatValue(uint16 spell_id, const char* stat_identifier, uint8 slot = 0);
|
||||
bool IsCastRestrictedSpell(uint16 spell_id);
|
||||
|
||||
#endif
|
||||
|
||||
+2
-5
@@ -287,15 +287,12 @@ std::string Strings::Commify(const std::string &number)
|
||||
for (i = string_length - 3; i >= 0; i -= 3) {
|
||||
if (i > 0) {
|
||||
temp_string = "," + number.substr(static_cast<unsigned long>(i), 3) + temp_string;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
temp_string = number.substr(static_cast<unsigned long>(i), 3) + temp_string;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
temp_string = number.substr(0, static_cast<unsigned long>(3 + i)) + temp_string;
|
||||
}
|
||||
temp_string = number.substr(0, static_cast<unsigned long>(3 + i)) + temp_string;
|
||||
|
||||
return temp_string;
|
||||
}
|
||||
|
||||
@@ -57,9 +57,6 @@ typedef const char Const_char; //for perl XS
|
||||
|
||||
#define safe_delete(d) if(d) { delete d; d=nullptr; }
|
||||
#define safe_delete_array(d) if(d) { delete[] d; d=nullptr; }
|
||||
#define L32(i) ((uint32) i)
|
||||
#define H32(i) ((uint32) (i >> 32))
|
||||
#define L16(i) ((uint16) i)
|
||||
|
||||
#ifndef WIN32
|
||||
// More WIN32 compatability
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.9.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.13.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
@@ -42,7 +42,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9227
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9228
|
||||
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,8 @@
|
||||
#include "../common/repositories/zone_repository.h"
|
||||
#include "../common/repositories/base/base_content_flags_repository.h"
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
class ZoneStore {
|
||||
public:
|
||||
ZoneStore();
|
||||
@@ -43,6 +45,62 @@ public:
|
||||
const char *GetZoneName(uint32 zone_id, bool error_unknown = false);
|
||||
const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false);
|
||||
ZoneRepository::Zone *GetZoneWithFallback(uint32 zone_id, int version = 0);
|
||||
|
||||
glm::vec4 GetZoneSafeCoordinates(uint32 zone_id, int version = 0);
|
||||
float GetZoneGraveyardID(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneMinimumLevel(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneMaximumLevel(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneMinimumStatus(uint32 zone_id, int version = 0);
|
||||
int GetZoneTimeZone(uint32 zone_id, int version = 0);
|
||||
int GetZoneMaximumPlayers(uint32 zone_id, int version = 0);
|
||||
uint32 GetZoneRuleSet(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneNote(uint32 zone_id, int version = 0);
|
||||
float GetZoneUnderworld(uint32 zone_id, int version = 0);
|
||||
float GetZoneMinimumClip(uint32 zone_id, int version = 0);
|
||||
float GetZoneMaximumClip(uint32 zone_id, int version = 0);
|
||||
float GetZoneFogMinimumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
float GetZoneFogMaximumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
uint8 GetZoneFogRed(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
uint8 GetZoneFogGreen(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
uint8 GetZoneFogBlue(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
uint8 GetZoneSky(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneZType(uint32 zone_id, int version = 0);
|
||||
float GetZoneExperienceMultiplier(uint32 zone_id, int version = 0);
|
||||
float GetZoneWalkSpeed(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneTimeType(uint32 zone_id, int version = 0);
|
||||
float GetZoneFogDensity(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneFlagNeeded(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanBind(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanCombat(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCanLevitate(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneCastOutdoor(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneHotzone(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneInstanceType(uint32 zone_id, int version = 0);
|
||||
uint64 GetZoneShutdownDelay(uint32 zone_id, int version = 0);
|
||||
int8 GetZonePEQZone(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneExpansion(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneBypassExpansionCheck(uint32 zone_id, int version = 0);
|
||||
uint8 GetZoneSuspendBuffs(uint32 zone_id, int version = 0);
|
||||
int GetZoneRainChance(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
int GetZoneRainDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
int GetZoneSnowChance(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
int GetZoneSnowDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
|
||||
float GetZoneGravity(uint32 zone_id, int version = 0);
|
||||
int GetZoneType(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneSkyLock(uint32 zone_id, int version = 0);
|
||||
int GetZoneFastRegenHP(uint32 zone_id, int version = 0);
|
||||
int GetZoneFastRegenMana(uint32 zone_id, int version = 0);
|
||||
int GetZoneFastRegenEndurance(uint32 zone_id, int version = 0);
|
||||
int GetZoneNPCMaximumAggroDistance(uint32 zone_id, int version = 0);
|
||||
uint32 GetZoneMaximumMovementUpdateRange(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneMinimumExpansion(uint32 zone_id, int version = 0);
|
||||
int8 GetZoneMaximumExpansion(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneContentFlags(uint32 zone_id, int version = 0);
|
||||
const std::string& GetZoneContentFlagsDisabled(uint32 zone_id, int version = 0);
|
||||
int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0);
|
||||
int GetZoneLavaDamage(uint32 zone_id, int version = 0);
|
||||
int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0);
|
||||
|
||||
private:
|
||||
std::vector<ZoneRepository::Zone> m_zones;
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.9.1",
|
||||
"version": "22.13.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
+4
-4
@@ -701,11 +701,11 @@ void ChatChannelList::Process() {
|
||||
LogDebug("Empty temporary password protected channel [{}] being destroyed",
|
||||
CurrentChannel->GetName().c_str());
|
||||
|
||||
RemoveChannel(CurrentChannel);
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
else {
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,8 @@ int main() {
|
||||
->LoadLogDatabaseSettings()
|
||||
->StartFileLogs();
|
||||
|
||||
player_event_logs.SetDatabase(&database)->Init();
|
||||
|
||||
char tmp[64];
|
||||
|
||||
// ucs has no 'reload rules' handler
|
||||
|
||||
@@ -1801,23 +1801,9 @@ sub fetch_peq_db_full
|
||||
sub map_files_fetch_bulk
|
||||
{
|
||||
print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n";
|
||||
get_remote_file("http://analytics.akkadius.com/maps.zip", "maps/maps.zip", 1);
|
||||
get_remote_file("https://github.com/Akkadius/eqemu-maps/releases/latest/download/maps.zip", "maps/maps.zip", 1);
|
||||
unzip('maps/maps.zip', 'maps/');
|
||||
my @files;
|
||||
my $start_dir = "maps/EQEmuMaps-master/";
|
||||
find(
|
||||
sub { push @files, $File::Find::name unless -d; },
|
||||
$start_dir
|
||||
);
|
||||
for my $file (@files) {
|
||||
$destination_file = $file;
|
||||
$destination_file =~ s/maps\/EQEmuMaps-master\///g;
|
||||
print "[Install] Installing [" . $destination_file . "]\n";
|
||||
copy_file($file, "maps/" . $destination_file);
|
||||
}
|
||||
print "[Install] Fetched Latest Maps\n";
|
||||
|
||||
rmtree('maps/EQEmuMaps-master');
|
||||
unlink('maps/maps.zip');
|
||||
}
|
||||
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'bot_id'|empty|
|
||||
9226|2023_03_17_corpse_fields.sql|SHOW COLUMNS FROM `character_corpse_items` LIKE 'custom_data'|empty|
|
||||
9227|2023_03_24_npc_scale_global_base_verify.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|not_empty|
|
||||
9228|2023_05_08_character_tribute_primary_key.sql|SHOW COLUMNS FROM `character_tribute` LIKE 'character_id'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE `character_tribute`
|
||||
CHANGE COLUMN `id` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
@@ -36,9 +36,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
|
||||
s->SetDumpPath(cmd("--dump-path").str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Option
|
||||
*/
|
||||
// options
|
||||
s->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all);
|
||||
s->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all);
|
||||
s->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all);
|
||||
@@ -48,15 +46,11 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std:
|
||||
s->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all);
|
||||
s->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all);
|
||||
s->SetDumpAllTables(dump_all);
|
||||
|
||||
s->SetDumpWithNoData(cmd[{"--table-structure-only"}]);
|
||||
s->SetDumpTableLock(cmd[{"--table-lock"}]);
|
||||
s->SetDumpWithCompression(cmd[{"--compress"}]);
|
||||
s->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]);
|
||||
s->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]);
|
||||
|
||||
/**
|
||||
* Dump
|
||||
*/
|
||||
s->Dump();
|
||||
s->DatabaseDump();
|
||||
}
|
||||
|
||||
@@ -268,8 +268,8 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect
|
||||
strcpy(newline, "\r\n");
|
||||
else
|
||||
strcpy(newline, "^");
|
||||
std::vector<char> out;
|
||||
|
||||
auto out = fmt::memory_buffer();
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
ClientListEntry* cle = iterator.GetData();
|
||||
@@ -1008,7 +1008,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
if (whom)
|
||||
whomlen = strlen(whom->whom);
|
||||
|
||||
std::vector<char> out;
|
||||
auto out = fmt::memory_buffer();
|
||||
fmt::format_to(std::back_inserter(out), "Players on server:");
|
||||
if (connection->IsConsole())
|
||||
fmt::format_to(std::back_inserter(out), "\r\n");
|
||||
|
||||
+5
-5
@@ -361,7 +361,7 @@ void ConsoleTell(
|
||||
auto join_args = args;
|
||||
join_args.erase(join_args.begin(), join_args.begin() + 1);
|
||||
|
||||
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, Strings::Join(join_args, " ").c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), ChatChannel_Tell, 0, Strings::Join(join_args, " ").c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,7 +382,7 @@ void ConsoleBroadcast(
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, Strings::Join(args, " ").c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Broadcast, 0, Strings::Join(args, " ").c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,7 +403,7 @@ void ConsoleGMSay(
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, Strings::Join(args, " ").c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_GMSAY, 0, Strings::Join(args, " ").c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +457,7 @@ void ConsoleOOC(
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, Strings::Join(args, " ").c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_OOC, 0, Strings::Join(args, " ").c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,7 +478,7 @@ void ConsoleAuction(
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, Strings::Join(args, " ").c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Auction, 0, Strings::Join(args, " ").c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -146,6 +146,7 @@ std::vector<Reload> reload_types = {
|
||||
Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"},
|
||||
Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"},
|
||||
Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"},
|
||||
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
|
||||
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
|
||||
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
|
||||
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
void Disconnect() { if(connection && connection->Handle()) connection->Handle()->Disconnect(); }
|
||||
void SendMessage(const char *From, const char *Message);
|
||||
const std::shared_ptr<EQ::Net::ServertalkServerConnection> &GetConnection() const;
|
||||
inline bool IsConnected() const { return connection->Handle() ? connection->Handle()->IsConnected() : false; }
|
||||
|
||||
private:
|
||||
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
|
||||
|
||||
@@ -300,6 +300,8 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
||||
->SetLogPath(path.GetLogPath())
|
||||
->LoadLogDatabaseSettings();
|
||||
|
||||
LogSys.SetDiscordHandler(&WorldBoot::DiscordWebhookMessageHandler);
|
||||
|
||||
if (!ignore_db) {
|
||||
LogInfo("Checking Database Conversions");
|
||||
database.CheckDatabaseConversions();
|
||||
@@ -662,3 +664,18 @@ void WorldBoot::Shutdown()
|
||||
safe_delete(mutex);
|
||||
}
|
||||
|
||||
void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message)
|
||||
{
|
||||
if (UCSLink.IsConnected()) {
|
||||
auto pack = new ServerPacket(ServerOP_DiscordWebhookMessage, sizeof(DiscordWebhookMessage_Struct) + 1);
|
||||
auto *q = (DiscordWebhookMessage_Struct *) pack->pBuffer;
|
||||
|
||||
strn0cpy(q->message, message.c_str(), 2000);
|
||||
q->webhook_id = webhook_id;
|
||||
|
||||
UCSLink.SendPacket(pack);
|
||||
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include <string>
|
||||
#include "../common/types.h"
|
||||
#include "../common/discord/discord.h"
|
||||
|
||||
extern UCSConnection UCSLink;
|
||||
|
||||
class WorldBoot {
|
||||
public:
|
||||
@@ -16,6 +19,16 @@ public:
|
||||
static bool DatabaseLoadRoutines(int argc, char **argv);
|
||||
static void CheckForPossibleConfigurationIssues();
|
||||
static void Shutdown();
|
||||
static void SendDiscordMessage(int webhook_id, const std::string& message);
|
||||
static void DiscordWebhookMessageHandler(uint16 log_category, int webhook_id, const std::string &message)
|
||||
{
|
||||
std::string message_prefix = fmt::format(
|
||||
"[**{}**] **World** ",
|
||||
Logs::LogCategoryName[log_category]
|
||||
);
|
||||
|
||||
SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -311,7 +311,7 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
|
||||
strcpy(locked, "No");
|
||||
}
|
||||
|
||||
std::vector<char> out;
|
||||
auto out = fmt::memory_buffer();
|
||||
|
||||
if (connection->IsConsole()) {
|
||||
fmt::format_to(std::back_inserter(out), "World Locked: {}\r\n", locked);
|
||||
|
||||
@@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/content/world_content_service.h"
|
||||
#include "../common/repositories/player_event_logs_repository.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/patches/patches.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern GroupLFPList LFPGroupList;
|
||||
@@ -1296,6 +1297,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadOpcodes: {
|
||||
ReloadAllPatches();
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZDialogueWindow:
|
||||
case ServerOP_CZLDoNUpdate:
|
||||
case ServerOP_CZMarquee:
|
||||
|
||||
@@ -32,7 +32,6 @@ SET(zone_sources
|
||||
embparser.cpp
|
||||
embparser_api.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
encounter.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
@@ -77,7 +76,6 @@ SET(zone_sources
|
||||
lua_spell.cpp
|
||||
lua_stat_bonuses.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
fearpath.cpp
|
||||
@@ -186,7 +184,6 @@ SET(zone_headers
|
||||
dynamic_zone.h
|
||||
embparser.h
|
||||
embperl.h
|
||||
embxs.h
|
||||
encounter.h
|
||||
entity.h
|
||||
errmsg.h
|
||||
@@ -231,7 +228,6 @@ SET(zone_headers
|
||||
lua_stat_bonuses.h
|
||||
map.h
|
||||
masterentity.h
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
mob_movement_manager.h
|
||||
|
||||
+11
-10
@@ -1320,7 +1320,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
timer_duration = 0;
|
||||
}
|
||||
|
||||
if (!IsCastWhileInvis(rank->spell))
|
||||
if (!IsCastWhileInvisibleSpell(rank->spell))
|
||||
CommonBreakInvisible();
|
||||
|
||||
if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
|
||||
@@ -1333,7 +1333,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
target_id = GetPetID();
|
||||
|
||||
// extra handling for cast_not_standing spells
|
||||
if (!IgnoreCastingRestriction(rank->spell)) {
|
||||
if (!IsCastNotStandingSpell(rank->spell)) {
|
||||
if (GetAppearance() == eaSitting) // we need to stand!
|
||||
SetAppearance(eaStanding, false);
|
||||
|
||||
@@ -1398,27 +1398,28 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) {
|
||||
|
||||
void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) {
|
||||
for (auto &iter : aa_ranks) {
|
||||
AA::Ability *ability = zone->GetAlternateAdvancementAbility(iter.first);
|
||||
auto ability = zone->GetAlternateAdvancementAbility(iter.first);
|
||||
if (ability && aa_id == ability->id) {
|
||||
if (iter.second.second > 0) {
|
||||
iter.second.second -= 1;
|
||||
|
||||
if (iter.second.second == 0) {
|
||||
if (IsClient()) {
|
||||
AA::Rank *r = ability->GetRankByPointsSpent(iter.second.first);
|
||||
if (r) {
|
||||
CastToClient()->GetEPP().expended_aa += r->cost;
|
||||
}
|
||||
}
|
||||
if (IsClient()) {
|
||||
auto c = CastToClient();
|
||||
|
||||
auto r = ability->GetRankByPointsSpent(iter.second.first);
|
||||
if (r) {
|
||||
c->GetEPP().expended_aa += r->cost;
|
||||
}
|
||||
|
||||
c->RemoveExpendedAA(ability->first_rank_id);
|
||||
}
|
||||
|
||||
aa_ranks.erase(iter.first);
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
Client *c = CastToClient();
|
||||
auto c = CastToClient();
|
||||
c->SaveAA();
|
||||
c->SendAlternateAdvancementPoints();
|
||||
}
|
||||
|
||||
+3
-15
@@ -21,22 +21,10 @@
|
||||
#include "masterentity.h"
|
||||
#include "aa_ability.h"
|
||||
|
||||
AA::Rank *AA::Ability::GetMaxRank() {
|
||||
if(!first)
|
||||
return nullptr;
|
||||
|
||||
Rank *current = first;
|
||||
while(current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) {
|
||||
if(current_level == 0)
|
||||
return nullptr;
|
||||
|
||||
|
||||
if(!first)
|
||||
return nullptr;
|
||||
|
||||
@@ -65,6 +53,6 @@ int AA::Ability::GetMaxLevel(Mob *who) {
|
||||
max_level++;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
|
||||
return max_level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ public:
|
||||
Ability() { }
|
||||
~Ability() { }
|
||||
|
||||
Rank *GetMaxRank();
|
||||
Rank *GetRankByPointsSpent(int current_level);
|
||||
int GetMaxLevel(Mob *who);
|
||||
|
||||
|
||||
+1
-1
@@ -1161,7 +1161,7 @@ bool Mob::CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarge
|
||||
//offensive spell aggro
|
||||
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
|
||||
{
|
||||
if (NoDetrimentalSpellAggro(spell_id))
|
||||
if (IsNoDetrimentalSpellAggroSpell(spell_id))
|
||||
return 0;
|
||||
|
||||
int32 AggroAmount = 0;
|
||||
|
||||
+77
-69
@@ -160,7 +160,7 @@ int Mob::compute_tohit(EQ::skills::SkillType skillinuse)
|
||||
if (IsNPC())
|
||||
tohit += CastToNPC()->GetAccuracyRating();
|
||||
if (IsClient()) {
|
||||
double reduction = CastToClient()->m_pp.intoxication / 2.0;
|
||||
double reduction = CastToClient()->GetIntoxication() / 2.0;
|
||||
if (reduction > 20.0) {
|
||||
reduction = std::min((110 - reduction) / 100.0, 1.0);
|
||||
tohit = reduction * static_cast<double>(tohit);
|
||||
@@ -256,7 +256,7 @@ int Mob::compute_defense()
|
||||
defense += CastToNPC()->GetAvoidanceRating();
|
||||
|
||||
if (IsClient()) {
|
||||
double reduction = CastToClient()->m_pp.intoxication / 2.0;
|
||||
double reduction = CastToClient()->GetIntoxication() / 2.0;
|
||||
if (reduction > 20.0) {
|
||||
reduction = std::min((110 - reduction) / 100.0, 1.0);
|
||||
defense = reduction * static_cast<double>(defense);
|
||||
@@ -1473,7 +1473,7 @@ bool Mob::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
SetTarget(other);
|
||||
}
|
||||
|
||||
LogCombatDetail("Attacking [{}] with hand [{}] [{}]", other ? other->GetName() : "nullptr", Hand, bRiposte ? "this is a riposte" : "");
|
||||
LogCombatDetail("Attacking [{}] with hand [{}] [{}]", other->GetName(), Hand, bRiposte ? "this is a riposte" : "");
|
||||
|
||||
if (
|
||||
(IsCasting() && GetClass() != BARD && !IsFromSpell)
|
||||
@@ -2110,14 +2110,16 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
|
||||
//Check that we can attack before we calc heading and face our target
|
||||
if (!IsAttackAllowed(other)) {
|
||||
if (GetOwnerID())
|
||||
if (GetOwnerID()) {
|
||||
SayString(NOT_LEGAL_TARGET);
|
||||
if (other) {
|
||||
if (other->IsClient())
|
||||
other->CastToClient()->RemoveXTarget(this, false);
|
||||
RemoveFromHateList(other);
|
||||
LogCombat("I am not allowed to attack [{}]", other->GetName());
|
||||
}
|
||||
|
||||
if (other->IsClient()) {
|
||||
other->CastToClient()->RemoveXTarget(this, false);
|
||||
}
|
||||
|
||||
RemoveFromHateList(other);
|
||||
LogCombat("I am not allowed to attack [{}]", other->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2131,17 +2133,19 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
my_hit.skill = static_cast<EQ::skills::SkillType>(GetPrimSkill());
|
||||
OffHandAtk(false);
|
||||
}
|
||||
|
||||
if (Hand == EQ::invslot::slotSecondary) {
|
||||
my_hit.skill = static_cast<EQ::skills::SkillType>(GetSecSkill());
|
||||
OffHandAtk(true);
|
||||
}
|
||||
|
||||
//figure out what weapon they are using, if any
|
||||
const EQ::ItemData* weapon = nullptr;
|
||||
if (Hand == EQ::invslot::slotPrimary && equipment[EQ::invslot::slotPrimary] > 0)
|
||||
const EQ::ItemData *weapon = nullptr;
|
||||
if (Hand == EQ::invslot::slotPrimary && equipment[EQ::invslot::slotPrimary] > 0) {
|
||||
weapon = database.GetItem(equipment[EQ::invslot::slotPrimary]);
|
||||
else if (equipment[EQ::invslot::slotSecondary])
|
||||
} else if (equipment[EQ::invslot::slotSecondary]) {
|
||||
weapon = database.GetItem(equipment[EQ::invslot::slotSecondary]);
|
||||
}
|
||||
|
||||
//We dont factor much from the weapon into the attack.
|
||||
//Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons
|
||||
@@ -2154,34 +2158,34 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
}
|
||||
|
||||
switch (weapon->ItemType) {
|
||||
case EQ::item::ItemType1HSlash:
|
||||
my_hit.skill = EQ::skills::Skill1HSlashing;
|
||||
break;
|
||||
case EQ::item::ItemType2HSlash:
|
||||
my_hit.skill = EQ::skills::Skill2HSlashing;
|
||||
break;
|
||||
case EQ::item::ItemType1HPiercing:
|
||||
my_hit.skill = EQ::skills::Skill1HPiercing;
|
||||
break;
|
||||
case EQ::item::ItemType2HPiercing:
|
||||
my_hit.skill = EQ::skills::Skill2HPiercing;
|
||||
break;
|
||||
case EQ::item::ItemType1HBlunt:
|
||||
my_hit.skill = EQ::skills::Skill1HBlunt;
|
||||
break;
|
||||
case EQ::item::ItemType2HBlunt:
|
||||
my_hit.skill = EQ::skills::Skill2HBlunt;
|
||||
break;
|
||||
case EQ::item::ItemTypeBow:
|
||||
my_hit.skill = EQ::skills::SkillArchery;
|
||||
break;
|
||||
case EQ::item::ItemTypeLargeThrowing:
|
||||
case EQ::item::ItemTypeSmallThrowing:
|
||||
my_hit.skill = EQ::skills::SkillThrowing;
|
||||
break;
|
||||
default:
|
||||
my_hit.skill = EQ::skills::SkillHandtoHand;
|
||||
break;
|
||||
case EQ::item::ItemType1HSlash:
|
||||
my_hit.skill = EQ::skills::Skill1HSlashing;
|
||||
break;
|
||||
case EQ::item::ItemType2HSlash:
|
||||
my_hit.skill = EQ::skills::Skill2HSlashing;
|
||||
break;
|
||||
case EQ::item::ItemType1HPiercing:
|
||||
my_hit.skill = EQ::skills::Skill1HPiercing;
|
||||
break;
|
||||
case EQ::item::ItemType2HPiercing:
|
||||
my_hit.skill = EQ::skills::Skill2HPiercing;
|
||||
break;
|
||||
case EQ::item::ItemType1HBlunt:
|
||||
my_hit.skill = EQ::skills::Skill1HBlunt;
|
||||
break;
|
||||
case EQ::item::ItemType2HBlunt:
|
||||
my_hit.skill = EQ::skills::Skill2HBlunt;
|
||||
break;
|
||||
case EQ::item::ItemTypeBow:
|
||||
my_hit.skill = EQ::skills::SkillArchery;
|
||||
break;
|
||||
case EQ::item::ItemTypeLargeThrowing:
|
||||
case EQ::item::ItemTypeSmallThrowing:
|
||||
my_hit.skill = EQ::skills::SkillThrowing;
|
||||
break;
|
||||
default:
|
||||
my_hit.skill = EQ::skills::SkillHandtoHand;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2194,6 +2198,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
if (!mob) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mob->IsNPC() && mob->CastToNPC()->IsGuard()) {
|
||||
float distance = Distance(other->GetPosition(), mob->GetPosition());
|
||||
if ((mob->CheckLosFN(other) || mob->CheckLosFN(this)) && distance <= 70) {
|
||||
@@ -2910,19 +2915,17 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
||||
Mob* targetmob = GetTarget();
|
||||
bool on_hatelist = CheckAggro(other);
|
||||
|
||||
if (other) {
|
||||
AddRampage(other);
|
||||
if (on_hatelist) { // odd reason, if you're not on the hate list, subtlety etc don't apply!
|
||||
// Spell Casting Subtlety etc
|
||||
int64 hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod;
|
||||
AddRampage(other);
|
||||
if (on_hatelist) { // odd reason, if you're not on the hate list, subtlety etc don't apply!
|
||||
// Spell Casting Subtlety etc
|
||||
int64 hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod;
|
||||
|
||||
if (hatemod < 1)
|
||||
hatemod = 1;
|
||||
hate = ((hate * (hatemod)) / 100);
|
||||
}
|
||||
else {
|
||||
hate += 100; // 100 bonus initial aggro
|
||||
}
|
||||
if (hatemod < 1)
|
||||
hatemod = 1;
|
||||
hate = ((hate * (hatemod)) / 100);
|
||||
}
|
||||
else {
|
||||
hate += 100; // 100 bonus initial aggro
|
||||
}
|
||||
|
||||
// Pet that is /pet hold on will not add to their hate list if they're not engaged
|
||||
@@ -2955,7 +2958,7 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
||||
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
|
||||
return;
|
||||
|
||||
if (IsValidSpell(spell_id) && NoDetrimentalSpellAggro(spell_id))
|
||||
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id))
|
||||
return;
|
||||
|
||||
if (other == myowner)
|
||||
@@ -2999,29 +3002,26 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
||||
|
||||
// if other is a bot, add the bots client to the hate list
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
while (other->IsBot()) {
|
||||
|
||||
if (other->IsBot()) {
|
||||
auto other_ = other->CastToBot();
|
||||
|
||||
if (!other_ || !other_->GetBotOwner()) {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
auto owner_ = other_->GetBotOwner()->CastToClient();
|
||||
if (!owner_ || owner_->IsDead() ||
|
||||
!owner_->InZone()) { // added isdead and inzone checks to avoid issues in AddAutoXTarget(...) below
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner_->GetFeigned()) {
|
||||
AddFeignMemory(owner_);
|
||||
}
|
||||
else if (!hate_list.IsEntOnHateList(owner_)) {
|
||||
|
||||
hate_list.AddEntToHateList(owner_, 0, 0, false, true);
|
||||
owner_->AddAutoXTarget(this); // this was being called on dead/out-of-zone clients
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3883,9 +3883,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
damage = ReduceAllDamage(damage);
|
||||
TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);
|
||||
|
||||
if (skill_used)
|
||||
CheckNumHitsRemaining(NumHit::IncomingHitSuccess);
|
||||
|
||||
CheckNumHitsRemaining(NumHit::IncomingHitSuccess);
|
||||
}
|
||||
else {
|
||||
int64 origdmg = damage;
|
||||
@@ -4449,14 +4447,24 @@ void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id)
|
||||
}
|
||||
}
|
||||
else { // normal heals
|
||||
FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
|
||||
YOU_HEALED, caster->GetCleanName(), itoa(acthealed));
|
||||
// Message to caster
|
||||
if (caster->IsClient()) {
|
||||
caster->FilteredMessageString(caster, Chat::NonMelee,
|
||||
FilterSpellDamage, YOU_HEAL, GetCleanName(),
|
||||
itoa(acthealed));
|
||||
}
|
||||
|
||||
caster->FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
|
||||
YOU_HEAL, GetCleanName(), itoa(acthealed));
|
||||
// Message to target
|
||||
if (IsClient() && caster != this) {
|
||||
FilteredMessageString(caster, Chat::NonMelee,
|
||||
FilterSpellDamage, YOU_HEALED, caster->GetCleanName(),
|
||||
itoa(acthealed));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (CastToClient()->GetFilter(FilterHealOverTime) != (FilterShowSelfOnly || FilterHide)) {
|
||||
} else if (
|
||||
CastToClient()->GetFilter(FilterHealOverTime) != FilterShowSelfOnly ||
|
||||
CastToClient()->GetFilter(FilterHealOverTime) != FilterHide
|
||||
) {
|
||||
Message(Chat::NonMelee, "You have been healed for %d points of damage.", acthealed);
|
||||
}
|
||||
}
|
||||
|
||||
+395
-230
@@ -58,16 +58,10 @@ void Mob::CalcBonuses()
|
||||
void NPC::CalcBonuses()
|
||||
{
|
||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||
if (RuleB(NPC, UseItemBonusesForNonPets)) {
|
||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||
|
||||
if (GetOwner() || RuleB(NPC, UseItemBonusesForNonPets)) {
|
||||
CalcItemBonuses(&itembonuses);
|
||||
}
|
||||
else {
|
||||
if (GetOwner()) {
|
||||
memset(&itembonuses, 0, sizeof(StatBonuses));
|
||||
CalcItemBonuses(&itembonuses);
|
||||
}
|
||||
}
|
||||
|
||||
// This has to happen last, so we actually take the item bonuses into account.
|
||||
Mob::CalcBonuses();
|
||||
@@ -152,18 +146,7 @@ void Mob::CalcItemBonuses(StatBonuses* b) {
|
||||
int16 i;
|
||||
|
||||
for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_SKILL_END; i++) {
|
||||
const EQ::ItemInstance* inst = nullptr;
|
||||
if (IsOfClientBotMerc()) {
|
||||
inst = GetInv().GetItem(i);
|
||||
} else {
|
||||
const auto* item = CastToNPC()->GetItem(i);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inst = database.CreateItem(item->item_id);
|
||||
}
|
||||
|
||||
const EQ::ItemInstance* inst = GetInv().GetItem(i);
|
||||
if (!inst) {
|
||||
continue;
|
||||
}
|
||||
@@ -268,7 +251,7 @@ void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_a
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_tribute && !inst->IsEquipable(GetBaseRace(), GetClass())) {
|
||||
if (IsClient() && !is_tribute && !inst->IsEquipable(GetBaseRace(), GetClass())) {
|
||||
if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink) {
|
||||
return;
|
||||
}
|
||||
@@ -276,14 +259,14 @@ void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_a
|
||||
|
||||
const auto current_level = GetLevel();
|
||||
|
||||
if (current_level < inst->GetItemRequiredLevel(true)) {
|
||||
if (IsClient() && current_level < inst->GetItemRequiredLevel(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_ammo_item) {
|
||||
const auto recommended_level = is_augment ? recommended_level_override : inst->GetItemRecommendedLevel(true);
|
||||
|
||||
if (current_level >= recommended_level) {
|
||||
if (IsNPC() || current_level >= recommended_level) {
|
||||
b->HP += item->HP;
|
||||
b->Mana += item->Mana;
|
||||
b->Endurance += item->Endur;
|
||||
@@ -1225,6 +1208,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
newbon->HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] += base_value;
|
||||
else
|
||||
newbon->HitChanceEffect[limit_value] += base_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_ProcOnKillShot:
|
||||
@@ -1405,6 +1389,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DamageModifier: {
|
||||
@@ -1651,7 +1636,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
}
|
||||
|
||||
case SE_Illusion:
|
||||
newbon->Illusion = true;
|
||||
newbon->Illusion = rank.spell;
|
||||
break;
|
||||
|
||||
case SE_IllusionPersistence:
|
||||
@@ -2115,10 +2100,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
//Use AISpellEffects
|
||||
else {
|
||||
spell_effect_id = effect_id;
|
||||
effect_value = se_base;
|
||||
limit_value = se_limit;
|
||||
max_value = se_max;
|
||||
i = (EFFECT_COUNT - 1); // AISpellEffects do a single pass
|
||||
effect_value = se_base;
|
||||
limit_value = se_limit;
|
||||
max_value = se_max;
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
//Non-Focused Effect to modify incoming spell damage by resist type.
|
||||
if (spell_effect_id == SE_FcSpellVulnerability) {
|
||||
ModVulnerability(limit_value, effect_value);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch (spell_effect_id)
|
||||
@@ -2169,7 +2161,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
}
|
||||
else if ((effect_value - 100) < 0) { // Slow
|
||||
int real_slow_value = (100 - effect_value) * -1;
|
||||
real_slow_value -= ((real_slow_value * GetSlowMitigation()/100));
|
||||
real_slow_value -= (real_slow_value * GetSlowMitigation()/100);
|
||||
if (real_slow_value < new_bonus->haste)
|
||||
new_bonus->haste = real_slow_value;
|
||||
}
|
||||
@@ -2186,7 +2178,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
}
|
||||
else if ((effect_value - 100) < 0) { // Slow
|
||||
int real_slow_value = (100 - effect_value) * -1;
|
||||
real_slow_value -= ((real_slow_value * GetSlowMitigation()/100));
|
||||
real_slow_value -= (real_slow_value * GetSlowMitigation()/100);
|
||||
if (real_slow_value < new_bonus->hastetype2)
|
||||
new_bonus->hastetype2 = real_slow_value;
|
||||
}
|
||||
@@ -2196,7 +2188,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
case SE_AttackSpeed3:
|
||||
{
|
||||
if (effect_value < 0){ //Slow
|
||||
effect_value -= ((effect_value * GetSlowMitigation()/100));
|
||||
effect_value -= (effect_value * GetSlowMitigation()/100);
|
||||
if (effect_value < new_bonus->hastetype3)
|
||||
new_bonus->hastetype3 = effect_value;
|
||||
}
|
||||
@@ -2220,7 +2212,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
effect_value = effect_value * -1;
|
||||
|
||||
if (effect_value > 0 && effect_value > new_bonus->inhibitmelee) {
|
||||
effect_value -= ((effect_value * GetSlowMitigation()/100));
|
||||
effect_value -= (effect_value * GetSlowMitigation()/100);
|
||||
if (effect_value > new_bonus->inhibitmelee)
|
||||
new_bonus->inhibitmelee = effect_value;
|
||||
}
|
||||
@@ -3201,8 +3193,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_NegateAttacks:
|
||||
{
|
||||
if (!new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] ||
|
||||
((new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] && new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT]) && (new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] < max_value))){
|
||||
if (
|
||||
!new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] ||
|
||||
(
|
||||
new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] &&
|
||||
new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] < max_value
|
||||
)
|
||||
) {
|
||||
new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] = 1;
|
||||
new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT] = buffslot;
|
||||
new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] = max_value;
|
||||
@@ -3520,6 +3517,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
case SE_DoubleRiposte:
|
||||
{
|
||||
new_bonus->DoubleRiposte += effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_GiveDoubleRiposte:
|
||||
@@ -3805,6 +3803,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_PC_Pet_Rampage: {
|
||||
@@ -4063,15 +4062,6 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
case SE_TrapCircumvention:
|
||||
new_bonus->TrapCircumvention += effect_value;
|
||||
break;
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
//Non-Focused Effect to modify incoming spell damage by resist type.
|
||||
case SE_FcSpellVulnerability:
|
||||
ModVulnerability(limit_value, effect_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4317,11 +4307,11 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff
|
||||
case SE_SpellResistReduction:
|
||||
return focusResistRate;
|
||||
case SE_Fc_ResistIncoming:
|
||||
focusFcResistIncoming;
|
||||
return focusFcResistIncoming;
|
||||
case SE_Fc_Amplify_Mod:
|
||||
focusFcAmplifyMod;
|
||||
return focusFcAmplifyMod;
|
||||
case SE_Fc_Amplify_Amt:
|
||||
focusFcAmplifyAmt;
|
||||
return focusFcAmplifyAmt;
|
||||
case SE_SpellHateMod:
|
||||
return focusSpellHateMod;
|
||||
case SE_ReduceReuseTimer:
|
||||
@@ -4488,12 +4478,9 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
|
||||
case SE_AttackSpeed3:
|
||||
{
|
||||
if (effect_value > 0) {
|
||||
if (negate_spellbonus) { spellbonuses.hastetype3 = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.hastetype3 = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.hastetype3 = effect_value; }
|
||||
|
||||
}
|
||||
if (negate_spellbonus) { spellbonuses.hastetype3 = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.hastetype3 = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.hastetype3 = effect_value; }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4585,29 +4572,36 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
|
||||
case SE_AllStats:
|
||||
{
|
||||
if (negate_spellbonus) { spellbonuses.STR = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.DEX = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.AGI = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.STA = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.INT = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.WIS = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.CHA = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.STR = effect_value;
|
||||
spellbonuses.DEX = effect_value;
|
||||
spellbonuses.AGI = effect_value;
|
||||
spellbonuses.STA = effect_value;
|
||||
spellbonuses.INT = effect_value;
|
||||
spellbonuses.WIS = effect_value;
|
||||
spellbonuses.CHA = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) { itembonuses.STR = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.DEX = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.AGI = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.STA = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.INT = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.WIS = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.CHA = effect_value; }
|
||||
if (negate_itembonus) {
|
||||
itembonuses.STR = effect_value;
|
||||
itembonuses.DEX = effect_value;
|
||||
itembonuses.AGI = effect_value;
|
||||
itembonuses.STA = effect_value;
|
||||
itembonuses.INT = effect_value;
|
||||
itembonuses.WIS = effect_value;
|
||||
itembonuses.CHA = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.STR = effect_value;
|
||||
aabonuses.DEX = effect_value;
|
||||
aabonuses.AGI = effect_value;
|
||||
aabonuses.STA = effect_value;
|
||||
aabonuses.INT = effect_value;
|
||||
aabonuses.WIS = effect_value;
|
||||
aabonuses.CHA = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) { aabonuses.STR = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.DEX = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.AGI = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.STA = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.INT = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.WIS = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.CHA = effect_value; }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4643,23 +4637,30 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
|
||||
case SE_ResistAll:
|
||||
{
|
||||
if (negate_spellbonus) { spellbonuses.MR = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.DR = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.PR = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.CR = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.FR = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MR = effect_value;
|
||||
spellbonuses.DR = effect_value;
|
||||
spellbonuses.PR = effect_value;
|
||||
spellbonuses.CR = effect_value;
|
||||
spellbonuses.FR = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) { aabonuses.MR = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.DR = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.PR = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.CR = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FR = effect_value; }
|
||||
if (negate_aabonus) {
|
||||
aabonuses.MR = effect_value;
|
||||
aabonuses.DR = effect_value;
|
||||
aabonuses.PR = effect_value;
|
||||
aabonuses.CR = effect_value;
|
||||
aabonuses.FR = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.MR = effect_value;
|
||||
itembonuses.DR = effect_value;
|
||||
itembonuses.PR = effect_value;
|
||||
itembonuses.CR = effect_value;
|
||||
itembonuses.FR = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) { itembonuses.MR = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.DR = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.PR = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.CR = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FR = effect_value; }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4796,23 +4797,29 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
|
||||
case SE_AllInstrumentMod:
|
||||
{
|
||||
if (negate_spellbonus) { spellbonuses.singingMod = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.brassMod = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.percussionMod = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.windMod = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.stringedMod = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.singingMod = effect_value;
|
||||
spellbonuses.brassMod = effect_value;
|
||||
spellbonuses.percussionMod = effect_value;
|
||||
spellbonuses.windMod = effect_value;
|
||||
spellbonuses.stringedMod = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) { itembonuses.singingMod = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.brassMod = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.percussionMod = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.windMod = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.stringedMod = effect_value; }
|
||||
if (negate_itembonus) {
|
||||
itembonuses.singingMod = effect_value;
|
||||
itembonuses.brassMod = effect_value;
|
||||
itembonuses.percussionMod = effect_value;
|
||||
itembonuses.windMod = effect_value;
|
||||
itembonuses.stringedMod = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) { aabonuses.singingMod = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.brassMod = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.percussionMod = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.windMod = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.stringedMod = effect_value; }
|
||||
if (negate_aabonus) {
|
||||
aabonuses.singingMod = effect_value;
|
||||
aabonuses.brassMod = effect_value;
|
||||
aabonuses.percussionMod = effect_value;
|
||||
aabonuses.windMod = effect_value;
|
||||
aabonuses.stringedMod = effect_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4823,8 +4830,11 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_ResistFearChance:
|
||||
if (negate_spellbonus) { spellbonuses.Fearless = false; }
|
||||
if (negate_spellbonus) { spellbonuses.ResistFearChance = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Fearless = false;
|
||||
spellbonuses.ResistFearChance = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) { aabonuses.ResistFearChance = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.ResistFearChance = effect_value; }
|
||||
break;
|
||||
@@ -5001,12 +5011,21 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_CriticalSpellChance:
|
||||
if (negate_spellbonus) { spellbonuses.CriticalSpellChance = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.SpellCritDmgIncrease = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.CriticalSpellChance = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.SpellCritDmgIncrease = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.CriticalSpellChance = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.SpellCritDmgIncrease = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.CriticalSpellChance = effect_value;
|
||||
spellbonuses.SpellCritDmgIncrease = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.CriticalSpellChance = effect_value;
|
||||
aabonuses.SpellCritDmgIncrease = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.CriticalSpellChance = effect_value;
|
||||
itembonuses.SpellCritDmgIncrease = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_SpellCritDmgIncrease:
|
||||
@@ -5168,35 +5187,53 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
}
|
||||
|
||||
case SE_NegateAttacks:
|
||||
if (negate_spellbonus) { spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] = effect_value;
|
||||
spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_MitigateMeleeDamage:
|
||||
if (negate_spellbonus) { spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value;
|
||||
spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_MeleeThresholdGuard:
|
||||
if (negate_spellbonus) { spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) { spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value;
|
||||
spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1;
|
||||
spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_SpellThresholdGuard:
|
||||
if (negate_spellbonus) { spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) { spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value;
|
||||
spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1;
|
||||
spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_MitigateSpellDamage:
|
||||
if (negate_spellbonus) { spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value;
|
||||
spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_MitigateDotDamage:
|
||||
if (negate_spellbonus) { spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value;
|
||||
spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_ManaAbsorbPercentDamage:
|
||||
@@ -5204,8 +5241,11 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_Endurance_Absorb_Pct_Damage:
|
||||
if (negate_spellbonus) { spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_DRAIN_PER_HP] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] = effect_value;
|
||||
spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_DRAIN_PER_HP] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_ShieldBlock:
|
||||
@@ -5316,11 +5356,6 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough:
|
||||
if (negate_spellbonus) { spellbonuses.StrikeThrough = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.StrikeThrough = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.StrikeThrough = effect_value; }
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough2:
|
||||
if (negate_spellbonus) { spellbonuses.StrikeThrough = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.StrikeThrough = effect_value; }
|
||||
@@ -5433,8 +5468,10 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
{
|
||||
for (int e = 0; e < MAX_RESISTABLE_EFFECTS * 2; e += 2)
|
||||
{
|
||||
if (negate_spellbonus) { spellbonuses.SEResist[e] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.SEResist[e + 1] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.SEResist[e] = effect_value;
|
||||
spellbonuses.SEResist[e + 1] = effect_value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5458,12 +5495,21 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_SlayUndead:
|
||||
if (negate_spellbonus) { spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value;
|
||||
spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value;
|
||||
itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value;
|
||||
aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_DoubleRangedAttack:
|
||||
@@ -5513,9 +5559,12 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_ImprovedTaunt:
|
||||
if (negate_spellbonus) { spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL] = effect_value;
|
||||
spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD] = effect_value;
|
||||
spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_FrenziedDevastation:
|
||||
@@ -5525,18 +5574,27 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_Root:
|
||||
if (negate_spellbonus) { spellbonuses.Root[SBIndex::ROOT_EXISTS] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Root[SBIndex::ROOT_EXISTS] = effect_value;
|
||||
spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Rune:
|
||||
if (negate_spellbonus) { spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] = effect_value;
|
||||
spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_AbsorbMagicAtt:
|
||||
if (negate_spellbonus) { spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] = -1; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] = effect_value;
|
||||
spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Berserk:
|
||||
@@ -5564,57 +5622,111 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_HeadShot:
|
||||
if (negate_spellbonus) { spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_HeadShotLevel:
|
||||
if (negate_spellbonus) { spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Assassinate:
|
||||
if (negate_spellbonus) { spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_AssassinateLevel:
|
||||
if (negate_spellbonus) { spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
itembonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_FinishingBlow:
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value;
|
||||
itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_FinishingBlowLvl:
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value;
|
||||
itembonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Sanctuary:
|
||||
@@ -5653,41 +5765,76 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_Melee_Damage_Position_Mod:
|
||||
if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Damage_Taken_Position_Mod:
|
||||
if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value;
|
||||
itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Melee_Damage_Position_Amt:
|
||||
if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_Damage_Taken_Position_Amt:
|
||||
if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; }
|
||||
break;
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value;
|
||||
itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_DS_Mitigation_Amount:
|
||||
if (negate_spellbonus) { spellbonuses.DS_Mitigation_Amount = effect_value; }
|
||||
@@ -5714,21 +5861,39 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_PC_Pet_Rampage:
|
||||
if (negate_spellbonus) { spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SE_PC_Pet_AE_Rampage:
|
||||
if (negate_spellbonus) { spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; }
|
||||
if (negate_spellbonus) { spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_itembonus) { itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_aabonus) { aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; }
|
||||
if (negate_spellbonus) {
|
||||
spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_itembonus) {
|
||||
itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
if (negate_aabonus) {
|
||||
aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value;
|
||||
aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -5783,26 +5948,26 @@ void Mob::CalcHeroicBonuses(StatBonuses* newbon)
|
||||
|
||||
void Mob::SetHeroicWisBonuses(StatBonuses* n)
|
||||
{
|
||||
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0;
|
||||
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0;
|
||||
n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0;
|
||||
n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0;
|
||||
n->HealAmt += GetHeroicWIS() * RuleR(Character, HeroicWisdomIncreaseHealAmtMultiplier);
|
||||
|
||||
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
|
||||
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0;
|
||||
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0;
|
||||
n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0;
|
||||
n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0;
|
||||
n->HealAmt += GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisHealAmt);
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::SetHeroicIntBonuses(StatBonuses* n)
|
||||
{
|
||||
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0;
|
||||
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0;
|
||||
n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0;
|
||||
n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0;
|
||||
n->SpellDmg += GetHeroicINT() * RuleR(Character, HeroicIntelligenceIncreaseSpellDmgMultiplier);
|
||||
|
||||
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
|
||||
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0;
|
||||
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0;
|
||||
n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0;
|
||||
n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0;
|
||||
n->SpellDmg += GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntSpellDmg);
|
||||
}
|
||||
}
|
||||
|
||||
+40
-59
@@ -259,7 +259,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
|
||||
const SPDat_Spell_Struct& spell = spells[buffs[j1].spellid];
|
||||
|
||||
if (int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); NimbusEffect && !IsNimbusEffectActive(NimbusEffect)) {
|
||||
if (int NimbusEffect = GetSpellNimbusEffect(buffs[j1].spellid); NimbusEffect && !IsNimbusEffectActive(NimbusEffect)) {
|
||||
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
|
||||
}
|
||||
|
||||
@@ -422,12 +422,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
}
|
||||
|
||||
cur_end = max_end;
|
||||
|
||||
// Safety Check to confirm we have a valid raid
|
||||
if (HasRaid() && !GetRaid()->IsRaidMember(GetBotOwner()->CastToClient())) {
|
||||
Bot::RemoveBotFromRaid(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Bot::~Bot() {
|
||||
@@ -1501,7 +1495,7 @@ bool Bot::LoadPet()
|
||||
}
|
||||
|
||||
MakePet(pet_spell_id, spells[pet_spell_id].teleport_zone, pet_name.c_str());
|
||||
if (!GetPet() || !GetPet()->IsNPC()) {
|
||||
if (!GetPet()->IsNPC()) {
|
||||
DeletePet();
|
||||
return false;
|
||||
}
|
||||
@@ -2413,6 +2407,10 @@ bool Bot::TrySecondaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* s_item) {
|
||||
s_itemdata = s_item->GetItem();
|
||||
}
|
||||
|
||||
if (!s_itemdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool use_fist = true;
|
||||
if (s_itemdata) {
|
||||
use_fist = false;
|
||||
@@ -2432,10 +2430,10 @@ bool Bot::TrySecondaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* s_item) {
|
||||
if (random < DualWieldProbability) { // Max 78% for DW chance
|
||||
Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary);
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
if (CanThisClassDoubleAttack() && CheckBotDoubleAttack() && tar->GetHP() > -10) {
|
||||
Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand
|
||||
}
|
||||
@@ -2453,33 +2451,33 @@ bool Bot::TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item) {
|
||||
|
||||
Attack(tar, EQ::invslot::slotPrimary);
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false);
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary);
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
if (CanThisClassDoubleAttack()) {
|
||||
|
||||
if (CheckBotDoubleAttack()) {
|
||||
Attack(tar, EQ::invslot::slotPrimary, true);
|
||||
}
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
if (GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) {
|
||||
|
||||
Attack(tar, EQ::invslot::slotPrimary, true);
|
||||
}
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
// quad attack, does this belong here??
|
||||
if (GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) {
|
||||
Attack(tar, EQ::invslot::slotPrimary, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
// Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack).
|
||||
if (int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance)) {
|
||||
|
||||
@@ -2488,12 +2486,12 @@ bool Bot::TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item) {
|
||||
MessageString(Chat::NPCFlurry, YOU_FLURRY);
|
||||
Attack(tar, EQ::invslot::slotPrimary, false);
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
Attack(tar, EQ::invslot::slotPrimary, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetTarget() || GetAppearance() == eaDead) { return false; }
|
||||
if (GetAppearance() == eaDead) { return false; }
|
||||
auto ExtraAttackChanceBonus =
|
||||
(spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] +
|
||||
aabonuses.ExtraAttackChance[0]);
|
||||
@@ -3303,11 +3301,16 @@ bool Bot::Spawn(Client* botCharacterOwner) {
|
||||
}
|
||||
|
||||
if (auto raid = entity_list.GetRaidByBotName(GetName())) {
|
||||
raid->VerifyRaid();
|
||||
SetRaidGrouped(true);
|
||||
// Safety Check to confirm we have a valid raid
|
||||
if (raid->IsRaidMember(GetBotOwner()->CastToClient())) {
|
||||
Bot::RemoveBotFromRaid(this);
|
||||
} else {
|
||||
raid->LearnMembers();
|
||||
SetRaidGrouped(true);
|
||||
}
|
||||
}
|
||||
else if (auto group = entity_list.GetGroupByMobName(GetName())) {
|
||||
group->VerifyGroup();
|
||||
group->LearnMembers();
|
||||
SetGrouped(true);
|
||||
}
|
||||
|
||||
@@ -3602,19 +3605,6 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) {
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color) {
|
||||
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
auto wc = (WearChange_Struct*)outapp->pBuffer;
|
||||
|
||||
wc->spawn_id = GetID();
|
||||
wc->material = material;
|
||||
wc->color.Color = color;
|
||||
wc->wear_slot_id = material_slot;
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
// Returns the item id that is in the bot inventory collection for the specified slot.
|
||||
EQ::ItemInstance* Bot::GetBotItem(uint16 slot_id) {
|
||||
EQ::ItemInstance* item = m_inv.GetItem(slot_id);
|
||||
@@ -3666,6 +3656,10 @@ void Bot::BotRemoveEquipItem(uint16 slot_id)
|
||||
|
||||
void Bot::BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database)
|
||||
{
|
||||
if (!inst) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (save_to_database) {
|
||||
if (!database.botdb.SaveItemBySlot(this, slot_id, inst)) {
|
||||
*error_message = BotDatabase::fail::SaveItemBySlot();
|
||||
@@ -4626,8 +4620,13 @@ return true;
|
||||
}
|
||||
|
||||
void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) {
|
||||
if (spell_id == 0)
|
||||
if (!from) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spell_id == 0) {
|
||||
spell_id = SPELL_UNKNOWN;
|
||||
}
|
||||
|
||||
//handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds
|
||||
if (attacked_timer.Check()) {
|
||||
@@ -4891,7 +4890,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max
|
||||
if (botweapon->ItemType == EQ::item::ItemTypeShield)
|
||||
hate += botweapon->AC;
|
||||
|
||||
hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100);
|
||||
hate = (hate * (100 + GetSpellFuriousBash(botweapon->Focus.Effect)) / 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5067,7 +5066,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
}
|
||||
}
|
||||
|
||||
if (taunting && target && target->IsNPC() && taunt_time) {
|
||||
if (taunting && target->IsNPC() && taunt_time) {
|
||||
if (GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) {
|
||||
BotGroupSay(
|
||||
this,
|
||||
@@ -5145,7 +5144,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
float HasteModifier = (GetHaste() * 0.01f);
|
||||
uint16 skill_to_use = -1;
|
||||
int bot_level = GetLevel();
|
||||
int reuse = (TauntReuseTime * 1000);
|
||||
int reuse = (TauntReuseTime * 1000); // Same as Bash and Kick
|
||||
bool did_attack = false;
|
||||
switch (GetClass()) {
|
||||
case WARRIOR:
|
||||
@@ -5205,7 +5204,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
if (GetWeaponDamage(target, GetBotItem(EQ::invslot::slotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQ::invslot::slotShoulders)) <= 0)
|
||||
dmg = DMG_INVULNERABLE;
|
||||
|
||||
reuse = (BashReuseTime * 1000);
|
||||
DoSpecialAttackDamage(target, EQ::skills::SkillBash, dmg, 0, -1, reuse);
|
||||
did_attack = true;
|
||||
}
|
||||
@@ -5232,7 +5230,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
|
||||
if (GetWeaponDamage(target, GetBotItem(EQ::invslot::slotFeet)) <= 0)
|
||||
dmg = DMG_INVULNERABLE;
|
||||
|
||||
reuse = (KickReuseTime * 1000);
|
||||
DoSpecialAttackDamage(target, EQ::skills::SkillKick, dmg, 0, -1, reuse);
|
||||
did_attack = true;
|
||||
}
|
||||
@@ -5539,7 +5536,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
|
||||
increase += 20;
|
||||
}
|
||||
|
||||
if (IsMezSpell(spell_id))
|
||||
if (IsMesmerizeSpell(spell_id))
|
||||
tic_inc += GetAA(aaMesmerizationMastery);
|
||||
|
||||
return (((duration * increase) / 100) + tic_inc);
|
||||
@@ -5857,16 +5854,6 @@ void Bot::GenerateSpecialAttacks() {
|
||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if (GetClass() == BARD) {
|
||||
if (!ApplyBardPulse(bardsong, this, bardsong_slot))
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
|
||||
stopLogic = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
|
||||
|
||||
if (
|
||||
@@ -6339,7 +6326,7 @@ void Bot::CalcRestState() {
|
||||
for (unsigned int j = 0; j < buff_count; j++) {
|
||||
if (IsValidSpell(buffs[j].spellid)) {
|
||||
if (IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
|
||||
if (!DetrimentalSpellAllowsRest(buffs[j].spellid))
|
||||
if (!IsRestAllowedSpell(buffs[j].spellid))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -6687,8 +6674,6 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband)
|
||||
|
||||
Mob* healer = nullptr;
|
||||
Mob* slower = nullptr;
|
||||
Mob* nuker = nullptr;
|
||||
Mob* doter = nullptr;
|
||||
|
||||
for (auto iter : group->members) {
|
||||
if (!iter)
|
||||
@@ -6804,10 +6789,6 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband)
|
||||
healer->CastToBot()->SetGroupHealer();
|
||||
if (slower && slower->IsBot())
|
||||
slower->CastToBot()->SetGroupSlower();
|
||||
if (nuker && nuker->IsBot())
|
||||
nuker->CastToBot()->SetGroupNuker();
|
||||
if (doter && doter->IsBot())
|
||||
doter->CastToBot()->SetGroupDoter();
|
||||
}
|
||||
|
||||
Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName) {
|
||||
@@ -6901,7 +6882,7 @@ void Bot::ProcessClientZoneChange(Client* botOwner) {
|
||||
else if (tempBot->HasGroup()) {
|
||||
Group* g = tempBot->GetGroup();
|
||||
if (g && g->IsGroupMember(botOwner)) {
|
||||
if (botOwner && botOwner->IsClient()) {
|
||||
if (botOwner->IsClient()) {
|
||||
// Modified to not only zone bots if you're the leader.
|
||||
// Also zone bots of the non-leader when they change zone.
|
||||
if (tempBot->GetBotOwnerCharacterID() == botOwner->CharacterID() && g->IsGroupMember(botOwner))
|
||||
|
||||
@@ -196,10 +196,8 @@ public:
|
||||
void SetAttackTimer() override;
|
||||
uint64 GetClassHPFactor();
|
||||
int64 CalcMaxHP() override;
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
|
||||
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
|
||||
void Camp(bool save_to_database = true);
|
||||
void SetTarget(Mob* mob) override;
|
||||
void Zone();
|
||||
|
||||
+31
-28
@@ -2526,9 +2526,17 @@ void bot_command_apply_poison(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
Bot *my_rogue_bot = nullptr;
|
||||
if (c->GetTarget() && c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID() && c->GetTarget()->CastToBot()->GetClass() == ROGUE) {
|
||||
my_rogue_bot = c->GetTarget()->CastToBot();
|
||||
auto t = c->GetTarget();
|
||||
|
||||
if (
|
||||
t &&
|
||||
t->IsBot() &&
|
||||
t->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID() &&
|
||||
t->GetClass() == ROGUE
|
||||
) {
|
||||
my_rogue_bot = t->CastToBot();
|
||||
}
|
||||
|
||||
if (!my_rogue_bot) {
|
||||
|
||||
c->Message(Chat::White, "You must target a rogue bot that you own to use this command!");
|
||||
@@ -2696,7 +2704,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, ab_arg.c_str(), sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
|
||||
if (ActionableBots::PopulateSBL(c, ab_arg, sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3582,14 +3590,13 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<int16> equipable_slot_list;
|
||||
std::vector<int16> equipable_slot_list;
|
||||
for (int16 equipable_slot = EQ::invslot::EQUIPMENT_BEGIN; equipable_slot <= EQ::invslot::EQUIPMENT_END; ++equipable_slot) {
|
||||
if (item_data->Slots & (1 << equipable_slot)) {
|
||||
equipable_slot_list.push_back(equipable_slot);
|
||||
equipable_slot_list.emplace_back(equipable_slot);
|
||||
}
|
||||
}
|
||||
|
||||
std::string msg;
|
||||
std::string text_link;
|
||||
|
||||
EQ::SayLinkEngine linker;
|
||||
@@ -3616,7 +3623,7 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
||||
bot_iter->GetCleanName()
|
||||
);
|
||||
|
||||
for (auto slot_iter : equipable_slot_list) {
|
||||
for (const auto& slot_iter : equipable_slot_list) {
|
||||
// needs more failure criteria - this should cover the bulk for now
|
||||
if (slot_iter == EQ::invslot::slotSecondary && item_data->Damage && !bot_iter->CanThisClassDualWield()) {
|
||||
continue;
|
||||
@@ -5124,8 +5131,6 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string error_message;
|
||||
|
||||
bool available_flag = false;
|
||||
if (!database.botdb.QueryNameAvailablity(bot_name, available_flag)) {
|
||||
c->Message(
|
||||
@@ -5559,8 +5564,6 @@ void bot_subcommand_bot_delete(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string error_message;
|
||||
|
||||
if (!my_bot->DeleteBot()) {
|
||||
c->Message(Chat::White, "Failed to delete '%s' due to database error", my_bot->GetCleanName());
|
||||
return;
|
||||
@@ -6407,19 +6410,20 @@ void bot_subcommand_bot_report(Client *c, const Seperator *sep)
|
||||
|
||||
std::string ab_type_arg = sep->arg[1];
|
||||
if (ab_type_arg.empty()) {
|
||||
if (c->GetTarget()) {
|
||||
if (c->GetTarget()->IsClient() && c->GetTarget()->CastToClient() == c)
|
||||
auto t = c->GetTarget();
|
||||
if (t && t->IsClient()) {
|
||||
if (t->CastToClient() == c) {
|
||||
ab_type_arg = "ownergroup";
|
||||
else if (c->GetTarget()->IsClient() && c->GetTarget()->CastToClient() != c)
|
||||
} else {
|
||||
ab_type_arg = "targetgroup";
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
ab_type_arg = "spawned";
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, ab_type_arg.c_str(), sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
|
||||
if (ActionableBots::PopulateSBL(c, ab_type_arg, sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
|
||||
return;
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
@@ -6959,7 +6963,6 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
if (ab_type == ActionableBots::ABT_All) {
|
||||
std::string query;
|
||||
if (toggle_helm) {
|
||||
if (!database.botdb.ToggleAllHelmAppearances(c->CharacterID()))
|
||||
c->Message(Chat::White, "%s", BotDatabase::fail::ToggleAllHelmAppearances());
|
||||
@@ -7327,7 +7330,7 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se
|
||||
|
||||
uint8 armor_type_value = 255;
|
||||
if (sep->IsNumber(1))
|
||||
armor_type_value = Strings::ToInt(armor_type_arg.c_str());
|
||||
armor_type_value = Strings::ToInt(armor_type_arg);
|
||||
|
||||
if (armor_type_value > ARMOR_TYPE_LAST) {
|
||||
c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST);
|
||||
@@ -7356,7 +7359,7 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se
|
||||
|
||||
float critical_ratio = CRITICAL_HP_RATIO_BASE;
|
||||
if (sep->IsNumber(2))
|
||||
critical_ratio = Strings::ToFloat(critical_arg.c_str());
|
||||
critical_ratio = Strings::ToFloat(critical_arg);
|
||||
else if (!critical_arg.compare("+"))
|
||||
critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) + HP_RATIO_DELTA;
|
||||
else if (!critical_arg.compare("-"))
|
||||
@@ -7393,7 +7396,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep)
|
||||
|
||||
uint8 armor_type_value = 255;
|
||||
if (sep->IsNumber(1))
|
||||
armor_type_value = Strings::ToInt(armor_type_arg.c_str());
|
||||
armor_type_value = Strings::ToInt(armor_type_arg);
|
||||
|
||||
if (armor_type_value > ARMOR_TYPE_LAST) {
|
||||
c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST);
|
||||
@@ -7422,7 +7425,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep)
|
||||
|
||||
float safe_ratio = SAFE_HP_RATIO_BASE;
|
||||
if (sep->IsNumber(2))
|
||||
safe_ratio = Strings::ToFloat(safe_arg.c_str());
|
||||
safe_ratio = Strings::ToFloat(safe_arg);
|
||||
else if (!safe_arg.compare("+"))
|
||||
safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) + HP_RATIO_DELTA;
|
||||
else if (!safe_arg.compare("-"))
|
||||
@@ -7536,7 +7539,7 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se
|
||||
uint32 hr_change_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S;
|
||||
|
||||
if (!change_interval_arg.empty()) {
|
||||
hr_change_interval_s = Strings::ToInt(change_interval_arg.c_str());
|
||||
hr_change_interval_s = Strings::ToInt(change_interval_arg);
|
||||
}
|
||||
else {
|
||||
hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS();
|
||||
@@ -7684,14 +7687,14 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
|
||||
hr_adaptive_targeting = true;
|
||||
if (!fast_heals_arg.compare("on"))
|
||||
hr_fast_heals = true;
|
||||
hr_interval_s = Strings::ToInt(interval_arg.c_str());
|
||||
hr_interval_s = Strings::ToInt(interval_arg);
|
||||
}
|
||||
else if (!casting_override_arg.compare("off")) {
|
||||
if (!adaptive_targeting_arg.compare("on"))
|
||||
hr_adaptive_targeting = true;
|
||||
if (!fast_heals_arg.compare("on"))
|
||||
hr_fast_heals = true;
|
||||
hr_interval_s = Strings::ToInt(interval_arg.c_str());
|
||||
hr_interval_s = Strings::ToInt(interval_arg);
|
||||
}
|
||||
|
||||
if (hr_interval_s < CASTING_CYCLE_MINIMUM_INTERVAL_S || hr_interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL_S)
|
||||
@@ -9009,7 +9012,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
}
|
||||
|
||||
|
||||
auto my_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(bot_name.c_str(), "", bot_owner->GetLevel(), bot_race, bot_class, bot_gender), bot_owner);
|
||||
auto my_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(bot_name, "", bot_owner->GetLevel(), bot_race, bot_class, bot_gender), bot_owner);
|
||||
|
||||
if (!my_bot->Save()) {
|
||||
bot_owner->Message(
|
||||
@@ -9259,7 +9262,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
||||
destination_number,
|
||||
local_entry->long_name,
|
||||
text_link
|
||||
).c_str()
|
||||
)
|
||||
);
|
||||
|
||||
destination_count++;
|
||||
@@ -9294,7 +9297,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
||||
destination_number,
|
||||
local_entry->long_name,
|
||||
text_link
|
||||
).c_str()
|
||||
)
|
||||
);
|
||||
|
||||
destination_count++;
|
||||
|
||||
+10
-10
@@ -110,7 +110,7 @@ bool Bot::BotCastSong(Mob* tar, uint8 botLevel) {
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
continue;
|
||||
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
switch (spells[iter.SpellId].target_type) {
|
||||
case ST_AEBard:
|
||||
@@ -144,7 +144,7 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
continue;
|
||||
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
switch (spells[iter.SpellId].target_type) {
|
||||
case ST_AEBard:
|
||||
@@ -176,7 +176,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
|
||||
continue;
|
||||
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
|
||||
continue;
|
||||
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
|
||||
continue;
|
||||
if (spells[iter.SpellId].target_type != ST_Target)
|
||||
continue;
|
||||
@@ -316,7 +316,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) {
|
||||
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -582,7 +582,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
if (
|
||||
((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
|
||||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) &&
|
||||
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -892,7 +892,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
||||
(IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
|
||||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())
|
||||
) &&
|
||||
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -1902,7 +1902,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) {
|
||||
if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)) {
|
||||
BotSpell botSpell;
|
||||
botSpell.SpellId = botSpellList[i].spellid;
|
||||
botSpell.SpellIndex = i;
|
||||
@@ -1940,7 +1940,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
|
||||
if (
|
||||
(
|
||||
IsEffectInSpell(botSpellList[i].spellid, spellEffect) ||
|
||||
GetTriggerSpellID(botSpellList[i].spellid, spellEffect)
|
||||
GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)
|
||||
) &&
|
||||
spells[botSpellList[i].spellid].target_type == targetType
|
||||
) {
|
||||
@@ -2313,7 +2313,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) {
|
||||
for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
|
||||
// Assuming all the spells have been loaded into this list by level and in descending order
|
||||
if (
|
||||
IsMezSpell(botSpellListItr->SpellId) &&
|
||||
IsMesmerizeSpell(botSpellListItr->SpellId) &&
|
||||
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
|
||||
) {
|
||||
result.SpellId = botSpellListItr->SpellId;
|
||||
@@ -2388,7 +2388,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) {
|
||||
Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) {
|
||||
Mob* result = 0;
|
||||
|
||||
if (botCaster && IsMezSpell(botSpell.SpellId)) {
|
||||
if (botCaster && IsMesmerizeSpell(botSpell.SpellId)) {
|
||||
|
||||
std::list<NPC*> npc_list;
|
||||
entity_list.GetNPCList(npc_list);
|
||||
|
||||
+448
-381
File diff suppressed because it is too large
Load Diff
+14
-13
@@ -67,6 +67,7 @@ namespace EQ
|
||||
#include "task_client_state.h"
|
||||
#include "cheat_manager.h"
|
||||
#include "../common/events/player_events.h"
|
||||
#include "../common/data_verification.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
// since windows defines these within windef.h (which windows.h include)
|
||||
@@ -306,7 +307,6 @@ public:
|
||||
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
|
||||
void TradeRequestFailed(const EQApplicationPacket* app);
|
||||
void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app);
|
||||
void TraderUpdate(uint16 slot_id,uint32 trader_id);
|
||||
void FinishTrade(Mob* with, bool finalizer = false, void* event_entry = nullptr, std::list<void*>* event_details = nullptr);
|
||||
void SendZonePoints();
|
||||
|
||||
@@ -322,7 +322,6 @@ public:
|
||||
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); }
|
||||
virtual bool Process();
|
||||
void ProcessPackets();
|
||||
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
|
||||
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
|
||||
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false);
|
||||
@@ -379,12 +378,8 @@ public:
|
||||
|
||||
void SetPetCommandState(int button, int state);
|
||||
|
||||
bool CheckAccess(int16 iDBLevel, int16 iDefaultLevel);
|
||||
|
||||
void CheckQuests(const char* zonename, const char* message, uint32 npc_id, uint32 item_id, Mob* other);
|
||||
bool AutoAttackEnabled() const { return auto_attack; }
|
||||
bool AutoFireEnabled() const { return auto_fire; }
|
||||
void MakeCorpse(uint32 exploss);
|
||||
|
||||
bool ChangeFirstName(const char* in_firstname,const char* gmname);
|
||||
|
||||
@@ -394,7 +389,6 @@ public:
|
||||
|
||||
virtual void SetMaxHP();
|
||||
int32 LevelRegen();
|
||||
void HPTick();
|
||||
void SetGM(bool toggle);
|
||||
void SetPVP(bool toggle, bool message = true);
|
||||
|
||||
@@ -938,7 +932,7 @@ public:
|
||||
inline uint32 GetAAPercent() const { return m_epp.perAA; }
|
||||
void SetAATitle(std::string title);
|
||||
void SetTitleSuffix(std::string suffix);
|
||||
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0);
|
||||
void MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction = 0);
|
||||
|
||||
// Item methods
|
||||
void UseAugmentContainer(int container_slot);
|
||||
@@ -972,6 +966,8 @@ public:
|
||||
void DropItem(int16 slot_id, bool recurse = true);
|
||||
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
|
||||
|
||||
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
|
||||
|
||||
int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
|
||||
|
||||
void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false);
|
||||
@@ -999,6 +995,7 @@ public:
|
||||
void SetThirst(int32 in_thirst);
|
||||
void SetConsumption(int32 in_hunger, int32 in_thirst);
|
||||
bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; }
|
||||
int32 GetIntoxication() const { return m_pp.intoxication; }
|
||||
|
||||
bool CheckTradeLoreConflict(Client* other);
|
||||
bool CheckTradeNonDroppable();
|
||||
@@ -1588,6 +1585,7 @@ public:
|
||||
void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; }
|
||||
inline bool GetInvulnerableEnvironmentDamage() const { return invulnerable_environment_damage; }
|
||||
void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; }
|
||||
void SetIntoxication(int32 in_intoxication);
|
||||
|
||||
void ShowNumHits(); // work around function for numhits not showing on buffs
|
||||
|
||||
@@ -1643,6 +1641,7 @@ public:
|
||||
PlayerEvent::PlayerEvent GetPlayerEvent();
|
||||
void RecordKilledNPCEvent(NPC *n);
|
||||
|
||||
uint32 GetEXPForLevel(uint16 check_level);
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcEdibleBonuses(StatBonuses* newbon);
|
||||
@@ -1719,7 +1718,6 @@ private:
|
||||
int64 CalcHPRegen(bool bCombat = false);
|
||||
int64 CalcManaRegen(bool bCombat = false);
|
||||
int64 CalcBaseManaRegen();
|
||||
uint64 GetClassHPFactor();
|
||||
void DoHPRegen();
|
||||
void DoManaRegen();
|
||||
void DoStaminaHungerUpdate();
|
||||
@@ -1819,7 +1817,6 @@ private:
|
||||
bool temp_pvp;
|
||||
|
||||
void NPCSpawn(const Seperator* sep);
|
||||
uint32 GetEXPForLevel(uint16 level);
|
||||
|
||||
void SendLogoutPackets();
|
||||
void SendZoneInPackets();
|
||||
@@ -1842,9 +1839,6 @@ private:
|
||||
|
||||
WaterRegionType last_region_type;
|
||||
|
||||
// this is used to try to cut back on position update reflections
|
||||
int position_update_same_count;
|
||||
|
||||
PTimerList p_timers; //persistent timers
|
||||
Timer hpupdate_timer;
|
||||
Timer camp_timer;
|
||||
@@ -2043,6 +2037,13 @@ private:
|
||||
bool CanTradeFVNoDropItem();
|
||||
void SendMobPositions();
|
||||
void PlayerTradeEventLog(Trade *t, Trade *t2);
|
||||
|
||||
// full and partial mail key cache
|
||||
std::string m_mail_key_full;
|
||||
std::string m_mail_key;
|
||||
public:
|
||||
const std::string &GetMailKeyFull() const;
|
||||
const std::string &GetMailKey() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+7
-51
@@ -288,7 +288,7 @@ int64 Client::CalcHPRegen(bool bCombat)
|
||||
|
||||
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
||||
auto max_hp = GetMaxHP();
|
||||
int fast_regen = 6 * (max_hp / zone->newzone_data.fast_regen_hp);
|
||||
int64 fast_regen = 6 * (max_hp / (zone ? zone->newzone_data.fast_regen_hp : 180));
|
||||
if (base < fast_regen) // weird, but what the client is doing
|
||||
base = fast_regen;
|
||||
}
|
||||
@@ -506,50 +506,6 @@ int64 Client::CalcBaseHP()
|
||||
return base_hp;
|
||||
}
|
||||
|
||||
// This is for calculating Base HPs + STA bonus for SoD or later clients.
|
||||
uint64 Client::GetClassHPFactor()
|
||||
{
|
||||
int factor;
|
||||
// Note: Base HP factor under level 41 is equal to factor / 12, and from level 41 to 80 is factor / 6.
|
||||
// Base HP over level 80 is factor / 10
|
||||
// HP per STA point per level is factor / 30 for level 80+
|
||||
// HP per STA under level 40 is the level 80 HP Per STA / 120, and for over 40 it is / 60.
|
||||
switch (GetClass()) {
|
||||
case DRUID:
|
||||
case ENCHANTER:
|
||||
case NECROMANCER:
|
||||
case MAGICIAN:
|
||||
case WIZARD:
|
||||
factor = 240;
|
||||
break;
|
||||
case BEASTLORD:
|
||||
case BERSERKER:
|
||||
case MONK:
|
||||
case ROGUE:
|
||||
case SHAMAN:
|
||||
factor = 255;
|
||||
break;
|
||||
case BARD:
|
||||
case CLERIC:
|
||||
factor = 264;
|
||||
break;
|
||||
case SHADOWKNIGHT:
|
||||
case PALADIN:
|
||||
factor = 288;
|
||||
break;
|
||||
case RANGER:
|
||||
factor = 276;
|
||||
break;
|
||||
case WARRIOR:
|
||||
factor = 300;
|
||||
break;
|
||||
default:
|
||||
factor = 240;
|
||||
break;
|
||||
}
|
||||
return factor;
|
||||
}
|
||||
|
||||
// This should return the combined AC of all the items the player is wearing.
|
||||
int32 Client::GetRawItemAC()
|
||||
{
|
||||
@@ -841,10 +797,10 @@ uint32 Client::CalcCurrentWeight()
|
||||
|
||||
int32 Client::CalcAlcoholPhysicalEffect()
|
||||
{
|
||||
if (m_pp.intoxication <= 55) {
|
||||
if (GetIntoxication() <= 55) {
|
||||
return 0;
|
||||
}
|
||||
return (m_pp.intoxication - 40) / 16;
|
||||
return (GetIntoxication() - 40) / 16;
|
||||
}
|
||||
|
||||
int32 Client::CalcSTR()
|
||||
@@ -922,8 +878,8 @@ int32 Client::CalcINT()
|
||||
int32 val = m_pp.INT + itembonuses.INT + spellbonuses.INT;
|
||||
int32 mod = aabonuses.INT;
|
||||
INT = val + mod;
|
||||
if (m_pp.intoxication) {
|
||||
int32 AlcINT = INT - (int32)((float)m_pp.intoxication / 200.0f * (float)INT) - 1;
|
||||
if (GetIntoxication()) {
|
||||
int32 AlcINT = INT - (int32)((float)GetIntoxication() / 200.0f * (float)INT) - 1;
|
||||
if ((AlcINT < (int)(0.2 * INT))) {
|
||||
INT = (int)(0.2f * (float)INT);
|
||||
}
|
||||
@@ -946,8 +902,8 @@ int32 Client::CalcWIS()
|
||||
int32 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS;
|
||||
int32 mod = aabonuses.WIS;
|
||||
WIS = val + mod;
|
||||
if (m_pp.intoxication) {
|
||||
int32 AlcWIS = WIS - (int32)((float)m_pp.intoxication / 200.0f * (float)WIS) - 1;
|
||||
if (GetIntoxication()) {
|
||||
int32 AlcWIS = WIS - (int32)((float)GetIntoxication() / 200.0f * (float)WIS) - 1;
|
||||
if ((AlcWIS < (int)(0.2 * WIS))) {
|
||||
WIS = (int)(0.2f * (float)WIS);
|
||||
}
|
||||
|
||||
+83
-73
@@ -656,7 +656,7 @@ void Client::CompleteConnect()
|
||||
|
||||
const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid];
|
||||
|
||||
int NimbusEffect = GetNimbusEffect(buffs[j1].spellid);
|
||||
int NimbusEffect = GetSpellNimbusEffect(buffs[j1].spellid);
|
||||
if (NimbusEffect) {
|
||||
if (!IsNimbusEffectActive(NimbusEffect))
|
||||
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
|
||||
@@ -721,17 +721,17 @@ void Client::CompleteConnect()
|
||||
case SE_AddMeleeProc:
|
||||
case SE_WeaponProc:
|
||||
{
|
||||
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
|
||||
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
|
||||
break;
|
||||
}
|
||||
case SE_DefensiveProc:
|
||||
{
|
||||
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
|
||||
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
|
||||
break;
|
||||
}
|
||||
case SE_RangedProc:
|
||||
{
|
||||
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
|
||||
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1265,7 +1265,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
|
||||
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
|
||||
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
|
||||
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */
|
||||
database.LoadCharacterTribute(this); /* Load CharacterTribute */
|
||||
|
||||
// this pattern is strange
|
||||
// this is remnants of the old way of doing things
|
||||
auto mail_keys = database.GetMailKey(CharacterID());
|
||||
m_mail_key_full = mail_keys.mail_key_full;
|
||||
m_mail_key = mail_keys.mail_key;
|
||||
|
||||
/* Load AdventureStats */
|
||||
AdventureStats_Struct as;
|
||||
@@ -1309,7 +1315,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
|
||||
/* If we can maintain intoxication across zones, check for it */
|
||||
if (!RuleB(Character, MaintainIntoxicationAcrossZones))
|
||||
m_pp.intoxication = 0;
|
||||
SetIntoxication(0);
|
||||
|
||||
strcpy(name, m_pp.name);
|
||||
strcpy(lastname, m_pp.last_name);
|
||||
@@ -1508,30 +1514,31 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (group) {
|
||||
// If the group leader is not set, pull the group leader infomrmation from the database.
|
||||
if (!group->GetLeader()) {
|
||||
char ln[64];
|
||||
char MainTankName[64];
|
||||
char AssistName[64];
|
||||
char PullerName[64];
|
||||
char NPCMarkerName[64];
|
||||
char mentoree_name[64];
|
||||
int mentor_percent;
|
||||
GroupLeadershipAA_Struct GLAA;
|
||||
memset(ln, 0, 64);
|
||||
database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA);
|
||||
Client *c = entity_list.GetClientByName(ln);
|
||||
if (c)
|
||||
group->SetLeader(c);
|
||||
|
||||
group->SetMainTank(MainTankName);
|
||||
group->SetMainAssist(AssistName);
|
||||
group->SetPuller(PullerName);
|
||||
group->SetNPCMarker(NPCMarkerName);
|
||||
group->SetGroupAAs(&GLAA);
|
||||
group->SetGroupMentor(mentor_percent, mentoree_name);
|
||||
}
|
||||
char ln[64];
|
||||
char MainTankName[64];
|
||||
char AssistName[64];
|
||||
char PullerName[64];
|
||||
char NPCMarkerName[64];
|
||||
char mentoree_name[64];
|
||||
int mentor_percent;
|
||||
GroupLeadershipAA_Struct GLAA;
|
||||
memset(ln, 0, 64);
|
||||
database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA);
|
||||
group->LearnMembers();
|
||||
|
||||
if (!group->GetLeader()) {
|
||||
Client *c = entity_list.GetClientByName(ln);
|
||||
if (c) {
|
||||
group->SetLeader(c);
|
||||
}
|
||||
}
|
||||
|
||||
group->SetMainTank(MainTankName);
|
||||
group->SetMainAssist(AssistName);
|
||||
group->SetPuller(PullerName);
|
||||
group->SetNPCMarker(NPCMarkerName);
|
||||
group->SetGroupAAs(&GLAA);
|
||||
group->SetGroupMentor(mentor_percent, mentoree_name);
|
||||
JoinGroupXTargets(group);
|
||||
group->UpdatePlayer(this);
|
||||
LFG = false;
|
||||
@@ -5568,10 +5575,8 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app)
|
||||
if (IntoxicationIncrease < 0)
|
||||
IntoxicationIncrease = 1;
|
||||
|
||||
m_pp.intoxication += IntoxicationIncrease;
|
||||
SetIntoxication(GetIntoxication()+IntoxicationIncrease);
|
||||
|
||||
if (m_pp.intoxication > 200)
|
||||
m_pp.intoxication = 200;
|
||||
}
|
||||
DeleteItemInInventory(alc->from_slot, 1);
|
||||
|
||||
@@ -6466,27 +6471,28 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMSummon_Struct)) {
|
||||
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMSummon_Struct));
|
||||
|
||||
if (app->size != sizeof(GMFind_Struct)) {
|
||||
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct));
|
||||
return;
|
||||
}
|
||||
|
||||
//Break down incoming
|
||||
GMSummon_Struct* request = (GMSummon_Struct*)app->pBuffer;
|
||||
auto* request = (GMFind_Struct*) app->pBuffer;
|
||||
//Create a new outgoing
|
||||
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMSummon_Struct));
|
||||
GMSummon_Struct* foundplayer = (GMSummon_Struct*)outapp->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
|
||||
auto* foundplayer = (GMFind_Struct*) outapp->pBuffer;
|
||||
//Copy the constants
|
||||
strcpy(foundplayer->charname, request->charname);
|
||||
strcpy(foundplayer->gmname, request->gmname);
|
||||
//Check if the NPC exits intrazone...
|
||||
Mob* gt = entity_list.GetMob(request->charname);
|
||||
if (gt != 0) {
|
||||
auto* gt = entity_list.GetMob(request->charname);
|
||||
if (gt) {
|
||||
foundplayer->success = 1;
|
||||
foundplayer->x = (int32)gt->GetX();
|
||||
foundplayer->y = (int32)gt->GetY();
|
||||
|
||||
foundplayer->z = (int32)gt->GetZ();
|
||||
foundplayer->zoneID = zone->GetZoneID();
|
||||
foundplayer->x = gt->GetX();
|
||||
foundplayer->y = gt->GetY();
|
||||
foundplayer->z = gt->GetZ();
|
||||
foundplayer->zoneID = zone->GetZoneID();
|
||||
}
|
||||
//Send the packet...
|
||||
FastQueuePacket(&outapp);
|
||||
@@ -6999,7 +7005,7 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
|
||||
//we have a raid.. see if we're in a raid group
|
||||
uint32 grp = raid->GetGroup(memberToDisband->GetName());
|
||||
bool wasGrpLdr = raid->members[raid->GetPlayerIndex(memberToDisband->GetName())].is_group_leader;
|
||||
if (grp < 12) {
|
||||
if (grp < MAX_RAID_GROUPS) {
|
||||
if (wasGrpLdr) {
|
||||
raid->SetGroupLeader(memberToDisband->GetName(), false);
|
||||
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||
@@ -8613,47 +8619,51 @@ void Client::Handle_OP_Illusion(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app)
|
||||
{
|
||||
|
||||
if (app->size != sizeof(InspectResponse_Struct)) {
|
||||
LogError("Wrong size: OP_InspectAnswer, size=[{}], expected [{}]", app->size, sizeof(InspectResponse_Struct));
|
||||
return;
|
||||
}
|
||||
|
||||
//Fills the app sent from client.
|
||||
EQApplicationPacket* outapp = app->Copy();
|
||||
InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer;
|
||||
Mob* tmp = entity_list.GetMob(insr->TargetID);
|
||||
const EQ::ItemData* item = nullptr;
|
||||
auto outapp = app->Copy();
|
||||
auto insr = (InspectResponse_Struct *) outapp->pBuffer;
|
||||
auto tmp = entity_list.GetMob(insr->TargetID);
|
||||
const EQ::ItemData *item = nullptr;
|
||||
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
for (int16 L = EQ::invslot::EQUIPMENT_BEGIN; L <= EQ::invslot::EQUIPMENT_END; L++) {
|
||||
const EQ::ItemInstance* inst = GetInv().GetItem(L);
|
||||
for (int16 L = EQ::invslot::EQUIPMENT_BEGIN; L <= EQ::invslot::EQUIPMENT_END; L++) {
|
||||
const auto inst = GetInv().GetItem(L);
|
||||
item = inst ? inst->GetItem() : nullptr;
|
||||
|
||||
if (item) {
|
||||
strcpy(insr->itemnames[L], item->Name);
|
||||
if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
const EQ::ItemData *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
insr->itemicons[L] = aug_item->Icon;
|
||||
}
|
||||
else if (inst->GetOrnamentationIcon()) {
|
||||
insr->itemicons[L] = inst->GetOrnamentationIcon();
|
||||
}
|
||||
else {
|
||||
if (inst) {
|
||||
const auto augment = inst->GetOrnamentationAugment();
|
||||
|
||||
if (augment) {
|
||||
insr->itemicons[L] = augment->GetItem()->Icon;
|
||||
} else if (inst->GetOrnamentationIcon()) {
|
||||
insr->itemicons[L] = inst->GetOrnamentationIcon();
|
||||
}
|
||||
} else {
|
||||
insr->itemicons[L] = item->Icon;
|
||||
}
|
||||
} else {
|
||||
insr->itemicons[L] = 0xFFFFFFFF;
|
||||
}
|
||||
else { insr->itemicons[L] = 0xFFFFFFFF; }
|
||||
}
|
||||
|
||||
InspectMessage_Struct* newmessage = (InspectMessage_Struct*)insr->text;
|
||||
InspectMessage_Struct& playermessage = GetInspectMessage();
|
||||
memcpy(&playermessage, newmessage, sizeof(InspectMessage_Struct));
|
||||
database.SaveCharacterInspectMessage(CharacterID(), &playermessage);
|
||||
auto message = (InspectMessage_Struct *) insr->text;
|
||||
auto inspect_message = GetInspectMessage();
|
||||
|
||||
if (tmp != 0 && tmp->IsClient()) { tmp->CastToClient()->QueuePacket(outapp); } // Send answer to requester
|
||||
memcpy(&inspect_message, message, sizeof(InspectMessage_Struct));
|
||||
database.SaveCharacterInspectMessage(CharacterID(), &inspect_message);
|
||||
|
||||
return;
|
||||
if (
|
||||
tmp &&
|
||||
tmp->IsClient()
|
||||
) {
|
||||
tmp->CastToClient()->QueuePacket(outapp);
|
||||
} // Send answer to requester
|
||||
}
|
||||
|
||||
void Client::Handle_OP_InspectMessageUpdate(const EQApplicationPacket *app)
|
||||
@@ -9223,7 +9233,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
if (i == 0) {
|
||||
if (!IsCastWhileInvis(item->Click.Effect)) {
|
||||
if (!IsCastWhileInvisibleSpell(item->Click.Effect)) {
|
||||
CommonBreakInvisible(); // client can't do this for us :(
|
||||
}
|
||||
if (GetClass() == BARD){
|
||||
@@ -9295,7 +9305,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (!IsCastWhileInvis(augitem->Click.Effect)) {
|
||||
if (!IsCastWhileInvisibleSpell(augitem->Click.Effect)) {
|
||||
CommonBreakInvisible(); // client can't do this for us :(
|
||||
}
|
||||
if (GetClass() == BARD) {
|
||||
@@ -11460,7 +11470,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
||||
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) {
|
||||
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY);
|
||||
if (!response.empty()) {
|
||||
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true);
|
||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -11469,7 +11479,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
||||
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) {
|
||||
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY);
|
||||
if (!response.empty()) {
|
||||
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true);
|
||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -11675,7 +11685,7 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
std::string buffer;
|
||||
|
||||
std::string MailKey = database.GetMailKey(CharacterID(), true);
|
||||
std::string MailKey = GetMailKey();
|
||||
EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown;
|
||||
|
||||
// chat server packet
|
||||
|
||||
@@ -189,9 +189,10 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
if (camp_timer.Check()) {
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if (raid)
|
||||
raid->RemoveMember(this->GetName());
|
||||
Raid *myraid = entity_list.GetRaidByClient(this);
|
||||
if (myraid) {
|
||||
myraid->MemberZoned(this);
|
||||
}
|
||||
LeaveGroup();
|
||||
Save();
|
||||
if (GetMerc())
|
||||
@@ -517,9 +518,9 @@ bool Client::Process() {
|
||||
Save(0);
|
||||
}
|
||||
|
||||
if (m_pp.intoxication > 0)
|
||||
if (GetIntoxication() > 0)
|
||||
{
|
||||
--m_pp.intoxication;
|
||||
SetIntoxication(GetIntoxication()-1);
|
||||
CalcBonuses();
|
||||
}
|
||||
|
||||
@@ -1034,7 +1035,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
|
||||
BuffFadeNonPersistDeath();
|
||||
}
|
||||
|
||||
int SpellEffectDescNum = GetSpellEffectDescNum(SpellID);
|
||||
int SpellEffectDescNum = GetSpellEffectDescriptionNumber(SpellID);
|
||||
// Rez spells with Rez effects have this DescNum (first is Titanium, second is 6.2 Client)
|
||||
if(RuleB(Character, UseResurrectionSickness) && SpellEffectDescNum == 82 || SpellEffectDescNum == 39067) {
|
||||
SetHP(GetMaxHP() / 5);
|
||||
@@ -1967,7 +1968,7 @@ void Client::CalcRestState()
|
||||
for (unsigned int j = 0; j < buff_count; j++) {
|
||||
if(IsValidSpell(buffs[j].spellid)) {
|
||||
if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
|
||||
if(!DetrimentalSpellAllowsRest(buffs[j].spellid))
|
||||
if(!IsRestAllowedSpell(buffs[j].spellid))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,13 +71,3 @@ float CombatRecord::GetHealedReceivedPerSecond() const
|
||||
double time_in_combat = TimeInCombat();
|
||||
return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received;
|
||||
}
|
||||
|
||||
int64 CombatRecord::GetDamageReceived() const
|
||||
{
|
||||
return m_damage_received;
|
||||
}
|
||||
|
||||
int64 CombatRecord::GetHealReceived() const
|
||||
{
|
||||
return m_heal_received;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ public:
|
||||
bool InCombat() const;
|
||||
void ProcessHPEvent(int64 hp, int64 current_hp);
|
||||
double TimeInCombat() const;
|
||||
int64 GetDamageReceived() const;
|
||||
int64 GetHealReceived() const;
|
||||
float GetDamageReceivedPerSecond() const;
|
||||
float GetHealedReceivedPerSecond() const;
|
||||
private:
|
||||
|
||||
+5
-2
@@ -131,6 +131,7 @@ int command_init(void)
|
||||
command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) ||
|
||||
command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) ||
|
||||
command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) ||
|
||||
command_add("entityvariable", "[clear|delete|set|view] - Modify entity variables for yourself or your target", AccountStatus::GMAdmin, command_entityvariable) ||
|
||||
command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) ||
|
||||
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) ||
|
||||
command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) ||
|
||||
@@ -140,6 +141,7 @@ int command_init(void)
|
||||
command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) ||
|
||||
command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) ||
|
||||
command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) ||
|
||||
command_add("findcurrency", "[Search Criteria] - Search for an alternate currency", AccountStatus::Guide, command_findcurrency) ||
|
||||
command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) ||
|
||||
command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) ||
|
||||
command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) ||
|
||||
@@ -230,7 +232,7 @@ int command_init(void)
|
||||
command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) ||
|
||||
command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) ||
|
||||
command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) ||
|
||||
command_add("opcode", "Reloads all server patches", AccountStatus::GMImpossible, command_opcode) ||
|
||||
command_add("opcode", "Reloads all opcodes from server patch files", AccountStatus::GMMgmt, command_reload) ||
|
||||
command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) ||
|
||||
command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) ||
|
||||
command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) ||
|
||||
@@ -976,12 +978,14 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/emptyinventory.cpp"
|
||||
#include "gm_commands/enablerecipe.cpp"
|
||||
#include "gm_commands/endurance.cpp"
|
||||
#include "gm_commands/entityvariable.cpp"
|
||||
#include "gm_commands/exptoggle.cpp"
|
||||
#include "gm_commands/faction.cpp"
|
||||
#include "gm_commands/feature.cpp"
|
||||
#include "gm_commands/findaa.cpp"
|
||||
#include "gm_commands/findcharacter.cpp"
|
||||
#include "gm_commands/findclass.cpp"
|
||||
#include "gm_commands/findcurrency.cpp"
|
||||
#include "gm_commands/findfaction.cpp"
|
||||
#include "gm_commands/findnpctype.cpp"
|
||||
#include "gm_commands/findrace.cpp"
|
||||
@@ -1069,7 +1073,6 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/nukeitem.cpp"
|
||||
#include "gm_commands/object.cpp"
|
||||
#include "gm_commands/oocmute.cpp"
|
||||
#include "gm_commands/opcode.cpp"
|
||||
#include "gm_commands/path.cpp"
|
||||
#include "gm_commands/peekinv.cpp"
|
||||
#include "gm_commands/peqzone.cpp"
|
||||
|
||||
+2
-1
@@ -82,6 +82,7 @@ void command_emoteview(Client *c, const Seperator *sep);
|
||||
void command_emptyinventory(Client *c, const Seperator *sep);
|
||||
void command_enablerecipe(Client *c, const Seperator *sep);
|
||||
void command_endurance(Client *c, const Seperator *sep);
|
||||
void command_entityvariable(Client *c, const Seperator *sep);
|
||||
void command_exptoggle(Client *c, const Seperator *sep);
|
||||
void command_faction(Client *c, const Seperator *sep);
|
||||
void command_faction_association(Client *c, const Seperator *sep);
|
||||
@@ -90,6 +91,7 @@ void command_findaa(Client *c, const Seperator *sep);
|
||||
void command_findaliases(Client *c, const Seperator *sep);
|
||||
void command_findcharacter(Client *c, const Seperator *sep);
|
||||
void command_findclass(Client *c, const Seperator *sep);
|
||||
void command_findcurrency(Client *c, const Seperator *sep);
|
||||
void command_findfaction(Client *c, const Seperator *sep);
|
||||
void command_findnpctype(Client *c, const Seperator *sep);
|
||||
void command_findrace(Client *c, const Seperator *sep);
|
||||
@@ -180,7 +182,6 @@ void command_nukebuffs(Client *c, const Seperator *sep);
|
||||
void command_nukeitem(Client *c, const Seperator *sep);
|
||||
void command_object(Client *c, const Seperator *sep);
|
||||
void command_oocmute(Client *c, const Seperator *sep);
|
||||
void command_opcode(Client *c, const Seperator *sep);
|
||||
|
||||
#ifdef PACKET_PROFILER
|
||||
void command_packetprofile(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -14,13 +14,10 @@
|
||||
#define _CLIENTCORPSE(x) (x && x->IsCorpse() && x->CastToCorpse()->IsPlayerCorpse() && !x->CastToCorpse()->IsBecomeNPCCorpse())
|
||||
#define _NPCCORPSE(x) (x && x->IsCorpse() && (x->CastToCorpse()->IsNPCCorpse() || x->CastToCorpse()->IsBecomeNPCCorpse()))
|
||||
#define _CLIENTPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient())
|
||||
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
|
||||
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
|
||||
|
||||
//LOS Parameters:
|
||||
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
|
||||
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
|
||||
#define CHECK_LOS_STEP 1.0f
|
||||
|
||||
#define ARCHETYPE_HYBRID 1
|
||||
#define ARCHETYPE_CASTER 2
|
||||
@@ -44,7 +41,6 @@
|
||||
|
||||
//Spell specialization parameters, not sure of a better place for them
|
||||
#define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized
|
||||
#define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized
|
||||
|
||||
//these are large right now because the x,y,z coords of the zone
|
||||
//lines do not make a lot of sense
|
||||
@@ -232,7 +228,6 @@ enum GravityBehavior {
|
||||
LevitateWhileRunning
|
||||
};
|
||||
|
||||
struct TradeEntity;
|
||||
class Trade;
|
||||
enum TradeState {
|
||||
TradeNone,
|
||||
@@ -846,7 +841,6 @@ public:
|
||||
virtual ~Trade();
|
||||
|
||||
void Reset();
|
||||
void SetTradeCash(uint32 in_pp, uint32 in_gp, uint32 in_sp, uint32 in_cp);
|
||||
|
||||
// Initiate a trade with another mob
|
||||
// Also puts other mob into trader mode with this mob
|
||||
|
||||
+3
-3
@@ -623,13 +623,13 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
|
||||
if (!alt_mode) { // original function
|
||||
if (!m_is_open) {
|
||||
if (!m_disable_timer) {
|
||||
LogDoorsDetail("door_id [{}] starting timer", md->doorid);
|
||||
LogDoorsDetail("door_id [{}] starting timer", m_door_id);
|
||||
m_close_timer.Start();
|
||||
}
|
||||
m_is_open = true;
|
||||
}
|
||||
else {
|
||||
LogDoorsDetail("door_id [{}] disable timer", md->doorid);
|
||||
LogDoorsDetail("door_id [{}] disable timer", m_door_id);
|
||||
m_close_timer.Disable();
|
||||
if (!m_disable_timer) {
|
||||
m_is_open = false;
|
||||
@@ -638,7 +638,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
|
||||
}
|
||||
else { // alternative function
|
||||
if (!m_disable_timer) {
|
||||
LogDoorsDetail("door_id [{}] alt starting timer", md->doorid);
|
||||
LogDoorsDetail("door_id [{}] alt starting timer", m_door_id);
|
||||
m_close_timer.Start();
|
||||
}
|
||||
m_is_open = true;
|
||||
|
||||
+3
-3
@@ -810,9 +810,9 @@ void Client::SendDisciplineUpdate() {
|
||||
|
||||
bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
// Dont let client waste a reuse timer if they can't use the disc
|
||||
if ((IsStunned() && !IgnoreCastingRestriction(spell_id))||
|
||||
if ((IsStunned() && !IsCastNotStandingSpell(spell_id))||
|
||||
IsFeared() ||
|
||||
(IsMezzed() && !IgnoreCastingRestriction(spell_id)) ||
|
||||
(IsMezzed() && !IsCastNotStandingSpell(spell_id)) ||
|
||||
IsAmnesiad() ||
|
||||
IsPet())
|
||||
{
|
||||
@@ -837,7 +837,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DivineAura() && !IgnoreCastingRestriction(spell_id)) {
|
||||
if (DivineAura() && !IsCastNotStandingSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+17
-19
@@ -179,6 +179,10 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_ITEM_CLICK_CAST_CLIENT",
|
||||
"EVENT_DESTROY_ITEM_CLIENT",
|
||||
"EVENT_DROP_ITEM_CLIENT",
|
||||
"EVENT_MEMORIZE_SPELL",
|
||||
"EVENT_UNMEMORIZE_SPELL",
|
||||
"EVENT_SCRIBE_SPELL",
|
||||
"EVENT_UNSCRIBE_SPELL",
|
||||
// Add new events before these or Lua crashes
|
||||
"EVENT_SPELL_EFFECT_BOT",
|
||||
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
|
||||
@@ -835,25 +839,6 @@ void PerlembParser::ExportVar(const char *pkgprefix, const char *varname, float
|
||||
}
|
||||
}
|
||||
|
||||
void PerlembParser::ExportVarComplex(const char *pkgprefix, const char *varname, const char *value)
|
||||
{
|
||||
|
||||
if (!perl) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
perl->eval(std::string("$").append(pkgprefix).append("::").append(varname).append("=").append(value).append(";").c_str());
|
||||
}
|
||||
catch (std::string e) {
|
||||
AddError(
|
||||
fmt::format(
|
||||
"Error exporting Perl variable [{}]",
|
||||
e
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void PerlembParser::ExportVar(const char *pkgprefix, const char *varname, const char *value)
|
||||
{
|
||||
if (!perl) {
|
||||
@@ -2179,6 +2164,19 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_MEMORIZE_SPELL:
|
||||
case EVENT_UNMEMORIZE_SPELL:
|
||||
case EVENT_SCRIBE_SPELL:
|
||||
case EVENT_UNSCRIBE_SPELL: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "slot_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "spell_id", sep.arg[1]);
|
||||
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[1]))) {
|
||||
ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[1])]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,6 @@ private:
|
||||
void ExportVar(const char *pkgprefix, const char *varname, uint32 value);
|
||||
void ExportVar(const char *pkgprefix, const char *varname, float value);
|
||||
void ExportVar(const char* pkgprefix, const char* varname, const char* classname, void* value);
|
||||
void ExportVarComplex(const char *pkgprefix, const char *varname, const char *value);
|
||||
|
||||
int EventCommon(
|
||||
QuestEventID event,
|
||||
|
||||
+1474
-19
File diff suppressed because it is too large
Load Diff
+39
-6
@@ -314,14 +314,47 @@ bool Embperl::SubExists(const char *package, const char *sub) {
|
||||
return(hv_exists(stash, sub, len));
|
||||
}
|
||||
|
||||
bool Embperl::VarExists(const char *package, const char *var) {
|
||||
HV *stash = gv_stashpv(package, false);
|
||||
if(!stash)
|
||||
return(false);
|
||||
int len = strlen(var);
|
||||
return(hv_exists(stash, var, len));
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
|
||||
XS(XS_EQEmuIO_PRINT); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_EQEmuIO_PRINT)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int r = 1; r < items; r++) {
|
||||
char *str = SvPV_nolen(ST(r));
|
||||
char *cur = str;
|
||||
|
||||
/* Strip newlines from log message 'str' */
|
||||
*std::remove(str, str + strlen(str), '\n') = '\0';
|
||||
|
||||
std::string log_string = str;
|
||||
|
||||
if (
|
||||
log_string.find("did not return a true") != std::string::npos ||
|
||||
log_string.find("is experimental") != std::string::npos
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; *cur != '\0'; i++, cur++) {
|
||||
if (*cur == '\n') {
|
||||
LogQuests("{}", str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!log_string.empty()) {
|
||||
LogQuests("{}", log_string);
|
||||
}
|
||||
}
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
#endif //EMBPERL
|
||||
|
||||
|
||||
@@ -73,13 +73,6 @@ class Embperl
|
||||
private:
|
||||
//if we fail inside a script evaluation, this will hold the croak msg (not much help if we die during construction, but that's our own fault)
|
||||
mutable std::string errmsg;
|
||||
//kludgy workaround for the fact that we can't directly do something like SvIV(get_sv($big[0]{ass}->{struct}))
|
||||
SV * my_get_sv(const char * varname) {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "if(defined(%s)) { $scratch::temp = %s; } else { $scratch::temp = 'UNDEF'; }", varname, varname);
|
||||
eval(buffer);
|
||||
return get_sv("scratch::temp", false);
|
||||
}
|
||||
|
||||
//install a perl func
|
||||
void init_eval_file(void);
|
||||
@@ -97,25 +90,11 @@ public:
|
||||
|
||||
void Reinit();
|
||||
|
||||
//return the last error msg
|
||||
std::string lasterr(void) const { return errmsg;};
|
||||
//evaluate an expression. throws string errors on fail
|
||||
int eval(const char * code);
|
||||
//execute a subroutine. throws lasterr on failure
|
||||
int dosub(const char * subname, const std::vector<std::string> * args = nullptr, int mode = G_SCALAR|G_EVAL);
|
||||
|
||||
//Access to perl variables
|
||||
//all varnames here should be of the form package::name
|
||||
//returns the contents of the perl variable named in varname as a c int
|
||||
int geti(const char * varname) { return static_cast<int>(SvIV(my_get_sv(varname))); };
|
||||
//returns the contents of the perl variable named in varname as a c float
|
||||
float getd(const char * varname) { return static_cast<float>(SvNV(my_get_sv(varname)));};
|
||||
//returns the contents of the perl variable named in varname as a string
|
||||
std::string getstr(const char * varname) {
|
||||
SV * temp = my_get_sv(varname);
|
||||
return std::string(SvPV_nolen(temp),SvLEN(temp));
|
||||
}
|
||||
|
||||
//put an integer into a perl varable
|
||||
void seti(const char *varname, int val) const {
|
||||
SV *t = get_sv(varname, true);
|
||||
@@ -163,13 +142,8 @@ public:
|
||||
//idea borrowed from perlembed
|
||||
int eval_file(const char * packagename, const char * filename);
|
||||
|
||||
inline bool InUse() const { return(in_use); }
|
||||
|
||||
//check to see if a sub exists in package
|
||||
bool SubExists(const char *package, const char *sub);
|
||||
|
||||
//check to see if a variable exists in package
|
||||
bool VarExists(const char *package, const char *var);
|
||||
};
|
||||
#endif //EMBPERL
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef EMBPERL
|
||||
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "embxs.h"
|
||||
#include "embperl.h"
|
||||
#include "masterentity.h"
|
||||
#include "command.h"
|
||||
|
||||
const char *getItemName(unsigned itemid)
|
||||
{
|
||||
const EQ::ItemData* item = nullptr;
|
||||
item = database.GetItem(itemid);
|
||||
|
||||
if (item)
|
||||
return item->Name;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* Perl__qc_getItemName(unsigned itemid)
|
||||
{
|
||||
return getItemName(itemid); // possible nullptr return
|
||||
}
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
|
||||
XS(XS_EQEmuIO_PRINT); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_EQEmuIO_PRINT)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items < 2)
|
||||
return;
|
||||
// Perl_croak(aTHX_ "Usage: EQEmuIO::PRINT(@strings)");
|
||||
|
||||
int r;
|
||||
for (r = 1; r < items; r++) {
|
||||
char *str = SvPV_nolen(ST(r));
|
||||
char *cur = str;
|
||||
|
||||
/* Strip newlines from log message 'str' */
|
||||
*std::remove(str, str + strlen(str), '\n') = '\0';
|
||||
|
||||
std::string log_string = str;
|
||||
|
||||
if (log_string.find("did not return a true") != std::string::npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log_string.find("is experimental") != std::string::npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
int pos = 0;
|
||||
int len = 0;
|
||||
|
||||
for (i = 0; *cur != '\0'; i++, cur++) {
|
||||
if (*cur == '\n') {
|
||||
LogQuests("{}", str);
|
||||
len = 0;
|
||||
pos = i + 1;
|
||||
}
|
||||
else {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
if (!log_string.empty()) {
|
||||
LogQuests("{}", log_string);
|
||||
}
|
||||
}
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
#endif // EMBPERL
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user